0%

last updated 2021.02.04

develop

ホバーで背景色がスライドしながら変わるCSS

最終更新日から1年以上過ぎています。
内容が古くなっている可能性もあるのでご注意ください。

このブログのUIには、ホバーすると「左からスライドするように背景色が変わる」とか「左から下線が伸びてくる」といった演出を多用してます。(言葉で説明しようとするとむつかしい…)

こういうことです。

demo

ホバーorタップでスライド

ただ単に「ふわっと背景色が変わる」だけならたった1行「transition:.3s」とかで完了ですが、この表現を実装しようとするともうひと手間必要になってきます。

手間がかかるぶん、ほかのサイトとちょっと差がつくのでおすすめの演出です

考え方

background-colorの塗面積を指定する方法はない

基本的に、background-colorは「左側30%だけ塗る」といったサイズ指定ができません。(liner-gradientプロパティを使って疑似的に実装する方法はありますが、liner-gradientプロパティにはtransitionが効かないので今回の実装には使えません)

なので、別のアプローチをとる必要があります。

背景色用の::before疑似要素を差し込む

そこで登場するのが、htmlの構造を変えないまま要素を追加できる「疑似要素」です。
ちょっとトリッキーな存在からか初心者コーダーには敬遠されがちですが、一度覚えてしまうと手放せない便利な要素。
これをホバーでアニメーションさせたい要素に挿入し、疑似要素自体のサイズを変化させることで、文字通り「疑似的に」背景画像の塗面積が変わっていくアニメーションを実装します。(便宜上::beforeとしてますが、この実装では::afterを使っても同じように機能します)

index.pug
<div class="hovItem">テキスト</div>
style.css
.hovItem::before {
  content: '';
}

こうすることで、DOM上ではこのような状態になります。contentが空白なので何も表示はされませんが。

index.pug
<div class="hovItem"><!-- ::before疑似要素 -->テキスト</div>

初心者(というかかつての私)が間違えがちな部分ですが、::before疑似要素はセレクタとして指定した要素の「“直前(要素外)”」に挿入されるのではなく、「“先頭(要素内)”」に挿入されます

この疑似要素と、親要素にあたる.hovItem本体にいくつかの設定を行っていきます。

style.css
.hovItem {
  position: relative;
  background-color: $baseColor;
}
.hovItem::before {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: $hoverColor;
}

親要素にホバー前の背景色、疑似要素にホバー後の背景色を付けたうえで、親要素にrelative、疑似要素にabsoluteの設定を行います。
親要素の中で自由に位置を設定できるようになった疑似要素に対し、widthとheightをそれぞれ100%、topとleftをそれぞれ0に設定すれば、親要素にすっぽり重なる疑似要素のできあがりです。

疑似要素は初期設定では「inline要素」です。widthやheightを設定できないので、設定するために「block」や「inline-block」に変えてあげてください

これを、width:0%とし、親要素にhoverした時には100%とする記述を足すことで、「hoverで左からスルッと現れる別背景色」が完成します。

アニメーションさせるためにtransitionの設定もお忘れなく!

親要素と疑似要素のz-indexを整える

ここまでやってみてプレビューを見た方は気づくと思いますが、まだ期待した状態になっていないはずです。
疑似要素が元の背景色どころかテキストまで隠してしまっているはず。これを直しましょう。

下記のように両要素にz-indexを設定してみてください。

style.css
.hovItem {
  z-index: 0;
}
.hovItem::before {
 z-index: -1;
}

これで期待どおりの見え方になったはず

この記事では詳しい説明は省きますが、「疑似要素のz-indexを負の値に」「親要素のz-indexを0以上に」設定することで、疑似要素は要素と背景色の間に入ってくれます。

試しに数値をいろいろ変えたり、省略したりしてみると、↑の条件以外では望む状態にならないことが確認できるはずです。

コピペ用コード

ワンクリックでコピーできるソース一覧をご用意しました。デモ用の余計な装飾はカットしてありますので、ご自由にカスタマイズしてください。

index.html
<div class="hovItem">テキスト</div>

htmlはこれだけ

style.css
.hovItem {
  position: relative;
  z-index: 0;
  overflow: hidden;
  background-color: $baseColor;
}
.hovItem::before {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  width: 0%;
  height: 100%;
  background-color: $hoverColor;
  -webkit-transition: .5s;
  transition: .5s;
}
.hovItem:hover::before {
  width: 100%;
}

scss/Autoprefixツールをお使いの方はこちら↓をどうぞ。

style.scss
.hovItem {
	position:relative;
	z-index:0;
	overflow:hidden;
	background-color: $baceColor;
	&::before {
		content:'';
		display: block;
		position:absolute;
		top:0;
		left:0;	
		z-index:-1;
		width:0%;
		height: 100%;
		background-color: $hoverColor;
		transition: .5s;
	}
	&:hover::before {
		width:100%;
	}
}

まとめ

しっかりとコンテンツの設計ができていることや、デザインのメインテーマが整っていることの方が大事ではありますが、細部の動きにまで工夫が行き届いたウェブサイトは使っていてきもちいいものです。
よかったら取り入れてみてください。

recommend

develop / 2021.05.09

svgの縦横比を可変にする
svg