CSSライブラリを goober から TailwindCSS に移行した

/
#nextjs#typescript#tailwindcss

β機能である Next.js v13 app dir で CSS in JS が Server Components で非対応という事を見落として、次の様な goober 関連のエラーに遭遇した。

image

Warning: CSS-in-JS is currently not supported in Server Components.

Styling: CSS-in-JS | Next.js

ただし、styled-jsxstyled-componentsuse client と明記して適切な処理を加えれば Client Components (以下 CC)で動くとも書いてある。まあ取り敢えず TailwindCSS に移行することにした。同様の処理で goober やその他の CSS in JS ライブラリが動くかどうかは別レポジトリで試したい。

goober

※メモ書き

コード

goober 使用下ではこんな感じになっていた。Next.js v13 app dir では v12 までの _app.tsx_document.tsx が非対応なので、エラーを起こして当然ではある。

src/styles/goober.js
src/styles/goober.js
1
import { createGlobalStyles } from 'goober/global'
2
3
export const GlobalStyles = createGlobalStyles`
4
:root {
5
--color-miku: #00e1ee;
6
}`
src/pages/_app.tsx
src/styles/_app.tsx
1
import { setup } from 'goober'
2
3
setup(React.createElement, prefix)
4
5
export default function MyApp({ Component, pageProps}: AppProps) {
6
return (
7
<>
8
<Head />
9
<GlobalStyles />
10
<Component {...pageProps} />
11
</>
12
)
13
}
src/pages/_document.tsx
src/pages/_document.tsx
1
import { extractCss } from "goober"
2
3
export default class MyDocument extends Document<{ css: string }> {
4
static async getInitialProps({ renderPage }: DocumentContext) {
5
const page = await renderPage()
6
// Extrach the css for each page render
7
const css = extractCss()
8
return { ...page, css }
9
}
10
11
render() {
12
return (
13
<Html>
14
<Head>
15
<style
16
id={'_goober'}
17
// And defined it in here
18
dangerouslySetInnerHTML={{ __html: ' ' + this.props.css }}
19
/>
20
</Head>
21
<body>
22
<Main />
23
<NextScript />
24
</body>
25
</Html>
26
)
27
}
28
}
src/components/markdown/codeblock/copy-button.tsx
src/components/markdown/codeblock/copy-button.tsx
1
import { styled } from 'goober'
2
3
interface PasssedProps {
4
code: string
5
}
6
7
interface Props extends PasssedProps {
8
className?: string
9
}
10
11
const Component = ({ className, code }: Props) => (
12
<button className={className}>{code}</button>
13
)
14
15
const StyledComponent = styled(Component)`
16
background: var(--color-miku);
17
font-weight: bold;
18
padding: 0.2rem 0.5rem;
19
`
20
21
const ContainerComponent: React.FC<PasssedProps> = (props) => <StyledComponent {...props} />
22
23
export const Button = ContainerComponent

TailwindCSS

基本的に Install Tailwind CSS with Next.js - Tailwind CSS に倣って導入した。

undefined
1
npm i -D tailwindcss postcss autoprefixer
2
npm i @heroicons/react
3
npx tailwindcss init -p
4
npm i -D @tailwindcss/typography sass

CSS

/src/styles/globals.css
1
@tailwind base;
2
@tailwind components;
3
@tailwind utilities;
4
5
@layer base {
6
:root {
7
--color-miku: #00e1ee;
8
}
9
10
.markdown {
11
h2 > a::before {
12
/* Safari 用のフォールバック */
13
content: '## ';
14
/* 読み上げ等に対しては空文字として認識させる */
15
content: '## ' / '';
16
}
17
}
18
}
markdown list
リスト
image
タイポグラフィ

::before::after の疑似要素や置換要素 content などの使い方は、jxck 氏の blog.jxck.io を勝手に参考にさせてもらいました。

また、CSS の :has():is():not() といった疑似要素をはじめて使いましたが、結構便利でした。

/src/styles/globals.scss
1
figure:has(img), :not(figure) > img {
2
border: 1px solid gray;
3
}
4
5
:is(figure) > img {
6
border: none;
7
}
8
9
figcaption {
10
text-align: center;
11
}

Prettier for TailwindCSS

TailwindCSS 推奨のクラス名に並べ替えるための Pretteir プラグインを利用した。

terminal
1
npm i -D prettier prettier-plugin-tailwindcss

ESLint や Prettier の他のプラグインなどと違って、こちらは何の設定もなく動いた。

It works seamlessly with custom Tailwind configurations, and because it’s just a Prettier plugin, it works anywhere Prettier works — including every popular editor and IDE, and of course on the command line.

Automatic Class Sorting with Prettier - Tailwind CSS

参照