CSSのみで左下・右下にある画像にテキストを回り込ませる
画像を下揃えにしてテキストを回り込ませるレイアウトは紙媒体では結構あると思うんですが、CSSだと実装が難しいですよね。
今回見つけた方法がスマートだったので紹介したいと思います。
キモとして利用するのはshape-outsideプロパティで、IE11がなくなったことでほとんどのブラウザで対応済み。
ただ検証した感想としては挙動が完全ではない部分があるようで、これで解決!とまではいかなさそうという印象でした。
そのあたりも以下にまとめますので、使う際の参考になれば幸いです。
Contents
shape-outsideプロパティって?
CSSのプロパティで、ざっくりこんな感じの概要です。
- 隣接するインラインコンテンツが回り込むシェイプ (形状) を定義するプロパティ
- シェイプは円や楕円、多角形や画像、パスを指定することも可能
- 隣接コンテンツの回り込みが前提のプロパティなので、floatプロパティとセットで指定
テキストの回り込みに関してだいぶ自由度があがりましたね。
先ほど書いた通り、現在ほとんどのブラウザで対応されています。
使用例はこちらのリンク(https://developer.mozilla.org/ja/docs/Web/CSS/shape-outside)をご参照ください。
左下・右下にある画像にテキストを回り込ませる(サンプル)
今回はこちらの記事を参考にさせていただきました。
Float an Element to the Bottom Corner
サンプルはこちら。
See the Pen float bottom image by BICOxxx (@BICOxxx) on CodePen.
resizeプロパティでボックスの幅変更が可能な状態なので、動かしてレスポンシブ時の挙動も確認してみてください。
(パンダ画像の右下あたりをつまめます)
CSSの説明
自分用に構造をメモしてきます。
<div.float>
- 直近で画像を囲うdiv.floatはheight:100%でボックス全体の高さをとった上で、flexboxで下揃え(div.wrapperもflexboxなので高さがとれる)
floatで右寄せもしてるが、高さが100%なのでこのままだとテキストは回り込みしない - div.floatに更に「shape-outside: inset(calc(100% – 150px) 0 0);」を指定することで、上にテキストを流し込ませている。
inset()は内側の矩形の辺の位置を定義するもの。shape-outsideプロパティを設定している要素の領域から「どれくらい内側までテキスト流し込みしていいよ!」というのを伝える値になる。
→今回の場合は画像の高さが150pxなので、「画像の上ギリギリ(calc(100% – 150px)分)まで流し込んでいいよ!」という意味になっている。
(ちなみにもっと画像上の余白を取りたいならcalc(100% – 175px)とかでもOK。テキストの行間によって上余白が広く見える時もあるので、それを考慮しつつ調整する)
<隣接するテキストコンテンツ>(あいうえおかきくけこさしすせそ…の部分)
- shape-outsideプロパティの定義に「隣接するインラインコンテンツ」とあるので、サンプルの通り画像を包含するdivに隣接して直接テキストを設置する
- 試しに以下のようにpタグで囲っても回り込みはされたが、指定していない場所に突如謎の空間が空いたり等不審な挙動があったため、直接テキストを設置する形が無難と考える
(もしかしたらpタグにdisplay:inlineを使えばよかったかもですね….)
<div class="wrapper">
<div class="box">
<div class="float"><img src="https://drive.google.com/uc?export=view&id=1O6__DYHBNjkGP0K2phLqygvG2W3BIFQF" alt="" width="150" height="150"></div>
<p>あいうえおかきくけこさしすせそたちつてと。...(中略)...はひふへほまみむめもやゆよらりるれろわをん。</p>
</div>
</div>
動作確認済みブラウザ
shape-outsideプロパティの対応状況は先に書いた通りで、2022/11/9時点ではほとんどのブラウザで全く問題ありません。
flexboxとの組み合わせでおかしくなることはないかな?と思ったので一通り動作確認しましたが、Win11/Macの各種ブラウザとAndroid/iOSスマホ実機でおおよそ問題なく右下・左下画像へのテキスト回り込みが確認できました。
実装する際の懸念点
最初に「挙動が完全ではない部分があるようで」と書いた通り、少し気になる部分があったのでここで紹介します。
この方法で実装すると、ウィンドウ幅/デバイス幅によって
・文章の見切れ
・下揃えにならない
という状態が見られました。
▼文章の見切れ例
510px時 最後の「れろわをん」が見切れている
▼下揃えにならない例
525px時 最終行が空白になる
親・先祖要素のtext-align: justify;とoverflow:hiddenを外すと、これらの状態がよりわかりやすいと思います。
shape-outsideプロパティを使用した際に回り込んだテキストの高さをちゃんと取得できていないのか、ブラウザの何かしらの計算のズレかな〜と思ってるんですが、ラップするコンテンツからはみ出してしまったり画像より手前で回り込みが止まってしまったりします。
文章量によってこれらが発生する幅が変わり、個人的にはTBサイズ以下で発生することが多い印象でした。
なので、スマホ〜タブレットで回り込み解除というレイアウトにすれば、そこまで気にならないかもしれません。
気になる場合はそのタイミングで、メディアクエリーで下余白をちょこちょこ調整する…という対応も可能かも。(※ 文章量が確定している場合に限り)
それらを踏まえると、この方法が向く・向かないケースは以下のラインかなと思ってます。
- スマホ・タブレット時はテキストの回り込みを解除するレイアウト
- テキストの回り込みを行う箇所のラッパーに背景色や線の装飾がない(テキストと画像が下揃えじゃなくても違和感を感じにくい)
- テキストの回り込みを行う箇所の下に大きく余白をとれる
- 多少ずれがあっても、違和感がなければ問題ない案件
こういうブログの下層ページのように、自由度の高い場所だと使いやすいんじゃないかと思います。
- スマホ・タブレット時もテキストの回り込みを行いたい
- 厳密に、常に画像と下揃えの状態でテキストを回り込ませたい
- やや不自然なテキストの回り込み方が許容できない
- テキストの回り込みを行う箇所のすぐ下にコンテンツを設置したい場合(テキストが下に滑り込んでしまう場合があるため)
特に仕事の案件など、間違ってもテキストが見えない状態になってはいけない状況では慎重に使っていきましょう。
その他の方法のご紹介
画像下揃えでテキストを回り込ませるレイアウトは、空divで画像上の高さを取る方法をよく見かけました。
レスポンシブ時は基本的にjsを使って調整を行う形になります。
今回の方法より厳密に画像・テキストの下揃え&レスポンシブ対応をするならこちらでしょうか。
また、画像とテキストの下揃えの実現方法について、スタック・オーバーフローの質問で色んな方法が提案されていました。
今回のもの以外にも色んな方法が掲載されてるので試してみるのも良いと思います!
Floating an image to the bottom right with text wrapping around
感想
英語で検索すると定期的にこの話題がでているみたいで、こんな発想があるんだ!と感じるCSSの使い方がいくつもありました。
floatは最近なかなか使う機会が減っていましたが、shape-outsideプロパティが使えることでfloatを使う案件も増えてきそうですね。
float関連だとdisplay:flow-rootなんかも対応されているので、overflow:hidden以外でのfloatラッパーができるのも楽になりましたね。
どんどん使いこなしていきたいです。