見出し画像

CSSレイアウトパターン(3)(4)左右の一方が固定、一方が可変

これだけは身に付けてほしい、6つのCSSレイアウトパターン」の詳細解説です。
3つ目(上揃え)と4つ目(上下中央揃え)は、利用シーンや注意点が異なりますが、CSSの書き方はほとんど変わらないのでまとめて解説します。

このパターンには2通りの作成方法があるのですが、この記事では初級・中級のウェブ制作者が比較的理解しやすい、flexboxを使用する方をご紹介します。

はじめての方はお読みください↓↓

サンプル

実際にブラウザで見られるサンプルはこちらです。

上揃え

上下中央揃え

基本的な挙動

特に指示がなかったり、おまかせ or 自分がデザイナーであれば、以下のような挙動が基本です。画像とテキストの左右二段組みに使用されることが圧倒的に多いです。

  • 基本的にどのウィンドウサイズでも見た目は変わらない

  • モバイル端末(640px未満、768px未満)では画面に収まらない場合のみ、段組を解除して上下に分ける

  • 左右二段組の、片側(画像が入っている方)の幅を固定する

  • 左右二段組の、もう一方を100% - 画像の幅で埋める

このパターンが使用されるパーツ

このパターンのレイアウトは、サイト内に大小さまざまな形で使用されています。「テキストの量が少ない場合は上下中央揃え、多い場合は上揃え」がセオリーとなっています。

写真とテキストが左右に並んでいるメニューの場合は、テキストは上下中央揃えとなります。
ナビゲーションが画面の端に帯のように配置されたレイアウト枠の場合は、上揃えとなります。

Googleマップで店舗を検索したときのプレイス情報の外枠も、情報量が多いのでCSSは複雑ですが、この記事と同じ仕組みで作成されています。

なぜ片側を固定するのか

初学者向けの教本では、左右どちらの幅も「割合=%」となっているか、すべて同じ幅となっているパターンの解説が多いです。WordPressで段組を作成する「カラム」ブロックも%が前提です。
ですが、このシリーズは左右の一方を固定するパターンを、学習の優先度が高いとしました。

「端末によって画面幅が変わるのに、なぜわざわざ固定しなければならないのだろう?」と気になるかもしれません。これは、画面幅が変わったときの画像とテキストの挙動が違うためです。

特別なことをしていない限り、画像はウィンドウサイズが変わると、縦横比を保ったまま伸縮します。つまり、モバイル端末などの狭い画面だと幅も高さも少なくなり、広い画面だと幅も高さも多くなります。

一方テキストは、特別なことをしていない限り、空いている部分を埋めるように流し込まれていきます。つまり、モバイル端末などの狭い画面だと一行に収まる文字数が少ない=行数が多くなり、広い画面だと一行に収まる文字数が多い=行数が少なくなります。

このため、両方とも%で幅を指定していると、幅が広いウィンドウで表示したときに、画像とテキストのバランスが悪くなってしまうことになります。

デザインを重視しているサイトでは避けたい現象なので、無難な落とし所として、画像が入っている方の幅を固定する(または、幅に上限を設けて大きくなりすぎないようにする)という手法がよく使われています。

「特別なことをしていない限り」という言葉が二回出てきました。そうです。最近はもっと違う、デザイナーが喜ぶ方法もあります。上級向けとして、またいずれ解説したいと思います。

HTML

全体を任意のクラス名を付けた要素で囲み、さらに中に2つの要素を書きます。画像が入る方は「そのパーツの英語名__image」、テキストが入る方は「そのパーツの英語名__contents」というクラス名とします。

多くの制作会社が採用しているBEM記法だと、以下の通りになります。このサンプルでは画像が「テキストを説明する図版」であるとして、figure要素で囲んでいますが、div要素でも大きな問題はありません。

<div class="sample">
    <figure class="sample__image">
        <!-- ここに画像が入る -->
    </figure>
    <div class="sample__contents">
        <!-- ここにテキストが入る -->
    </div>
</div><!-- /.sample -->

WordPressの公式テーマやブロックで使用されているSMACSS記法だと、ハイフン区切りなので以下の通りになります。

<div class="sample">
    <figure class="sample-image">
        <!-- ここに画像が入る -->
    </figure>
    <div class="sample-contents">
        <!-- ここにテキストが入る -->
    </div>
</div><!-- /.sample -->

なお、この記事では都合上、パーツのクラス名を「.sample」としていますが、この手のレイアウトはサイト内で頻繁に使用するので「.media」「.summary」のような、使い回しがきく名前にすることが多いです。

CSS

まず、パーツ全体を囲んでいる要素に display: flex を指定して、flexboxによるレイアウトを有効にします。
この時点で、その要素のすぐ下(子要素)がすべて、横に整列します。これはflexboxの初期状態なので、プロパティを追加して変えていきます。

.sample {
    display: flex;
}

画像とテキストがくっついてしまうのは困るので、 gap プロパティで余白を指定します。
gap は値が1個だけだと「全方向」、2個書くと「上下、左右」となります。なのでこの例では「0 30px」としました。

.sample {
    display: flex;
    gap: 0 30px;
}

続いて、上下中央揃えにしたい場合のみ、 align-items: center を指定します。これは、flexboxで配置している子要素すべてに反映されます。
上揃えの場合はこの指定は必要ありません。

.sample {
    display: flex;
    gap: 0 30px;
    align-items: center;
}
  • align-items の初期値が上(flex-start)ではないブラウザがあるかもしれませんが、マニアックなブラウザには対応しない、で構いません

  • 厳密には align-items は「上下」ではありません。これをよくわかっていないとハマることがあるので、またいずれ解説します

子要素の基本動作

次に、子要素の基本的な挙動を指定します。セレクタを「.sample > *」とすると「.sample の直下の要素すべて」となります。直下、ですから孫には影響しません。

.sample > * {
    flex: 1;
}

「flex: 1」は以下の略記(ショートハンド)です。画像の大きさやテキストの量に関係なく、可能な限り幅を伸ばすようになります。

flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;

固定している側

次に、幅を固定したい側のスタイルを追加します。可能な限り幅を伸ばすようになっているので、 max-width で幅を指定すると、その幅で止まる=固定されることになります。

.sample__image {
    max-width: 100px;
}

flex-basis で幅を指定する方法もありますが割愛します。詳しくは後述します。

残りを埋める側

テキストが入る側は、幅などの指定は特に必要ありません。

TIPS

手順としてはここで終わりなのですが、より即戦力に近付くためのTIPSを2つ解説します。

テキストのはみ出しを回避する

実は、この時点では右側に長いURLが入ると崩れます。ブログの新着などで公開の半年後くらいに起きる事故です。忘れた頃の問い合わせは地獄みがあります。

これは、英数字=英語と日本語の改行ルールが異なるために起きる現象です。英語は単語の途中で改行されると読めないので、単語単位で改行する仕様が初期値となっいます。このため、区切りがないURLを入れると、どこまでも改行されずに崩れてしまうのです。
word-break: break-all; を指定しておくと、幅の限界に来たときに改行するようになります。

.sample__contents {
    word-break: break-all;
}

上を完璧に揃える

上揃えにしたとき「画像の上の辺とテキストの上端が揃わない」という問題が起きます。これはCSSの仕様上、テキストに行高さがあると、文字の上下に行高さの半分の余白が設けられるためです。

例えば文字サイズが16px、行間が1.5であれば、4pxずれます。

大抵の画像加工ソフトは行間のズレを考慮しないので、カンプの方は上端がきっちり揃っていて、悩むことになります。

大抵は、デザイナーさんはそこまでこだわっていません。悩んだときは、まず相談してください。「あーちょっとくらいズレても大丈夫ですよ!」とお返事が来ます。

…が、これは解決方法があります。CSSで計算結果を表示する関数 calc() を使って、以下の通り margin-top で上にずらすと、ぴったり揃います。marginが使えない場合は transform: translateY や position: relative でも構いません。

calc( ( ( 行間 - 1 ) / -2 ) * 1em )

行間が1.75だったら以下となります。

.sample__contents {
    line-height: 1.75;
    margin-top: calc( ( ( 1.75 - 1 ) / -2 ) * 1em );
}

中級向け:flex-basis を割愛した理由

勉強中の方はこの項は読み飛ばしてください。

この記事では、flex-basis プロパティを常に「0%」として解説しました。
flexboxとしては flex-basis プロパティで定義するのが本来の仕様で、こちらを解説しているテキストも多いのですが、本記事では max-width にしました。

.sample__image {
    flex-grow: 0;
    flex-basis: 100px;
}

flex-basisは「幅」ではなく「要素の主要部分の初期の寸法」という高度な概念で算出されており、内容の量や幅によって柔軟に変わります。このため「指定した通りの幅にならない」というハマりが起きることがあり、扱いが難しいです。

flexbox は flex-grow, flex-basis をコントロールすることで「横4段組のボックスのひとつが後で不要になり削除、3段組に変更」などにも柔軟に対応できるのが強みです。

WordPressなどのCMSで管理されている、内容がどう変わるかわからないサイトではこの強みを活かせますが、幅をしっかり固定した方が想定外の崩れが出にくくハマりや手戻りが少ない、というのがウェブ制作の現実です。

まとめ

左右の一方が固定、一方が可変のパターンの解説は以上です。とにかく出番が多いのですが、その割に理解・習得が難しいです。
最初に書いたとおり、flexboxを使用する方法とCSS Gridを使用する方法の二通りがあったり、flexboxの仕様説明を最低限に絞らなければならなかったので、まとめるのに数日かかってしまいました…

CSS Gridを使用する方法は上級向けですが、内容が複雑になっても崩れにくく、ポータルサイトなどで力を発揮します。こちらの解説は番外編としてまたいずれ。

今回はここまで。
このブログが、皆さんに必要なくなることを願っています。

この記事が気に入ったらサポートをしてみませんか?