CSS
2023.02.01(更新)
コード量激減!ブレイクポイントなしでレスポンシブ対応してみた【メリットしかない!】
レスポンシブ対応のブレイクポイントがややこしくて大変…。
今回はこんなお悩みに答えていきます。
本記事の内容
- ブレイクポイントなしでレスポンシブデザインを実装する方法
本記事を対象とする方
- フロントエンドエンジニアを目指す方
- Webデザイナーを目指す方
この記事を書いている僕はプログラミング歴2年5ヶ月です。webエンジニアとして”社内転職”に成功しました。
レスポンシブデザインとは?
まずは簡単にレスポンシブデザインの説明をします。
Webページのレイアウトにおいて、「ビューポート」を意識したカラムレイアウトは非常に重要です。スマホの時の見え方、タブレットの時の見え方、PCの時の見え方。それぞれのスクリーン幅が異なる中で、メインコンテンツを極力見やすくしてUXを高めないと、ユーザーがWebページを離れる割合が高くなってしまいます。SEOを意識して優良なコンテンツを作り上げたとしても、意味がなく効果もありません。幸いなことに現在のCSS3にはメディアクエリという、言わば条件分岐が用意されていて、「ビューポート」の幅に応じて最適なカラムレイアウトデザインを設計することができます。これをレスポンシブデザインと言います。
メディアクエリ(条件分岐)は、ブレイクポイントと呼ばれるレイアウトを変更する際の条件値を設定でき、例えば425px以下の時はAデザインを採用、426px以上の時はBデザインを採用という風に、柔軟にデザインを変更できる大変便利な仕様です。
一方で、CSS設計者においてはコンテンツありきの設計ではなく、「ビューポート」ありきの設計になります。ブレイクポイントが多くなればなるほど、コンテンツの内容を変更する必要があり、それはつまりコード量・工数が増えるという悩ましいものであることも事実です。メーカーによってサイズもマチマチだし、スマホやタブレットを横長で見る時はさらにややこしいです。少なくとも僕には「大変」というイメージがあり、そう感じる方も少なくないのではないでしょうか。
メディアクエリのブレイクポイントをいちいちCSSで設定しなくても、レスポンシブ対応できたらこれほど楽チンなことはありません。でもそんな方法あるのでしょうか…?
それがまたあるんです!しかもCSSのコード量はたったの28行です!次章でその実装方法を説明していきます。
実装方法
今回は2カラムレイアウトの場合で実装します。
結論から言うと次のコードを実行するだけで、ブレイクポイントなしにレスポンシブ対応が可能となります。
【HTML】
- <div class="parent">
- <article class="main-child">
- <p>
- This is the main contents.
- </p>
- </article>
- <aside class="sub-child">
- <p>This is the sub contents.</p>
- </aside>
- </div>
【CSS】
- .parent {
- display: flex;
- flex-wrap: wrap;
- gap: 1rem;
- }
- .parent .main-child {
- flex-basis: 0;
- flex-grow: 999;
- min-width: 50%;
- }
- .parent .sub-child {
- flex-basis: 15rem;
- flex-grow: 1;
- }
- @media not all and (-webkit-min-device-pixel-ratio: 0), not all and (min-resolution: 0.001dpcm) {
- @supports (-webkit-appearance: none) and (not (translate: none)) {
- .parent {
- margin-top: 1rem;
- }
- }
- }
- @media not all and (-webkit-min-device-pixel-ratio: 0), not all and (min-resolution: 0.001dpcm) {
- @supports (-webkit-appearance: none) and (not (translate: none)) {
- .parent > * + * {
- margin-left: 1rem;
- }
- }
- }
デモページは下記からご覧いただけます。
HTMLの説明は不要かと思いますが、メイン要素とサブ要素はarticle、asideでなくても構いません。ではCSSの解説をしていきます。ポイントは下記の通りです。
- main-childは親コンテナのスペースを占有させる
- main-childのmin-width: 50%;でしきい値をつける
- sub-childの幅をflex-basisで固定
- 親コンテナのgapにはSafari対策を施す
main-childは親コンテナのスペースを占有させる
- .main-child {
- flex-basis: 0;
- flex-grow: 999;
- min-width: 50%;
- }
.main-child(メインコンテンツ)のflex-growの値は非常に大きい(999)ので、親コンテナ(.parent)の利用可能なスペースの全てを占有できるようになっています。
main-childのmin-width: 50%;でしきい値をつける
ここが今回のテクニックの肝なんですが、min-width: 50%;で、main-childの幅が親コンテナの50%未満にならないようにしています。50%未満になってしまうくらい親コンテナの幅が小さくなった時は、強制的にメインコンテンツとサイドバーが縦並びになります。これが折り返しのしきい値となり、ブレイクポイントとなります。
- main-child {
- flex-basis: 0;
- flex-grow: 999;
- min-width: 50%; /* 折り返しのしきい値 */
- }
min-widthとは?
要素の最小幅を指定します
min-widthで120pxを指定した場合、その要素の幅は120px未満にはならず120px以上になり、120pxを下回ることはなくなります
sub-childの幅をflex-basisで固定
- .sub-child {
- flex-basis: 15rem;
- flex-grow: 1;
- }
.sub-childの幅の設定にはflex-basisを使い、flex-growで幅を伸張できるようにします。これは基本的にはflex-basisの幅を採用するけど、必要に応じて幅を伸ばすことができる、という意味になります。必要に応じて幅が伸びる時ってどんな時?それはmain-childとsub-childが縦並びになった時です。
flex-basisとは?
対象となる子要素の初期の幅を指定します
子要素の伸張(flex-grow)、収縮(flex-shrink)、折り返しを有効にすることにより、利用可能なスペースの中で各子要素の幅ができるだけ初期値になるように調整されます
親コンテナのgapにはSafari対策を施す
通常、サイドバーとメインコンテンツとの間には明確な隙間を入れることが多いです。それには親コンテナにgapを指定します。
- .parent {
- display: flex;
- flex-wrap: wrap;
- gap: 1rem; /* 隙間を作る */
- }
このgapは垂直方向に並んだ時でも有効になります。
ただし、このgapは古いSafariには効かないので、以下のような設定をしてあげます。
- @media not all and (-webkit-min-device-pixel-ratio: 0), not all and (min-resolution: 0.001dpcm) {
- @supports (-webkit-appearance: none) and (not (translate: none)) {
- .parent {
- margin-top: 1rem;
- }
- }
- }
- @media not all and (-webkit-min-device-pixel-ratio: 0), not all and (min-resolution: 0.001dpcm) {
- @supports (-webkit-appearance: none) and (not (translate: none)) {
- .parent > * + * {
- margin-left: 1rem;
- }
- }
- }
今回のまとめ
今回はブレイクポイントなしでサイドバーのレスポンシブ対応を実装する方法について紹介しました。最後まで読んで頂きありがとうございました。
main-childは親コンテナのスペースを占有させる
main-childにmin-width: 50%;を設定することで、レスポンシブ対応のブレイクポイントを作る
sub-childの幅をflex-basisで固定
親コンテナのgapにはSafari対策を施す