Open10

LitでTailwind CSSを使う

LitでTailwind CSSを使いたい

LitのコンポーネントごとにCSS書くのめんどくさいのでTailwind CSSを使ってCSS書く量を減らしたい。

実際のコードはこれ

https://github.com/takanorip/lit-tailwind

LitでTailwind CSSを使う方法として、大きく2つの道がある。

  1. Shadow DOMを使わないようにする
  2. Shadow DOMのstyleの中にどうにかしてねじ込む

Shadow DOMのstyleの中にどうにかしてねじ込む技術選定

やりたいこと

LitElementcss にTailwind CSSのクラス名を埋め込みたい

export class LitTailwind extends LitElement {
  static styles = css`
    @tailwind base;
    @tailwind utilities;
  `;

  render() {
    return html`
      <p class="text-gray-900">Hello!</p>
    `;
  }
}

↑これがこうなると嬉しい↓

export class LitTailwind extends LitElement {
  static styles = css`
    .text-gray-900 { ... }
  `;

  render() {
    return html`
      <p class="text-gray-900">Hello!</p>
    `;
  }
}

CSS Module Scripts

https://web.dev/css-module-scripts/

これはまだChromeでしかサポートされていないので互換性の観点から難しそう。

参考記事

https://dev.to/43081j/using-tailwind-at-build-time-with-web-components-1bhm
https://dev.to/43081j/using-tailwind-at-run-time-with-web-components-47c

これはsnowpackを使っている例

https://github.com/danielkoek/tailwind-to-lit

Twind

これはランタイムで動作するTailwind CSSのコンパイラ。

https://twind.dev/

PostCSSで頑張る

この記事にある通りに設定してみたら下記エラーがでた。
postcss-syntaxtailwind が衝突してしまった。
Issueもあがってないようだ。つらい。

TypeError: Cannot read property 'append' of undefined

postcss-syntax はPostCSSを .css 以外のファイルで動作させるために必要なライブラリだが、あまりメンテナンスされてないっぽいので別の方法を考えたほうが良さそう。

NEXT ACTION

  1. 自分でプラグインを作る
  2. バンドルツールを使う

やりたいこと

  1. Litのコンポーネント中で使われているクラス名を取得
  2. Tailwind CSSをビルド
  3. それをLitElementの css につっこむ
  4. もしくはビルドされたCSSをテンプレートリテラルに変換してインポートする

↑上記のプラグインが微妙に使える状態じゃなかったのでForkして修正して @takanorip/rollup-plugin-lit-tailwindcss として公開した。(後々TSに書き換えたい)

https://github.com/takanorip/rollup-plugin-lit-tailwindcss

rollup.config.js はこんな感じ。

import summary from 'rollup-plugin-summary';
import resolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import litTailwind from '@takanorip/rollup-plugin-lit-tailwindcss';

export default {
  input: './src/my-element.ts',
  output: {
    dir: './dev',
    format: 'esm',
    sourcemap: true,
  },
  plugins: [
    typescript(),
    resolve(),
    summary(),
    litTailwind({
      include: 'src/**/*.ts',
      placeholder: 'tw_placeholder',
      exclude: undefined,
    }),
  ],
};

実装はこれ

https://github.com/takanorip/lit-tailwind

これが

export class MyElement extends LitElement {
  static styles = css`tw_placeholder`;
  render() {
    return html`
      <h1 class="text-purple-400">Hello!</h1>
    `;
  }
}

こうなる

let MyElement = class MyElement extends n$1 {
    constructor() {
        super(...arguments);
    }
    render() {
        return y `
      <h1 class="text-purple-400">Hello!</h1>
    `;
    }
};
MyElement.styles = r$4 `
.text-purple-400 {
    --tw-text-opacity\: 1;
    color\: rgba(167, 139, 250, var(--tw-text-opacity))
}`;

rollup-plugin-lit-tailwindcssでやっていること

  1. include で指定されたパス配下を探索
  2. Tailwind CSSのJITでCSSをPurge
  3. placeholderをCSSに置き換え

イマイチなところ

  • placeholderを書かないといけないところ
  • 全部のコンポーネントに同じCSSが埋め込まれるところ
    • コンポーネントAで text-purple-400、コンポーネントBで text-white を使用している場合、両方のコンポーネントに text-purple-400text-white のCSSが挿入される
    • 理想的にはコンポーネントごとに使ってるCSSが埋め込まれるようにしたい
作成者以外のコメントは許可されていません