Laravel: Tailwindを使って見た目を整える

Laravelを使って研究室の材料・サンプル管理システムを開発していきます。

以下の前回の終了時点の状態を再現できます。

$ git clone https://kiku3.tsbio.info/git/study-laravel.git study_laravel
$ git checkout step3

一度ここで自分のブランチをつくっておくとよいです。

$ git checkout -b my4

今後は基本的にsrcディレクトリで作業します。VisualStudioCodeを使っている場合は、code srcとするとよいです。

LaravelでのCSSの書き方

src/publicはブラウザーからアクセスできるので、ここにstyle.cssをおけば、HTMLのheadタグ内で <link rel="stylesheet" href="/style.css" /> とすることができます。

しかしこの方法では、以下の問題が生じる場合があります。

  1. ベースURLが変更になったとき(特にサブディレクトリでアプリケーションを動かす場合)、hrefを書き換える必要が生じる。
  2. CSSがブラウザーにキャッシュされて、変更が反映されないことがある。

これらを避けつつ、さらに便利な機能を使えるようになっています。

resources/css/app.css を使う

LaravelではCSSは resources/css ディレクトリに置きます。 基本的に app.css に書いて、さらにファイルを分割したいときは app.css から @import で読み込むようにします。

resources/css/app.css
@import 'tailwindcss';
 
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
 
@theme {
    --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol', 'Noto Color Emoji';
}
 
/* 以下を追加してCSSの効果を確かめる */
header {
    background-color: #3B82F6;
    color: white;
}

cssを読み込むように、HTMLのheadタグを修正します。

resources/views/layouts/html.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', config('app.locale')) }}">
  <head>
    <meta charset="utf-8">
    <title>{{ config('app.name') }}</title>
    {{-- viteがコンパイルしたファイルの場所を含むlinkとかscriptタグに置き換えられる --}}
    @vite(['resources/css/app.css', 'resources/js/app.js'])  
  </head>
  <body>
    @yield('body')
  </body>
</html>

app.cssをコンパイルします。

$ npm run build

ブラウザーで再読み込みをすると反映されます。

ブラウザーでソースコードをみると、@viteの部分が以下のように書き換えられているのがわかります。

<link rel="preload" as="style" href="http://xxx/build/assets/app-PDEzYLFL.css" />
のように置換されているのがわかります。 `npm run build`でつくられるファイルは毎回名前が変わるので、それに合わせたファイル名をhrefとして書き出しているのがわかります。

HMR (Hot Module Replacement)を使う

CSSを書き換えるたびにnpm run buildなんかしてられないとすぐに思います。 viteのHMRという機能を使うと、ブラウザーの再読み込みすら必要なく、CSSやビューが反映されるようになります。 そのために、画面表示に関わる部分は resourcesディレクトリにまとめられています。

まずviteを起動します。 これは常駐するので、新しいターミナルを開いておくとよいでしょう。

$ npm run dev

このとき@viteの部分は以下のように書き換えられます。

<script type="module" src="http://127.0.0.1:5173/@@vite/client"></script>
<link rel="stylesheet" href="http://127.0.0.1:5173/resources/css/app.css" />
<script type="module" src="http://127.0.0.1:5173/resources/js/app.js"></script>

これはviteが5173ポートで待ち受けていることを示しています。 そして、ソースコードが書き換えられると、ブラウザーと通信して、画面の書き換えを行います。

app.cssを修正すると、ブラウザーを再読み込みすることも、npm run buildすることもなく、画面が変更されるのがわかります。

tailwindcssを使う

tailwindcssはCSSフレームワークです。

通常、CSSはHTMLのタグ(要素)やそれに設定されたクラスに対して、プロパティと値を設定して使います。 しかし、ここまでつくってきたように、HTMLがレイアウトとか、コンポーネントととかで細切れになってくると、HTMLのどの要素のスタイルがどのCSSに入っているのかがわからなくなってきます。

tailwindcssではHTMLの要素に直接スタイルと対応するクラスをつけて、CSSを扱うようになっています。

クラスの一覧は Tailwind CSS 日本語チートシート を参照するとよい。

resources/views/layouts/app.blade.php
@extends('layouts.html')
 
@section('body')
  <header class='bg-blue-500 text-white py-2 px-2'>  {{-- 背景色、文字色、余白(padding) --}}
    <h1>My Lab's Stock</h1>
  </header>
  <nav class='bg-yellow-100 py-2 px-2'>
    <ul id='module-tabs' class='flex'>  {{-- タブが横並びになるようにflexを追加 --}}
      <li class='module-tab'><a id='oligo-tab' href='/oligo'>オリゴDNA</a></li>
      {{-- モジュールが複数並んだときの様子がわかるようにダミーを追加 --}}
      <li class='module-tab'><a id='dummy1-tab' href='/dummy1'>ダミー1</a></li>
      <li class='module-tab'><a id='dummy2-tab' href='/dummy2'>ダミー2</a></li>
      <li class='module-tab'><a id='dummy3-tab' href='/dummy3'>ダミー3</a></li>
    </ul>
  </nav>
  <main id='modules' class='bg-yellow-100 px-2 min-h-screen'>
    @yield('module')
  </main>
@endsection

クラスにtailwindcssを設定する

moduleとfeatureのタブは繰り返しでてくるので、tailwindcssの@applyディレクティブを使ってtailwindcssのクラスを使います。

resources/css/app.css
@import 'tailwindcss';
 
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
 
@theme {
    --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol', 'Noto Color Emoji';
}
 
.module-tab {
    @apply
        border border-black /* 枠線の設定 */
        first:rounded-l  /* first: によって、最初の要素に限定する。左側(-l)のみ丸める(rounded)。 */
        last:rounded-r  /* 同様に最後の枠線の右側(-r)を丸める。 */
        font-sans font-bold 
        px-6 bg-white  /* 文字の左右の余白(padding x)を6px、背景色を白に設定 */
        hover:bg-blue-500 hover:text-white /* ホバー時の背景色を青、文字色を白に設定 */
    ;
}
 
.feature-tabs {
    @apply flex;
}
.feature-tab {
    @apply border-t border-x border-black rounded-t-md mx-1 px-6 font-sans font-bold bg-gray-400 hover:bg-white hover:text-black;
}
 
.features {
    @apply bg-white p-2 min-h-screen;
}