21
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

こんな使い方が!? 意外と知らないCSS Flexboxの応用

Posted at

今や横並びの標準といえばFlexboxという時代ですが、そんなFlexboxでも意外と知られてないであろう使い方をご紹介します。
記述量を減らしたり、動的なサイトで重宝したり、リキッドレイアウトにも対応できちゃいます。
IEを含め主要ブラウザに対応してます。

#1. 一つが固定幅もう一つが残りの幅いっぱいの横並びボタン
スクリーンショット 2018-05-18 3.36.04.png
こんな感じのものを一度の横幅指定だけで作る

html

<ul class="list">
  <li class="item-short"><a href="">リスト1</a></li>
  <li><a href="">リスト2</a></li>
</ul>

固定幅にしたい方に固有のclassを与えてやりましょう。
##css

.list {
  display: flex;
}

.list li {
  border: 1px solid #ccc;
  flex: 1 0 0%;
  box-sizing: border-box;
  text-align: center;
}

.list li a {
  display: block;
  padding: .5em;
}

.list li.item-short {
  width: 30%;

  /* flexで書き換えるとこうなる */
  flex: 0 0 30%;
 /* ただし、IEでは11でもこの指定は効かないことがあるためmax-widthとセット */
  max-width: 30%;
}

.list li:not(:last-child) {
  margin-right: 3%;
}

ポイントはliにあたっているプロパティflexです。
ご存知の方は多いかと思いますがこれはflex-grow, flex-shrink, flex-basisのショートハンドで、今回関わってくるのはflex-growflex-basisです。
flex-growはflexアイテムの横幅を計算してflexコンテナに対して余白がある場合その余白を埋めるかどうかの指定です。
初期値は0で整数値を指定するとその比率で余ったスペースを指定されたflexアイテムで配分するというものです。
flex-basisは横幅の指定です。widthと同じです。初期値はautoです。
でもflex: 1 0 0%;っておかしくない?flex: 1 0 auto;ではダメなの?
と思った方、当然です。
これもまたIEのバグ対策です。
autoだと値が正常に計算されないのでここは数値で指定する必要があります。
ただこの数値、本当に何でも良いです(笑)
0%でも100%でも変わらないので好きな数値を指定してください。
数値が指定されていることが重要みたいです。

まとめると、flexコンテナの30%をli.item-shortが占めて、残りの70%からmarginを引いた分が、classの付いていないliの横幅になるというレイアウトです。
値の指定が一つだけで良いので計算も楽になるかと思います。

flexプロパティについて詳しくは仕様書

#2. 要素数が可変な横並びのボタンを均等幅に

スクリーンショット 2018-05-18 3.10.40.png

Flexboxを使えば一行あたりのflexアイテムの数ごとにclassを用意せずとも、flexアイテムの数に関わらず均等幅になるレイアウトが可能です。
##html

<ul class="flex-list">
  <li><a href="">リスト1</a></li>
  <li><a href="">リスト2</a></li>
  <li><a href="">リスト3</a></li>
</ul>

はい、普通のリストです。

##CSS

.flex-list {
  display: flex;
}

.flex-list li {
  flex: 1 0 0%;
  border: 1px solid #ccc;
  text-align: center;
  box-sizing: border-box;
}

.flex-list li:not(:last-child) {
  margin-right: 1%;
}

.flex-list li a {
  display: block;
  padding: .5em;
}

flexプロパティ、また出ましたね。
今回は上の応用的な考え方です。
flexアイテムの全てのflex-growを1にして比率を均等にすることでli内にどれだけテキストが入ろうが、 またliがいくつになろうがそれぞれ均等幅にすることが可能です。
コードもこれだけすっきりします。

#3. さらに横並びのボタンの一部だけテキストが複数行になった場合に縦中央揃え
こんなレイアウト
スクリーンショット 2018-05-18 5.01.48.png
特に動的なサイトの場合、line-heighthegihtを固定にできないため今まではjsのプラグインで解決している方が多かったかと思いますがFlexboxを使えばjsも要りません。
##html

<ul class="flex-list">
  <li><a href="">リスト1</a></li>
  <li><a href="">リスト2<br>リスト2リスト2</a></li>
  <li><a href="">リスト3</a></li>
</ul>

##css

.flex-list {
  display: flex;
}

.flex-list li {
  flex: 1 0 0%;
  border: 1px solid #ccc;
  text-align: center;
  box-sizing: border-box;
}

.flex-list li:not(:last-child) {
  margin-right: 1%;
}

.flex-list li a {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  box-sizing: border-box;
  padding: .5em;
}

基本的にheightの%指定はその親要素の値が未指定、もしくは%指定だと効きませんでしたが、a自体をflexコンテナにしてしまえばheight: 100%;が効くようになります。
そしてalign-items: center;で縦の中央寄せを指定しています。

#まとめ
いかがでしたか?
少しでも皆さんのコーディングライフの助けになれば幸いです。
まだまだ奥が深そうなFlexbox。
もっと不思議な使い方もあるかもしれないので今後も色々試していきたいと思います。
また、既にそういったのをご存知の方がいれば是非教えてください。

21
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?