AstroとLessのcssClassを同期する方法
Astroで個人ブログを開発するとき、CSSのクラスやIDを変更する際にAstroファイルとLessファイルの両方を変更する必要があった。複数個所でCSSクラスを使っている場合、変更漏れがないか確認するのに時間がかかる。この記事では、確認にかかる時間を減らすために、AstroとLessファイルのCSSクラスを同期する方法を紹介する。
Astroの設定ファイルであるastro.config.mjsと、内部で利用されているViteの機能を組み合わせることで、AstroとLessの間でCSSクラスを同期できる。
関連するファイルと初期値
body要素にcontainerというクラスを指定していると想定する。
関係するファイルは以下の通り。
astro.config.mjsenv.d.tsBody.astrostyle.less
import { defineConfig } from "astro/config";
export default defineConfig({…});// …---
---
<body class="container"> <slot /></body>.container { position: relative;}AstroとLessのCSSクラスを同期する方法
同期するには、astro.config.mjsで、vite.defineとvite.css.preprocessorOptions.less.modifyVarsに共通の値を設定する。
import { defineConfig } from "astro/config";
// 共通する定数を定義const CONSTANTS = { CSS_CLASS_CONTAINER: "container", OTHER_CONSTANTS: "/icon.svg",};
function mapForDefine() { return Object.entries(CONSTANTS).reduce((pre, [key, value]) => { // vite.defineでは文字列の場合JSON.stringify()する必要がある pre[key] = JSON.stringify(value); return pre; }, {});}
export default defineConfig({ vite: { define: { ...mapForDefine(), }, css: { preprocessorOptions: { less: { modifyVars: { ...CONSTANTS, }, }, }, }, },});vite.defineで定義した定数はビルド時に指定した値で置き換えてくれる。詳しくは、Astroで定数管理をするならvite.defineを設定するの記事を参照してほしい。
modifyVarsで定義した変数はimportなどは不要で、Lessファイル内で通常のLess変数として利用できる。modifyVarsオブジェクトのキーが変数名になる。
declare const CSS_CLASS_CONTAINER: string;declare const OTHER_CONSTANTS: string;env.d.tsに型を定義して型エラーをなくし、インテリセンスに表示させる
---
---
<body class="container"><body class={CSS_CLASS_CONTAINER}> <slot /></body>.container {.@{CSS_CLASS_CONTAINER} { position: relative;}以上でastro.config.mjsのCONSTANTSオブジェクトに定数を一元管理できるようになった。
定数をCSSの文字列として扱いたい場合
Less内で[class$="container"]のように文字列として扱いたい場合は、[class$="@{CSS_CLASS_CONTAINER}"]のように書く。
同様に、content: url("/icon.svg");は、content: url("@{OTHER_CONSTANTS}");と書く。
まとめ
文字列やCSSクラスを一元管理できるとコードの保守・変更がしやすくなる。Viteの設定とLessの機能を組み合わせることで、HTMLとCSSのclassを同期できた。
色の変数も定義できるが、個人的にLessのColor Operation Functionsを用いてプログラマーっぽく定義したい。なので色変数はcolor.lessという変数用ファイルに定義している。