とあるサイトをコーディング中に商品リストでこんな感じのレイアウトがありまして。
印刷物の商品リストでよく見るタイプですよね。
左に商品画像があって、右側に詳細があって右上に商品帯があって、右下に値段があるパターン。
これをCSSで再現する時に肝となるのは左側の詳細で「一部は右下」で「一部は右上」で、なおかつ商品が複数並んだ時に、各パーツがキチッと揃ってるっていうのが、必要です。
結果を先にいうと、(1)display:tableを使ってレイアウトしたら、IE11で激崩れしたので、displayflexのmargin:autoの特性を使ってレイアウトしなおしたって話です。
【HTML】※共通
<ul class="product_list"> <li> <div class="img"> <img src="../img/img01.jpg" alt="" /> </div> <div class="info"> <p class="band">CATEGORY</p> <div class="bottom"> <p class="name">商品名が入ります</p> <span> 商品の説明商品の説明商品の説明<br /> 商品の説明商品の説明商品の説明<br /> </span> <p class="price">500<small>円</small></p> </div> </div> </li> <li> <div class="img"> <img src="../img/img02.jpg" alt="" /> </div> <div class="info"> <p class="band">CATEGORY</p> <div class="bottom"> <p class="name">商品名が入ります</p> <span> 商品の説明商品の説明商品の説明<br /> 商品の説明商品の説明商品の説明<br /> </span> <p class="price">500<small>円</small></p> </div> </div> </li> </ul>
CSS
.product_list li { display: table; float: left; width: 47.5%; padding-right: 5%; } .product_list li:nth-child(2n) { padding-right: 0; } .product_list li .img { display: table-cell; width: 40%; padding-right: 5%; } .product_list li .info { position: relative; display: table-cell; width: 55%; vertical-align: top; } .product_list li .info .band { width: 100%; margin-bottom: 10px; padding: 5px; background-color: #f00; border-radius: 5px; color: #fff; font-size: 12px; text-align: center; box-sizing: border-box; } .product_list li .info .bottom { position: absolute; bottom: 0; width: 100%; padding-top: 2em; text-align: right; } .product_list li .info .name { font-size: 18px; font-weight: bold; } .product_list li .info .price { color: #f00; font-size: 20px; } .product_list li .info span { display: block; margin: 5px 0; font-size: 13px; color: #535353; } .product_list li .info .price small { font-size: 0.5em; }
写真と文章の横並びをfloatやinline-blockだと文章側の高さが画像と並ばないので、うまく画像と平行に右下に行かないんですね。
なので、display:tableを使ってセル内で同じ高さを設けて、右下部分をposition:absoluteでbottom:0で右下にもっていきました。
※ただし、右下の文章が写真の高さを超える文章量だとレイアウトが崩れます。
↓こうなります。
まぁ、今回の場合は文字数に制限がある事が前提だったので、スマホでは1カラムにすれば、そこまで気にしなくていいだろうと、思って進めていると、IE11で見たらビックリしましたよ。
↓こんなんになってました。
どうやら、IE11の場合はtableのセル内ではpositionの基準点の解釈が他のブラウザと違うみたいで、これはあまりにもヒドすぎるだろうということで代替え案を探しました。
CSS
.product_list { display: flex; flex-wrap: wrap; } .product_list li { display: flex; width: 47.5%; margin-right: 5%; } .product_list li:nth-child(2n) { margin-right: 0; } .product_list li .img { width: 40%; margin-right: 5%; } .product_list li .info { display: flex; flex-wrap: wrap; width: 55%; } .product_list li .info .band { width: 100%; height: 1em; margin-bottom: 10px; padding: 5px; background-color: #f00; border-radius: 5px; color: #fff; font-size: 12px; text-align: center; } .product_list li .info .bottom { width: 100%; margin-top: auto; text-align: right; } .product_list li .info .name { font-size: 18px; font-weight: bold; } .product_list li .info .price { color: #f00; font-size: 20px; } .product_list li .info span { display: block; margin: 5px 0; font-size: 13px; color: #535353; } .product_list li .info .price small { font-size: 0.5em; }
flexbox内でmargin:autoを使うと反対側に押し出される仕様で天地中央も簡単に実装できます。
この要領で値段部分はmargin-top:autoにすると一番下に押されるわけですね。
Flex boxの登場でレイアウトの幅が簡単に広がります。
IEとの相性やバグもありますが、IEのバグでflexboxで対応したらうまく行ったっていう珍しい事例だったかもしれません。今回は以上です。
CSS Flexboxとmargin: auto;の自動マージンがどのように相互作用するか、両端揃え・右寄せの実装テクニック