エンジニアブログ

RSS

CSS3で文字色・背景色がワイプするナビゲーション

tweets admin CSS3

コーディング工房のサイトを作る際に、どうしてもナビゲーションに背景色と文字色がワイプして変わるエフェクトをCSS3で実装してみたかったのだけれど、良い実装方法が思い浮かばず試行錯誤の末にたどり着いた方法をご紹介します。

なるべく簡単な構造を、ということで試行錯誤した結果の物です。
言葉だと伝わりにくいので、画像にまとめて見ました。
構造解説

まず、リストタグの中にa要素を入れ子にし、さらにその中にspan要素を入れ子にします。
それぞれの要素レベルをblockにし、全てがliと同じ幅・高さになるように設定します。

次に、a要素に未hover状態の画像を背景として設定し、同様にspan要素にhover時の画像を背景として設定します。
この状態だと、単純にspan要素が一番上にきているので、当然span要素しか見えません。

そしてここからがポイント。
a要素にposition:relativeを設定し、span要素にposition:absoluteを設定して、a要素に対するspanの相対位置を-100%にします。
こうすることにより、li要素の可視範囲と同じ高さの分が相対的に上にあがることになり、span要素の下にあるa要素が可視状態になります。
そして、span要素の背景画像の縦位置に(li要素の高さ-span要素の背景画像の高さ)÷2+li要素の高さの数値を設定します。

本当は縦位置をパーセンテージで設定したりしたかったのですが、background-positionでのパーセンテージの親の扱いがそもそも違ったので、出来ませんでした・・・。
※(li要素の高さ-span要素の背景画像の高さ)÷2が、background-positionの縦のcenter(50%)と同じ値になります。

最後にhover状態の設定をします。
a要素がhover状態の時に、span要素の相対位置を0にし、a要素の上に重なるようにします。
そして、span要素の背景画像の縦位置を50%に設定します。
これで、hover時にのみspan要素が出てくるようになります。

あとは、CSS3のtransitionプロパティを設定し、スムーズにspan要素が移動するようにします。
span要素の位置が-100%から0になるのと同時に、背景画像の縦位置が150%から50%へと変わるため、背景画像がspan要素に追従せず、常に一定位置に固定されているように見えます。

ここで問題なのが、transitionプロパティで背景画像の高さの変化をスムーズにする際に、変化前と変化後のposition値の単位が同じでないとうまく動作しません。
そのため、hover時のspan要素の背景画像の縦位置には、(li要素の高さ-span要素の背景画像の高さ)÷2を設定する必要があります。

これを実装したコードが以下のものになります。

HTML:

<ul>
	<li class="nav01 cur"><a href="#"><span></span>トップページ</a></li>
	<li class="nav02"><a href="#"><span></span>サービス概要</a></li>
</ul>

CSS:
ul li {
	display			: block;
	float			: left;
	margin-right		: 10px;
	width			: 135px;
	height			: 100px;
	overflow		: hidden;
}

ul li a {
	display			: block;
	width			: 100%;
	height			: 100%;
	text-indent		: -9999px;
	background		: no-repeat center center;
	position		: relative;
}

ul li a span {
	display			: block;
	width			: 100%;
	height			: 100%;
	background		: no-repeat center 134px #444;	/* ( li-height - background-height ) / 2 + li-height */
	position		: absolute;
	top			: -100%;
	border-radius		: 0 0 5px 5px;
	-webkit-border-radius	: 0 0 5px 5px;
	-moz-border-radius	: 0 0 5px 5px;
	transition		: 0.2s ease-out;
	-webkit-transition	: 0.2s ease-out;
	-moz-transition		: 0.2s ease-out;
}

ul li.cur a span,
ul li a:hover span {
	top			: 0;
	background-position	: center 34px;	/* ( li-height - background-height ) / 2 */
}

ul li.cur a span	{ background-color : #333; }

ul li.nav01 a		{ background-image : url(nav01b.gif) }
ul li.nav01 a span	{ background-image : url(nav01w.gif) }

ul li.nav02 a		{ background-image : url(nav02b.gif) }
ul li.nav02 a span	{ background-image : url(nav02w.gif) }

サンプル


とまぁ、試行錯誤して簡単でスマートな方法を模索したにも関わらずこんなわけのわからない構造になってしまったわけで。。。
JavaScript使わずにもっと簡単にやれる方法無いかなぁ・・・。