Webサイトのデザインでよく見かける、画像(バナーや写真)にマウスが乗ったとき、ふわっとオシャレに色が変わる画像ホバー効果。
「自分でも実装してみたい!」と思い、通常のボタンと同じ感覚で画像要素(img)に直接 :hover を指定して背景色を変えようとすると、「なぜか狙った色にならず、写真がただ白っぽく色褪せるだけになってしまう……」という初心者の壁に必ずぶつかります。
「ホバーの命令も書いたし、背景色も指定したのに、なぜボタンと同じじゃダメなの?」と悩んでしまいます。
そこで今回は、画像ホバーが白く薄くなってしまう根本的な原因をスッキリ解決します!
さらに、色指定を直感的に微調整できる「HSLAカラー」の魅力を100%引き出し、商業サイトのような上品な画像ホバーを実装するための「正しい着色ルール」を分かりやすく解説します。
【実験】ボタンと同じコードで画像にホバーするとどうなる?
まずは、ボタンへのホバーによる背景色の変化の時とまったく同じ考え方で、画像要素(img)に対して直接 :hover を指定するシンプルなコードを見てみます。
HTML
<img src=”画像の保存先URL/画像ファイル名.jpg” alt=”ブランドバッグ” class=”test-img”>
</div>
CSS
💡ボタンの時と同じように、CSSクラス名(.test-img)の後ろにスペースを空けず「:hover」を書き足すだけで命令ができます。
.test-img {
width: 100%;
max-width: 600px;
height: auto;
cursor: pointer; /* リンクがなくてもカーソルを指の形にする */
display: block; /* (1)画像をブロック要素にして背景を認識させる */
}
/* ホバー時の画像(ボタンと同じように直接指定) */
.test-img:hover {
background-color: hsla(240, 100%, 50%, 1); /* (2)ホバー時の色を「HSLA」で指定 */
opacity: 0.6; /* (3)画像を60%の薄さにして後ろの色を透かす */
}
😱 実験結果:青くならずに「白っぽく薄く」なるだけ
画像にカーソルを合わせると色の変化がわかります。
このコードを動かすと、マウスが乗った瞬間にカーソルは指の形に変わり、画像自体にもちゃんとホバーの命令が届きます。
しかし、画面をよく見てみてください。背景色に hsla(240, 100%, 50%, 1) という「真っ青(ブルー)」を指定したにもかかわらず、画像に白がかかったようにふわっと薄くなるだけで、青みがかった変化にはならないはずです。
「ホバーの命令も書いたし、背景色も指定したのに、なぜ白っぽくなってしまうの?」と頭を抱えてしまいます。
CSSコードの意味
上記のCSSコードでは、「display: block;」「background-color」を記述しています。
これはWordPressの投稿ページなどで画像を確実にコントロールするために必要な設定です。
- (1) display: block;
記述理由は、「画像を文字の扱いから『四角いブロック(箱)』へと変更し、画像の大きさを正しく確定させるため」です。画像(<img>タグ)は初期状態だと文字と同じ扱い(インライン要素)になっているため、そのままでは外側の箱(.banner-box)が画像の縦横のサイズを1ミリの狂いもなく正確に認識してくれません。画像をブロック化することで、ブラウザが画像の正確なサイズを認識できるようになり、外側の箱が画像にピタッと密着(display: inline-block;が正常に機能)して、手前の膜(::after)がはみ出すバグを防ぐことができます。 - (2) background-color
次章の「実験結果:背景色に青を指定したのになぜ画像ホバーで画像が白く薄くなるの?」を参照してください。
(3) opacity
次章の「実験結果:背景色に青を指定したのになぜ画像ホバーで画像が白く薄くなるの?」を参照してください。
実験結果:背景色に青を指定したのになぜ画像ホバーで画像が白く薄くなるの?
通常のボタンであれば、ホバー時に背景色を指定するだけで思い通りのデザインに切り替わります。
しかし、画像(img)に同じことをすると、指定した「真っ青(ブルー)」にはならず、ただ白っぽく色褪せるだけという奇妙な現象が起きます。
この現象が起きる理由は、画像(img)が初期状態で持っている「インライン要素」という特殊な性質にあります。
画像の裏側には、最初から「背景色を敷くスペース」がない
CSSでホバー時に background-color を指定する行為は、「画像」と「サイトの一番奥」の間に、新しく背景色を挟み込む命令です。
しかし、画像(<img> タグ)は初期状態だと、文字と同じ「インライン要素」という扱いになっています。
文字と同じ扱いのままだと、ブラウザは「文字の後ろに背景色を敷くスペースなんてないよ」と判断してしまいます。
そのため、background-colorの記述で「画像とサイトの奥の間に、青い色を挟んだ」つもりになっていても、ブラウザはその命令を無視し、画像の真裏には青色の土台を一切敷いてくれません。
画像の真裏は、background-color を指定する前の空っぽの状態と同じです。
画像を「すりガラス」に変えると、一番奥(Webサイトの背景面の色)がそのままのぞく
ここで、ホバー時のコードに書いた opacity: 0.6;(不透明度60%)という命令が関係してきます。
この命令は、.test-img:hover で指定している要素(画像)そのものを「透明なセロハン(すりガラス)」に変える性質を持っています。
画像の真裏が空っぽの状態のまま、画像がすりガラスに変わして写真が透けると、裏側では以下のような「重なり(レイヤー構造)」の現象が起きています。
【手前:画像(60%のすりガラスに変わった写真)】 ➔ 【真裏:何も敷かれていない(空っぽ)】 ➔ 【一番奥:Webサイト全体の背景色】
画像の真裏に青色が一切挟まれていないため、写真がすりガラスになった瞬間、一番奥(最背面)にあるWebサイト全体の背景色が何にも遮られることなく、そのまま100%突き抜けて人間の目に届いてしまいます。
・Webサイトの背景が「白」の場合:
一番奥の白がそのまま透けて届くため、画面上では「ただ白っぽく薄くなった画像」に見えます。
・Webサイトの背景が「黒」の場合:
一番奥の黒がそのまま透けて届くため、画面上では「ただドス黒く沈んだ画像」に見えます。
これが、画像直接ホバーで起きる失敗 of 正体、「ボタンと同じじゃダメな理由」です。
画像が初期状態でインライン要素である以上、「真裏に背景色が敷けず、一番奥にあるサイトの背景色(白や黒)がそのままのぞき込んでくるという現象」を絶対に回避できません。
これではせっかくのHSLA(透明度調整)の魅力が台無しになってしまうため、商業サイトの実務ではこの方法は採用しないのです。
💡 仕組みが分かるとスッキリ解ける「2つの疑問」
この「真裏が空っぽで、一番奥が透けている」という仕組みが分かると、初心者が迷いやすい次の疑問もスッキリ解決します。
- 疑問①:画像を透かしたら、元の画像の色自体が変わっちゃうの?
➔ いいえ、画像が持っている色(データ)そのものが別の色へ変化しているわけではありません。
opacity は画像全体の「色の濃さ(不透明度)」をガクンと薄くする命令です。ホバーしたときに色が変わって見えるのは、画像自体が薄くなったことで、今まで隠れていた一番奥の背景色(白や黒)が前面に透けて混ざり合って見えているからです。画像そのものが変色しているわけではありません。 - 疑問②:background-colorって、画像の上から色を被せる命令じゃないの?
➔ いいえ、上から被せるのではなく、100%「画像の真裏(下側)」に色を敷く命令です。
background-color(背景色)という名前の通り、画像とWebサイトの土台の間に色を挟み込む行為です。だからこそ、画像がインライン要素のままだと「裏側に挟むスペースがない」ために、今回の失敗が起きてしまったのです。
解決策!HSLAカラーを綺麗に出す「着色ルール」
実務の現場で「バナー画像を綺麗にブランドカラー(青や赤など)に染めたい」「WEBサイトの背景が何色であってもデザインを崩したくない」という時は、画像そのものを透かす方法(直接ホバー)は採用しません。
画像ホバーを綺麗に成功させるための本当の着色ルールは、「画像自体は100%不透明のままいじらず、画像の一歩手前(前面)に、HSLAで染めた『透明なセロハンの膜』を新しく1枚重ねてホバーさせる」ことです。
この「手前に新しい膜を作り出す」ために、CSSの疑似要素 ::after という仕組みを少しだけ拝借します。
HSLAが美しく発色するプロのコード
HTML
<img src=”画像の保存先URL/画像ファイル名.jpg” alt=”ブランドバッグ” class=”banner-img”>
</div>
CSS
.banner-box {
display: inline-block; /* (4) */
position: relative; /* (5)💡手前に重ねる膜の「基準の壁」にする */
overflow: hidden; /* (6) */
cursor: pointer; /* リンクがなくてもカーソルを指の形にする */
}
/* 画像の通常時(透明度は100%のまま一切いじらない!) */
.banner-img {
width: 100%;
max-width: 600px;
height: auto;
display: block;
}
/* 💡画像の手前に作り出す「透明なセロハンの膜」 */
.banner-box::after {
content: “”; /* (7) contentの値は必ず半角シングルクォーテーション2つか半角ダブルクォーテーション2つ */
position: absolute; /* (5)箱(.banner-box)に対して絶対的な位置に配置する */
top: 0;
left: 0;
width: 100%;
height: 100%;
/* 通常時(ホバー前)は、完全に透明(Aを0)にしておく */
background-color: hsla(240, 100%, 50%, 0);
}
/* 💡マウスが乗ったとき(ホバー時)の命令 */
/* 画像ではなく、手前に作った膜(::after)のHSLAカラーを変化させる! */
.banner-box:hover::after { /* (8) */
/* 透明度を0.4(40%)にして、ブランドカラーの青みをのぞかせる */
background-color: hsla(240, 100%, 50%, 0.4);
}
💡 実験結果:白っぽく薄くならずに「青く」なる
画像にカーソルを合わせると色の変化がわかります。

