LoginSignup
5
1

More than 1 year has passed since last update.

vanilla-extract の Sprinkles について

Last updated at Posted at 2022-12-10

はじめに

vanilla-extractSprinkles というパッケージについて紹介します。
まず vanilla-extract を軽く説明すると TypeScript でスタイルを記述することができ、ビルド時に静的な CSS ファイルを出力します。公式では「 Zero-runtime Stylesheets-in-TypeScript. 」と表現されております。

Sprinkles

Sprinkles は vanilla-extract のためのゼロランタイムアトミックCSSフレームワークです。カスタムユーティリティクラスの静的なセットを生成し、ビルド時は静的に、実行時は動的に構成します。つまり Tailwind CSS などのゼロランタイムでタイプセーフなバージョンを自分で作るようなものになります。
この説明を読んでも理解し難いので、公式のコードを参考にして理解していきます。

defineProperties

まず以下のコードのように definePropertiescreateSprinkles をインポートします。
※ 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 で定義したプロパティ名やメディアクエリなどが使用されていることが分かります。また、これらの paddingXsmallmobile などはエディタ( VSCode )で補完されるため、かなり便利です。

vanilla-extract の公式サイトでも Sprinkles は使用されていますので、拝見してみると理解が深まると思います。

おわりに

Why We're Breaking Up with CSS-in-JS の記事をお読みになられた方は CSS-in-JS の今後について一度は考えたのではないでしょうか。
この記事をきっかけに、 CSS-in-JS の次の候補として vanilla-extract を考えてみてはいかがでしょうか。
あなたのきっかけになれれば幸いです。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1