Post on:2025年6月3日
sponsorsr
小規模のプロジェクトをはじめ、大規模のプロジェクトもサポートしたCSSのベースとなるテンプレートを紹介します。
大きな特徴は、@layer
でCSSの構造を明確にし、リセットCSSやサードパーティのCSS、オリジナルのCSSなどのカスケードをより効率よく管理できることです。詳細度や!important
に頭を悩ますこともなくなります。
CSS boilerplate
CSS boilerplate -GitHub
まずは、CSS boilerplateの中身をご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* 事前にレイヤーの順序を決定する */ @layercore,third-party,components,utility; @layercore.reset,core.tokens,core.base; @layerthird-party.imports,third-party.overrides; @layercomponents.base,components.variations; /* リセットCSSやノーマライズ */ @importurl('uaplus.css')layer(core.reset); /* ユーティリティのclass */ @layerutility{ .visually-hidden{ clip:rect(0000); clip-path:inset(50%); height:1px; overflow:hidden; position:absolute; white-space:nowrap; width:1px; } } |
CSSのボイラープレートとはHTMLのボイラープレートと同様に、すべてのプロジェクトで繰り返し使用できる定型のCSSです。人によっては単なるリセットCSSだったり、ベースとなるCSSだったり、場合によってはコンポーネントのスタイルなども含まれることがあります。
このCSS boilerplateは、それをさらに一歩進めたものです。
リセットCSSを使用し、定義済みのルールも付属していますが、重要なのはカスケードレイヤーを使用して構造を確立して、カスケードをより細かく制御できるようにしていることです。
CSSの@layer
カスケードレイヤーは、2022年にすべてのブラウザにサポートされています。
参考:
カスケードレイヤー「@layer」でCSSの実装がどう変わるのか、仕組みと基礎知識、さまざまな使用例を徹底解説
CSS boilerplateは主に、4つのレイヤーで構成されています。
coreレイヤーは、グローバルのカスタムプロパティとベーススタイルのためのレイヤーです。グローバルのカスタムスタイルとは、サイト全体で共有したいスタイルです。ベーススタイルとは、サイトのすべてのHTML要素または多くのHTML要素の適用するスタイルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /* リセットCSSやノーマライズ */ @importurl('uaplus.css')layer(core.reset); /* デザイントークンと基本スタイル */ @layercore{ @layertokens{ html{ --color-light:oklch(0.970.010); --color-dark:oklch(0.220.010); } } @layerbase{ body{ background-color:var(--color-light); color:var(--color-dark); font-family:Helvetica,sans-serif; } p{ margin-block:01em; } } } |
グローバルのカスタムプロパティを専用のレイヤーに配置する必要はないことに注意してください。ベーススタイルも専用のレイヤーに配置する必要はありません。レイヤー化されていない場合、coreレイヤー内のレイヤー化されたスタイルを上書きします。そうすることで見た目がより整理され、coreレイヤーがより複雑になった場合にも管理しやすくなります。
third-partyレイヤーはbaseレイヤーを上書きし、サードパーティのスタイルを含みます。何かを上書きしたい場合はimportsサブレイヤーにインポートすることで、、overridesサブレイヤーやレイヤー化されていないスタイルを使用できます。
1 2 | @importurl('bootstrap.css')layer(third-party.imports); @importurl('prism.css')layer(third-party.imports); |
componentsレイヤーでは、ティーザーやナビゲーションやウィジェットなど、サイトで使用するCSSルールのほとんどを記述します。
1 2 3 4 5 6 7 8 9 | @layercomponents{ .teaser{ … } .teaser-large{ … } } |
CSSのルールをより多くのレイヤーにネストすることで、コンポーネントのバリエーションやさまざまな状態をより細かく制御できます。
1 2 3 4 5 6 7 8 9 10 11 12 | @layercomponents{ @layerbase{ .teaser{ … } } @layervariations{ .teaser-large{ … } } } |
バグを修正するためにCSSを追加するときがあると思います。そんな時は、componentsレイヤーに記述します。これらのレイヤー化されていないスタイルは、レイヤー化されたスタイルよりも詳細度が高くなり、最初に記述されたCSSと区別することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @layercomponents{ @layerbase{ .teaser{ … } } @layervariations{ .teaser-large{ … } } /* バグを修正するためのCSS */ .teaser{ … } } |
utilityレイヤーは、ユーティリティのために予約されています。ユーティリティのclassは通常のスタイルの中でももっとも詳細度を高くしなければならないため、レイヤーの順序は最後になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* Utility classes */ @layerutility{ .visually-hidden{ clip:rect(0000); clip-path:inset(50%); height:1px; overflow:hidden; position:absolute; white-space:nowrap; width:1px; } .mbe0{ margin-block-end:0; } } |
最低限必要なのは、レイヤーの順序を定義する最初の行です。小規模なプロジェクトであれば、これで十分です。
まずは、HTMLに外部スタイルシートとして記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1.0"> <title>タイトル</title> <linkrel="stylesheet"href="style.css"> </head> <body> </body> </html> |
CSSは、下記のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | @layercore,third-party,components,utility; @layercore{ html{ --color-light:oklch(0.970.010); --color-dark:oklch(0.220.010); } body{ background-color:var(--color-light); color:var(--color-dark); font-family:Helvetica,sans-serif; } } @layercomponents{ .teaser{ … } .teaser-large{ … } .hero-image{ } } |
大規模なプロジェクトの場合、おそらくスタイルを複数のファイルに分割する必要があると思います。index.css
ファイルで順序を定義し、他のCSSファイルをインポートして使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @layercore,third-party,components,utility; @layercore.reset,core.tokens,core.base; @layerthird-party.imports,third-party.overrides; @layercomponents.base,components.variations; /* リセットCSS、UA+ */ @importurl('third-party/uaplus.css')layer(core.reset); /* サードパーティ */ @importurl('third-party/prism.css')layer(third-party.imports); /* ユーティリティ */ @importurl('helpers.css')layer(utility); @importurl('utility.css')layer(utility); /* コンポーネント */ @importurl('components/teaser.css')layer(components); @importurl('components/hero-image.css')layer(components); |
リセットCSSに使用しているUA+については、先日の記事をご覧ください。
アクセシビリティを重視した新時代のリセットCSS、ベースとなるより良いスタイルシートを求める人に最適 -UA+
index.css
に設定するのではなく、head
内に設定することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width, initial-scale=1.0"> <title>タイトル</title> <style> @layer core, third-party, components, utility; @layer core.reset, core.tokens, core.base; @layer third-party.imports, third-party.overrides; @layer components.base, components.variations; /* リセットCSS、UA+ */ @import url('/assets/css/third-party/uaplus.css') layer(core.reset); /* サードパーティ */ @import url('/assets/css/third-party/prism.css') layer(third-party.imports); /* ユーティリティ */ @import url('/assets/css/utility/helpers.css') layer(utility); @import url('/assets/css/utility/utility.css') layer(utility); /* コンポーネント */ @import url('/assets/css/components/teaser.css') layer(components); @import url('/assets/css/components/hero-image.css') layer(components); </style> </head> <body> </body> </html> |
大規模なプロジェクトでは、各コンポーネントファイルを個別にインポートするのではなく、ビルドステップで結合する必要がある場合があります。
sponsors