土曜日, 7月 12, 2025
土曜日, 7月 12, 2025
- Advertisment -
ホームニューステックニュース【CSS】ありのままで〜幅、親に合わせて〜【Flexbox】【width: stretch】 #CSS - Qiita

【CSS】ありのままで〜幅、親に合わせて〜【Flexbox】【width: stretch】 #CSS – Qiita



【CSS】ありのままで〜幅、親に合わせて〜【Flexbox】【width: stretch】 #CSS - Qiita

この記事のように、width: stretch が一部のブラウザでリリースされたことで、「width: 100% ではなくてこちらを使うべき」という受け止め方がされています。

しかし、要素の横幅について、もっと気を付けておくべきこと が見過ごされています。


それは、横幅は、余計なことをしなければ、親に合わせて勝手に良い感じになってくれる ということです。

OK の例では、カード内の各子要素がカードの幅いっぱいに広がっている。 DON'T の例では、カード内の各子要素がカードの左側に寄っていて、右下のボタンを右側に寄せることに失敗している。

CodeSandbox あります

良い例、悪い例をまとめてカンタンに確認できる CodeSandbox を用意しました。

わかりやすさのために表示している枠線を消したり、width: stretch を付け外ししたりして確認できます。

✅️ OK: デフォルトで良い感じになる

まず、良い例から出しましょう。HTML と CSS(ネスト機能を利用しています)の抜粋は以下の通りです。

  • .card : カード本体、縦向きの flexbox

    • .card__title : カードのタイトル
    • .card__description : 本文
    • .card__footer[data-align="end"]: ボタンたちを横向きに右揃えで配置する
class="card">

class="card__title">カード #1

class="card__description">春はあけぼの、やうやう白くなりゆく山際

class="card__footer" data-align="end">

.card {
  display: flex;
  flex-direction: column;
  padding: 8px 0;
  /* 中略: ボーダー設定など */
}

.card__title {
  margin: 0;
  padding: 0 16px;
}

.card__description {
  margin: 0;
  padding: 0 16px;
}

.card__footer {
  display: flex;
  padding: 0 16px;

  &[data-align="end"] {
    justify-content: end;
  }
}

.card__button {
  appearance: none;
  border: none;
  /* 詳細は省略 */
}

これだけだと、どこが「良い」「ありのまま」のか分かりにくいと思うので、さっそく「ダメ」「余計」な例を見てみましょう。

ダメな例: 余計な align-items: start

ここで、「親」である .cardalign-items: start を追加してみましょう。

  .card {
    display: flex;
    flex-direction: column;
+   align-items: start;
    padding: 8px 0;
    /* 中略: ボーダー設定など */
  }

なんか、子要素はだいたい左側に寄ってるから、とりあえず左に寄せとけばええやろ

と軽い気持ちで書いてしまいがちなこの一行ですが……

OK の例では、カード内の各子要素がカードの幅いっぱいに広がっている。 DON'T の例では、カード内の各子要素がカードの左側に寄っていて、右下のボタンを右側に寄せることに失敗している。

なんと、もともと横幅いっぱいに広がっていた各子要素が、己の自然な横幅まで縮んで、左側に寄ってしまいました……

タイトルや本文は無事ですが、フッター(.card__footer) は悲惨な状態です。

フッターは、それ自体が「子」であるボタンたちをレイアウトする立場にあるので、このように横幅が縮んでしまうのは痛手です。

width: stretch で帳尻合わせ

では、どうすれば良いのでしょうか?

フッター(含め各子要素は)の横幅は、自然に狭まってしまわず、親の幅いっぱいに広がるべき

という素朴な考えをそのまま CSS に落とし込んで、width: stretch (あるいは、 align-self: stretch)を使いたくなるでしょう。

  .card {
    display: flex;
    flex-direction: column;
    align-items: start;
    padding: 8px 0;
    /* 中略: ボーダー設定など */
  }

  .card__title {
+   width: stretch;
    margin: 0;
    padding: 0 16px;
  }

  /* 以下、
     .card__description, .card__footer 
     も同様… */

実際に、問題はこれで解決します。そう、表面的には……

align-items: start を設定してしまったほうも、スタイルが意図通りに戻った。

問題点: 子が親のことを知りすぎている

しかし、これを「OK のコード」と比較することによって、問題点が見えてきます。

  .card {
    display: flex;
    flex-direction: column;
+   align-items: start;    
    padding: 8px 0;
    /* 中略: ボーダー設定など */
  }

  .card__title {
+   width: stretch;
    margin: 0;
    padding: 0 16px;
  }

  .card__description {
+   width: stretch;
    margin: 0;
    padding: 0 16px;
  }

  .card__footer {
+   width: stretch;
    display: flex;
    padding: 0 16px;

    &[data-align="end"] {
      justify-content: end;
    }
  }

  .card__button {
    appearance: none;
    border: none;
    /* 詳細は省略 */
  }

そうです。親(.card)が余計な設定を追加したことによって、子側で余計な記述が必要になっています。

純粋にコードの量が増えています。「こちらが減って、あちらが増えた」というトレードオフさえありません。

このように「根本的な問題を解決せず、末端のワークアラウンドで何とかする」「子が親のことを知る必要がある」のがマズい状況だということは、プログラミング一般の知識として共有されていますが、CSS でのスタイリングについても同様です。

特に、React で開発していて、以下のように組み合わせて使用するコンポーネント群(Compound Component パターン)を実装したい場合には、コンポーネント実装コードの理解しづらさにつながり、メンテナンスが困難になります。

Card.Root>
  Card.Title>カード #1Card.Title>
  Card.Description>
    春はあけぼの、やうやう白くなりゆく山際
  Card.Description>
  Card.Footer align="end">
    Card.Button color="danger">削除Card.Button>
    Card.Button>編集Card.Button>
  Card.Footer>
Card.Root>  

ちなみに、align-items が初期値(= stretch)の Flexbox の、子要素たちの横幅を制御する挙動は、Flexbox ではなく単なる display: block のときと同様です。

実は、今回のコード例では Flexbox の機能を全く活用していないので、 display: block にしても全く問題ありません。たとえば「カードを3カラムで並べて表示するので、 .card__descriptionflex-grow: 1 による高さ調整が必要で、 Flexbox を使った」といったテイでご容赦ください。

まとめ: じゃあいつ width: stretch が必要なのか?。

この記事では、width: stretch に飛びつく前に知っておくべきこととして、「親の Flexbox を注意深く書けば(初期値だと案外うまくくいきがち)、そもそも width: stretch を使うまでもない」ということを提示しました。

ちなみに、CSS Grid や、通常の display: block についても同様です。

特に、CSS Grid は、親子の役割分担の明確化という点では、Flexbox よりもかなり有効なので、CSS Grid を第一の選択肢として、Flexbox はその次と捉えるのが良いと思います。(この記事で Flexbox を使ったのは、単に説明のしやすさのためです。)

width: stretch が必要になるケースは、下記の記事にうまくまとまっています。





Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -