Open13

vanilla-extractの調査

fumiyakifumiyaki

ドキュメントTOPで書かれているvanilla-extractの強み

  • Type-safe theming
  • Variables, the way they were intended
  • Organise your styles with ease
  • Generate real stylesheets

2個めのVariables, the way they were intendedの書き方がよく分からぬ・・・

styles.css.ts
import { style, createVar } from '@vanilla-extract/css';

const shadowColor = createVar();

export const shadow = style({
  boxShadow: `0 0 10px ${shadowColor}`,
  selectors: {
    '.light &': {
      vars: { [shadowColor]: 'black' }
    },
    '.dark &': {
      vars: { [shadowColor]: 'white' }
    },
  }
});

一旦先に進む

fumiyakifumiyaki

vanilla-extractはスタイルをexport/importすることによってバンドル時に良い感じにcssファイルに変換されるようだ
ゼロランタイムのやつはだいたいそんな感じなのかな?

fumiyakifumiyaki

vanilla-extractのコードと変換後のコードの比較がこうやって並べてくれているのわかりやすい
そしてglobalStyleそんな感じで使えるのね。

vanilla-extractのコードと変換後のコードの比較

fumiyakifumiyaki

2個めのVariables, the way they were intendedの書き方のヒント1
後はselectorsさえ理解出来れば完全に理解できる

Variables, the way they were intendedの書き方のヒント1

fumiyakifumiyaki

Selectorsでた
vanilla-extractにはシンプルなSelectorsと複雑なSelectorsの2種類があるようだ。
https://vanilla-extract.style/documentation/styling/#selectors

Variables, the way they were intendedの例は複雑なSelectorsが使用されていたのね
https://vanilla-extract.style/documentation/styling/#complex-selectors

styles.css.ts
import { style } from '@vanilla-extract/css';

const link = style({
  selectors: {
    '&:hover:not(:active)': {
      border: '2px solid aquamarine'
    },
    'nav li > &': {
      textDecoration: 'underline'
    }
  }
});

ここの例はlinkを渡される(&で表現される)タグ自身の:hover:not(:active)や直系の親がliでnavで括られていたらtextDecoration: 'underline'を適用していたりするのね。

'nav li > &'のスタイルが適用される
<nav>
  <ul>
    <li>
      <a class={link}>sample</a>
    </li>
  </ul>
</nav>

完全に理解した(うまく説明は出来ない)

fumiyakifumiyaki

これでVariables, the way they were intendedのコードが理解できる?

styles.css.ts
import { style, createVar } from '@vanilla-extract/css';

const shadowColor = createVar();

export const shadow = style({
  boxShadow: `0 0 10px ${shadowColor}`,
  selectors: {
    '.light &': {
      vars: { [shadowColor]: 'black' }
    },
    '.dark &': {
      vars: { [shadowColor]: 'white' }
    },
  }
});

本来はlightかdarkは固定値ではなくprospで渡したりする(と思われる)。

lightと一緒に使われると仮置き
<div class={`.light ${shadow}`}></div>
生成されるCSS
.light .styles_myStyle__1hiof570 {
  --global-variable__f1kfgw: white;
}
.styles_myStyle__1hiof570 {
  boxShadow: '0 0 10px white',
}

的な感じかな?

fumiyakifumiyaki
styles.css.ts
import { style } from '@vanilla-extract/css';

const link = style({
  selectors: {
    '&:hover:not(:active)': {
      border: '2px solid aquamarine'
    },
    'nav li > &': {
      textDecoration: 'underline'
    }
  }
});

上の例はあくまでlinkが渡されるタグに対してのスタイリングになっている。
対して下の例ではlinkが渡されたタグの子に対してアプローチしようとしている。
それは駄目だよってことね。

invalidStyles.css.ts
const link = style({
  selectors: {
    '& a[href]': {
      color: red
    },
    '& ~ div > .otherClass': {
      color: blue
    }
  }
});
fumiyakifumiyaki

globalStyleを使うとlinkが渡されたタグの子に対してアプローチできちまうのかーい
一貫してくれた方がわかりやすかったぞーい