【CSS】Flexboxを使って実用的なレイアウトを実装

Webサイト制作
サイト制作
2020.07.16

みなさんは横並びのレイアウトのスタイルはどう書かれていますか?
float、display:inline-block、display:table-cell、そしてdisplay:flexと、シーンに合わせて使い分けていますか?
今回はfloatに代わる横並びスタイルの記述方法として注目され、その利便性が定着しつつあるFlexboxについて実用的なレイアウトサンプルを交えて使い方を解説したいと思います。

Flexboxとは?

Flexboxは、CSS3から導入された比較的新しいレイアウトモジュールです。
項目を行方向または列方向に配置する1次元レイアウトを実現します。

正式名称は「CSS Flexible Box Layout」と言い、その名の通りフレキシブルなレイアウトが可能です。
横並びのレイアウトはもちろん、アイテムの整列や中央揃え、均等配置、アイテムの高さ調整や折り返し表示などが簡単に実装できます。

現在ではすべての主要ブラウザに対応しており、非対応のCSSプロパティが多いIEでもIE10から対応しています。

横並びのレイアウトを行う時、少し前まではfloatやdisplay:table-cellなどのプロパティを使うのが一般的でした。
それが今ではFlexboxを使って実現していくケースが多くなっています。

Flexboxの有用性

以前から横並びレイアウトに用いられてきたプロパティであるfloatやdisplayと比べると、Flexboxには次のような利点があります。

  • HTML、CSS共に記述量が少なくなる
  • スマホ時代には欠かせない「レスポンシブデザイン」との親和性が高い
  • floatよりもFlexboxのほうがパフォーマンスが良く、処理速度が高い
  • カラム幅を指定する必要がなく、自動で横並びレイアウトが可能
  • テキストにも画像にも簡単に対応できる
  • カラムの順番の入れ替えや、並び方向の変更など、カスタマイズ性が高く自由自在
  • floatを使って横並びレイアウトを行うとアイテムの高さが合わなくなることがあったが、Flexboxは自動調整できる

このように、これまでフロントエンドエンジニアが悩まされてきた問題をサクッと解消してくれるのがFlexboxです。

Flexboxは、floatやdisplayでは大変だったレイアウトを少ないコードで実現できます。
希望のレイアウトを実現するためにHTMLとCSSが煩雑になってしまう問題とはさよならです。

Flexboxはボックス単位にレイアウトが適用されるため、中身はテキストでも画像でも対応可能なため、幅広く適用することができます。
昨今、大量の画像を横並びにするInstagramのようなレイアウトが採用されるケースが多くなってきていますが、こういった場面でもFlexboxによるコーディングが便利です。

コーディングしていく上で、かゆいところにまで手が届くため、今ではfloatやdisplay:table-cellを使ったレイアウトを廃止し、Flexboxをメインとするフロントエンドエンジニアが多くなってきています。

floatにできてFlexboxにはできないこと

ここまでFlexboxの魅力を紹介してきましたが、「floatにできて、Flexboxにはできないこと」もあります。
それが「文字の回り込み」です。

floatはもともと、要素を左右どちらかに側に配置し、テキストや画像などのインライン要素がその要素の周りに回り込むことができるようにするためのプロパティでした。

floatの「回り込むことができる」という特徴を利用し、横並びレイアウト用のプロパティとして使われてきましたが、本来は画像とテキストを組み合わせた雑誌のようなレイアウトを実現するためにあるプロパティだったのです。

このfloatの本来の使い方は、Flexboxを使って再現することはできません。
Flexboxが主流になったとしても「floatでできたこと=何でもFlexboxでできる」ではないので注意しましょう。

Flexboxの基本

親要素にdisplay:flexをつけるだけです。こうすることで親要素はFlexboxコンテナーになり、 そして子要素は自動的にFlexboxアイテムになります。これが基本になります。

プロパティーについて

このFlexboxコンテナーFlexboxアイテムにはそれぞれに指定出来るいくつかのプロパティーがあります。
以下はその一例です。

分類 プロパティ 役割 挙動
Flexboxコンテナー flex-direction Flexboxのコンテナーの主軸を設定し、Flexboxアイテムがどのように並ぶかを決める。 row Flexboxアイテムが左から右へ横並びになる
row-reverse Flexboxアイテムが右から左へ横並びになる
column Flexboxアイテムが上から下へ縦並びになる
columc-reverse Flexboxアイテムが下から上へ縦並びになる
flex-wrap Flexboxコンテナ内で、アイテムを1行で表示するか、複数行で表示するかを決める。 nowrap アイテムは1行に配置。1行の幅に納まるよう、幅が自動調整される。
wrap アイテムは複数行に配置。左から右へまたは上から下への順番になる。
wrap-reverse アイテムは複数行に配置。右から左へまたは下から上への順番になる。
Flexboxアイテム order Flexboxコンテナー内に配置されるアイテムの順番を決める。

HTMLの配置順に関わらず、このプロパティで指定した順番に並ぶ。

整数(正の値、負の値または0)。

デフォルト値は0

設定値の昇順に並ぶ。

負の値で絶対値の大きいものが先、正の値で絶対値が大きいものが後。

flex-grow 指定するFlexboxアイテムが、他のアイテムと比較してどのくらいの大きさにするかを指定 数値(負の値は不可)。

デフォルト値は0。

すべてのアイテムに対して値を同じにすると、アイテムの大きさはすべて同じになる。

すべてのアイテムに1を設定し、ある1つのアイテムのみ2を設定した場合、2を設定したアイテムが他と比べて大きくなる。

align-self Flexboxアイテムの整列方法を決める。 auto 親要素の「align-items」の値から計算する
flex-start 開始位置揃え(通常、上揃え)
flex-end 終了位置揃え(通常、下揃え)
center 中央揃え
stretch Flexboxコンテナーの大きさに合わせてアイテムを引き伸ばして揃える

ほかにもプロパティーを理解するのにわかりやすいサイトもあるので、是非チェックしてみてください!

おすすめのサイト

Flexboxを使った実用的なデザインサンプル

プロパティーを割愛させていただいたところで早速サンプルを作っていきましょう。

sample1-フォトギャラリーを作る

Instagramで見慣れているような3カラム正方形のフォトギャラリーをflexboxを使って実装します。

DEMO

まずはhtmlです。

<div class="photogallery">
           <div class="photo">
            <div class="inner">
                <img src="./images/s_FH000019.JPG" alt="">
            </div>
        </div>
           <div class="photo">
               <div class="inner">
                   <img src="./images/s_FH000023.JPG" alt="">
               </div>
           </div>
           <div class="photo">
               <div class="inner">
                   <img src="./images/s_FH000024.JPG" alt="">
               </div>
           </div>
           <div class="photo">
               <div class="inner">
                   <img src="./images/s_FH000027.JPG" alt="">
               </div>
           </div>
           <div class="photo">
               <div class="inner">
                   <img src="./images/s_FH000030.JPG" alt="">
               </div>
           </div>
           <div class="photo">
               <div class="inner">
                   <img src="./images/s_FH000031.JPG" alt="">
               </div>
           </div>
           <div class="photo">
               <div class="inner">
                   <img src="./images/s_FH000032.JPG" alt="">
               </div>
           </div>
        </div>

次にcssです。親要素である.photogalleryにdisplay:flexをつけます。 そして子要素の.photoはFlexboxアイテムになります。 縦に並んでいた画像が横並びになったかと思います。

.photogallery{
            display: flex;
        }

▼関連記事

アイテムの折り返しを指定するflex-wrap

このままだと画像は1行に並列されるので、flex-wrapを使って画面内でアイテム要素を折り返すようにします。

.photogallery{
            display: flex;
            flex-wrap: wrap;
        }

これはとてもシンプルなFlexboxの使い方ですね。
今回はInstagram風という事で、下記のスタイルも合わせて実装しているのでそちらのcssも合わせてご参考ください!

  • レスポンシブ時でも縦横比を保ち3カラムのままボックス要素を拡縮させる。
  • 写真をセンターで1:1の比率にトリミング
/*sample1*/
        .photogallery{
            display: flex;
            display: -webkit-flex;
            flex-wrap: wrap;
            -webkit-flex-wrap: wrap;
        }
        .photo {
            position: relative;
            width: 31%;
            height: auto;
            margin: 1%;
            overflow: hidden;
        }
        .photo:before {
            content: "";
            display: block;
            padding-top: 100%;
        }
        .inner {
            position: absolute;
            top: 0; left: 0;
            width: 100%;
            height: 100%;
        }
        .inner img{
            position: absolute;
            top: 50%;
            left: 50%;
            -webkit-transform: translate(-50%, -50%);
            -ms-transform: translate(-50%, -50%);
            transform: translate(-50%, -50%);
            width: auto;
            height: 100%;
        }

sample2-メディアオブジェクトを作る

左に画像、右にテキストといったようなレイアウト、よく使いますよね。これもflexboxで実装するととても簡単です!

DEMO

まずはhtmlです

<div class="profile_card">
            <div class="card_photo">
                <div class="card_photo_img"><img src="./images/sample2_img1.jpg" class="hoverZoomLink"></div>
                <h1>Peco Taro</h1>
                <h2>株式会社ペコプラ</h2>
            </div>
            <div class="profile_bio">
                <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,</p>
                <ul class="profile_sociallinks">
                    <li>
                        <a target="_blank" href="https://www.facebook.com/">
                            <i class="fa fa-facebook"></i>
                        </a>
                    </li>
                    <li>
                        <a target="_blank" href="https://twitter.com/">
                            <i class="fa fa-twitter"></i>
                        </a>
                    </li>
                    <li>
                        <a target="_blank" href="#">
                            <i class="fa fa-google-plus"></i>
                        </a>
                    </li>
                    <li>
                        <a target="_blank" href="#">
                            <i class="fa fa-instagram"></i>
                        </a>
                    </li>
                </ul>
            </div>
        </div>

h2の「株式会社ペコプラ」までを左側に。テキストとSNSシェアボタンは右側に配置します。

.profile_card{
            display: flex;
        }

垂直方向の揃え方を指定するalign-items

次に垂直方向に中央で揃えたいので、align-itemscenterを指定。

.profile_card{
            display: flex;
            align-items: center
        }

水平方向の揃え方を指定するjustify-content

SNSシェアボタンも横並びにしたいので.profile_sociallinksにdisplay: flex;を指定します。またセンターにする為に平方向の揃え方を指定するjustify-contentcenterを指定すれば完成です。

レスポンシブ対応も簡単です!メディアクエリでブレイクポイントを指定し、flexコンテナである.profile_cardのdisplayプロパティをblockにすればOKです。

@media screen and (max-width: 700px) {
            .profile_card{
                 display: block;
            }
        }

sample3-高さの異なるメディアオブジェクトを並べる

Flexboxの便利な点の一つは高さを揃えるという事じゃないでしょうか。
sample2で作成したメディアオブジェクトをそれぞれ高さを変え、横に並べたいと思います。

DEMO

今までのマークアップ同様、親要素にdisplay: flex;を記述し横並びにします。
そうすると高さの異なる3つの子要素が同じ高さになって横並びになると思います。これはsample2でも出てきたalign-itemsがデフォルトの状態であるstretchだからです。

ここで子要素内のSNSシェアボタンを下揃えにしたい!なんていうのも簡単です。
各子要素内でSNSボタンとそれ以外の要素を分けて、flex-direction: column;(縦配置なので見た目はそのまま)。
主軸に対して端揃えになるjustify-content: space-between;を指定します。ここでは端揃え=上下揃えです。
今までposition: absolute;なんかで無理やり位置を指定していたmoreボタンやなんかにもガンガン使えますね!

SNSシェアボタンの作成方法については下記の記事で解説しています。

sample4-価格表示のグリッドデザインを作る

レスポンシブ時には要素の順番を入れ替えたい!なんていう事を叶えてくれるのもFlexboxの魅力のひとつです!
下記のような料金表を実装していきましょう。

DEMO

まずはhtmlです。

<ul class="pricecards">
               <li class="pricecard free">
                   <h3>Free</h3>
                   <h4>0</h4>
                   <div>yen/月</div>
                   <p>freeプランのテキストが入ります。freeプランのテキストが入ります。freeプランのテキストが入ります。</p>
                   <a href="">申し込み</a>
               </li>
               <li class="pricecard premium">
                   <h3>Premium</h3>
                   <h4>2,980</h4>
                   <div>yen/月</div>
                   <p>Premiumプランのテキストが入ります。Premiumプランのテキストが入ります。Premiumプランのテキストが入ります。</p>
                   <a href="">申し込み</a>
               </li>
               <li class="pricecard standard">
                   <h3>Standard</h3>
                   <h4>1,200</h4>
                   <div>yen/月</div>
                   <p>standardプランのテキストが入ります。standardプランのテキストが入ります。standardプランのテキストが入ります。</p>
                   <a href="">申し込み</a>
               </li>
           </ul>

そして例の如く包括しているulタグに.pricecardsを付けてdisplay: flex;を指定します。 flexアイテムである.pricecardには下記のようにflex-basisで33%の幅を設定。ここではまとめてflexで記述します。
またPremiumプランを目立たせたいのでpaddingで高さを出し、align-items:にcenterを指定して上下中央揃えにする事で、他のプランより大きく見えるようにしました。

.pricecards{
            display: flex;
            display: -webkit-flex;
            flex-wrap: wrap;
            -webkit-flex-wrap: wrap;
            align-items: center;
            -webkit-align-items: center;
            justify-content: center;
            -webkit-justify-content: center;
        }
        .pricecard{
            flex: 0 0 33%;
            text-align: center;
            border: 1px solid #eee;
            padding-bottom: 1rem;
            box-sizing: border-box;

        }
        .pricecard h3{
            background: #a2bc10;
            color: #fff;
            padding: 10px;
            margin: 0;
        }
        .pricecard.premium{
            border: 3px solid #06c7ea;
            padding-bottom: 3rem
        }
        .pricecard.premium h3{
            background: #06c7ea;
            color: #fff;
            padding: 10px;
            margin: 0;
        }
        .pricecard h4{
            font-size: 300%;
            margin: 0 auto;
            padding: 1rem 0 0;
        }
        .pricecard.premium h4 {
            padding: 20px;
        }
        .pricecard p{
            margin: 0;
            padding: 1rem;
            text-align: left;
        }
        .pricecard a{
            padding: 10px 40px;
            background: #fb5859;
            color: #fff;
            text-decoration: none;
            border-radius: 3px;
            display: inline-block;
        }

レスポンシブは親要素のflex-directionwcolumnにして縦並びにすれば一発なのですが、
一押しプランの「Premiun」をスマホ閲覧時は上から価格順に表示させたいといった場合があります。
こんな時はorderプロパティが便利!順番が入れ替えられます。

@media screen and (max-width: 700px) {
.pricecards{
flex-direction: column;
}
.pricecard.premium{
order: 1;}
}

まとめ

いかがでしたか?Flexboxについて実用的なレイアウトサンプルをいくつか作成していきました。
今まで地味に苦労していた横並び要素の高さを揃えるだとか、上下左右センター揃えといったマークアップが、Flexboxでは簡単に実装できます!
わたし自身は大まかなレイアウトなどには未だにfloatを使っていたりするのですが、モバイルフレンドリーな時代のサイトをよりフレキシブルにマークアップしていけるよう、さらにFlexbox使いこなしていきたいと思います!

モバイルフレンドリーについては下記の記事でも解説しています。

SEOやWEB制作に関する情報を検索する

コラム

最新コラム

人気コラム

過去の記事

ご質問やご相談などお気軽にお問い合わせください。