Tailwind CSSでトランジションとメディアクエリをサクッとPhoenixフレームワークに導入・実装する

# 概要

__[Tailwind CSS](https://tailwindcss.com/)__で、CSSトランジションとレスポンシブ対応のためのメディアクエリを、Webフレームワーク__[Phoenix](https://phoenixframework.org/)__に導入・実装します。

![tailwind.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211052/066126b1-aba8-0e9c-5697-2d4615a42885.gif)

### Tailwind CSS

flex, pt-4, text-center, rotate-90 などのCSSクラスを準備している「ユーティリティ・ファースト」のCSSフレームワークです。
__モダンなWebサイトをすばやく構築__できます。（公式より引用和訳）

### Phoenix

膨大なアクセスやデータに対する高速処理、堅牢性に強みのあるプログラミング言語__Elixir__製のWebフレームワークです。

※ 本記事ではTailwindCSSをメイントピックにしているので、Phoenixについては以下の拙記事などご覧ください。

- [【Elixir 1.11】Phoenix Framework + DB開発をDockerでやる #1（コンテナ開発環境構築~CRUD実装~テスト](https://qiita.com/im_miolab/items/84d9d71d109d689d267d)
- [【Elixir 1.11】Phoenix Framework + DB開発をDockerでやる #2（CIパイプライン導入）](https://qiita.com/im_miolab/items/f5f426985f968e686e85)

### 実行環境・バージョン

- macOS
- VSCode
- __Tailwind CSS__ 2.0.2
- Node.js 14.15.4
- Phoenix 1.5.7
  - Elixir 1.11.2 (compiled with Erlang/OTP 22)

# コードとセットアップ

### Phoenixプロジェクトディレクトリ作成

任意の名前でディレクトリをつくって、その中に入って`mix phx.new`を実行します。

```terminal:terminal
$ mix phx.new . --app sample_app --no-ecto

$ mix deps.get && mix deps.compile

$ cd assets && npm install && node node_modules/webpack/bin/webpack.js --mode development
```

### TailwindCSSセットアップ

- `/assets`内で、Tailwind CSSと依存パッケージをインストール。

```terminal:terminal
$ npm install --save-dev tailwindcss@2.0.2 postcss@8.2.2 autoprefixer@10.1.0 postcss-loader@4.1.0
```

- `postcss.config.js`を新規作成し`webpack.config.js`にpostcss-loaderを追加。

```js:assets/postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  }
}
```

```js:assets/webpack.config.js
use: [
  MiniCssExtractPlugin.loader,
  'css-loader',
  'postcss-loader',  // <-- add
  'sass-loader',
],
```

- npxで`tailwind.config.js`を生成。

```terminal:terminal
$ npx tailwindcss init

   tailwindcss 2.0.2
  
   ✅ Created Tailwind config file: tailwind.config.js
```

- 最後に、CSS（SCSS）にインポート。

```css:assets/css/app.scss（以下コードを追加）
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
```

### フロントページにお試し実装

[公式トップのプロフィールカード](https://tailwindcss.com/)や、[こちらのチートシート](https://tailwindcomponents.com/cheatsheet/)を参考にして、お試し実装していきます。

```html:lib/sample_app_web/templates/layout/app.html.eex
    <main role="main" class="container">
      <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
      <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>

      <!-- 追加ここから -->
      <section>
        <h1 class="text-center font-medium text-4xl">
          <%= gettext "team %{name}", name: "im" %>
        </h1>
      </section>
      <%= @inner_content %>
      <%= @inner_content %>
      <!-- 追加ここまで -->

      <%= @inner_content %>
    </main>
  </body>
```

- 以下`index.html.eex`コード中にベタ書いているclassが、Tailwindの持つCSSクラスになります。

```html:lib/sample_app_web/templates/page/index.html.eex（まるごと以下に書き換える）
<section class="my-8">
  <figure
    class="md:flex transition duration-500 ease-in-out bg-gray-100 hover:bg-indigo-200 transform hover:-translate-y-1 hover:scale-105 rounded-xl p-8 md:p-0"
  >
    <!-- プロフィール画像は`/assets/static/images/`に準備 -->
    <img
      class="w-32 h-32 md:w-56 md:h-56 rounded-full md:rounded-none mx-auto md:mx-0"
      alt="im image"
      src="<%= Routes.static_path(@conn, "/images/im.jpg") %>"
    >
    <div class="pt-6 md:p-8 text-center md:text-left space-y-4">
      <p class="text-xl font-semibold">
        "Aenean eleifend, massa id scelerisque lacinia, odio elit blandit diam, at varius nisi turpis ut neque. Nam at consequat erat."
      </p>
      <figcaption class="font-medium">
        <div>
          <p class="text-purple-600">im</p>
        </div>
        <div>
          <p class="text-gray-500">Web Developer</p>
        </div>
      </figcaption>
    </div>
  </figure>
</section>

```

```elixir:test/sample_app_web/controllers/page_controller_test.exs（任意）
  test "GET /", %{conn: conn} do
    conn = get(conn, "/")
    assert html_response(conn, 200) =~ "Welcome to Phoenix!"  # <-- delete
    assert html_response(conn, 200) =~ "team im"    # <-- add
  end
end
```

ここまできたら、`mix phx.server`でローカルサーバー起動して、お使いのWebブラウザで`localhost:4000`を確認してみましょう。

実装は以上になります。

## 補足（Tailwind CSS IntelliSense）

VSCodeのプラグイン[Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)を導入すると、オートコンプリートやリンター機能のほか、Tailwind CSSクラスをホバーして生CSSを確認できたりするのでオススメです。
    ![hover_css.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211052/534c6421-e597-bb44-159c-2bef445a22a6.png)

# おわりに

Tailwind CSSをPhoenixフレームワークにお試し導入しました。

BootstrapみたいにUIコンポーネントが用意されているものではないのですが（例えば`btn btn-primary`のように一発でUI部品を作れない）、カスタマイズ性に優れていてPhoenixとの親和性も良いと感じました。

また、Tailwind CSSを導入することによって以下の効果が得られそうな予感を持ちました。

- CSSまわりのコードがスッキリする。（特にメディアクエリまわり）
- クラス名が直感的であり、お手軽にねらった効果を実装できる。

普段使いにも良さそうです。

---

### 参考

- [Tailwind CSS (Installation)](https://tailwindcss.com/docs/installation)
- [Using Tailwind CSS with Phoenix](https://s2g.io/using-tailwindcss-with-phoenix)
- [tailwind components Cheatsheet](https://tailwindcomponents.com/cheatsheet/)
- [Lorem ipsum](https://lipsum.com/)