「CSSの進化、知らなくて許されるのは小学生までだよねー」

## はじめに
ちゃんとCSS勉強されていますか？HTML勉強されていますか？何となくで誤魔化しでCSS使ってませんか？`float:left;`駆使してレスポンシブデザイン作ろうとしていませんか？

Webデザイナー、制作者のみなさん、古い情報ばかり追ってませんか？あなたが参考にしている記事はいつ書かれた記事ですか？WordPressの使い方、テーマの使い方ばかり追って、本質のコードを疎かにしていませんか？「コピペでOK！」みたいなのでとりあえずコピペで逃げてませんか？CSSでネストが使えることはちゃんと知っていますか？

フロントエンドエンジニアのみなさん、CSS疎かにして何でもJSでやろうとしていませんか？それではフロントエンジニアではなくJavaScriptエンジニアではないですか？子供の前で胸張ってフロントエンドエンジニアですって言えますか？[「CSS完全に理解した」](https://suzuri.jp/kakedashi-engineer/4256259/t-shirt/s/white)とかとりあえずネタ言って、本当はできない自分を誤魔化したりしてませんか？

バックエンド、インフラエンジニアのみなさん、こんにちは。

IEの終了した現在、ブラウザの進化はえげつないです。年始には97だったChromeのバージョンが、もう120になろうとしています。ブラウザの進化に伴って、HTML,CSS,JavaScriptも進化しています。特にCSSは、今までできなかったようなことがかなりできるようになってきました。
これを機会に年末年始、CSSの最新機能を振り返ってみませんか？

## ネスト
「いやいや、ネストはSassだろ」とお思いのあなた、もう普通のCSSでネストを使えますよ。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="xxMQVOy" data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/xxMQVOy">
  CSS Nest</a> by Tomoya Masaki
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```css:抜粋
.container {
  margin-left:2rem;
  >.button {
    cursor:pointer;
    background:#6de7a8;
    /* 省略 */
    &:hover { 
      scale:1.1;
      opacity:0.5;
    }
  }
}
```

CSSだけでちゃんとネストが書けるのめちゃくちゃ便利ですね。`&`を利用すると親のセレクタを参照できます。この場合は`.button`のhoverを参照しています。これでもうSassの必要性がまた一段と下がったのではないのでしょうか。

## 新しいmargin記法、`margin-inline`と`margin-block`
中央寄せするときに、よく使われるのが
```css
.content {
    margin-left:auto;
    margin-right:auto;
}
```
です。これが一行でかけるようになりました。
```css
.content {
    margin-inline:auto;
}
```
また、縦方向に関しても
```css
.content {
    margin-block:auto;
}
```
と簡潔にかけるようになりました。厳密にいうと、文字の方向によります。基本的には文字が左から右方向なので、`margin-inline`は左右になります。これが上から下方向の、日本語の縦書きのような文章だと上下になります。`write-mode`で変わるみたいです。
左右の幅を変えたかったら、
```css 
.content {
     margin-inline:40px 60px;
 }
```
のように書きます。

## アスペクト比を設定できる、`aspect-ratio`
画像などで、比を簡単に保てるプロパティです。`aspect-ratio`を使えば、16:9の画像も変にwidthとheightを細かく設定しなくてもよくなります。
```css 
.container {
    width:100%;
    aspect-ratio: 16 / 9;
}
```

## すりガラス表現が1行で、`backdrop-filter`
すりガラスのような表現が、`backdrop-filter:blur(3px);`のような形で書けます。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="vYbQJoM" data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/vYbQJoM">
  backdrop-filter</a> 
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```css:抜粋
.backdrop {
    backdrop-filter:blur(3px);
}
```
たったこれだけで、iPhoneの通知とかでよくみかけるようなすりガラス表現ができます。非常に楽ですね。比較としてとなりに背景を透過したものを載せました。
ぼかし表現がめちゃくちゃ簡単にできました。

## あらゆるコンテナの幅で条件分岐、コンテナクエリ
メディアクエリはご存知の方が多いと思います。画面サイズによって条件を変える、レスポンシブデザインでよくある手法です。
コンテナクエリはその強化版で、様々なコンテナサイズによって条件を変えられます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="MWLPPZP" data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/MWLPPZP">
  Container Query</a> 
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```css:抜粋
.container {
  container-type: inline-size;
  border:solid 1px;
}

@container (width < 500px) {
  .contents {
    flex-direction:column;
  }
}
```

`container-type: inline-size;`で、基準となるコンテナを指定してあげます。このコンテナの幅によってコンテナクエリが効きます。実際に動かしてもらうとわかりますが、`.container`のwidthによってBoxが横並びになったり縦並びにになったりします。この場合は500px未満のときに縦並びにできます。
メディアクエリだとデバイスサイズでしか今まで判定できなかったのが、コンテナクエリだとすごく自由度が高く判定を行えます。レスポンシブデザインでなくても、可変幅なコンテナがあれば適用できます。
例えば、文字の長さによって、短かったら中央寄せ、長かったら左寄せみたいなことだってできます。また、横幅でなく縦幅だって判定に使えます。
コンテナクエリに関してはめちゃくちゃ沼が深そうなのでこちらのサイトの記事を貼っておきます。

https://kojika17.com/2023/03/css-container-queries-swamp.html

ちなみに気づきましたか？今まで`min-width:100px`とかやっていたのを、`width < 100px`みたいに書けるようになったの。数学的に不等式を書けるようになりました。等号の入った不等式も扱えます。めちゃくちゃ直感的になりましたね。なので、`500px <= width < 1000px`みたいに書けるようになりました。これはメディアクエリでも同じです。

詳しく解説されていた記事があったのでそちらを貼っておきます。

https://zenn.dev/moneyforward/articles/css-range-syntax

## 優先度も自由自在、カスケードレイヤー
CSSの悩ましい問題として詳細度の問題があります。reset cssがなぜか優先されていたり、他のcssが優先されたり、それで!importantまみれになったり。
そこであらたに、カスケードレイヤーという概念が現れました。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ZEwmzQv"   data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/ZEwmzQv">
  Cascade Layer</a>
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```css:抜粋
@layer reset,base,utility;

@layer reset {
  h1 {
    font-size:1rem;
    letter-spacing:0rem;
  }
}

@layer base {
  h1 {
    font-size:1.2rem;
    letter-spacing:.1rem;
    color:#000;
  }
}

@layer utility {
  h1 {
    color: #007bc7;
  }
}
```

各プロパティ`@layer [名前]`で囲うとそれがレイヤーになります。そして一行目の`@layer reset,base,utility;`で優先度を決められます。右に行くほど優先度が高いです。
実際にこのCodepen内で、`@layer`のreset,base,utilityの順番を変えたり消してみたりしてください。各layerとマッチしたstyleがちゃんと適用されています。
レイヤー化されているCSSはされていないCSSより詳細度が低くなります。レイヤー同士で詳細度の高さも決められます。そのため、reset cssを一番優先度の低いCSSレイヤーに、カスタマイズをしたベースのCSSをreset cssよりも優先度を高く、そしてCSS-in-JSやTailwind CSSなどでコンポーネントに直接適用させる細かいスタイルはレイヤー化しなければ一番優先度が高くなります。
これで悩ましい`!important`問題ともうまくおさらばしやすいのではないでしょうか？

## 新登場`@scope`ルール
これは2023年11月現在はまだ残念ながらChromeおよびEdgeのみ対応です。
CSSの適用範囲を制限できるというめちゃくちゃ画期的な機能です。`@scope`をつけたクラス内はそれ以外の場所はスタイルの影響を受けないという機能です。今までクラス名に悩まされてBEMなどの記法で苦労していたのがなくなります。スーパーめちゃんこ重宝する機能です。
これに関してはここには書ききれないと思い、思いをまるまる一記事に書いたので、こちらをご覧ください。

https://qiita.com/mu_tomoya/items/f24baefdecb7ddcea973

クラス名がバッティングしてしまう、他のスタイルが適用されてしまうなどの悩みがほとんど解決されるのではないかと思っています。自分の中では、CSSライブラリ論争はすべて終了してしまうんじゃないかってレベルの強烈な衝撃を受けました。これとカスケードレイヤーを組み合わせれば詳細度などをあまり気にせず自由自在にCSSを記述できるんじゃないでしょうか？
おそらく、`@scope`は今後必須間違いなしの技術だと思います。フロントエンドエンジニア、Webデザイナーに関わらず。


## めちゃくちゃ便利な`:has()`
`:before`や`:hover`などと同じ擬似クラスの一種です。`.card:has(.hoge)`と書けば、`.hoge`というクラスが中にある`.card`にのみスタイルを設定できます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="wvNQvqX" data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/wvNQvqX">
  :has()</a>
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```css
.box {
  /* 省略 */
  &:has(h3) {
    background:#999999;
  }
}
```

この場合は`h3`タグを持っているボックスのみ色が暗くなるようにしています。複数リストを並べるときに、特定の条件にマッチする要素のみスタイルを設定するみたいなときにめちゃくちゃ有効です。`:not()`と組み合わせればその逆も可能です。
活用方法がめちゃくちゃあるの、ものすごく便利な`:has()`擬似クラスです。細かいスタイル調整に困ったら`:has()`を使うのありです。

## jsいらずのPopover API
もはやCSSだけの話でなくなってきています。純粋なHTMLです。純粋な`button`タグだけでポップオーバーが作れます。FireFoxだけはまだ対応していないですがもうすぐ対応しそうです。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ZEwmzpr" data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/ZEwmzpr">
  Popover</a>
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```HTML:抜粋
<button class="open-button" popovertarget="my-popover" popovertargetaction="show"> 開く </button>
<div id="my-popover" popover>
    <button popovertarget="my-popover" popovertargetaction="hide" class="close-button">
        <svg>
             ...
        </svg>
    </button>
</div>
```
`button`タグの`popovertarget`属性に、ポップとなる要素のidを指定してあげます。またポップとなる要素に`popover`という属性を追加してあげます。これだけでおしまいです。これなんと、jsを一行も書かずに実装しています。CSS側も、`z-index`など使用していないです。HTMLの進化もえげつないですね。
ページの上にちょこっと出す、広告などでよく使われる手段です。似たようなことをdialogタグでも実は実装できますが、こちらはjsでの操作が必要になってきます。またPopover APIで実装する場合はちゃんとaria-roleなどを付与してあげた方がいいです。
dialogはユーザーの操作をそれ以外制御する、Popover APIは制御しないとの違いなので、ユーザー削除などで何かの確認のときにはdialog、その他はPopover APIで実装と使い分けてあげるのが良さそうです。

## カードレイアウトが簡潔に、subgrid
ついにsubgridが使えるようになりました。gridの中にgridを書けるようになりました。
subgridは何が違うかというと、ちゃんと親のgridと連動しているところです。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="poGQzqK" data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/poGQzqK">
  SubGrid</a>
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```HTML
<div class="grid">
  <article class="card">
     ...
  </article>
  <article class="card">
     ...
  </article>
  <article class="card">
     ...
  </article>
</div>
```

```CSS:抜粋
.grid {
  display:grid;
  grid-template-columns:1fr 1fr 1fr;
}
.card {
  display:grid;
  grid-row: span 4;
  grid-template-rows: subgrid;
  gap: 0.2rem;
  /* 省略 */
}
```
gridの子となるクラスに`grid-template-rows:subgrid;`を設定してあげるとその中もまたgridになります。
今までだと個別でカード内にまた新たにgridを設定する必要がありました。そうすると各カード内の高さがまばらだったので、カード間で高さを揃えるのが難しかったです。それが、subgridを使うと綺麗に整うようになりました。

## フォームバリデーションのための、:user-valid,:user-invalid
これはWeb制作者向けです。ReactやVueなどのライブラリを使わない人向けです。またはそれらを使っていても、フォームはHTMLそのままで使う人向けです。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="BaMGjLE" data-editable="true" data-user="mu-tomoya" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mu-tomoya/pen/BaMGjLE">
  :user-valid&amp;:user-invalid</a>
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

こちらの例ではメールアドレスを入力するフォームです。`<input type="email"/>`で、入力はメールアドレス形式を受け付けています。
`:user-valid`は入力が正しいとき、`:user-invalid`は入力が正しくないときの擬似クラスです。これらを使えば、バリデーションの状態に対してスタイルを当てられます。
バリデーションエラーを起こすのはJavaScriptでも操作できます。ただし、エラーメッセージはHTML標準で出力されるツールチップが伴うので、それが邪魔に思う人はそもそもHTML標準のバリデーションを利用しない方が良さそうです。

## CSSはプログラミング言語だ！数学関数

https://qiita.com/degudegu2510/items/6d5d53ca9833aef7ec83

こちらはあまり自分では使用していないため、紹介に留めておきます。三角関数から指数関数、対数関数まで使えます。アニメーションで使う際にめちゃくちゃ有用そうですね。もはやCSSはプログラミング言語と呼べるのではってレベルですね。

## 終わりに
いかがでしょうか？何も他のライブラリは使ってません。通常のCSSのみしか使っていません。2023年はかなりの機能が増えました。アニメーション関連に関しては省きましたが、アニメーション関連の進化もめちゃくちゃすごいです。
アニメーション関連に関してはこちらの記事がとても詳しいのでご覧になってください。

https://qiita.com/degudegu2510/items/a6faf04f07afdece9022

JavaScriptで行ってきたことが大分JSレスで、CSSオンリーでできるようになりました。わずらわしい詳細度の問題もかなり解決できました。あとは`@scope`が全ブラウザ対応になればもう完璧ではないでしょうか？

ところで、人によっては「いやいや、最新ブラウザばかりの対応は難しいんだよ」という方もいます。あと、「もう疲れちゃって 全然覚えられなくてェ…」みたいな方もいると思います。
しかし、無理に覚える全部覚える必要もないですし、使えない状況下であれば別に使う必要もないです。こういう機能があるってことを知っておくことが大事です。知らないで使わないのと、知っていてあえて使わないのでは、使える手数が大きく変わってきます。
「どれが優先度高いかわからなくなっちゃった。そういえばなんかカスケードレイヤーみたいな機能があったなぁ」ってときにこの記事振り返ったり、ググったりすることがとても大事です。「何かそういうのあったな」って微かに覚えてて、調べて使う、そういう積み重ねがとても大事です。
あとは進化がすごいので、「こういったことCSSで実現できないかな」っていうのを機能ごとにうまく因数分解して調べることも有効です。もしかしたらそのときにできているかもしれません。

ぜひ皆さんも最新のCSSの動向を追ってみてください。