· 4分で読了

高さを揃えるレイアウトの解決策

この記事は中国語から自動翻訳されたものです。翻訳によりニュアンスが失われている場合があります。

フロントエンドのページ制作において、要素の高さを揃えるレイアウトに遭遇することはよくある。最も直感的な方法は、コンテナ内のすべての要素を floatinline-block に設定することだ。

float と inline-block

float でレイアウトを組む場合、親要素のコンテナを押し広げる(clearfix)必要があるだけでなく、子要素に対しても margin を設定しなければならない。 そのため、コンテンツが多すぎたり、高さが足りなかったりすると、すぐにレイアウト崩れが起きてしまう。

さらに、このようなレイアウトの最大の欠点は、高さを設定しなければならないことだ。

では、高さを設定しなければどうなるか? たとえ min-height を設定したとしても同じで、コンテンツが高さを超えてしまった場合、必ず overflow の危機に直面することになる。

その後、CSS の media query を使って画面幅ごとに異なる高さを指定することにした。 この解決策は面倒だし、少し不格好ではあるが、画面幅が狭くなったときにレイアウトが崩れる問題は確かに解決できた。

この問題はずっと僕の心の奥底にくすぶっていたが、最近になって flex の奥深さに気づいた。

レイアウトに困ったら、まずは flex を考えてみる

人生で挫折したときは、flex のことを思い出そう。このフレキシブルボックスは、しばしば僕たちを救ってくれる。 flex はすでに主要なブラウザのほとんどでサポートされており、本当に使い勝手がいい!

displayflex に設定した際、子要素に高さを指定していなければ、子要素の高さはその中で最も高いものに揃えられる。

たった1行のプロパティで、僕がずっと悩んでいた問題を解決してくれた。実にエレガントな flex だ。

しかしそれだけでなく、レイアウトに少し調整を加える必要がある。flex はデフォルトで flex-wrap プロパティが設定されていない場合、1行で表示しようとして親コンテナを突き破ってしまう。 そのため、もう1行追加することができる。

.wrap {
  flex-wrap: wrap;
}

これで、height を宣言することなく、高さを揃えたレスポンシブレイアウトの完成だ。おおよその CSS はこんな感じになる:

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}

.card {
  height: auto;
  width: 30%;
  border: 1px solid #aaa;
}

flex をサポートしていないブラウザはどうする?

まず大前提として、flex はすでに大半の主要ブラウザでサポートされている。「対応状況」を言い訳にして、こんなにも便利な flex を敬遠するべきではない。 それでもブラウザが本当にサポートしていない場合は、JavaScript でレイアウトを組む方法がある。基本的な原理は高さを設定せず、container 内の全要素を検知して最も高い要素を見つけ出し、その高さを各要素に適用するというものだ。

ごく基本的なサンプルコードを書いてみた:

var cards = document.querySelectorAll(".card")

function getMaxinumHeight(elements) {
  var nums = []

  elements.forEach(function(value) {
    nums.push(value.offsetHeight)
  })

  return nums.sort(function(a, b) {
    return a < b
  })[0]
}

var maxHeight = getMaxinumHeight(cards)
cards.forEach(value => {
  value.style.height = maxHeight + "px"
})

Table is new sexy

古めかしい table レイアウトは今や敬遠されがちだが、等高レイアウトのような場面で、不運にも flex が使えない場合は table の特性を利用して高さを揃えることができる。

table レイアウトを実装するには、display: tabledisplay: table-rowdisplay: table-cell を使えばよい。

display: table<table> に相当し、display: table-row<tr>display: table-cell<td> に相当する。

だが、等高の効果は得られるものの、HTML のマークアップはより複雑になってしまう。さらに table の利用には制約もあり、例えば table の内部では margin が効かないなど、モックアップを実装する上で大きな障害となる。だから、flex が使える状況であれば、できるだけ flex を使うのがおすすめだ!

関連記事

Flexbox responsive equal height

関連記事

他のトピックを探索