hoverで画像を拡大、でも文字は大きくしない【CSSのみ】

こんにちは!フリーランスWebディレクター兼エンジニアののせっち@nosecchi01です。

Web制作 + 物販を中心に生きており、70万〜90万円程の売上を上げています。
2020年上半期中には月商100万円を超えそうです。

今回は『hover時に画像をふわっと拡大させる、けど画像上に配置した文字は拡大したくない』場合の対処法を解説します。

CSSのみで実装できます!

それでは行ってみましょう!

目標物を確認

  • hover時に画像が拡大されている
  • 文字は等倍のまま(画像と一緒に拡大されない)

サンプルコード

サンプルコードは下記です。とてもシンプル

一つずつ切り出して解説していきますのでとりあえず流し見でOKです。

<div class="box">
 <div class="box-bg"></div>
   <div class="box-text">
     <h2>ここにタイトルが入ります</h2>
     <p>ここにテキストが入ります。ここにテキストが入ります。ここにテキストが入ります。</p>
   </div>
</div>
.box{
  overflow: hidden;
  position: relative;
  width: 100%;
  cursor: pointer;
}

.box-bg{
  background: url('画像のurl') center center / cover no-repeat;
  width: 100%;
  height: 450px;
  position: relative;
  z-index: 0;
  transition: .3s ease-in-out;
}

.box-bg:hover{
  transform: scale(1.1);
}

.box-bg::before{
  background: linear-gradient(45deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.3) 70%);
  content: "";
  height: 100%;
  position: absolute;
  width: 100%;
  z-index: -1;
}

.box-text{
  position: absolute;
  top: 25%;
  left: 40px;
  pointer-events: none;
}

.box-text h2{
  color: #fff;
  font-size: 28px;
  font-weight: bold;
}

.box-text p{
  color: #fff;
  font-size: 17px;
  margin-top: 20px;
}

簡単に解説

ポイントとしては下記の3点です。

  • 親要素に対してoverflow: hidden; 子要素にtransform: scale(数値);
  • 親要素に対してposition: relative; 画像とテキストは並列に
  • 画像上の文字に対してはpointer-events: none;

一応補足で、「ふわっと」の部分は下記の部分ですね!

transition: .3s ease-in-out;

親要素に対してoverflow: hidden; 子要素にtransform: scale(数値);

具体的には下記の部分です。

.box{
  overflow: hidden; /* 親要素にoverflow: hidden; */

  position: relative;
  width: 100%;
  cursor: pointer;
}

.box-bg{
  background: url('画像url') center center / cover no-repeat;
  width: 100%;
  height: 450px;
  position: relative;
  z-index: 0;
  transition: .3s ease-in-out;
}

.box-bg:hover{
  transform: scale(1.1); /* 子要素にtransform: scale; */
}

親要素にoverflow:hidden;をかけることで、親要素からはみ出す分は非表示にしてくれます。

親要素にoverflow: hidden;をかけていないと画像がそのまま拡大されてしまい変な感じになります・・・。

親要素に対してposition: relative; 画像とテキストは並列に

具体的には下記です。

<div class="box">
  <div class="box-bg"></div>  <!-- 並列 -->
  <div class="box-text">      <!-- 並列 -->
    <h2>ここにタイトルが入ります</h2>
    <p>ここにテキストが入ります。ここにテキストが入ります。ここにテキストが入ります。</p>
  </div>
</div>
.box{
  overflow: hidden;

  position: relative; /* 親要素にposition: relative; */

  width: 100%;
  cursor: pointer;
}

.box-bg{
  background: url('画像url') center center / cover no-repeat;
  width: 100%;
  height: 450px;

  /* 省略 */
}

.box-text{
  position: absolute; /* 親('.box')に対してposition: absolute; */
  top: 25%;
  left: 40px;
  pointer-events: none;
}

これにより、hover時に画像だけ大きくしてテキストは等倍のままにしておくことができます。

本来、画像(‘.box-bg’)を親要素→テキスト部分(‘.box-text’)をその子要素としたいところですが、こうすると画像を拡大させると文字も一緒に拡大されてしまいます・・・。

そのため、親要素に対してposition: relative; 画像とテキストは並列(兄弟要素)にします。

画像上の文字に対してはpointer-events: none;

具体的には下記です。

.box-text{
  position: absolute;
  top: 25%;
  left: 40px;

  pointer-events: none; /* 下記で詳しく解説 */
}

pointer-events: none;に設定すると、hover時にその要素を通過してくれます。

値を none に設定すると、要素がポインターイベントのターゲットではないことを示すのに加え、ポインターイベントが要素を「通過」して、代わりに要素の「下」をターゲットにすることを指示します。(developer.mozilla.orgより引用)

https://developer.mozilla.org/ja/docs/Web/CSS/pointer-events

なぜpointer-events: none;にするかというと、これを設定していないと、ポインタ(マウス)が文字上に来た際に、画像のhoverが解除されて、transform: scale(数値)が外れてしまうからです。

これは、文字の方が画像より上に配置されるからです。(当然ですね)

補足

これは補足ですが、上記実装ではCSSで画像にフィルタをかけています。

具体的には下記の部分です。

.box-bg{
  background: url('画像url') center center / cover no-repeat;
  width: 100%;
  height: 450px;
  transition: .3s ease-in-out;
  /* フィルタ部分 */
  position: relative;
  z-index: 0;
}

/* フィルタ部分 */
.box-bg::before{
  background: linear-gradient(45deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.3) 70%);
  content: "";
  height: 100%;
  position: absolute;
  width: 100%;
  z-index: -1;
}

別記事で解説していますので、気になる方はどうぞ!

この記事を書いた人

のせっち

福岡県出身。早稲田大学卒。創業100年の鉄鋼商社でバンコク駐在最年少抜擢。毎日擦り切れるまで働かなくても幸せに生きている人々を見てフリーランスになりました。
現在は、主にバンコクでWeb制作、物販を中心に生きています。