【CSS】新しい擬似クラス:hasのテクい活用方法

# 擬似クラス:hasとは？
2023年12月にやっと全ブラウザ対応されたばかりの新しい擬似クラスです。
hasと書いてある通りに、そのセレクタが、特定のセレクタを持っている場合に適用される擬似クラスです。
例えば、
```html
<nav>
    <ul>
        <li><a href="#" class="is-active">メニュー１</a></li>
        <li><a href="#">メニュー１</a></li>
        <li><a href="#">メニュー１</a></li>
    </ul>
</nav>
```
```css
li:has(.is-active) {
    border: 1px solid #ff0;
}
```
このようにすると、直接クラスが指定されていないDOMにliに対してスタイルをかけることができます。
あんまりこのケースはないとは思いますが、CMSなどによってクラスをつけれるところが制限されたりする場合は重宝したりします。
# 活用パターン集
### 逆隣接セレクト
例えばカードのスタイルを当てる上で、隣のDOMがあるかないかによって、行数を変えたいといった場合。
```scss
.p-card {
    &__description {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2; //通常の場合は２行表示
        overflow: hidden;
        line-height: 1.3;
        &:not(:has(~.p-card__tags)) { //隣にp-card__tagsがない場合は４行表示。
            -webkit-line-clamp: 4;
        }
    }
    &__tags {
        width: 100%;
        display: flex;
        justify-content: flex-start;
        column-gap: 8px;
        margin-top: auto;
    }
}
```
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="PovwaYa" data-user="dtweqbgd-the-vuer" 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/dtweqbgd-the-vuer/pen/PovwaYa">
  Untitled</a> by 苅田ハユセ (<a href="https://codepen.io/dtweqbgd-the-vuer">@dtweqbgd-the-vuer</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
このように特にクラスを変えずに、DOMの構造によってスタイルを変えることができます。
隣接セレクタで、「〜の次にある場合」というのはできてたのですが、「〜が次にある場合」というのはできなかったので、だいぶ手数が広がると思いますね！

### 空の時にレイアウトを変える
いわゆるempty state(空の場合の処理）についても使えます。
純粋に、空のコンポーネントがある場合出会ったり、そもそもからだった場合にも親のスタイルを変更できます。

```scss
&__wrapper {
        display: grid;
        grid-template-columns: max-content max-content;
        justify-content: space-between;
        min-height: 100px;
        gap: 8px;
        list-style: none;
        padding: 0;
        margin: 0;
        height: calc(100% - 32px);
        &:has(.c-empty-state) { //emptyコンポーネントがある場合、レイアウトを中央揃えにする
            display: flex;
            align-items: center;
            justify-content: center;
        }
```
```scss
.p-list {
    display: inline-block;
    border: 1px solid #ababab;
    width: max-content;
    padding: 24px;
    border-radius: 6px;
    margin: 16px;
    min-width: 246px;
    &:has(.p-list__wrapper:empty) { //ul要素が空（liがひとつもない場合）赤ボーダーにする
        border-color: #f00;
        color: #f00;
    }
```
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="wvbBxpz" data-user="dtweqbgd-the-vuer" 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/dtweqbgd-the-vuer/pen/wvbBxpz">
  Untitled</a> by 苅田ハユセ (<a href="https://codepen.io/dtweqbgd-the-vuer">@dtweqbgd-the-vuer</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 終わりに
今回は実案件でちょっといいなと思ったものを実装パターンとして紹介しています。
CMSなどのフロントエンドでこのような手数が増えるのはだいぶ助かりますね♪
また新しい使い方が見つかれば追記しようかなと思います。