Typewindで型安全なTailwindを書く
Tailwindを採用している場面で便利そうなライブラリTypewindについての概要と、簡単な使い方をまとめてみました。
- Typewindってなに?
- Tailwindでクラス書く時によくタイポする
- 型があればあるだけ良い
という方の参考になればと思います。
Typewindとは
以下公式ドキュメントから引用
Typewind is a typesafe and zero-runtime version of Tailwind CSS, a utility-first CSS framework that can be composed to build any design, directly in your markup.
要は型安全なTailwindです。
特徴
型安全
Typewindはtw
というobjectを提供しており、このobjectにアクセスすることでTailwindのクラスを取得できます。
tw
の型定義はtailwind.config.js
から生成されるため独自で定義したカラーパレットやプラグイン等の型も含まれています。
tw.
とすると補完が効き、存在しないプロパティにアクセスすると型チェックでエラーになるためstringのクラスを使用するより安全というわけです。
ゼロバンドルサイズ
使用されたすべてのスタイルをコンパイルし、ビルド時に静的なクラスに変換するのでバンドルサイズはゼロです。
プラグイン不要
Tailwindを使用する際、エディタにTailwindのプラグインをインストールして文字列の補完が出るようにしていると思いますが、前述の通りTypewindは補完が効くのでプラグインは不要になります。
対応フレームワーク
NextJS、SolidStart、Viteなど、ほとんどのJavascript/Typescriptフレームワークとビルドツールで動作します。
使用方法
ドキュメントを参考に簡単に使い方を説明します。
インストール、セットアップについては公式ドキュメント通りに進めれば簡単にできるためここでは省略します。
Normal Usage
tw
をインポートして、tw
のプロパティにアクセス、チェーンすることでTailwindのクラスを取得できます。
TypewindではTailwindのクラスのハイフン(-
)をアンダースコア(_
)に置き換えて使用します。
import { tw } from 'typewind';
export default function Button() {
return (
<button className={tw.bg_blue_500.text_white.rounded.py_3.px_4}>
Click Me
</button>
);
}
Modifiers
hover
、before
等の疑似要素、擬似クラスも使用できます。
import { tw } from 'typewind';
export default function Button() {
return (
<button
className={tw.bg_blue_500
.hover(tw.bg_blue_600).first_letter(tw.text_red_500.font_bold)
.text_white.rounded.py_3.px_4.md(tw.py_4.px_5)
.dark(tw.bg_sky_900.hover(tw.bg_sky_800))}
>
Click Me
</button>
);
}
Important
important
をつけたい場合はtw.important()
として引数に当てたいクラスを渡します。
import { tw } from 'typewind';
export default function Button() {
return (
<button
className={tw.important(tw.text_red_500).hover(tw.important(tw.text_red_600))}
>
Click Me
</button>
);
}
Arbitrary Values
Tailwindでいうtext-[20px]
のような任意の値を使用したい場合はtw.text_[20px]
のように書きます。
import { tw } from 'typewind';
export default function App() {
return (
<button className={tw.text_['20px'].py_3.px_4.bg_blue_500}>Click Me</button>
);
}
Arbitrary Variants
Tailwind v3.1で追加されたarbitrary variantsも使用できます。
tw.variant()
を使用し第一引数にバリアント、第二引数に当てたいクラスを渡します。
import { tw } from 'typewind';
export default function App() {
return (
<ul>
{Array(5)
.fill(' ')
.map((_, i) => (
<li
key={i}
className={
tw.variant('&:nth-child(3)', tw.underline)
.list_disc.mx_5.text_white
}
>
Item {i}
</li>
))}
</ul>
);
}
Container Queries
Tailwind v3.2以上で使用可能なコンテナクエリのプラグインtailwindcss-container-queriesにも対応しています。
コンテナクエリについては以下の記事が参考になります。
ドキュメントのContainer Queriesをみると、そのまま使用できるように見えますがセットアップが必要です。
tailwindcss-container-queriesのインストール
yarn add @tailwindcss/container-queries
tailwind.config.jsに追記
module.exports = {
theme: {
// ...
},
plugins: [
require('@tailwindcss/container-queries'),
// ...
],
}
typewind generateの実行
script名は各自の設定によりますが、Teypwindのドキュメント通りに設定していれば以下を実行すれば適用されます。
yarn postinstall
実際の使用方法は以下のようになります。
import { tw } from 'typewind';
export default function App() {
return (
<div className={tw.$container}>
<div className={tw.$lg(tw.underline)}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi, non.
</div>
</div>
);
}
まとめ
軽く触ってみたところ、導入の手軽さの割にメリットが多く開発体験も上がるのでなかなか良いのではと感じました。
エディタにTailwindプラグインを入れていれば一応補完もしてくれますし、存在しないクラスのWarningも出してくれます。
ただ補完のスピードがイマイチだったり、たまに効かないこともあるので(私だけ?)そこにフラストレーションを感じている方や、型でガチガチに縛られたい方は導入を検討してもいいかもしれません。
Discussion