きっかけ
最近久しぶりにCSSをしっかり使ってレスポンシブ対応をする機会があり、メディアクエリを使ってのレスポンシブはやはりめんどくさいなって思いました、、、。そこでモダンCSSについてキャッチアップしたので、注目すべき機能とプロパティ、それぞれがこれまでのCSSに比べてどのように改善されたかについて紹介していきます。
コンテナクエリ
コンテナクエリは、ウェブデザインにおいて非常に便利な技術です。これまで使用していたメディアクエリは、画面全体のビューポートのサイズに基づいてスタイルを適用します。使いにくい点は、ページ内の特定の要素のサイズに基づいてスタイルを調整することができないため、要素が異なるコンテキストで異なるサイズになる場合には柔軟性が欠けていました。
これまでのメディアクエリは、以下のような方法で使用されます。
@media (min-width: 600px) {
.example {
font-size: 20px;
}
}
これは、ビューポートの幅が600px以上の場合に.exampleクラスのフォントサイズを20pxに変更するというものです。ビューポートのサイズに依存するため、要素自体のサイズに基づいたスタイルの変更はできません。
・コンテナクエリの利点
コンテナクエリは、特定のコンテナ要素のサイズに基づいてスタイルを適用できるため、より柔軟で直感的なデザインが可能になります。
以下のHTMLとCSSの例を用いて、コンテナクエリの動作を説明します。
<div class="text-container first">
<div class="text-content">コンテナサイズに応じてテキストスタイルが変更されます。</div>
</div>
<div class="text-container second">
<div class="text-content">コンテナサイズに応じてテキストスタイルが変更されます。</div>
</div>
上記のHTMLには、二つの.text-containerクラスの要素があり、それぞれに.text-contentクラスのテキストを含んでいます。
.text-container {
container-type: inline-size;
width: 100%;
max-width: 400px;
border: 1px solid #000;
padding: 20px;
margin: 0 auto;
}
.text-content {
color: black;
font-size: 16px;
}
/* コンテナサイズが300px以上の場合にスタイルを変更 */
@container (min-width: 300px) {
.text-container.first .text-content{
color: blue;
font-size: 20px;
}
.text-container.second .text-content{
color: red;
font-size: 20px;
}
}
このCSSでは、.text-containerがコンテナとなり、そのサイズに基づいて内部の.text-contentのスタイルが変更されます。具体的には、コンテナの幅が300px以上の場合に以下の変更が適用されます。
.text-container.firstの.text-contentは、文字色が青、フォントサイズが20pxに変更されます。
.text-container.secondの.text-contentは、文字色が赤、フォントサイズが20pxに変更されます。
このように、コンテナのサイズに基づいてスタイルを変更することで、より柔軟でレスポンシブなデザインが可能となります。ビューポートのサイズに依存せず、要素自体のサイズに応じてスタイルを調整できるため、異なるレイアウトやコンテキストでも一貫したデザインを実現できます。
例えば、以下のようにコンテナサイズを変更してみましょう。
<div class="text-container first" style="max-width: 350px;">
<div class="text-content">コンテナサイズに応じてテキストスタイルが変更されます。</div>
</div>
<div class="text-container second" style="max-width: 280px;">
<div class="text-content">コンテナサイズに応じてテキストスタイルが変更されます。</div>
</div>
.text-container.firstの最大幅を350pxに設定すると、コンテナクエリが発動し、テキストが青色で20pxのフォントサイズになります。
.text-container.secondの最大幅を280pxに設定すると、コンテナクエリが発動せず、デフォルトの黒色で16pxのフォントサイズのままになります。
このように、コンテナクエリはより複雑で柔軟なレイアウトを作成するための強力なツールです。これを活用することで、ウェブデザインの柔軟性と応答性が大幅に向上します。
:has()
従来のCSSでは、親要素が特定の子要素を持つかどうかに基づいてスタイルを適用することは困難でした。このため、JavaScriptを使用してDOM操作を行う必要がありましたが、:has()擬似クラスを使用することで、これがCSSのみで実現可能となります。
例えば、次のようなHTML構造があるとします。
<ul>
<li><a href="#">リンク1</a></li>
<li>テキストのみ</li>
<li><a href="#">リンク2</a></li>
</ul>
この場合、リンクを含む<li>要素だけにスタイルを適用したいとします。従来のCSSではこれが不可能で、JavaScriptを使って下記のようにスタイルを変更する必要がありました。
document.querySelectorAll('li').forEach(li => {
if (li.querySelector('a')) {
li.style.fontWeight = 'bold';
}
});
・:has()擬似クラスの利点
:has()擬似クラスを使用すると、CSSだけでこのようなスタイリングが可能になります。これにより、HTML構造に依存したスタイリングが簡単に行えるようになります。
次のCSSを見てみましょう。
li:has(> a) {
font-weight: bold;
}
このCSSは、直接の子として<a>要素を持つ<li>要素に対してスタイルを適用しています。
<ul>
<li><a href="#">リンク1</a></li>
<li>テキストのみ</li>
<li><a href="#">リンク2</a></li>
</ul>
このHTMLに対して、以下のCSSを適用します。
li:has(> a) {
font-weight: bold;
}
<li>要素が直接の子として<a>要素を持つ場合、その<li>要素のフォントウェイトをボールドにします。
<ul>
<li><a href="#">リンク1</a></li>
<li>テキストのみ</li>
<li><a href="#">リンク2</a></li>
</ul>
<style>
li:has(> a) {
font-weight: bold;
}
</style>
上記を適用すると、リンクを含む<li>要素「リンク1」と「リンク2」が太字になります。
テキストのみの<li>要素は太字になりません。
・() 擬似クラスの応用例
:has() 擬似クラスは、さらに複雑なセレクターにも使用できます。例えば、フォーム入力フィールドがエラーメッセージを含む場合に、その親要素のスタイルを変更することができます。
<form>
<div class="form-group">
<input type="text" name="username">
<span class="error">エラーメッセージ</span>
</div>
<div class="form-group">
<input type="password" name="password">
</div>
</form>
.form-group:has(.error) {
border: 1px solid red;
}
このCSSは、.errorクラスを含む要素を持つ.form-group要素に対して赤い枠線を追加します。これにより、エラーメッセージを簡単に強調することができます。
:has() 擬似クラスは、CSSのセレクターにおいて親要素が特定の子要素を持つ場合にとても便利です。これにより、JavaScriptに頼ることなく、HTML構造に依存したスタイリングが簡単に行えます。モダンなウェブデザインにおいて、より柔軟で直感的なスタイルの適用が可能となり、開発効率も向上します。
subgrid
subgridは、CSS Grid Layoutの機能の一つで、複雑なグリッドレイアウトを簡単に構築できるようにします。これまで、子グリッドは親グリッドのレイアウトを継承することができず、グリッドの構造が複雑になると整合性を保つのが難しかったです。subgridを使用することで、子グリッドが親グリッドの行や列の設定を共有でき、一貫したデザインを保ちながら簡単にレイアウトを構築できます。
例えば、次のようなHTML構造があるとします。
<div class="parent">
<div class="child">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
</div>
そして、以下のようなCSSを使用します:
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.child {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
この場合、親のgrid-template-columns設定は子要素に継承されず、親と子で同じ列幅を再度設定する必要があります。これにより、グリッドの設定が冗長になり、管理が複雑になります。
・subgridの利点
subgridを使用することで、子グリッドは親グリッドの行や列の設定を継承でき、より簡潔で一貫したレイアウトが実現できます。
<div class="parent">
<div class="child">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
<div class="child">
<div>Item 4</div>
<div>Item 5</div>
<div>Item 6</div>
</div>
</div>
このHTMLに対して、以下のCSSを適用します。
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.child {
display: grid;
grid-template-columns: subgrid;
gap: 5px;
background-color: #f0f0f0;
}
この例では、親グリッドが3つの等しい幅の列で構成されており、子グリッドも親グリッドの列設定を継承しています。結果的に、子グリッド内の要素は親グリッドの列と完全に一致し、一貫したレイアウトが実現されています。
subgridは、CSS Grid Layoutの中でも特に便利な機能で、複雑なレイアウトを簡潔にし、一貫性のあるデザインを維持するのに役立ちます。これを利用することで、親グリッドの設定を子グリッドに継承させることができ、HTML構造とスタイルの管理が簡単になります。
scroll-behavior: smooth
scroll-behavior: smooth は、ページ内のスクロール操作を滑らかにするためのCSSプロパティです。このプロパティを使用することで、ユーザーがリンクやボタンをクリックした際に簡単にスクロールができるようになります。
これまで、スムーズスクロールを実現するためには、JavaScriptを使用する必要があり、以下のようなコードが必要でした。
document.querySelector('a[href="#section1"]').addEventListener('click', function(event) {
event.preventDefault();
document.querySelector('#section1').scrollIntoView({
behavior: 'smooth'
});
});
これに対して、CSSのscroll-behavior: smoothを使用することで、以下のようにシンプルな設定で同じ効果が得られます。
html {
scroll-behavior: smooth;
}
このように、CSSだけで簡潔にスムーズスクロールを実現できるため、開発効率が向上し、コードの保守性も高まります。
最後に
モダンCSSは、より柔軟で効率的なウェブデザインを実現します。上記で紹介した新機能は、これまでの使いにくかった部分を解消して、複雑なレイアウトやスタイリングをシンプルに行えるようになりました。これにより、一貫性のあるレスポンシブデザインが可能となり、開発効率とコードの保守性が向上します。モダンCSSを活用することで、ユーザー体験の向上と開発の迅速化が期待できるため、CSSを使う機会があればぜひ取り入れていきたいですね。