CSSで画像の上に文字を重ねて表示する例

画像加工って面倒ですよね。

1つ2つならHTMLやCSSをアレコレいじるよりもGIMPやPaint.Netなどでササっと文字入れしたり、ちょっとした図形ならInkScapeで描いてしまうのも良いでしょう。

でも、個人商店レベルでもネットショップだと数百種類の商品を扱っていることもめずらしくありませんし、その商品写真ひとつひとつを加工していたらとんでもなく時間がかかります。

商品写真の上に特価の価格を重ねたり、売り切れの場合はSOLD OUTの文字を重ねたり、そういうのはプログラムやCSSで自動的に出来たら画像加工の手間が省けて便利ですよね。

というわけで、今回はCSSを使った写真と文字の重ね合わせの話です。

写真の上に文字を重ねるにはpositionを使う

■表示例

我輩は犬である

■コード例

<img src="[画像ファイル]">
<div style="position:relative;top:-100px;">我輩は犬である</div>

■解説

おそらく一番単純な例。imgタグの後にdivタグを置き、divの位置を100px上にズラしただけです。

本来なら写真の下に文字が表示されるところですが、CSSの position:relative;top:-100px; で「現在位置から」上方向「-100px」に表示するように指定しています。

画像を並べて表示した場合に困る

例えば、幅160pxの写真を8枚並べてみます。

このブログは記事の幅が680pxでデザインされているため、横4枚、縦2枚で写真が並ぶと思います。

(レスポンシブデザインなので、スマホ表示の場合は横2枚、縦4枚)

この状態で、先ほどと同じようにimgタグのすぐ後にdivタグを配置し、position:relative;top:-100px;とするとこんなことになります。

我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である

imgタグはインライン要素のため、ページ上での配置は文字と同じ扱いで、並べて書けばページの横幅に合わせて良い感じで折り返してくれますが、その途中にdivタグのようなブロック要素が入ってくると改行されてしまうので、こんなことになるわけです。

じゃあdivタグじゃなくてspanタグならインライン要素だから良いかと言うと、上ではなく左にズラすことになるので、topではなくleft:-100px;にして、relativeで動かしただけでは余白が残ったままになるので、margin-leftにもマイナスを指定して…………とどんどんややこしく複雑になってくるので、もっと別の方法で楽をしましょう。

画像と文字は一組のグループと考える

HTMLにはせっかくfigureとfigcaptionというタグがあるので、これを使って考えていきます。別にこのタグじゃないと出来ないってわけではないので、divタグが好きならdivタグでOKです。div div div と同じタグが並ぶと見づらいのでfigureを使おうと思っただけなので。

さて、それではfigureタグの中にimgで画像を、figcaptionでその画像に重ねる文字を書いてみます。

■HTMLコード例

<figure>
 <img src="[画像ファイル]">
 <figcaption>我輩は犬である</figcaption>
</figure>

■表示例

我輩は犬である

figureをインラインブロックにする

figureはブロック要素なので、このまま8個並べても縦にずら~と並んでしまいます。レスポンシブデザインのようにページの横幅一杯まで使って画像を並べたい場合はインラインブロックにする必要があります。

■HTMLコード例

<figure style="display:inline-block;">
 <img src="[画像ファイル]">
 <figcaption>我輩は犬である</figcaption>
</figure>

×8個

■表示例

我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である

わかりやすいようにfigureタグは赤い枠線にしました。

figcaptionにrelative指定すると余白が気になる

一番最初の例のように画像の下にあるfigcaptionタグにposition:relative;top:-100px;といった相対指定をした場合、figcaptionが元々あった位置に余白が出来ます。
(divタグでもrelativeを使った場合は同じ)

■HTMLコード例

<figure style="display:inline-block;">
 <img src="[画像ファイル]">
 <figcaption style="position:relative;top:-100px;">我輩は犬である</figcaption>
</figure>

×8個

■表示例

我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である

ざっくりとしたデザインで良いんだよ、という場合はこれでも構わないのかも知れませんが、どうせならこのモヤっとした余白は取り除きたいところ。

position:absoluteは親要素に従う

CSSのposition:absoluteは絶対座標指定ということで、必ずページの左上からの座標指定をするもの、と勘違いされる場合もありますが、そんなことはありません。親要素にposition:relative;が付いていた場合、そこからの相対指定が可能なのです。

つまりこの場合は、figureタグにposition:relative;を指定し、figcaptionにposition:absolute;を指定すれば画像の左上からの座標指定が可能となるのです。

■HTMLコード例

<figure style="display:inline-block;position:relative;">
 <img src="[画像ファイル]">
 <figcaption style="position:absolute;top:60px;">我輩は犬である</figcaption>
</figure>

×8個

■表示例

我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である

inline-blockの隙間が気になる場合

赤枠内の余白は取り除けましたが、今度は赤枠の外にわずかな余白が出来ました。

これはinline-blockの要素の後に改行が入るとわずかに隙間ができるからなんです。

例えばWebページ上に「ああああ」と書いた場合、文字と文字の間は隙間なく表示されます。当たり前ですね。

これを

あ
あ
あ
あ

と改行を入れて書いた場合は、「あ あ あ あ」と文字と文字の間にわずかな隙間が出来るのです。これがinline-blockの謎の隙間となるわけ。なんとややこしい仕様なのか。

これをてっとり早く修正するためにはinline-blockの親要素の文字サイズを0にすることです。

つまり、figureタグの1つ上に適当にdivタグか何かを配置してfont-size:0を指定するわけです。

ただ、それだけだとfigcaptionのフォントサイズも0になってしまうため、figcaptionのstyle内であらためてfont-sizeを指定してあげる必要があります。

■HTMLコード例

<div style="font-size:0;">
 <figure style="display:inline-block;position:relative;">
  <img src="[画像ファイル]">
  <figcaption style="position:absolute;top:60px;font-size:16px;">我輩は犬である</figcaption>
 </figure>
</div>

■表示例

我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である
我輩は犬である

まとめ

  • CSSで画像の上に文字を配置するにはposition:relativeを使う
  • 文字側をposition:relativeにすると元の位置に余白ができる
  • 画像を並べて表示した上に文字も重ねたい場合は、画像と文字をひとつのグループと考え、figureタグやdivタグで囲もう
  • 囲んだタグをposition:relativeにすればその子要素でposition:absolute指定することで、相対座標指定ができるし、余白もなくなるので万々歳
  • figureやdivなどのブロック要素をレスポンシブデザインのように並べるならdisplay:inline-blockを使おう
  • inline-blockの余白は親要素にfont-size:0を指定することで消せる

といったところでしょうか。

画像の上に文字を配置する説明とか、ちゃちゃっと書けるでしょー、くらいなノリで書き始めたのですが、思ったより随分長くなってしまった…。

文字の装飾とか、矢印にする例も説明しようと思ってたんだけど、今回はとりあえずここまで!

adsbygoogle

フォロー