flexboxをなんとなく使っているけど、想定してる見た目に実装されない…
そんなお悩みありませんか?
FlexBoxには要素の性質を指定するプロパティが存在するのですが、正しく理解して指定しないと意図しない見た目になってしまいます。
この記事では、FlexBoxの子要素であるflexプロパティについて解説していきます!
プロパティをきちんと理解して、デザイン通りの実装ができるように頑張りましょう!!
なお、記事内に載せたCSSはFlexBoxと関係のない部分(背景色など)は省略してますので悪しからず。
FlexBoxの全体を把握したい方は、使用プロパティを網羅的に解説したこちらの記事から先にご覧ください!
flexプロパティとは?
flexアイテムの幅を指定するプロパティで、flex-grow, flex-shrink, flex-basisをまとめて指定するショートハンドです。
まずは-grow, -shrink, -basisの3つのプロパティを説明した上で、flexプロパティでの指定方法を解説します。
ちなみにflexアイテムとは、display: flex(もしくはinline-flex);で指定した要素の子要素のことで、親要素をflexコンテナといいます。
flex-grow(伸長)
flexアイテムの伸び率を指定するプロパティ。
正の整数(初期値:0)
flexコンテナに空白がある場合、指定した比率に基づいて空白部分をflexアイテムの幅に振り分けてくれます。
使用例
<div class="flex-grow">
<p>flex-grow指定なし</p>
<div class="flex-container">
<div class="flex-item">item1</div>
<div class="flex-item">item2</div>
<div class="flex-item">item3</div>
</div>
</div>
<div class="flex-grow">
<p>flex-grow指定あり</p>
<div class="flex-container">
<div class="flex-item item1">item1</div>
<div class="flex-item item2">item2</div>
<div class="flex-item item3">item3</div>
</div>
</div>
.flex-container {
display: flex;
}
.item1 {
flex-grow: 0;
}
.item2 {
flex-grow: 1;
}
.item3 {
flex-grow: 2;
}
item2とitem3にそれぞれflex-shrink:1と2を指定しました。
このとき空白部分が1:2の割合で各アイテムに振り分けられた…ということになります。
flex-shrink(圧縮)
flexアイテムの圧縮率を指定するプロパティ。
正の整数(初期値:1)
flexコンテナにflexアイテムが入りきらない場合に、指定された数値に基づいてアイテムの幅を縮めコンテナに納めます。
flex-growの反対ですね。
使用例
<div class="flex-shrink">
<p>flex-shrink指定あり① flex-shrink=0:0:0</p>
<div class="flex-container">
<div class="flex-item item1-1">item1</div>
<div class="flex-item item2-1">item2</div>
<div class="flex-item item3-1">item3</div>
</div>
</div>
<div class="flex-shrink">
<p>flex-shrink指定あり② flex-shrink=0:1:2</p>
<div class="flex-container">
<div class="flex-item item1-2">item1</div>
<div class="flex-item item2-2">item2</div>
<div class="flex-item item3-2">item3</div>
</div>
</div>
.flex-container {
display: flex;
width: 900px;
}
.flex-item {
width: 350px;
}
.item1-1, .item2-1, .item3-1 {
flex-shrink: 0;
}
.item1-2 {
flex-shrink: 0;
}
.item2-2 {
flex-shrink: 1;
}
.item3-2 {
flex-shrink: 2;
}
アイテム×3の幅は、コンテナ幅より大きく設定しました。
画像は、全てのアイテムをflex-shrink: 0 としたとき(指定あり①)と、それぞれ個別に設定したとき(指定あり②)を並べています。
上の指定あり①は、どのアイテムも圧縮させないでね!という指示になるので、コンテナ(薄グレー背景)からはみ出してますね。
指定あり②では、item1~3を0:1:2と指定したので、コンテナからはみ出た分が1:2で分割され、item2と3の圧縮分に割り当てられています。
flex-basis(長さ)
アイテムの基本の幅を指定します。
・auto(初期値)
・数値+単位(pxなど)
・%値
基本的にはwidthと同じ扱いでOKですが、アイテムが横並び(row)の場合の話。
縦並び(column)のとき、flex-basisはheightの役割を担うことになります。
また、width(もしくはheight)とflex-basisが同じ要素に同時に指定されている場合は、flex-basisが優先されるので注意しましょう。
使用例
<div class="flex-basis">
<p>flex-basis</p>
<div class="flex-container">
<div class="flex-item item1">item1</div>
<div class="flex-item item2">item2</div>
<div class="flex-item item3">item3</div>
</div>
</div>
.flex-container {
display: flex;
}
.item1 {
flex-basis: 50%;
}
.item2 {
flex-basis: auto;
}
.item3 {
flex-basis: 0px;
}
item1は親要素(フレックスコンテナ)の50%、item2はautoでコンテンツ要素(テキスト長さ)に依存、item3は0pxなのでこちらもコンテンツ要素に依存する長さになります。
flexプロパティでまとめて指定
上記で紹介した3つのプロパティをまとめて指定できます。
・-grow -shrink -basis の順に半角スペース区切りで指定
・initial → 0 1 auto
・auto → 1 1 auto
・none → 0 0 auto
もっとも一般的な使用方法としてflex: 1がありますが、これはflex: 1 1 0 を省略したものになります。
使用例
<div class="flex-basis">
<p>flex</p>
<div class="flex-container">
<div class="flex-item item1">item1</div>
<div class="flex-item item2">item2</div>
<div class="flex-item item3">item3</div>
</div>
</div>
.flex-container {
display: flex;
width: 900px;
}
.item1 {
flex: none;
/*
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
*/
}
.item2 {
flex: 0 1 200px;
/*
flex-grow: 0;
flex-shrink: 1;
flex-basis: 200px;
*/
}
.item3 {
flex: 1 0 0;
/*
flex-grow: 1;
flex-shrink: 0;
flex-basis: 0;
*/
}
item1で指定したnone = 0 0 auto は、伸び縮みなくコンテンツ(上だとテキスト幅)に応じた幅になります。
item2は-shrink(圧縮)を1としましたが、コンテナ幅(900px)を超える他アイテムが無いため、そのまま-basisの200pxが反映されています。
item3は-basisが0ですが、-growが効いてコンテナ幅いっぱいに広がっていますね。
最初のうちは慣れないかもしれませんが、色々と試してみてください!
flexプロパティ関連のバグと対策
ここからは、flexプロパティを使用するときに発生しがちなバグと対策方法をご紹介します。
全てInternet Explorerのバージョン10,11で確認されているバグです。
(IE)ショートハンドだとflex-grow値が効かない
<div class="flex">
<p>flex</p>
<div class="flex-container">
<div class="flex-item">item1</div>
<div class="flex-item">item2</div>
<div class="flex-item">item3</div>
</div>
</div>
.flex-container {
display: flex;
}
.flex-item {
flex: 1 0 0;
}
flex-basis値が0のときに、flex-growの値が無視されコンテナ幅いっぱいまでアイテム幅が伸びない事例です。
縦並び(flex-direction: column; )でも発生するバグで、この場合は高さが潰れます。
解消するにはflex-basisに単位を付ければOK。
.flex-container {
display: flex;
}
.flex-item {
flex: 1 0 0%;
}
0pxだとCSS圧縮時に削除されてしまう恐れがあるため、0%と記載するのがおすすめです。
(IE)ショートハンドだとflex-basis値をcalcで指定できない
<div class="flex">
<p>flex</p>
<div class="flex-container">
<div class="flex-item">item1</div>
<div class="flex-item">item2</div>
<div class="flex-item">item3</div>
</div>
</div>
.flex-container {
display: flex;
width: 900px;
}
.flex-item {
flex: 0 0 calc(100px * 2);
}
こちらはflexプロパティのショートハンドで、-basisにcalcを使用すると値が反映されない事例です。
.flex-container {
display: flex;
width: 900px;
}
.flex-item {
flex: 0 0;
flex-basis: calc(100px * 2);
}
解消させるにはflex-basisだけ別で指定すればOKです。
まとめ
今回flexプロパティについてご紹介しました。
理解するのに少々難しい部分もあるかもしれませんが、flexboxを扱うのに避けて通れない道です。
ぜひ理解を深めて、flexboxを使いこなせるようにしましょう!