Web制作実務役立ち

【モダンCSS】コンテナクエリ、:has()、aspect-ratio、論理プロパティ、ネストなど最新CSSをまとめてキャッチアップしよう!

【モダンCSS】コンテナクエリ、-has()、aspect-ratio、論理プロパティ、ネスト最新CSS
本ページにはプロモーションが含まれています。

最近のCSS、進化がめちゃくちゃ早いですよね。

IEを切れるようになってから、多くのモダンCSSがプロジェクトに取り入れられるようになったので、

怠け者エンジニア

まだIEがあるから、この機能は覚えなくていいや

が通じなくなってきたということです。恐ろしいですね。

とはいえ、モダンCSSと言っても大量に存在します。

【最新モダンCSS】コンテナクエリ、:has()、aspect-ratio、論理プロパティ、ネストなど最新CSSをまとめてキャッチアップしよう!
一部HTML側の仕様も入っていますが、、、
コーダーさん

・・・こんなに覚えきれないぞ(泣)

というのが、率直な感想かと思います。

そこで今回は、「個人的によく使うモダンCSS」に的を絞って解説しようと思います。

今回扱うモダンCSS
  • コンテナクエリ
  • :has()擬似クラス
  • 論理的プロパティ
  • ネスト
  • aspect-ratio

とりあえずこれぐらい知っておいて使いこなせれば最低限は大丈夫です。

ちなみに、同じくらい便利なclamp()に関しては以前記事にも動画にもしているので、今回は省いています。

また、CSS Gridsubgridに関しては次回解説予定です。

しょーご

この記事を書いたのは
しょーご@samurabrass

このブログ「しょーごログ」の運営者。2018年からエンジニアとしてサイト制作やシステム開発を行いつつ、ブログとYouTubeで情報発信を行っている。駆け出しエンジニアのコーディング課題添削も行う。

\現役エンジニアのレビュー付き/

実践レベルのコーディング課題公開中

デザインカンプからのコーディング練習課題【オリジナルポートフォリオを準備できるようになりました】
販売ページはこちら
  • デザインカンプからのコーディングを経験したい
  • 現役エンジニアのレビューを受けてみたい
  • 即戦力級のポートフォリオを用意したい

2024年にデザインを完全リニューアルしています!

コーディングを学習中の方はぜひご活用ください。

無料の入門編から本格企業サイトまで/

また、超実践編という鬼のようなコースもあるので、ほぼ実案件と同じ厳しい環境でコミュニケーション面までレビュー受けたい方がいれば、是非。

コーディング課題 超実践編

超実践編をとりあえず見てみる

YouTubeでも解説しました!

コンテナクエリ(Container Queries)

コンテナクエリ(Container Queries)は、コンテンツのサイズや形状に基づいてスタイルを変更するためのCSS機能で、

従来のメディアクエリ(Media Queries)がブラウザウィンドウのサイズに応じてスタイルを変更するのに対して、コンテナクエリは特定のコンテナ(要素)のサイズや特性に応じてスタイルを変更します。

既に各ブラウザで解禁されており、使うことができます。

2024/05時点

コンテナクエリの基本的な書き方

まずコンテナクエリの基本的な書き方を見てみます。

コンテナクエリの書き方
  1. 基準となるコンテナを決める
  2. 処理を書く

まず基準となるコンテナ要素に、container-type プロパティをつけます。

.container {
    container-type: inline-size;
}

container-typeですが、ほとんどレスポンシブは横方向を見ることが多いと思うので、inline-sizeを使うことが多いと思います。

そして、このコンテナに対するクエリを書いていきます。

このコードは、親要素コンテナが300px以下の時に、子要素の.exampleフォントサイズが12pxになるという処理です。

@container (max-width: 300px) {
    .example {
        font-size: 12px;
    }
}

コンテナクエリにおいては、Viewport(画面幅)ではなく、親要素の幅によって判断することを確認してください。

これらを踏まえて、例えば以下のようなボックスがあるとします。

【最新モダンCSS】コンテナクエリ、:has()、aspect-ratio、論理プロパティ、ネストなど最新CSSをまとめてキャッチアップしよう!

これを構成するコードがこうなっています。

<div class="box">
  <div class="child-element">
    This is a child element.
  </div>
</div>
.box {
  container-type: inline-size;
  container-name: my-container;
}
@container my-container (min-width: 300px) {
.child-element {
  background-color: lightblue;
  }
}
 @container my-container (min-width: 500px) {
.child-element {
  background-color: lightgreen;
 }
}

コンテナを区別するために、container-nameプロパティを使用していますが、この場合は無くても動作します。

この例では、コンテナ(.box)の幅が300px以上の場合、子要素の背景色がライトブルーになり、500px以上の場合はライトグリーンになります。

【最新モダンCSS】コンテナクエリ、:has()、aspect-ratio、論理プロパティ、ネストなど最新CSSをまとめてキャッチアップしよう!

コンテナが500px以上なら緑色(lightgreen)ですが、

コンテナが500px未満になると、青色(lightblue)になっています。

画面幅(Viewport)ではなく、.boxという親要素の幅によって子要素の色が変わっていることに注目してください。

どんな時に役立つ?

コンポーネント単位で要素を管理したい時に役立ちます。

例えばXのタイムラインを見てみると、 PCのときは3カラムになっているのが分かると思います。

これが一定以下の画面幅になると、サイドバーのテキストが消えてアイコンだけになるんですね。

こんな時、通常だったらメディアクエリを使用して、例えば

@media (max-width: 1280px) {
    .text-to-hide {
        display: none;
    }
}

このように「画面幅1280px以下になったら、テキストを消す」かもしれませんが、

コンテナクエリの場合は、「親コンテナが260px以下になったら、テキストを消す」みたいな書き方が可能です。

コードにするとこのようになります。

.box {
    container-type: inline-size;
}
@container (max-width: 260px) {
    .text-to-hide {
        display: none;
    }
}
ゆうきくん

う〜ん、でもわざわざコンテナクエリを使う必要があるのかなぁ?記述量は減らないじゃん

という疑問があるかと思います。それはごもっともで、個人的にはReact・Vue・Astroなどのコンポーネントをベースとした開発と特に相性がいいのかなと思っています。

https://www.intage-ts.com/entry/2022/11/01/0945

例えばコンポーネントベースだと、サイドバーだけでファイルを切り出したりします。

これによってコンポーネントの開発者は、そのコンポーネントがどこにどう配置されるかを気にする必要がなく、

あくまで自分がコンテナサイズに対してどのような表示になるかだけの関心を持てばよいので、メディアクエリよりも開発がしやすくなるんですね。

Web制作だとイメージしにくいかもしれませんが、「メディアクエリだとどうにもやりにくい」という場面には意外に出くわしますし、

使い方を知っているととても便利な機能なのは間違いないので、今のうちに取り入れておくといいかと思います。

メディアクエリ:ビューポート(ブラウザウィンドウ)全体

コンテナクエリ:適用対象: 特定の要素(コンテナ)

:has()擬似クラス

:has()は、CSSの新しい擬似クラスの一つで、多くの方が心待ちにしていた機能だと思います。

要素が特定の子要素を持つかどうかを判断でき、子要素を含む場合にスタイルを適用できるため、今日紹介するモダンCSSの中で最も強力な機能だと思います。

既に各ブラウザで解禁されており、使うことができます。

2024年5月時点

:has()の基本的な書き方

例えばこのようなHTMLがあったとします。

<div class="parent">
  <div class="child">Child Element</div>
</div>
<div class="parent">
  <!-- Child element is not here -->
</div>

ここで、.parentクラスを持つ要素の中に.childクラスを持つ要素が含まれている場合にのみ.parentの背景色を黄色にしたいとします。

この場合、:has()を使うと次のようになります。

.parent:has(.child) {
  background-color: yellow;
}

これにより、.childクラスを持つ子要素が含まれている親要素だけが、背景色が黄色に変更されます。

従来のCSSでは、このようなスタイリングを実現するためにはJavaScriptを使用する必要がありましたが、:has()を使うことで純粋なCSSだけで実現できるようになりました。

:has()はどんな時に役に立つ?

カードコンポーネントを例に見てみましょう。

サムネ画像が未指定の場合でも、表示が崩れないようにしたい

という要望があったとします。

WordPressなどCMSで運用しているとサムネ画像が未指定の場合もあると思います。

もちろんWordPressの場合PHPが使えるので、if文で代理のサムネ画像を出してもいいですが、:has()なら他のどんな環境だとしても対応できます。

/* サムネイル画像があるカード */
.card:has(.thumbnail) {
  display: flex;
  align-items: center;
}
/* サムネイル画像がないカード */
.card:not(:has(.thumbnail)) {
  display: block;
}

もう一つ、アコーディオンの具体例を見てみましょう。

アコーディオンの中で展開されているものの見出しだけ太字にしつつ、背景色もつけたい。

こういった場合も:has()を使えば楽です。

この要件を更に詳細にコードを使って言語化すると、

.accordion-itemの中の.accordion-contentdisplay: none;がついてなければ、.accordion-headerにCSSを付与

すればいいわけです。

よってこのコードになります。

/* 展開されたセクションのスタイル */
.accordion-item:has(.accordion-content:not([style*="display: none"])) .accordion-header {
  background-color: #e9e9e9;
  font-weight: bold;
}
しょーご

複雑に見えますが、慣れればすぐ理解できると思います。

論理プロパティ(Logical Properties and Values)

論理プロパティは、レイアウトの際に上下と左右といった物理的な方向ではなく、文字の記述される方向(書字方向)によって方向が変わるプロパティを論理的に表現しようというものです。

従来のCSSでは、レイアウトに関するプロパティは物理的な方向(top.bottom,right,left)を基準に指定されていました。

例えば、margin-left padding-top などです。しかし、これらの物理プロパティはページの書字方向が変わると意図した通りに適用されないことがあります。

これは結論として、

.avatar {
  margin-inline-end: 1rem;
}

これを指定してあげれば、どんな書字方向だとしても、常にアバターの後ろに余白が確保されます。

アラビア語は左から右に読みますし、日本語サイトには縦書きもありますよね?

論理プロパティは書字方向に依存しない抽象的な方向を基準に指定するので、これにより、異なる言語や書字方向でも一貫したレイアウトが保てます。

理解が難しい概念なので、具体例を見ていきましょう。

2024/05

論理プロパティはまず、インラインとブロックを理解せよ

論理プロパティにおいて、インラインとブロックの概念理解は重要です。

インラインは、テキストの流れに沿った方向を指します。日本語の場合横書きが多いと思いますが、横書きの場合は横方向がインラインになります。

ブロックは、テキストの流れの垂直方向を指します。横書きサイトの場合は縦方向を表します。

これを利用した論理プロパティの利用方法として分かりやすいのが「要素の中央揃え」だと思うので、それを例に使い方を解説していこうと思います。

論理プロパティの基本的な使い方

論理プロパティはかなり数が多いので、使いやすい余白に関するものだけここでは紹介していきます。

例えばこれまで要素を左右中央揃えにしたいとき、 margin-left: auto と margin-right: auto ってよく使ってましたよね?

.card {
  margin-left: auto;
  margin-right: auto;
}

もしくは、

.card {
  margin: 0 auto;
}

とする人もいたかもしれません。

これはleftとかrightとなっているので、物理プロパティです。

ではこれを論理プロパティを使うとどうなるのか。

.card {
  margin-inline: auto;
}

これでOKです。

ちなみに、margin: 0 auto;に関しては微妙な記述かなと思っており、インライン方向で中心にしたいだけなのに、margin-topmargin-bottomも指定してしまっているのが気持ち悪いですよね。

もちろんpaddingに対しても使うことができます。

.block {
  padding-left: 8px;
  padding-right: 8px;
}

従来ならこういった記述だったのが、

.block {
  padding-inline: 8px;
}

このように書くことができます。

エンジニアさん

書字方向が変わるような多言語サイト、自分は無縁だからな。。。

と思われたかもですが、このように記述量を単純に減らすことも可能なので、まずは要素の中央揃えから取り入れていくのがいいかと思います。

しょーご

論理プロパティは他にもwidth、height、border、Text alignなど多様な場所で使うことができるので、少しずつ覚えていけばいいかなと思います。

私もまだ使いこなせていません(^_^;)

ネスト(CSS Nesting)

ネストはSassを使っている人なら既にご存知だと思いますが、ようは入れ子ですね。

以前のCSSならネストにできないので、このHTMLに対して以下のコードを書く必要がありました。

<div class="container">
  <div class="box">中央揃えのボックス</div>
</div>
.container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    width: 100vw;
}

.container .box {
    width: 200px;
    height: 100px;
    background-color: lightblue;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 2px solid blue;
    text-align: center;
}

しかし、CSSのネストを使うことで、このように書けます。

/* ネストを使用することで、上記を以下のように書けます */
.container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    width: 100vw;

    .box {
        width: 200px;
        height: 100px;
        background-color: lightblue;
        display: flex;
        justify-content: center;
        align-items: center;
        border: 2px solid blue;
        text-align: center;
    }
}

メディアクエリのネストなども可能です。

.foo {
  color: blue;
  @media (min-width: 740px) {
    color: green;
  }
}
2024/05

SassのネストとCSSのネストの違い

Sassのネストとの違いに関しては、&(アンパサンド)でクラス名の接続ができないことです。

例えばBEMで設計されている場合、このように&でクラス名を省略して書くことがあるかと思います。

/* Sassでの親セレクタの参照 */
.button {
  display: inline-block;
  padding: 10px 20px;

  &--large {
    padding: 20px 40px;
  }

  &--primary {
    background-color: darkblue;
  }
}

このような書き方はCSSのネストでは不可能ということです。

しょーご

個人的にはこの書き方はクラス名の検索ができないのでNGです。なので使えなくても問題ないかなと。

コラム:Sass不要論に一言

まさひろくん

あれ?これもうSassいらない説!?勉強しなくてよくね?

とという発言がXで散見されますが、個人的にはまだそうとも言えないかと思います。

ほとんどのプロジェクトにSassは導入されていますし、Sassにしかない機能に依存しているとしたら、大変です。

確かに個人開発などで小規模なプロジェクトならCSSでもいいかもしれませんが、個人的にはCSSだけでメインに開発するのは数年先の話なのではと思います。

そもそもSassの学習コストなどたかがしれているので、現状の案件を踏まえるとわざわざ除外する意味もないかと思います。

aspect-ratio

aspect-ratio は、CSSプロパティの一つで、要素のアスペクト比(縦横比)を設定するために使用されます。

全然むずかしく無いので、今日解説した中では一番導入しやすいかもしれません。

2024/05

例えば、aspect-ratio: 16 / 9; は、16:9の比率を設定します。

.container {
    width: 100%;
    aspect-ratio: 16 / 9;
    background-color: lightgray;
}

また嬉しいのが、Webページ読み込み時に表示領域を確保してくれるので、widthとheightを指定しなくても、

ページがガクッと動く「レイアウトシフト」を防いでもくれるので、アクセシビリティにも良いという点です。

padding-topでの調整はもういらない

aspect-ratio以前の時代の、Google MapsやYouTubeのサイト埋め込みの場合、これまではpadding-topで無理やり調整するという古の方法がありました。

.container {
    width: 100%;
    padding-top: 56.25%; /* 16:9 アスペクト比 (9 / 16 * 100 = 56.25%) */
    background-color: lightgray;
    position: relative; /* 子要素の絶対位置指定のため */
}

.container > * {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

ただpadding-topをこのように使うのはかなり違和感がありますよね。全然直感的でないので、ぱっとみて何をしている処理なのかわかりにくいです。

これがaspect-ratioなら直感的に記述できるので、それを紹介します。

aspect-ratioの基本的な使い方

Google Mapsのサイト埋込みでよく使うので、これを実装してみようと思います。

この場合、従来のpadding-topを使った実装だとこのような直感的じゃないコードになっていましたた。

.map-container {
    position: relative;
    width: 100%;
    padding-top: 56.25%; /* 16:9 アスペクト比 (9 / 16 * 100 = 56.25%) */
    background-color: lightgray;
}

.map-container iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

aspect-ratioを使えばアスペクト比を指定するだけなので、直感的で楽です。

.map-container {
    width: 100%;
    aspect-ratio: 16 / 9; /* アスペクト比を指定 */
    background-color: lightgray;
}

.map-container iframe {
    width: 100%;
    height: 100%;
    border: 0;
}

object-fitと併用すると便利

例えばWordPressのような、色んな記事がぶち込まれる環境でaspect-ratioを使う際には気をつけておくことがあります。

例えばこちらを御覧ください。

aspect-ratioを使用したものの、実際に使われている画像は指定の16/9のものではないため、縦に潰れています。

WordPressのようなCMSを使う場合は、どのような画像が気ても崩れないようにしなければならないので、これではまずいです。

そこでobject-fitを使ってトリミングすることで、画像の縦横比の崩れを修正することができます。カードコンポーネントを実装する際は覚えておくといいかと思います。

ただobject-fitでトリミングすると、サムネ画像にテキストなど情報が入っている際にそこもトリミングされてしまうので、ベストなのは運用者に入稿する画像のアスペクト比を守ってもらうことかと思います。

object-fitの使い方を解説【CSSで画像をトリミングし縦横比を固定できる】
しょーご

ちなみに私のブログのサムネ部分もaspect-ratioによって管理されていますので、気になる方はコードを見てみてください。

まとめ モダンCSSに入門しよう

今回はモダンCSSの中でも厳選したものを紹介しましたが、更に紹介したモダンCSSに優先順位をつけるとしたら、以下の感じになります。

今回扱うモダンCSS
  • コンテナクエリ★☆☆
  • :has()★★★
  • 論理的プロパティ★☆☆
  • ネスト★★☆
  • aspect-ratio★★★

:has()は強力な機能なので是非皆さんにも使えるようになって欲しいですし、aspect-ratioもすぐに取り入れられると思います。

この他の★★★レベルのclamp()に関しては以前記事や動画にまとめているので、そちらも御覧ください。

CSS Gridに関しては特大テーマなので、この次の記事で扱う予定です。

お楽しみに!!

今回の記事の動画版はこちら👇

模擬案件チャレンジ開催のお知らせ

超実践編では納期厳守の模擬案件を経験し、スキル面以外にコミュニケーションも徹底レビューを受けることができます。

【超実践編】納期厳守の模擬コーディング案件で実務への自信を身につける!【学習沼からあなたを卒業させます】

最近は実案件のノウハウも多いですが、「納期が短い案件の中で、丁寧なコミュニケーションを本当に実践できますか?

この課題では、極限まで実案件に近い状況で、発注者である私とコミュニケーションを取りながら、

  1. 見積書提出
  2. 実装→初稿提出
  3. レビュー→修正
  4. 再修正→納品
  5. 請求書

この流れを実践していただき、最後にzoomであなたに全体レビューを行います。

【超実践編】納期厳守の模擬コーディング案件で実務への自信を身につける!【学習沼からあなたを卒業させます】
  • 学習はだいたい終わったけど、納期までに納品できるか不安
  • 中々継続と紹介で案件が回らない

このような中級者を飛躍させる超実践編、受講には条件がありますので、詳細はリンク先よりご確認下さい。

しょーご

あなたの挑戦を待っています!!

\レビューを受けて圧倒的な自信を身につける!/

応援して頂ける方へ

ご寄付を頂けると今後の更新の励みになります!

🍺 ビールをプレゼントする

あなたに是非読んでほしい記事です!
});