twin.macro でTailwind CSSをGatsbyプロジェクトで使用する

概要

styled-componentsを用いたGatsbyのプロジェクトに、Tailwind CSSを用いたプロジェクトのスタイリングをコピーして使うために、twin.macro (Twin)を使ってみました。忘れないようにメモしておきます。

困っていたこと

GatsbyプロジェクトX: styled-componentsを使用

GatsbyプロジェクトY: Tailwind CSSを使用

プロジェクトXのフッターコンポーネントにSNSアイコンをつけようと思いました。自分で改めてスタイリングするのは面倒と思ったので、プロジェクトYのスタイリングをコピーしようと思いましたが、どうしたらよいのかわかりませんでした。

プロジェクトYのコード抜粋

const FooterIconLink = ({ href, label, icon: Icon }) => {
  const linkParams = { href }

  if (href.startsWith("http")) {
    linkParams.target = "_blank"
    linkParams.rel = "noreferrer noopener"
  }

  return (
    <li className="inline-block px-2">
      <a
        {...linkParams}
        className="inline-flex h-8 w-8 border border-blue-800 text-blue-800 rounded-full items-center justify-center transition-colors duration-200 hover:text-white hover:bg-blue-400 hover:border-blue-400"
      >
        <span className="sr-only">{label}</span>
        <Icon className="w-3 h-3 fill-current" />
      </a>
    </li>
  )
}

プロジェクトYとは、具体的にはこちらなのですが、DevToolsでCSS Usedも用いて見ても大量のCSSが指定されていて、ちょっと扱えそうにないと思いました。

詳しい人に聴いたら、twin.macro を紹介いただきました。

手順

ここではGatsbyのプロジェクトで既に styled-compnents が使える状態からの手順のみを説明しています。完全Gatsby + styled-components に関する詳細はやり方はこちらにあります。

インストール

  1. 既に存在するGatsby + styled-components のプロジェクトなので、追加で以下をインストールする。
$ npm install twin.macro tailwindcss @emotion/react // ドキュメントには @emotion/react が必要とは書いていない
$ npm audit fix

グローバルスタイルの追加

ブラウザ間の不一致を軽減するためのTailwindのベーススタイルを軽減するために、TwinのGlobalStyles を次のように使います。

import React from 'react';
import { LayoutWrapper } from './styles';
import { Header } from '../Header';
import { Footer } from '../Footer';
import { GlobalStyles } from 'twin.macro';

const Layout = ({ children, ...rest }) => {
  return (
    <div {...rest}>
      <GlobalStyles />
      <LayoutWrapper>
        <Header />
        <main>{children}</main>
        <Footer />
      </LayoutWrapper>
    </div>
  );
};

export { Layout };

Twinの設定の追加

package.jsonに以下を追加する(2行目より)。

{
  "babelMacros": {
    "twin": {
      "preset": "styled-components"
    }
  },

Twinの使用

上記の FooterIconLink のコードは次ような形で、twin.macro を使って書くことができました。

import React from 'react';
import 'twin.macro';

export const FooterIconLink = ({ href, label, icon }) => {
  const linkParams = { href };

  if (href.startsWith('http')) {
    linkParams.target = '_blank';
    linkParams.rel = 'noreferrer noopener';
  }

  return (
    <li tw="inline-block px-2">
      <a
        {...linkParams}
        tw="inline-flex h-8 w-8 border border-blue-800 text-blue-800 rounded-full items-center justify-center transition-colors duration-200 hover:text-white hover:bg-blue-400 hover:border-blue-400"
      >
        <span tw="sr-only">{label}</span>
        {icon}
      </a>
    </li>
  );
};

この辺りのやり方については、Qiita記事「GatsbyにTailwind CSSを導入する最短手順(CSS-in-JS)」も参考になりました。

なお、icon の取り扱いについてはコードを少し変更し、サイズ等は呼び出し元で指定するようにしてみました。

:
import 'twin.macro';
:
:
         <FooterIconLink
            href={links.twitter}
            icon={<FaTwitter tw="w-4 h-4 fill-current" />}
            label="Twitter"
          />
          <FooterIconLink
            href={links.instagram}
            icon={<FaInstagram tw="w-4 h-4 fill-current" />}
            label="Instagram"
          />