基本的にコンテンツを横並びにする場合はflexを使用して実装しますがflexではどうしても再現できないパターンがあります。
そんな時はgridで再現する方法がありますが、gridで横並びを作ると高さが画面幅に合わせて変化するコンテンツのうち高い方に合わせて上下中央揃えで配置する事ができなくなります。
今回はそんな時の対処方を紹介します。
再現したいデザインを確認
画面幅768px以下の時のデザイン画像(以下spサイズ)
画面幅769px〜1400pxの時のデザイン画像(以下pcサイズ)
画面幅1400px以上の時のデザイン画像(以下オーバーサイズ)
flexでは実装できない?
今回のポイントはspサイズでコンテンツの並びが縦積みで上から『タイトル』『画像』『本文』という並びになっているがpcサイズになると左に『画像』右に『タイトル』と『本文』となっている点です。
このレイアウトはflexのみでは再現できません。
flexで再現するとなると、『sp用タイトル』『画像』『pc用タイトル』『本文』というhtml構成にし、spサイズで『pc用タイトル』をnoneで消し、pcサイズので『pc用タイトル』をnoneで消して再現するしかありません。
こうする事で再現はできますが、もしこのタイトルにH2を使用している場合、noneで非表示にしたり、同じ文章の入ったヘディングを作ることはSEO的にマイナスポイントになってしまいますのでこの方法は使用すべきではありません。
ですのでgridで実装するのが正しい方法になります。
gridで実装しよう
このデザインをgridで実装する方法自体は全然難しくないかと思います。
gridの詳しい使用方法はこちらを参考にしてください。

1 2 3 4 5 6 7 8 9 |
<div class="p-content-wp"> <div class="p-content__inner"> <h2 class="p-content__tile">タイトル</h2> <div class="p-content__img"><img src="img/hoge.jpg"></div> <div class="p-content__sentence"> kihontekinicontentwoyokonarabinisrubaaihaflexwosiyousimasugaflexdehadousitemosaigendekinaipata-ngaarimasu </div> </div> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
.p-content-wp { @media #{$screenSize_L768} { padding: 0 20px; } @media #{$screenSize_H769} { padding: 0; } @media #{$screenSize_H1024} { padding: 0 ; } @media #{$screenSize_H1400} {} max-width: 1400px; margin: 0 auto; } .p-content__inner { color:#555; width: 100%; @media #{$screenSize_H769} { display: grid; grid-template: 'img title' auto 'img desc' 1fr / 50% 1fr; gap: 0 50px; padding-right: 50px; } @media #{$screenSize_H1024} { padding-right: 100px; } @media #{$screenSize_H1400} { padding-right: 0; } } .p-content__tile { grid-area:title; @media #{$screenSize_L768} { font-size:32px; } @media #{$screenSize_H769} { font-size:40px; } } .p-content__img { grid-area:img; @media #{$screenSize_L768} { margin-top: 20px; } & img { width: 100%; } } .p-content__sentence{ grid-area:desc; width: 100%; word-break: break-all; line-height: 1.2; @media #{$screenSize_L768} { margin-top: 25px; font-size:16px; } @media #{$screenSize_H769} { font-size:18px; margin-top: 20px; } } |
*$screenSize_L768→メディアクエリ768以下
$screenSize_H769→メディアクエリ769以上
$screenSize_H1024→メディアクエリ1024以上
$screenSize_H1400→メディアクエリ1400以上
gridで中央揃えにする方法
gridで2つのコンテンツを中央揃えにする方法は少しひねりが必要でgridの機能だけでは再現するこができません。
まず、中央揃えにならない理由を考えます。
理由:テキストエリアの親の高さが写真の高さまで伸びてしまっているから。
ですので、テキストの親の高さをテキストの高さに合わせるために写真にposition: absolute;をつけて写真を浮かせることでコンテンツを抜きます。
すると写真側はコンテンツがなくなりますので親はテキストの高さまで縮んでくれます。
そして親からの絶対位置で上から半分の位置に配置すれば中央揃えになります。
scss
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.p-content__img { grid-area:img; position: relative; @media #{$screenSize_L768} { margin-top: 20px; } & img { width: 100%; @media #{$screenSize_H769} { position: absolute; top: 50%; left: 0; transform:translate(0,-50%); } } } |
absoluteする側がfrやautoで幅指定されてた場合
上記の例ではabsolute側(写真)の横幅が50%と指定されています。このような指定の方法なら問題ないのですが、時にはテキスト側は『改行されたくない』という理由などから横幅をpxで指定して、画像側を残った幅いっぱいに広がるというデザインにしたい場合があります。
その場合、gridのcssは以下のようになります。
css
1 2 3 4 5 6 7 |
display: grid; grid-template: 'img title' auto 'img desc' 1fr / 1fr 500px; gap: 0 50px; padding-right: 50px; |
こちらを実行してみると親の横幅が潰れて画像が表示されないことがあります。
そんな時は親にpadding-leftを使って横幅を維持させます。ですが、このpaddingは画面幅に合わせて伸び縮みして欲しいのでcalcを使って計算する必要があるのですが、なぜか%が使えないということが起こる場合があります。
その場合はvwが使用できるので、vwで計算させるしかないのですがvwは親の横幅に対してではなく画面幅に対しての相対値になってしまいますのでcalc式がややこしくなるのと、1400pxで頭打ち試したくて親にmax-width:1400pxを指定しても関係なく画面の伸びに合わせて無限に大きくなってしまいます。
ですでの対策として、メディアクエリで1400px以上の画面幅になったらimgのwidthを〇〇pxと、固定してやる必要が出てきます。
ちなみにcalcの計算式は以下になります。
1 |
padding-left: calc(100vw - 100px - 500px - 50px); |
同じレイアウトが複数続いて、間に余白を開けたい場合
現状だと、コンテンツの高さがテキストエリアの高さとなっているので、テキストエリアにマージンを設けたとしても、画像は関係なしに大きくなり上下のコンテンツを圧迫してしまいます。
初めから画像の最大値を予測して大きくマージンをつけておくというてもありますが、縮めた際に不自然に大きなスペースが開くのでよくないです。
さらに、今回はテキストダミーなのでテキストエリアの高さは同じですが、本番はそれぞれのテキストアリアの高さは文章量により変化するため、一律のマージンを与えることができなくなり、コンテンツに大きく依存してしまうcssとなるのでよくありません。
ではどうすれば良いかといいますと、gridを囲っている親の高さを画像の高さと同じにし、その親にマージンを与えます。
scss
1 2 3 4 5 6 |
height: calc((((100vw - 50px) / 2) - 50px) * 0.66); max-height: 434px; display: flex; align-items: center; padding: 0; margin:50px 0 50px 0; |
calcを使って親要素の高さを画像の高さと同じになるように計算しています。
(((100vw – 50px) / 2) – 50px)で画面幅から画像の横幅を割り出し、そこに画像の縦横比の66%をかけます。すると画像の高さと同じ値を算出できるのでこれをheightに設定します。
そして、今回はコンテンツが横幅1400px以上には広がらないように制限をかけていますが、画面幅はそれ以上に広がることができます。
それに比例して親の高さが大きくなってしまわないようにmax-heightを使って最大値を決めておきます。
この値は横幅の最大値に66%をかけたものです。
するとこのように画像からの余白を一律に与えることができ、見た目もよくスマートに実装することができます。
まとめ
簡単なレイアウトに見えつつも意外と難しかったのではないでしょうか。
ポイント
- 両方のコンテンツの高さを合わせるためにabsoluteで中のコンテンツを抜き、親からの絶対配置で中央に配置する
- absolute側の横幅を1frなどで指定すると親コンテンツの横幅が潰れるのでpadding-leftなどで横幅を保つ
- 上下の余白は親の高さを画像の高さと同じにしてそこからマージンをつける
以上
コメント