Tailwind CSS で WYSIWYG から出力されたスタイリングをする
こんにちは森田です。Gaji-Labo では shadcn/ui など Tailwind CSS を採用したプロダクトのコンポーネント開発が増えてきました。
Tailwind CSS は class 要素に直接スタイルを書くので、WYSIWYG などの HTML を返すデータのコンテンツのスタイルは直接指定できません。
しかしグローバルな CSS に書いたりせず、コンポーネントで Tailwind CSS で完結したいところ。
そんな時は、arbitrary variants を使って指定していきましょう。
arbitrary variants とは
arbitrary variants はセレクター修飾子を class に直接記述し親セレクタから子または子孫セレクタを指定する機能です。
arbitrary variants で指定する
子孫要素の指定は &_
を使い指定します。
const Content = ({
data,
}) => {
return (
<article
className={cn(
"[&_a]:underline",
)}
>
{data}
</article>
);
};
上記のコードでは article の子孫の a要素にスタイルが当たります。
このように取得する各要素に子孫セレクタで指定していきましょう。
ただ、指定する要素を className に書いていくと、とても行が長くなるし見づらいので変数にまとめましょう
const contentClasses = [
"[&_a]:underline",
"[&_p]:text-gray-900 [&_p]:mb-4",
];
const Content = ({
data,
}) => {
return (
<article
className={cn(
...contentClasses
)}
>
{data}
</article>
);
};
このようにまとめると見やすくなります。
arbitrary variants を使えば class属性や data属性が付いた HTML でも自由に指定できます。
WYSIWYG上で文字寄せなどをすると class属性の付いたHTMLが出力されることはよくあります。
const contentClasses = [
"[&_a]:underline",
"[&_p]:text-gray-900 [&_p]:mb-4",
"[&_p[data-hoge]]:text-[#50d71e]",
"[&_.aligncenter]:text-right",
];
もしも、BEMのアンダースコア2つを付ける `.block__list` クラスなどが返ってくる場合は、arbitrary variants では子孫セレクタのスペースをアンダースコアでパースするためうまく処理ができません。
`String.raw` を使いアンダースコアをエスケープさせれば指定可能です。
const contentClasses = [
"[&_a]:underline",
"[&_p]:text-gray-900 [&_p]:mb-4",
"[&_p[data-hoge]]:text-[#50d71e]",
"[&_.list]:list-disc",
"[&_.block__list]:my-8", // これだとうまく動かない
String.raw`[&_.block\_\_list]:my-8`, // String.rawを使う
];
おわりに
WYSIWYG など HTML をこちらでコントロールできない場面は意外に多いと思います。
Tailwind CSS は基本的には直接 class要素にスタイルを当てていくべきと思いますが、このように外部化してまとめることも可能です。
ただし、この指定方法はスコープのない子孫セレクタを使うことになるので注意が必要です。
Gaji-Laboでは、 Next.js 経験が豊富なフロントエンドエンジニアを募集しています
弊社では Next.js の知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違う Gaji-Labo を味わいに来ませんか?
Next.js の設計・実装を得意とするフロントエンドエンジニア募集要項
もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!