この記事は、ハシゴ Advent Calendar 2020の 3 日目の記事です。
また飽きもせず JAMStack なプロダクトの話です。今日は Tailwind CSS の構成ファイルを(ほぼ)全部晒して、実際にどういう設定で運用しているかを見ていきます。
tailwind.config.js
はいこれ!
const defaultTheme = require("tailwindcss/defaultTheme");
const plugins = [require("@tailwindcss/typography")];
if (process.env.NODE_ENV !== "production")
plugins.push(require("tailwindcss-debug-screens"));
module.exports = {
future: {
removeDeprecatedGapUtilities: true,
purgeLayersByDefault: true,
},
theme: {
extend: {
fontFamily: {
sans: ["YakuHanJP", "Noto Sans JP", ...defaultTheme.fontFamily.sans],
skip: [
"YakuHanJP",
"FOT-スキップ Std M",
...defaultTheme.fontFamily.sans,
],
"skip-b": [
"YakuHanJP",
"FOT-スキップ Std B",
...defaultTheme.fontFamily.sans,
],
},
screens: {
s: "375px",
m: "560px",
l: "960px",
f: "1336px",
},
spacing: {
"2px": "0.125rem",
"3px": "0.1875rem",
"5px": "0.3125rem",
"6px": "0.375rem",
"7px": "0.4375rem",
"8px": "0.5rem",
"10px": "0.625rem",
"13px": "0.8125rem",
"15px": "0.9375rem",
"16px": "1rem",
"18px": "1.125rem",
"20px": "1.25rem",
"25px": "1.5625rem",
"30px": "1.875rem",
"40px": "2.5rem",
"50px": "3.125rem",
"60px": "3.75rem",
"80px": "5rem",
"100px": "6.25rem",
},
fontSize: {
"9px": "0.5625rem",
"10px": "0.625rem",
"12px": "0.75rem",
"14px": "0.875rem",
"16px": "1rem",
"18px": "1.125rem",
"20px": "1.25rem",
"22px": "1.375rem",
"26px": "1.625rem",
"40px": "2.5rem",
},
colors: {
text: {
primary: "#2FB297",
secondary: "#00ADD3",
},
theme: {
primary: "#2ecaa9",
secondary: "#00bfd7",
},
},
opacity: {
70: ".7",
},
},
},
variants: {
padding: ["responsive", "first", "last", "hover", "group-hover"],
margin: ["responsive", "first", "last", "hover", "group-hover"],
},
plugins: plugins,
purge: false,
};
これはもうホントに、包み隠すところなく、これで全部です。
そんなにゴリゴリに拡張してるわけではありませんが、このレベルでも快適に CSS Styling していくことができます。Tailwind みんな使おう。
全体方針
全体の方針として、デフォルトで用意されている class もできるだけ使いたい、かつ、構成ファイルの記述量をできるだけ抑えたいというのがあったので、デフォルトテーマを拡張する形で定義しています。
デフォルトは使わずに、ここでカチっと全部縛った方がスタイルガイドとしてはいいのですが、そこまでここにコストかけてられないっていうのが正直なところなので、こういう方針としています。
また汎用性の低いものに関しては無理に Tailwind を経由することなく、Component 内に直接 css を定義しています。Tailwind で書こうとすると逆に複雑になるようなものも同様です。
では以下で、ディレクティブ毎に軽く解説を加えていきます。
fontFamily
デフォルトでsans
が当たるので、それを拡張したものと、タイトル等で使っているskip
の定義があるだけです。デフォルトがsans
なのでこれは class で当てることはなく、skip
系のフォントを当てたい箇所でfont-skip
とかで適用している感じです。
余談ですが、skip は有料フォントで組み込み自体は簡単だったんですが、ページ内にあるフォントだけ読み込むダイナミックなんとかっていう機能がありまして。まぁ日本語全部読み込まれたらそらエグい通信量になるのでありがたい機能ではあるんですが、ページ遷移の時に発火させるのが結構ツラミがありました。
最終的には辞書ファイルを用意して初回読み込み時に一気にドカンと持ってくるようにしています。
screens
ブレイクポイントの設定ですね。特に説明することはないと思います。
ちなみにこれ最近気づいたんですが、f: "1336px"
の定義間違ってまして。1366px
が狙っていたサイズです(爆
spacing、fontSize
プロジェクト全体としては基本的にrem
を使って組んでいます。
が、Figma なり XD なりのデザインツールで見える CSS って、基本 px ベースなんですよね。なのでここでは、px ベースの class 名を生成することで、脳死で class を当てていけるようにしています。
こうしておくと、例えば Finma を見て 18px のフォントサイズだったら、text-18px
という class を付与してあげれば1.125rem
で当たってくれます。
これは結構便利なハックだと思うので、ぜひやってみてください。
colors
色の定義を書いているだけなので割愛。
opacity
opacity の定義を書いているだけなので割愛。
variants
Configuring Variants - Tailwind CSS
上記がデフォルトでついている variants なんですが、これを拡張したかったのでいくつか記載しています。
例えば padding はデフォルトだとresponsive
しかついてません。
padding: ["responsive"],
ただこれだとちょっと不便で、例えば for で回した時のfirst-child
だけ適用したい、とかいうパターンを実現したければ、first
をつけてあげる必要があります。
padding: ["responsive", "first"],
このあたりは結構分かりづらいので、多少慣れが必要ですね。慣れないうちは、Component 内で直接 css 書いちゃったほうが早いと思います。
plugins
開発時は画面サイズがわかるようにtailwindcss-debug-screens
を有効にしてます。これ地味に便利。
Component 例
実際の使用例も見たほうがイメージしやすいと思うので、Component の実装を晒しておきます。これはタグの Component で、粒度的には Atoms です。
<template>
<g-link :to="`/tag/${slug}`">
<p
class="bg-theme-secondary text-12px m:text-14px m:py-2 m:px-8 inline rounded-full px-3 py-1 text-white"
>
#{{ text }}
</p>
</g-link>
</template>
<script>
export default {
props: {
text: {
type: String,
required: true,
},
slug: {
type: String,
required: true,
},
},
};
</script>
前述した通り、デフォルトの class も使いつつ、独自定義した class も使っているというイメージがちょっとはついたんじゃないでしょうか:)
おわりに
Tailwind CSS は、結構いろんなエンジニアさんがブログでおすすめしているし、僕の手にも結構馴染みました。えいやで入れたわりには、結構いい技術選定だったんじゃないかなーと思っています。
また、開発も結構頻繁に行われていて(多分コア開発者はフルタイムでやってる)、僕は全然使ってませんが、アニメーション周りも結構強化されてきています。
これから新規プロダクト、あるいはリニューアルなんかが控えている方は、これを機会に採用してみてはどうでしょうか?
明日は ship.js で回しているリリースフローの話をしようと思います:)