はじめに
最近流行りのTailwind CSSを使ってみました。
筆者は普段、Bootstrapを主に使用して仕事してます。
Bootstrapと比べて何が良いんだろうと比べつつ私が思うメリット、デメリットを考えてみたいと思います。
今更ながら graphql-code-generator の便利さを痛感するで作成した、TODOアプリに Tailwind CSSを導入して、感触を確かめてみようと思います。
今回作成する内容はgraphql-code-generatorのサンプルが主ですが、GitHubに置いてあります。
このTODOアプリは、create-react-appで作成しており、特にスタイルは変更していません。
Tailwind CSSを入れる前は、こんな感じです。
インストール
公式通りにやりますが、私はyarnで入れます
$ yarn add -D tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
CRACOを使わないといけないらしいのでインストールする
$ yarn add @craco/craco
cracoの設定
react-scriptsを使用しているeject以外のスクリプトをcracoに変更します。
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
+ "start": "craco start",
+ "build": "craco build",
+ "test": "craco test",
"eject": "react-scripts eject",
}
cracoで動かすので、設定ファイルを作成します。
module.exports = {
style: {
postcss: {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
],
},
},
}
この時点で、cracoの設定は完了しているので、動くようにはなりました。
tailwindの設定
$ yarn tailwindcss init
tailwind.config.jsファイルが生成されました。
本番環境用に、このファイルのpurgeというところの設定を変更するそうです。
tailwindはかなり多くのclassを用意していますが、本番環境でも全てのclass定義を読み込んでしまうと重たくなってしまいます。
この設定は、未使用のclassは読み込まないようにする設定となります。
今回は、本番で動作させないのでスキップします。
本番環境用の設定を行いたい場合は、こちらを参照してください。
Tailwind CSSを使う下準備は整ったので、今のスタイル(ロゴも)を全て削除してみます。
このまっさらな状態に、Tailwind CSSのスタイルを少しずつ当てていきたいと思います。
Tailwind CSSのclassを利用できるようにする
@tailwind base;
@tailwind components;
@tailwind utilities;
この時点では、こんな感じです。
画面の真ん中辺りに表示してみる
左上に表示されてしまっているので、真ん中辺りにカードを用意し、その中にリストが並んでいる感じにしてみます。
とりあえず真ん中に表示
flex items-center justify-centerのclassを追加して真ん中に表示します。
水平方向には中央揃えされましたが、垂直方向には中央揃え出来てません。
※位置関係がわかりにくいので、htmlタグにbg-gray-500のclassを追加して色付けしてます。
flexをつけた要素がそもそも小さいようです。
高さを追加してやります。
tailwindcss heightと調べてここに辿り着きました。
かなり多くのclassが用意されていますね。
Bootstrapにも100vhの高さを指定する用のvh-100がありますが、種類に関しては、tailwindcssの方が多いと実感させられますね。
今回は、高さを目一杯広げたいので、flexを追加した要素にh-screenを追加します。
垂直方向にも中央に表示されました。
カード形式で表示させてみる
Bootstrap脳なので、card的なclassを使いたいところですね。
中央要素の背景色を白っぽくしてみる
まずは、中央要素の背景をbg-whiteを使って白くしてみました。
用意されている背景色用のclassを見てみましたが、やっぱり豊富ですね。
せっかくなのでbg-whiteではなくbg-gray-50にしておきます。(あんまり変わりませんがなんとなく)
角に丸みをつけてパディングをつけてみる
border-radiusも多いっすね〜
rounded-lgにしてみますか
paddingは、p-8辺りにしてみます。
bg-gray-50を追加した要素にrounded-lgとp-8を追加します。
なんか一気に雰囲気が出てきました
影もつけてみる
背景色が結構濃い色になってるので、box-shadowから、きつめのshadow-2xlを選びました。
うん、いい感じ
カードのタイトルをいい感じにする
カードの中のスタイルをつけていきます
Bootstrap脳だとcard-titleとかつけるとこですね
タイトルがcreate-react-appで作った時のままになってるので、文言を変えます
文字サイズと文字色を変更
font-sizeから探して、text-3xlくらいにしてみます。
せっかくなので文字色もtext-colorから探して、text-red-800にしてみます。
入力欄をいい感じにする
Todoの名称を入力する入力フィールドにスタイルをつけていきます
上下の要素と距離感が近いので余白をあけます
marginから探してmy-4をつけてみます。
あとは、枠線、影、角の丸み、paddingあたりをつけてみます。
-
borderから
border -
box-shadowから
shadow -
border-radiusから
rounded -
paddingから縦は
py-2、横はpx-3
いい感じになってきました
リストをいい感じにする
リストで表示している部分にスタイルをつけてきます
Todo名とボタンが近いのでこれをなんとかします
Todo名を80%くらい、ボタンを20%くらいの4/5 - 1/5って感じにしたいですね〜
widthを探すとw-1/5とかw-4/5ってやつがありました。
liタグにflexをつけて、Todo名の要素にw-4/5、ボタン要素にw-1/5をつけてみます。
いい感じに離れてくれました。
リスト同士にも距離感をつけてみる
リスト同士も少し距離感が近いので、liにpy-2をつけてみます。
マウスオーバーでリストの背景色を変えてみる
リストをホバーした際、li要素をbg-gray-200な背景色に変えてみます。
li要素にhover:bg-gray-200を追加するだけでした。
これはめっちゃ便利
Todo名の左に余裕がないのと、ホバーした際の背景色領域の角に丸みをつけてよりいい感じにします。
Todo名の要素にpx-1を追加、liタグにroundedを追加しました。
削除ボタンをいい感じにする
削除ボタンにスタイルをつけていきます
付けたいスタイルは以下です。
- 枠線
-
border-widthから
border-2
-
border-widthから
- 枠線の色
-
border-colorから
border-red-400
-
border-colorから
- パディング
-
paddingから
p-2
-
paddingから
- 改行禁止
-
whitespaceから
whitespace-nowrap
-
whitespaceから
- 角の丸み
-
border-radiusから
rounded
-
border-radiusから
- 文字色
-
text-colorから
text-red-400
-
text-colorから
- ホバー時(
hover:)- 文字色
-
text-colorから
text-white
-
text-colorから
- 背景色
-
background-colorから
bg-red-400
-
background-colorから
- 文字色
ボタンから文言がはみ出てしまってますね
カードの幅を大きくする
h-screenを追加した要素に、p-20を追加して、bg-gray-50を追加したカード要素にw-fullを追加します。
Todo名とボタンの表示高さがズレているので、items-centerをli要素に追加します。
あと、入力欄も小さいのでw-fullをつけて大きくします。
ボタンのサイズが大きくなっているのが気になりますね〜
あと、Todo名が長すぎる場合、改行されてしまうので、なんとかしたいです。
ボタンのサイズを必要最低限にして、Todo名がはみ出たら...で表示する
Todo名のw-4/5とボタンのw-1/5を削除して、Todo名要素にflex-autoをつけます
Todo名がはみ出たら...にする為に、text-overflowのtruncateをTodo名要素につけます
ここまでくると、実は気になっていた、Todoを登録するボタンがバランス的に欲しくなってきました。
Todoの登録ボタンを追加してみる
Tailwindの話から一時的に逸れますが登録ボタンを追加しました。
削除ボタンのblueバージョンを登録ボタンのスタイルにしました。
レスポンシブにもしてみる
今は、画面の表示領域に余裕がある前提でやっているので、これを小さくてもいい感じに見えるようにしてみます。
それほど表示している項目が多いわけではないので、違和感があると言われたらあんまりないですが、Tailwind CSSのレスポンシブを体験してみます。
画面幅が小さければ、カードのサイズを少し広げてみる
responsive-designに用意されているように、smやlgのように接頭辞をつけると画面幅の状況によって、反映させたいスタイルを変更することができるとのことです。
hoverの時とおんなじ感じですね。
h-screenを使っている要素では、p-20としていましたが、これをlg:p-36 md:p-28 sm:p-20 p-4に変更します。
p-4と接頭辞をつけていないものがある理由はこちらにも記載があるように、接頭辞がないものをモバイル(画面が小さい時)に反映させたいclassという風にするそうです。
smをつけているp-20は、画面幅が640px以上の時に反映されます。
mdをつけているp-28は、画面幅が768px以上の時に反映されます。
lgをつけているp-36は、画面幅が1024px以上の時に反映されます。
接頭辞をつけていないp-4は、画面幅が640pxより小さい時に反映されます。
↑ chromeで表示できる一番小さいサイズにした時、カードの幅が広がりました。
↑ 画面幅が1024pxなので、p-36が反映されました。
画面幅が小さいときは、Todoの追加が行いやすいように入力欄の下に大きく表示できるようにしてみる
画面幅が640pxより小さい場合を画面幅が小さい時とします。
- 入力欄とボタンを横並びにする為に、
flexを使用しているこれを、sm:flexにする。 - 登録ボタンの横幅を
w-fullにする- 画面幅が
640px以上の場合、w-autoにする為に、sm:w-autoにする
- 画面幅が
- 登録ボタンの左のマージンに
sm:をつける - 入力欄の下に画面幅が
640pxより小さい場合、登録ボタンとの間隔を空ける為にmb-3をつける- 画面幅が
640px以上の場合、mb-0にする為に、sm:mb-0にする
- 画面幅が
↑ 画面幅が小さい場合は、登録ボタンが入力欄の下に大きく表示されるようになりました。
画面幅が大きい場合は、これまで通り表示されます。
いい感じになったのではないでしょうか!
終わりに
実際に使ってみて感じた個人的なメリット、デメリットをあげてみます。
メリット
- 用意されている
classが豊富で、自分でスタイルを定義する必要がなさそう- 自分でスタイルを定義すると、クラス名とか考えないといけないので大変な部分が解消
-
smとかmdとか、hoverとかの接頭辞をつけるだけで、色々できるので、超簡単 - 公式サイトの
classの説明が見やすいので調査コストが少ない?
デメリット
- 凝ったデザインにすると
classがかなり長くなる- 今回一番長かったのは登録ボタンのこれ
sm:ml-3 border-2 p-2 whitespace-nowrap rounded text-blue-400 border-blue-400 hover:text-white hover:bg-blue-400 sm:w-auto w-full
- HTMLが汚くなりそうだけど、ReactとかVue.jsは、変数にクラス名を詰め込んでおいて、それをコンポーネントで利用するとHTMLの部分は綺麗に書くこともできそう?
- 結局変数名を考えてしまっているので、スタイルを定義する時のクラス名を考えるのと同コストかも?
- 今回一番長かったのは登録ボタンのこれ
- 同様の凝ったスタイルを別の箇所で利用する時、冗長になりそう
- ReactやVue.jsでは共通コンポーネントにしてしまうことで解消できそう?
- cssの知識がある前提
- 当たり前と言われれば当たり前
-
Bootstrapを利用したことがあって、Bootstrapが用意しているclass名だけを覚えている人は大変かも
普段Bootstrapを使って仕事している筆者は、〇〇なスタイルが含まれたクラスはないかな〜って感じで調べることもあるので、個人的には、スタイル直なクラスが用意されている方が嬉しみがあったので、使い勝手が良さそうな感触でした。
参考文献
https://tailwindcss.com/docs/guides/create-react-app
https://reffect.co.jp/react/react-tailwind




























