レイアウトの設定を管理しやすくするCSS変数の使い方

CSS変数 (カスタムプロパティ) を使いこなせていますか?

今回はCSS変数を使用して、FlexboxレイアウトやGridレイアウトの設定を管理しやすくするための小技を紹介します。

レイアウトの設定が管理しづらいと思った理由

FlexboxレイアウトとGridレイアウトには、「コンテナ」と「アイテム」という概念があります。

Flexboxレイアウトの場合、display: flex; を指定した要素は「フレックスコンテナ」となり、その子要素は「フレックスアイテム」になります。

Gridレイアウトの場合、display: grid; を指定した要素は「グリッドコンテナ」となり、その子要素は「グリッドアイテム」になります。

アイテムはコンテナに設定したプロパティの影響を受けるため、通常、コンテナとアイテムの設定はまとめて行います。そのため、CSSファイルを細かく分けて管理するような場合、コンテナとアイテムが分けられないといったことが起こります。

コンテナとアイテムを分けて管理する方法

CSS変数 (カスタムプロパティ) を使用すると、アイテム側の設定をコンテナ側で一括管理できるようになり、コンテナとアイテムを分けることができるようになります。

Flexboxレイアウトの場合

フレックスアイテム側のCSSコードは次のようになります。

:where(.container) > .item {
  flex: var(--container-item--flex, initial);
  place-self: var(--container-item--place-self, auto);
}

あらかじめ、使用することが想定されるプロパティの値に変数を設定しておきます。変数に値が設定されなかった場合を考慮して代替値を設定しておきます。

あとは、フレックスコンテナ側で好きなように設定します。例えば、コンテナいっぱいにアイテムを横並びにしたい場合は次のようなCSSコードになります。

.container {
  display: flex;
  --container-item--flex: 1;
}

アイテムの数や役割が決まっている場合は、アイテム毎に固有の接頭辞を持つ変数を設定しておくといいでしょう。

/* main.css */
:where(.content) > .main {
  flex: var(--main--flex, initial);
  place-self: var(--main--place-self, auto);
}

/* side.css */
:where(.content) > .side {
  flex: var(--side--flex, initial);
  place-self: var(--side--place-self, auto);
}

/* content.css */
.content {
  display: flex;
  flex-flow: wrap;
  --main--flex: 100000 50%;
  --side--flex: 1 320px;
}

Gridレイアウトの場合

グリッドアイテム側のCSSコードは次のようになります。

/* main.css */
:where(.content) > .main {
  grid-area: var(--main--grid-area, auto);
  place-self: var(--main--place-self, auto);
}

/* side.css */
:where(.content) > .side {
  grid-area: var(--side--grid-area, auto);
  place-self: var(--side--place-self, auto);
}

あとは、グリッドコンテナ側で好きなように設定します。

/* content.css */
.content {
  display: grid;
  grid: "M S" / 1fr auto;
  --main--grid-area: M;
  --side--grid-area: S;
}

これから使う機会が増えそうな:has擬似クラスとの相性も良く、メディアクエリとも組み合わせやすくなります。

.content:has(> .main):has(> .side) {
  display: grid;
  grid: "M" "S";
  --main--grid-area: M;
  --side--grid-area: S;
}
.content:has(> .main:only-child) {
  display: block;
  …
}
@media (min-width: 961px) {
  .content:has(> .main):has(> .side) {
    grid: "M S" / 1fr auto;
    --main--place-self: start auto;
    --side--place-self: start auto;
  }
}

もっと柔軟に設定するための一工夫

上記のアイテム側のCSSコードで使用したプロパティは、いずれも一括指定 (ショートハンドプロパティ) です。個々のプロパティでも設定したい場合は次のようにします。

:where(.container) > .item {
  flex: var(--container-item--flex, var(--container-item--flex-grow, 0) var(--container-item--flex-shrink, 1) var(--container-item--flex-basis, auto));
  place-self: var(--container-item--place-self, var(--container-item--align-self, auto) var(--container-item--justify-self, auto));
}

CSS変数は扱い方を誤ると地獄を見る可能性がございますので、用法・容量を踏まえて正しくお使いください。

関連記事