CSSのフレックスボックスを理解して自由にレイアウトを組めるようになろう
CSSにはレイアウトを自由に操ることができるフレックスボックスがあります。
フレックスボックスを利用すると、文章、画像、動画といったアイテムをレスポンシブに対応した自由に配置にできるようになるので、さっそく学んでいきましょう。
フレックスボックスの使い方
フレックスボックスを使うには、次の3ステップを行います。
- フレックスボックスを利用したい部分のHTML要素をdivタグで囲う
- そのdivタグにクラスを付与する
- そのクラスに対してdisplayプロパティでflexと指定する
下の例では、1,2,3というコンテンツの入った3つのdivタグにフレックスボックスを適用したいとします。
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
.box {
width: 100px;
height: 100px;
}
.box1 {
background: orange;
flex: 1;
}
.box2 {
background: skyblue;
}
.box3 {
background: tomato;
}
その場合、フレックスボックスを適用するには、次のステップの通りです。
- 3つのdivタグをさらにdivタグで囲う
- その囲ったdivタグにcontainerクラスを付与する
- そのcontainerクラスに対してCSSでdisplayプロパティでflexと指定する
<div class="container">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
</div>
.container {
display: flex;
}
.box {
width: 100px;
height: 100px;
}
.box1 {
background: red;
flex: 1;
}
.box2 {
background: blue;
}
.box3 {
background: green;
}
画面いっぱいにレスポンシブ対応にする方法
そして、上のボックスのどれかを画面いっぱいに伸ばしたい場合、そのクラスに対して、flex: 1;を指定してあげるだけで可能になります。
たとえば上のredだけを画面いっぱいに伸ばしたい場合、redがついているクラスに対して、flex: 1;を指定してあげます。
それではフレックスボックスの仕組みをみていきましょう。
flexboxの仕組み
上の例をそのまま使って説明してフレックスボックスの仕組みを説明していきます。
まず、containerクラスにdisplayプロパティの値をflexと指定すると、主軸と交差軸という概念がでてきます。
主軸と交差軸には次の特徴があります。
- 主軸は左から右の軸のこと
- 交差軸は上から下の軸のこと
- 主軸にそって要素が並んでいく
フレックスボックスを利用すると、marginの相殺は起きません。
フレックスボックスで使えるプロパティは以下の通りです。
たくさんありますが、フレックスボックスを利用する上で必要な知識になるので、順々に説明していきます。
フレックスボックスを操作するためのプロパティ一覧
Flex Container | Flex Item |
---|---|
flex-direction | align-self |
justify-content | order |
align-items | flex-basis |
flex-wrap | flex-grow |
align-content | flex-shrink |
flex-flow | flex |
それぞれのプロパティの意味と使い方をマスターしましょう。
まずは、Flex Container関連のプロパティを学んでいきましょう。
Flex Container関連のプロパティ
flex-directionプロパティ
flex-directionプロパティは、主軸と交差軸の方向を決めるプロパティです。
主軸の方向を左右に操作するrow
初期値はrowで左から右にアイテムが並ぶようになっています。
値にrow-reverseを指定することで右から左にアイテムを並べられるようになります。
主軸を上下に変更するcolumn
flex-directionプロパティの値をcolumnにすることで、交差軸と主軸を逆転させことができます。
つまり、主軸に沿って並べられるので、初期値では左から右にアイテムを並べていましたが、columnと指定することで、主軸が交差軸と入れ替わり、上から下に向かってアイテムが配置されるようになります。
このようにflex-directionプロパティでは、主軸にそってどう配置するかではなく、主軸と交差軸のそもそもの方向を変更できる点に注意しましょう。
column-reverseで主軸の向きを下から上に変えることができます。
flex-directionプロパティの値まとめ
- row(初期値)
- row-reverse
- column
- column-reverse
justify-contentプロパティ
justify-contentプロパティは、主軸にそってアイテムをどう揃えるかを決めることができます。
初期値のflex-startなら主軸の始点(左から右)で配置されます。左揃えのことです。幅に余裕があれば右側に空白ができます。
justify-contentプロパティの値をflex-endにすると、主軸の終点から配置されるようになります。つまり右揃えになります。幅に余裕があれば左側に空白ができます。
justify-contentプロパティの値をcenterにした場合、中央揃えになります。幅に余裕があれば両サイド均等に空白ができます。
そして、justify-contentプロパティの値をspace-betweenにした場合、アイテムの間に均等にスペースをつくることができます。
justify-contentプロパティの値まとめ
- flex-start(初期値)
- flex-end
- center
- space-between
align-itemsプロパティ
align-itemsプロパティは、交差軸にそってアイテムをどう揃えるかを決めます。
flexboxで「align」という言葉が出てきたら、それは交差軸についての操作を意味するので覚えておきましょう。
align-itemsプロパティは、交差軸に余裕がある場合にのみ有効になります。
align-itemsプロパティの値をflex-startは上揃えです。高さに余裕があれば、下に空白ができます。
align-itemsプロパティの値をflex-endにすると交差軸の終点に配置することになります。つまり下揃えです。高さに余裕があれば、上に空白ができます。
align-itemsプロパティの値をcenterにすると中央揃えになります。高さに余裕があれば、上下に均等に空白ができます。
align-itemsプロパティの値は他にもstretch,safe,baselineなどたくさんありますが、一度に把握するのは難しいため、まずは上の値を抑えて操作できるようになりましょう。詳しく知りたい場合はMDNで確認できます。
まずおさえておきべきalign-itemsプロパティの値まとめ
- flex-start
- flex-end
- center
flex-wrapプロパティ
flex-wrapプロパティは、並べたいアイテムがflex-containerの幅を超える場合、単一行に押し込むか、あるいは複数行に折り返すかを指定できます。
flex-wrapプロパティの初期値はnowrapで、それぞれの幅が縮まって単一行に押し込むことができます。フレックスコンテナーからはみ出ることもあります。
flex-wrapプロパティの値をwrapにすると、はみ出した分を折り返すことができます。折り返すことになるアイテムのスタート地点(cross-start)は、flex-directionプロパティのstartまたはbeforeと同一になります。
flex-wrapプロパティの値をwrap-reverseにすると、はみ出した分を折り返すことができるのはwrapと同じですが、交差軸が反転します。つまり下から上にアイテムを詰めていくことができます。
flex-wrapプロパティの値まとめ
- nowrap
- wrap
- wrap-reverse
flex-flowプロパティ
flex-flowプロパティを使うと、flex-directionとflex-wrapを一括で指定することができるので、合わせて知っておきましょう。
たとえば、flex-flow: row wrapという感じです。
慣れてきたら、flex-flowプロパティを使うと短く記述できて便利でしょう。
align-contentプロパティ
align-contentプロパティは交差軸に対してどう揃えるかを指定できます。
align-contentプロパティは単一行に収まっている場合やflex-wrapプロパティの値がnowrapの場合は効果を示しません。
align-contentプロパティはflex-wrapプロパティでwrapもしくはwrap-reverseが指定されているときに効果があります。
align-contentプロパティの値をflex-startにした場合、交差軸方向で上のアイテムにくっつくようにして配置されます。
align-contentプロパティの値をflex-endにした場合、交差軸方向で下のアイテムにくっつくようにして配置されます。
align-contentプロパティの値をcenterにした場合、交差軸方向で中央でアイテムがくっつくようにして配置されます。
align-contentプロパティの値をspace-betwwenにした場合、間に余った余白が入ります。
align-contentプロパティの値は他にもたくさんあるのですが、まずは基本の上の値を操作できるようになりましょう。
align-contentプロパティの値まとめ
- flex-start
- flex-end
- center
- space-between
Flex Item関連のプロパティ
つぎに、Flex Item関連のプロパティを学んでいきましょう。
Flex Item関連のプロパティは個々の要素を調整するときに使います。
align-selfプロパティ
align-selfプロパティは特定のアイテムに対して交差軸でどう揃えるかを操作できます。
align-selfプロパティの初期値はautoになっていて、align-itemsプロパティの結果を上書きする形で操作します。
align-selfプロパティの値をflex-startにすると、そのアイテムだけを通常通りの交差軸の始点、つまり上揃えになります。
align-selfプロパティの値をflex-endにすると、そのアイテムだけを交差軸の終点、つまり下揃えにすることができます。
align-selfプロパティの値をcenterにすると、そのアイテムだけを交差軸の中央、つまり中央揃えにすることができます。
align-selfプロパティの値は、他にもstretch,baseline,safeなどいろいろありますが、まずは上で紹介した値を操作できるようになりましょう。
align-selfプロパティの値まとめ
- flex-start
- flex-end
- center
orderプロパティ
orderプロパティは順番を指定することができます。
orderプロパティの初期値は0です。
例えば2のアイテムにorderプロパティの値を1と設定すると、2が最後に回ります。
逆にorderプロパティの値をマイナス1にすると、先頭にもってくることができます。
orderプロパティの値をそれぞれ1,2,3と指定すると、その順番に並べることができます。
orderプロパティの値まとめ
- 初期値は0
- 大きい数字を指定すると後の順番になる
- マイナスの数字も扱えて、先頭にもってくることができる
flex-basisプロパティ
flex-basisプロパティは、次に紹介するflex-growやflex-shrinkで使われる要素のサイズを決めるプロパティです。
box-sizingプロパティを指定していない限り、このflex-basisプロパティでボックスコンテンツのサイズを定義することができます。
まず、flex-basisプロパティはflex-directionの値と深く関わりがあります。
flex-directionプロパティの値がrowの場合、そのアイテムのflex-basisはアイテムの幅を意味することになります。
flex-directionプロパティの値がcolumnの場合、そのアイテムのflex-basisはアイテムの高さを意味することになります。
flex-basisプロパティの初期値はautoとなっています。
もしwidthが設定されていればその値になり、widthの設定がなければコンテンツの幅になります。
flex-basisプロパティの値に任意の値を指定することもできます。
たとえば、100pxと値を指定すれば、100pxの幅や高さになります。
ただし、flex-basisプロパティの値より、max-widthが指定されている場合はそちらが優先される点に注意しましょう。
flex-basisプロパティの値まとめ
- flex-direction:rowのとき、flex-basisは幅を意味する
- flex-direction:columnのとき、flex-basisは高さを意味する
- 初期値はautoはwidthの値、widthの指定がなければコンテンツ幅になる
- 任意の値を指定できる
flex-growプロパティ
flex-growプロパティはflex-contentの余白部分をどう埋めるかを決めることができます。
flex-growプロパティの初期値は、0です。つまり余白があっても伸ばすことをしない設定になっています。
flex-growプロパティを1:1:2で割り振りたい場合、下のように設定します。
余白の80pxが1:1:2で割り振られ、
それぞれ120, 120, 140pxになる。
また、一つのアイテムだけ、値を1にする方法もよく使われます。
値に1を指定したアイテムで、余白の部分を埋めることができます。
プロパティの値まとめ
- 初期値は0で余白があっても伸びない
- 1:1:2などで指定することができる
- 値に1を指定すると、そのアイテムだけで余白を埋められる
flex-shrinkプロパティ
flex-shrinkプロパティは、幅が足りないときに、どう割り振るかを決めるプロパティです。
80px足りない場合をみていきましょう。
1:1:1:1なら下のように、それぞれのアイテムから均等に幅を小さくして調整することができます。
0:0:1:1なら下のように、1を設定したそれぞれのアイテムから均等に幅を小さくして調整することができます。
値に0を設定すると、縮みません。
プロパティの値まとめ
- 1:1:1:1でそれぞれ幅を均等に縮ませて調整できる
- 0:0:1:1なら1のアイテムだけ幅を縮ませて調整できる
- 値を0にすると縮まない
flexプロパティ
flexプロパティは、flex-grow、flex-shrink、flex-basisを一括して指定できる一括指定プロパティです。
flex-grow: 1;
flex-shrink: 1;
flex-basis: 100px;
なら、
flex: 1 1 100px;
で指定することが可能です。
また、flexプロパティの値にinitialを指定すると、それぞれ初期値になります。
flexプロパティの値にautoを指定すると、1 1 autoの意味になります。
flexプロパティの値にnoneを指定すると、0 autoの意味になります。
一つの要素だけに、flexプロパティの値を1と指定することがよくあります。
その場合、flex-basisプロパティは初期値のautoではなく、0%になります。
1つの要素にflexプロパティの値を1を指定すると、 1 1 0%になります。
0%の理由は、widthを0%にしたほうが1:1:1で配分しやすくなるからです。
widthをたとえば800pxのままにした場合、余った余白分を1:1:2などで割り振ることになり、計算がややこしくなってしまいます。
まとめ
フレックスボックスを使う上で、知っておくべきプロパティを紹介しました。
下のそれぞれの使い方はわかりますか?
Flex Container | Flex Item |
---|---|
flex-direction | align-self |
justify-content | order |
align-items | flex-basis |
flex-wrap | flex-grow |
align-content | flex-shrink |
flex-flow | flex |
わからない場合、上に戻って復習してみましょう。
実際にフレックスボックスを使ってみよう
フレックスボックスを使えば、次のようなメニュー表を簡単につくることができるようになります。
HTML
<figure class="curry">
<div class="curry__hero">
<img src="ここに画像のURL">
</div>
<div class="curry__content">
<div class="curry__title">
<h1 class="curry__heading">焼きチーズカレー</h1>
<div><a href="#" class="curry__tag curry__tag--1">#カレー</a></div>
<div><a href="#" class="curry__tag curry__tag--2">#大人気</a></div>
<p class="curry__description">チーズがとろーり!たっぷりのチーズでこんがりと焼き上げた大人気スパイスカレーです。</p>
<div class="curry__details">
<p class="curry__detail"><span class="emoji">🍛</span>850 KCAL</p>
<p class="curry__detail"><span class="emoji">🧭</span>10 分</p>
<p class="curry__detail"><span class="emoji">😄</span>4.7 / 5</p>
</div>
</div>
<div class="curry__price">1,000円</div>
</figure>
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-image: linear-gradient(to bottom right, rgb(100, 236, 118), rgb(131, 159, 238));
height: 100vh;
padding: 100px;
color: #444;
display: flex;
align-items: center;
justify-content: center;
}
.curry {
max-width: 1000px;
overflow: hidden;
border-radius: 4px;
box-shadow: 0 30px 80px 10px rgba(0, 0, 0, .2);
display: flex;
}
.curry__img {
width: 100%;
display: block;
}
.curry__hero {
flex: 0 1 45%;
}
.curry__content {
background-color: #fff;
flex: 1;
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
}
.curry__price {
flex: 0 0 50px;
background-image: linear-gradient(to bottom, rgb(100, 236, 118), rgb(131, 159, 238));
writing-mode: vertical-rl;
color: white;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
}
.curry__title {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.curry__heading {
font-size: 20px;
margin-right: auto;
}
a {
text-decoration: none;
text-align: center;
}
.curry__tag {
font-size: 10px;
text-transform: uppercase;
color: #fff;
}
.curry__title a:link,
.curry__title a:visited {
display: inline-block;
font-size: 12px;
border-radius: 100px;
padding: 2px 7px;
margin-left: 7px;
}
.curry__title a:hover,
.curry__title a:active {
color: #555;
}
.curry__tag--1:hover,
.curry__tag--1:active {
background-color: rgb(44, 226, 68);
}
.curry__tag--2:hover,
.curry__tag--2:active {
background-color: rgb(91, 127, 226);
}
.curry__tag--1 {
background-color: rgb(100, 236, 118);
}
.curry__tag--2 {
background-color: rgb(131, 159, 238);
}
.curry__description {
font-size: 14px;
}
.curry__details {
display: flex;
margin-top: auto;
}
.curry__detail {
font-size: 15px;
margin-right: 20px;
display: flex;
align-items: center;
}
.emoji {
font-size: 20px;
margin-right: 3px;
}
また、flexの横並びの要素を解除したいときは、display:blockを指定することで解除できます。
たとえば、スマホ対応でmediaクエリに次のように指定します。
@media screen and (max-width: 960px) {
.curry{
display: block;
}
.curry__img {
min-width: 100%;
display: block;
}
.curry__heading {
min-width: 100%;
}
.curry__price {
min-width: 100%;
writing-mode: horizontal-tb;
font-size: 24px;
}
}