この記事は jiyuujin Advent Calendar 2023 の 14 日目の記事になります。
そもそも Vue で CSS を書く方法を、下に示してみます。
- Scoped
- CSS modules
- Tailwind CSS / UnoCSS
React におけるプロジェクトと違い、あまり CSS in JS/TS のツールは、見受けられませんでした。
しかし、Vue 環境でも CSS in JS/TS を使用可能な Pinceau について書かせていただきます。
Vue Fes Japan Online 2022 のとあるセッション内で上がった技術ネタより起因しました。このイベントをきっかけに Vue Fes Japan 2023 公式ウェブサイトでの採用を進めました。最近も 1.0 ベータへ更新されています。
ざっくり Pinceau について、解説すると。
下に示した、ごくシンプルな Vue コンポーネントがあったとします。
CSS を書く方法がいろいろ存在する中、TypeScript で CSS を書けるようになりました。
<script setup lang="ts">
const pinceauUrl = ref('https://www.npmjs.com/package/pinceau')
</script>
<template>
<div class="wrapper">
<a :href="pinceauUrl" target="_blank">
Pinceau
</a>
</div>
</template>
<style lang="ts" scoped>
css({
'.wrapper': {
display: 'grid',
placeItems: 'center',
'::v-deep(a)': {
color: '{color.vue.green}',
},
},
})
</style>
他、ざっくり説明させていただくと、下に示す通り。
- Design System に則って設定できる
- CSS でスクリプト関数を渡せる
- Auto Complete が効く
もちろん、書き味として、型補完も効いてきます。
ちなみに、開発者向けに VS Code をお使いの方には朗報、その拡張機能も利用できます。
Pinceau 環境を構築する
Pinceau パッケージをインストールしましょう。
Pinceau の導入については、公式ドキュメント と合わせご確認ください。
Vue Fes Japan 2023 ウェブサイトでは、Nuxt 3 の上に構築を目指していましたので、とてもシンプルに構築できます。
pnpm install -D pinceau
正直、この Pinceau を構築する過程で、ひとつハマったポイントがありました。
Nuxt のバージョンとの不一致より伴う、型定義を巡るエラーに出会します。
こういう依存関係は粘り強くエラーと向き合っていくしかありません。
nuxt.config.ts の module に pinceau/nuxt
を追加してください。
export default defineNuxtConfig({
modules: ['pinceau/nuxt'],
})
トークン情報をカスタマイズする
メディアクエリをはじめ、カラーやフォントサイズなどに代表されるデザイントークンを定義してみます。
ルートに tokens.config.ts を作成します。
import { defineTheme } from 'pinceau'
export default defineTheme({
//
})
メディアクエリをはじめ、カラーやフォントサイズなどに代表されるデザイントークンを定義してみます。
ルートに tokens.config.ts を作成します。
作成した tokens.config.ts をnuxt.config.ts より読み込みます。
export default defineNuxtConfig({
pinceau: {
configFileName: 'tokens.config',
},
})
基本的に Pinceau 導入のフェーズは、いたってシンプルとなります。
メディアクエリを定義する
メディアクエリを定義したい場合は、下のように記せます。
import { defineTheme } from 'pinceau'
export default defineTheme({
media: {
mobile: '(max-width: 771px)',
tablet: '(max-width: 981px)',
desktop: '(max-width: 1920px)',
},
})
実際に Vue コンポーネントでは、下のように使います。
<style lang="ts" scoped>
css({
'.container': {
margin: 0,
'@tablet': {
margin: '0 auto',
},
'@mobile': {
margin: '0 auto',
},
},
})
</style>
独自のカラーを定義する
独自のカラーを定義したい場合は、下のように記せます。
import { defineTheme } from 'pinceau'
export default defineTheme({
color: {
vue: {
blue: '#35495E',
green: '#42B983',
},
},
})
実際に Vue コンポーネントでは、下のように使います。
<style lang="ts" scoped>
css({
'.link': {
fontFamily: 'DIN',
fontSize: 'calc(18*{fontSize.base})',
fontWeight: '700',
color: '{color.vue.green}', // 独自のカラーを定義する
lineHeight: '1',
whiteSpace: 'nowrap',
},
})
</style>
独自のフォントサイズを定義する
独自のフォントサイズを定義したい場合は、下のように記せます。
import { defineTheme } from 'pinceau'
export default defineTheme({
fontSize: {
base: '0.0625rem',
},
})
実際に Vue コンポーネントでは、下のように使います。
<style lang="ts" scoped>
css({
'.link': {
fontFamily: 'DIN',
fontSize: 'calc(18*{fontSize.base})', // 独自のフォントサイズを定義する
fontWeight: '700',
color: '{color.vue.green}',
lineHeight: '1',
whiteSpace: 'nowrap',
},
})
</style>
Pinceau 1.0 ベータへ更新する
Vue Fes Japan 2023 ウェブサイトでは、当日直前のバージョン更新を避けるため、この新しい 1.0 ベータへ更新せず、当日を迎えたのでその恩恵は受けていません。
なお、1.0 ベータについては、以下 CHANGELOG をご確認いただきたい。
中でも 1.0-beta.1 に集中していました。