CSSの進化がすごい!モダンCSS8選
こんにちは!
株式会社ココナラフロントエンド開発グループの雨嶋です。
最近の CSS の進化はすさまじいです。
今までは Javascript 数行で実装していた部分が CSS1 行で済んだりします。
ただ知ってないと使えないので、自分の勉強も兼ねて便利そうな CSS を 8 個選定しました。
大体モダンな CSS を選定したつもりですが、もうモダンではないものもあるかもしれません。
(いつからがモダンなのか、、)
本記事ではそれぞれ軽く説明するに留めますので、詳細については MDN Web Docs などで調べていただければと思います。
コンテナクエリ
コンテナクエリは、要素のサイズに応じてスタイルを適用するための機能です。
メディアクエリのようにブラウザ画面の横幅などに応じてスタイルを適用するものではなく、要素自体のサイズに応じてスタイルを切り替えることができます。
コンテナクエリを使用するには、基準にしたい要素に container-type プロパティを設定します。
/* コンテナとして設定 */
.container {
container-type: inline-size;
}
/* コンテナクエリ部分 */
@container (min-width: 300px) {
ul {
display: flex;
justify-content: space-between;
}
li {
width: 33%;
}
}
<div class="container first">
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
</div>
<div class="container second">
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
</div>
container クラスの要素の幅が 300px 以上なら横並びにして、300px より狭ければ縦並びになるというスタイルです。
親要素のサイズに基づいてスタイル調整できるので、柔軟なデザインを実現できそうです。
:has()
擬似クラス関数の一つです。
引数に渡したセレクタを持っている親要素を取得してスタイル適用することができます。
親要素に基づいて子要素を取得することはできましたが、子要素に基づいて親要素を取得するのは:has()により可能になりました。
.box:has(.blue) {
color: blue;
}
<div class="box">
<p class="blue">青い文字</p>
</div>
<div class="box">
<p>黒い文字</p>
</div>
blue クラス要素を直下に持つ box クラス要素にcolor: blue
を適用するようにしました。
親要素や子要素に対してさらに条件を指定したりすることもできます。
例えば、ラジオボタンで画面全体の色を切り替えるスタイルを考えてみます。
<body>
<label for="color-blue">青</label>
<input type="radio" id="color-blue" name="color" value="blue" />
<label for="color-green">緑</label>
<input type="radio" id="color-green" name="color" value="green" />
<div class="main-color">メインカラーの要素</div>
<div class="accent-color">アクセントカラーの要素</div>
</body>
/* 青のラジオボタン #color-blue が選択されていた場合 */
:root:has(#color-blue:checked) .main-color {
/* メインカラー */
background-color: darkblue;
color: white;
}
:root:has(#color-blue:checked) .accent-color {
/* アクセントカラー */
color: deepskyblue;
}
/* 緑のラジオボタン #color-green が選択されていた場合 */
:root:has(#color-green:checked) .main-color {
/* メインカラー */
background-color: darkgreen;
}
:root:has(#color-green:checked) .accent-color {
/* アクセントカラー */
color: springgreen;
}
ラジオボタンがチェックされているかどうかを見て、スタイル適用するなんてこともできます。
subgrid
subgrid により親グリッドのサイズを子グリッドに引き継ぐことができるようになりました。
これにより、入れ子のグリッドをより柔軟に制御できます。
<div class="parent-grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item subgrid">
<div class="subitem">A</div>
<div class="subitem">B</div>
<div class="subitem">C</div>
</div>
</div>
<div class="parent-grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">
<div class="subitem">A</div>
<div class="subitem">B</div>
<div class="subitem">C</div>
</div>
</div>
.parent-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
margin-bottom: 12px;
}
.subgrid {
display: grid;
grid-template-columns: subgrid; /* 子グリッドの列を親グリッドに合わせる */
grid-template-rows: subgrid; /* 子グリッドの行を親グリッドに合わせる */
background-color: #e0e0e0;
}
subgrid を設定していない方の要素は、子要素の高さに引きづられて縦に伸びてしまっています。
この例では、親グリッド内に入れ子の子グリッドを作成しています。subgrid を使用することで、子グリッドの列と.subgrid 内の.subitem は、親グリッドのサイズに応じて適切に配置されます。
scroll-behavior: smooth
今までは Javascript で実装していたようなスムーススクロールが、CSS1 行設定するだけで実装できちゃいます。
<nav>
<label for="jump_a1" class="label">Jump 1</label>
<label for="jump_a2" class="label">Jump 2</label>
<label for="jump_a3" class="label">Jump 3</label>
</nav>
<div class="box scroll_smooth">
<div id="item_1" class="item">
<input type="radio" name="s" id="jump_a1"> Item 1
</div>
<div id="item_2" class="item">
<input type="radio" name="s" id="jump_a2"> Item 2
</div>
<div id="item_3" class="item">
<input type="radio" name="s" id="jump_a3"> Item 3
</div>
</div>
.scroll_smooth {
scroll-behavior: smooth; /* スクロールがスムースになる */
}
scroll-behavior: smooth
を設定するだけで、選択した要素にスムーススクロールするアニメーションが実装できました。
ただし移動速度の設定はできません。速度はブラウザ依存です。
aspect-ratio
要素のアスペクト比を設定します。
<div class="box hd">16:9</div>
<div class="box square">1:1</div>
<div class="box square">
サイズ調整されます。サイズ調整されます。サイズ調整されます。サイズ調整されます。サイズ調整されます。
</div>
.hd {
aspect-ratio: 16 / 9;
}
.square {
aspect-ratio: 1;
}
注意すべきは、aspect-ratio はコンテンツを優先して内容に合わせてサイズ調整される点です。
max-width などを指定すれば、サイズ調整されるのを防止または制御することができます。
margin-inline
インライン軸(テキストが流れる方向)に沿って要素の余白を設定します。通常、水平方向の余白を設定するのに使用されます。
/* Before */
margin-left: auto;
margin-right: auto;
/* After */
margin-inline: auto;
2 行必要だったところが 1 行でよくなりました。
従来のmargin: 0 auto
でも中央寄せできますが、この場合は margin-top と margin-bottom も設定されてしまうのがネックです。
text-underline-offset
text-decoration を使用して適用された下線のテキスト装飾線の本来の位置からのオフセット距離を設定できます.
<p>これは <a href="#" class="my-link">リンク</a> です。</p>
.my-link {
text-decoration: underline;
text-underline-offset: 10px; /* 本来の位置から10pxオフセット */
color: blue;
}
わかりやすく大袈裟に下線を離してみました。
text-decoration-color や、text-decoration-thickness と併用してさらに下線をカスタマイズ可能です。
accent-color
チェックボックスやラジオボタンの選択した時の色を変更できます。
<input type="checkbox" id="ac1" checked />
<label for="ac1">チェックボックス</label><br />
<input type="radio" id="ac2" checked />
<label for="ac2">ラジオボタン</label><br />
<input type="range" id="ac3" />
<label for="ac3">レンジ</label><br />
<progress max="100" value="70"></progress>
:root {
accent-color: mediumvioletred;
}
accent-color: auto
にすると、ユーザーエージェントが選択した色を表します。プラットフォームの強調色がある場合は、それと一致します。
まとめ
個人的にはコンテナクエリ、:has()、scroll-behavior: smooth あたりがコード量をグっと減らしてくれそうで業務でも使いたいと思いました。
フロントエンド開発グループ以外も部署ごとに環境の改善などに取り組んでいますので、ご興味のある方はぜひカジュアル面談にお越しください。
募集求人については下記のリンクからご確認ください。
Discussion
[property]-right, [property]-leftを[property]-inline、[property]-top, [property]-bottomを[property]-blockで書けるようになったのはいいですね
それよりもtop, right, bottom, leftをinsetでまとめられるのが良くて、inset-inline, inset-blockと書けます
inset-block-start, inset-block-end, inset-inline-start, inset-inline-endの方がtop, right, bottom, leftと書くより統一感があって何となく好きです