💭

Tailwindでちょい足しスタイルのすすめ

2024/03/19に公開

Tailwind だけで開発って辛くない?

自分は基本的に Next.js or React で開発することが多いです。フロントの開発をしているとやっぱり CSS は問題として上がりやすい。
今までの経験からすると CSS modules, CSS in JS, Tailwind で開発をしたことがあります。どれもメリットデメリットがもちろんありますが、結論から言うと CSS modules と Tailwind の組み合わせがいいんじゃないか?って思ってます。ちなみに、Tailwind だけで開発したことももちろんあるんですが、個人的には結構辛かったです。理由としては

  • html, jsx がどんどん汚染されていく、見づらくなる
  • 擬似クラスとかブレークポイントが絡むとコードが辛くなってくる

ちょっとでも凝ったスタイルにしようと思うと途端にコードを書くのが億劫になるし、コードが見づらくなります。これだったら CSS 直で書いた方が早いし見やすいって思ってました。
ただ、Tailwind が悪いと言っているわけではなく、要は使い方なんです。
そこで CSS modules メインでスタイリングして、Tailwind は「ちょい足し」として使うのはどうかなと。

ちょい足しスタイルの提唱

とは言ったもののこのちょい足しスタイルって結構前からありますよね。
https://github.com/hiloki/flocss

FLOCSS でも Utility を定義しています。

Component と Project レイヤーの Object のモディファイアで解決することが難しい・適切では無い、わずかなスタイルの調整のための便利クラスなどを定義します。

そう、この Utility は自前で用意しなければならなかったわけですよ。それを Tailwind を Utility として使うのが良いと思ったわけです。

  • 元々 Utility として大量のクラススタイルが用意されている
  • 使っているものだけバンドルされるから必要以上にファイルサイズが上がらない
  • 公式ドキュメントが充実している
  • VSCode の拡張機能でクラス名がサジェストされる

ちょい足しスタイルとは?

ではちょい足しスタイルとはなんなのか。メインとなるスタイリングの方法があって、軽微なスタイルの調整をするために付与するクラススタイルのことです。っとちゃんとした感じに言ってますが簡単に言うと例えば「ここだけマージン 4rem なのかー。他は 2rem なのになー」ってところでベースのコンポーネントは 2rem で作っているはずなので一箇所だけ 4rem にするのにわざわざ props で渡してゴニョゴニョしないで「ちょい足し」しちゃおうぜってことです。

ちょい足しスタイルを使うにあたって

ちょい足しスタイルを使うにあたってまずはメインとなるスタイリングの方法が必要です。Next.js なら CSS modules でスタイリングが妥当ですかね。あともちろん Tailwind のセットアップも必要です。あと他にも注意することがあります。

important をつけないとちょい足しにならない

基本スタイルは CSS modules なので Tailwind のちょい足しは「上書き」が前提になります。なので !important を使う必要があります。
tailwind.config.js に important: true を設定しましょう。

tailwind.config.js
module.exports = {
  content: ['./src/**/*.{ts,tsx}'],
  theme: {},
  plugins: [],
  important: true // 絶対必要
}

eslint は必須

Tailwind を使うので、className 内の順番を整形してくれる eslint-plugin-tailwindcss を導入しましょう!これだけで JSX, TSX 内の記述が整います。

ベースとなる CSS も tailwind のものを使う

global.css
@tailwind base;
@tailwind components;
@tailwind utilities;

これとは別に基本となるスタイルを設定すると思います。例えば以下のように base.css があったとして

base.scss
html,
body {
  font-size: 100%;
}

html {
  background: white;
}

body {
  color: #222;
  background: white;
  line-height: 1.6;
}

Tailwind の単位が rem なので font-size: 100% or 1rem(16px 相当);にしておかないと意図した文字の大きさにならないので注意が必要です。
昔よくあったテクニックの font-size: 62.5%;(10px 相当)にして計算しやすくする方法とかやっていると Tailwind が意図していない font-size, margin, padding になります。また VSCode でサジェストされる font-size などで出てくるのも 100%を基準にした rem と px 表記で出てくるので確実に混乱します w

ちょい足しできるように React のコンポーネントを作ってみる

あくまで一例ですが Button.tsx を作ってみます。
size, color, isBlocked は Props として渡せるようにします。そのほか className を渡してちょい足しできるようにしましょう。
その際にクラス名を動的に設定を楽にする clsx というライブラリを使うと良いです。

https://www.npmjs.com/package/clsx

color と size については tailwind のちょい足しで変更することもできますが、それだとサービス or サイト全体でボタンスタイルのばらつきが出来てしまうので、props で渡せるようにしてあげたほうが統一性があるスタイルになります。
Button にちょい足しはなかなか機会がないですが、例えばマージンを下につけたいときなどはちょい足しすると良いでしょう。

Button.tsx
import clsx from 'clsx'
import type React from 'react'
import type { Color, Size } from '~/common/types'
import styles from './styles.module.css'

type Props = {
  size?: Size // "lg" | "md" | "sm"
  color?: Color // "primary" | "secondary"
  isBlocked?: boolean
} & React.ButtonHTMLAttributes<HTMLButtonElement>

export const Button = ({ children, className, size = 'md', color = 'primary', isBlocked, ...rest }: Props) => {
  return (
    <button
      type="button"
      className={clsx(styles.btn, className, {
        [styles.sm]: size === 'sm',
        [styles.lg]: size === 'lg',
        [styles.primary]: color === 'primary',
        [styles.secondary]: color === 'secondary',
        [styles.blocked]: isBlocked,
      })}
      {...rest}
    >
      {children}
    </button>
  )
}

Button コンポーネントにマージンをちょい足し

<Button onClick={() => {}} className="mb-8">
  送信ボタン
</Button>

まとめ

CSS modules + ちょい足し Tailwind のすすめでした。公式ドキュメントが豊富でプロジェクトにあとから参加した人にもドキュメントがしっかりしているのは助かります。
また、VSCode の拡張機能も使いやすいので、自前でユーティリティクラスを用意するよりも遥かにメリットが多いですよね。また Component 側で Tailwind の className を型で制御して決まったクラスしか指定できないようにするなんて使い方もできそうです。

Discussion