はじめに
vanilla-extract の Sprinkles というパッケージについて紹介します。
まず vanilla-extract を軽く説明すると TypeScript でスタイルを記述することができ、ビルド時に静的な CSS ファイルを出力します。公式では「 Zero-runtime Stylesheets-in-TypeScript. 」と表現されております。
Sprinkles
Sprinkles は vanilla-extract のためのゼロランタイムアトミックCSSフレームワークです。カスタムユーティリティクラスの静的なセットを生成し、ビルド時は静的に、実行時は動的に構成します。つまり Tailwind CSS などのゼロランタイムでタイプセーフなバージョンを自分で作るようなものになります。
この説明を読んでも理解し難いので、公式のコードを参考にして理解していきます。
defineProperties
まず以下のコードのように defineProperties と createSprinkles をインポートします。
※ createSprinkles は後ほど説明します。
import {
defineProperties,
createSprinkles
} from '@vanilla-extract/sprinkles';
defineProperties は properties / conditions / shorthands を持つユーティリティクラスのコレクションを定義します。これらに関しても見ていきます。
properties
properties は CSS プロパティとそのプロパティの利用可能な値を定義します。
const responsiveProperties = defineProperties({
properties: {
display: ['none', 'block', 'flex'],
flexDirection: ['row', 'column'],
alignItems: [
'stretch',
'flex-start',
'center',
'flex-end'
],
justifyContent: [
'stretch',
'flex-start',
'center',
'flex-end'
],
gap: {
none: 0,
small: 4,
medium: 8,
large: 16
}
}
});
gap
のように任意の名前を持つ値を設定することもできます。
また vanilla-extract の Theming で作成した値を用いることもできます。
import { vars } from './vars.css.ts';
const responsiveProperties = defineProperties({
properties: {
gap: vars.space
}
});
conditions
conditions は properties で定義したプロパティに対する media / feature / container を定義します。
以下のコードはメディアクエリの例になります。
const responsiveProperties = defineProperties({
conditions: {
mobile: {},
tablet: { '@media': 'screen and (min-width: 768px)' },
desktop: { '@media': 'screen and (min-width: 1024px)' }
},
defaultCondition: 'mobile'
});
またセレクタに対して定義することも可能です。
const properties = defineProperties({
conditions: {
default: {},
hover: { selector: '&:hover' },
focus: { selector: '&:focus' }
},
defaultCondition: 'default'
});
shorthands
shorthands は properties の元となる CSS プロパティにマップします。以下のコードでは padding
/ paddingX
/ paddingY
を定義します。
import { vars } from './vars.css.ts';
const responsiveProperties = defineProperties({
properties: {
paddingTop: vars.space,
paddingBottom: vars.space,
paddingLeft: vars.space,
paddingRight: vars.space
},
shorthands: {
padding: [
'paddingTop',
'paddingBottom',
'paddingLeft',
'paddingRight'
],
paddingX: ['paddingLeft', 'paddingRight'],
paddingY: ['paddingTop', 'paddingBottom']
}
});
createSprinkles
createSprinkles は defineProperties で定義したプロパティにアクセスするためのタイプセーフな関数を作成します。
const responsiveProperties = defineProperties({
/* ... */
});
const unconditionalProperties = defineProperties({
/* ... */
});
const colorProperties = defineProperties({
/* ... */
});
export const sprinkles = createSprinkles(
responsiveProperties,
unconditionalProperties,
colorProperties
);
使用
createSprinkles で作成した関数を使用してスタイルを作成します。
import { sprinkles } from './sprinkles.css.ts';
export const container = sprinkles({
display: 'flex',
paddingX: 'small',
flexDirection: {
mobile: 'column',
desktop: 'row'
},
background: {
lightMode: 'blue-50',
darkMode: 'gray-700'
}
});
実際に defineProperties で定義したプロパティ名やメディアクエリなどが使用されていることが分かります。また、これらの paddingX
や small
、 mobile
などはエディタ( VSCode )で補完されるため、かなり便利です。
vanilla-extract の公式サイトでも Sprinkles は使用されていますので、拝見してみると理解が深まると思います。
おわりに
Why We're Breaking Up with CSS-in-JS の記事をお読みになられた方は CSS-in-JS の今後について一度は考えたのではないでしょうか。
この記事をきっかけに、 CSS-in-JS の次の候補として vanilla-extract を考えてみてはいかがでしょうか。
あなたのきっかけになれれば幸いです。