トップページのCSS3効果②

CSS3効果

さて、ここからが本題のCSS3効果です。CSS3のスタイル指定は、a要素にのみ行っています。

ノーマル時のスタイル

ナビゲーションボタンには、マウスがボタンに乗った時に見た目が変化する、いわゆるロールオーバー効果を適用しています。ですから、スタイル指定は、ノーマル時とオーバー時の指定に分かれます。では、ノーマル時の指定から見ていきましょう。


#top_topnav li a {
	border-radius:64px;
	color:rgba(240,240,240,0.6);
	background-color:rgba(0,0,0,0.1);
	text-shadow:0px 0px 6px rgba(0,0,0,0.7);
	box-shadow:0px 0px 12px 1px rgba(255,255,255,0.5), inset 0px 0px 8px 1px rgba(0,0,0,0.4), inset 0px 8px 12px rgba(255,255,255,0);
}

border-radius

まずborder-radiusプロパティで、ボタンの左右が半円状になるように、角丸を指定しています。横長のボックスの場合、角を半円にするには高さの1/2サイズを、角丸半径として指定します。

半円角丸の概念図

しかし、ボタンの高さは、文字サイズ+上下のpaddingで決まっていますが、それらはすべてem値を使っているため、指定からは正確なサイズは分かりません。IE開発者ツールで実サイズを計測することも可能ですが、半円の場合、1/2よりも大きな数を指定しても、形が崩れることはありません。ですので、ほぼ確実に1/2を超える64ピクセルという数値を指定しています。

透明カラー

colorプロパティは文字色の指定ですが、ここでは透明色にするため、rgba関数を使っています。同様に、backgroud-colorによる背景色も、rgba関数による透明色です。

text-shadow

その文字を少し浮き立たせるため、周囲にtext-shadowプロパティでドロップシャドウを適用しています。初めの2つの値は、影の左右、上下のオフセットを表します。ともに0にし、3つ目の値でぼかしをかけることで、周囲に影(明るい色であれば光彩)が広がるグロウ効果を得ています。最後の値は色指定で、ここでもrgba関数による透明色を使っています。

これらの値の役割は、box-shadowプロパティと同じですが、text-shadowには影の拡張(スプレッド)を指定する値は存在しません。

box-shadow

最後に、ボックスの輪郭を際立たせているのが、box-shadowプロパティです。ここでは、外側に1つ、内側に2つの指定を行っています。

ひとつ目の「0px 0px 12px 1px rgba(255,255,255,0.5)」が、外側に白いグロウ効果をかけている指定です。4つ目の値で、影を外側に1ピクセル拡張し、そのうえで12ピクセルのぼかしをかけています。色は白の半透明色ですから、しろくぼやけた“影”が周囲に付くことで、ボタンの縁を、背景の画像の白っぽさに加味して、浮き上がらせています。

あとは、内側に黒いグロウ効果を付けることで、ボタンがへこんでいるように演出していますが、その指定が「inset 0px 0px 8px 1px rgba(0,0,0,0.4)」です。

box-shadowの構成図

では、3つ目の「inset 0px 8px 12px rgba(255,255,255,0)」は何でしょう? これは、ボタン上辺から内側に8ピクセル下へ伸びる、白い“影”です。しかし、不透明度で0を指定してあるため完全に透明になり、当然、見えません。なんだか、無駄な指定のようです。が、しかし、この指定もきちんと役立っているのです。その理由は後のお楽しみにしておきましょう。

オーバー時のスタイル

オーバー時を、擬似クラスhoverを使ったセレクターで特定するのは、CSS2と3に違いはありません。

なお、キーボード(tabキー)で選択した時も同じ設定にするため、active、focusの擬似クラスも実際には指定していますが、ソースコードをわかりやすくするため、以下の例示では省いてあります。


#top_topnav li a:hover {
	color:rgba(0,0,0,0.6);
	box-shadow:0px 0px 12px 1px rgba(255,255,255,0.4), inset 0px 0px 8px 1px rgba(0,0,0,0.9), inset 0px 8px 12px rgba(255,255,255,0.6);
	-webkit-transform:scale(1.15);
	transform:scale(1.15);
}
colorの変化

まず、文字の色(color)は、黒の透明色に変わるようにしてあります。

box-shadowの変化

次いで、ドロップシャドウ(box-shadow)は、外側の白いぼかしを不透明度0.4に下げることで、その効果を抑制しています。逆に、内側の黒い影は、不透明度を0.9に上げ、強調しています。そして、3つ目の白い影も、不透明度を0から0.6に上げることで、見えるようにしてあります。この白い影が、ボタン上部にかかることによって、へこんでいたものが、逆に浮き出ているように見えるはずです。

hoverの構成図

こうした効果は、上部が白(明るい)色で、下部が濃い(暗い)色になるグラデーションで、表現することができます。もちろん、CSS3ではグラデーションによる背景色(background-image)が指定できるので、それを使うこともできます。ただし、IE9はグラデーションに対応していないので、IE9が対応しているドロップシャドウを利用して、こうしたグラデーションに相当する効果を得たわけです。

transform

さらに、オーバー時にはボタンのサイズを拡大しています。それには、幅や高さを指定するのではなく(そもそも、今回のボタンには幅や高さを指定していません)、transformプロパティのscale関数を使って、1.15倍に拡大しています。transformプロパティは、対象要素の拡大/縮小(scale)、回転(rotate)、斜変形(skew)、移動(translate)といった変形を指定可能です。

transformプロパティ値の関数一覧
移動(2D)
translate(x, y) 対象を移動。引数はX、Y方向の移動距離
translateX(距離) 対象をX方向に移動。引数は移動距離
translateY(距離) 対象をY方向に移動。引数は移動距離
移動(3D)
translateZ(距離) 対象をZ方向に移動。引数は移動距離
translate3d
(x, y, z)
対象を3次元で移動。引数はX、Y、Z方向の移動距離
回転(2D)
rotate(角度) 対象を回転。引数は回転角度
回転(3D)
rotateX(角度) 対象をX軸で回転。引数は回転角度
rotateY(角度) 対象をY軸で回転。引数は回転角度
rotateZ(角度) 対象をZ軸で回転。引数は回転角度
rotate3d
(番号x, 番号y, 番号z, 角度)
対象を3D回転。引数は各軸につき番号0で不使用、1で使用、そして共通の回転角度を指定する
拡大縮小(2D)
scale(x, y) 対象を拡大・縮小。引数はXおよびY方向の倍率を0~1で指定
scaleX(倍率) 対象をX方向に拡大・縮小。引数倍率を0~1で指定
scaleY(倍率) 対象をY方向に拡大・縮小。引数倍率を0~1で指定
拡大縮小(3D)
scaleZ(倍率) 対象をZ方向に拡大・縮小。引数倍率を0~1で指定
scale3d(x, y, z) 対象をX、Y、Z方向に拡大・縮小。引数倍率を0~1で指定
斜変形(2Dのみ)
skew(x, y) 対象を斜変形。引数はX、Y軸で傾ける角度
skewX(角度) 対象をX軸で斜変形。引数は傾ける角度
skewY(角度) 対象をY軸で斜変形。引数は傾ける角度

また、変形の原点は、デフォルトで対象要素の中心点に設定されています。ですから、ボタンを中心から上下左右に拡大させることが、できているのです。なお、変形の原点はtransform-originで変更可能です。デフォルトで中心点になっているのは、transform-origin:center centerという指定になっているということです。

オーバー時の背景色

nth-of-type

さて、各ボタンは、オーバー時に背景色も変わるようになっています。そして、3つの色が使われています。この3色を交互に指定するため、以下のようなセレクターを使っています。


#top_topnav li:nth-of-type(odd) a:hover {
	background-color:hsla(280,100%,70%,0.2);
}
#top_topnav li:nth-of-type(even) a:hover {
	background-color:hsla(240,90%,70%,0.2);
}
#top_topnav li:nth-of-type(3n+0) a:hover {
	background-color:hsla(320,80%,70%,0.2);
}

この、nth-of-typeという擬似クラスは、同じ親要素を持つ、兄弟要素をまず特定します。この例では、親要素top_topnavの中に入っている、li要素ということになります。それだけなら、#top_topnav liでも特定できますが、nth-of-typeの特徴は、その後ろの()の中にあります。最初のセレクターでは、oddと記述されていますが、これは奇数を意味します。ですから、top_topnavの中のli要素のうち、奇数個目のli要素だけを特定できます。同様にevenは、偶数を意味します。

そして、最後の3n+0は、「an+b」式と呼ばれるものです。このうち、nは0から1ずつ増えていく、決められた値です。いわゆる、インクリメントです。あとは、aとbに任意の数値を指定できるのですが、ここではaが3、bが0です。すると、以下のような計算が繰り返されることになります。

3×0+0=0(該当無し)
3×1+0=3
3×2+0=6

つまり、0から始まって、3つおきのli要素を特定できるわけです。aは幾つおきか、bは何個目から始めるのか、を意味しています。

今回のボタンは、全部で7つありますから、1個目と5個目と7個目(odd)、2個目と4個目(even)、3個目と6個目(3n+0)に、それぞれ異なる背景色を指定したことになります。

li要素の特定順序
HSLカラーモード

その背景色ですが、もちろんbackground-colorで指定していますが、値の関数はrgbaではなく、hslaです。aは、どちらも不透明度を表しますが、HSLは色彩理論の色相(Hue)・彩度(Saturation)・明度(Lightness)に基づく色指定です。

色相は、色の種類を意味し、RYGCBMRの色変化を時計回りで円周上にならべた色相環で表します。ですから、色は0~360度の角度で指定することになります。

HLS色相環
色相環の概念図
色相環では色同士の角度の遠近から、近似色や補色を関係付け、色選択に役立てる。

彩度は、色の鮮やかさで、100%で最も鮮やかになり、それが色相の色(純色)になります。0%では色が無くなり、白、グレー、もしくは黒(無彩色)になります。

彩度の概念図

明度は、色の明るさで、100%で白、50%で純色、0%で黒になります。つまり、彩度が0%の場合、明度によってグレーのレベルが決まるのです。また、彩度100%かつ明度50%のときに、純色になります。たとえば赤の純色(rgb255,0,0)はhsl(0,100%,50%)で表されます。

明度を基準にしたカラーチャート
明度を基準にした、H0(赤)のカラーチャート

ちなみにCorelDRAWでは、HSLをHLSの順で表していますが、各値をCSS上では入れ替えて指定すればOKです。

CorelDRAWの色指定画面
CorelDRAWインタラクティブ塗りつぶしツールのプロパティバー。HLSで構成されている。

似たようなカラーモデルとしてHSBがありますが、Bは輝度(Brightness)になります。同様に明るさを定義するものですが、輝度は100%で純色を表すため、その数値を明度に直接置き換えることはできません。たとえば、Illustrator CS5(CS6のとこは知りません)は、偉そうなくせに、HSLもしくはHLSには非対応で、HSBしか使えません。情けないですね。

HSBカラーチャート
HSBを基準にしたH0(赤)のカラーチャート。HSLとは分布が異なる。

transition

以上が、CSS3の視覚効果なのですが、ナビゲーションボタンはマウスオーバー時に、若干の時間をかけて色やサイズの変化を行っています。IE9は、そうした効果に対応していないので、パッと変化するだけですが、IE10や他の最新ブラウザーの場合、変化には0.8秒かかっています。マウスが離れ、元の状態に戻る時も同様です。これが、transitionという効果です。

transitionの指定方法

transitionは、以下のように、ノーマル状態を定義した要素の側に指定します。


#top_topnav li a {
	-webkit-transition-property:color, background-color, box-shadow, -webkit-transform;
	transition-property:color, background-color, box-shadow, transform;
	transition-duration:0.8s;
}

指定は簡単で、まずtransition-propertyプロパティで、変化させるスタイルのプロパティ名を値に記述します。ここでは、以下の4つを指定しています。

  • color
  • background-color
  • box-shadow
  • transform

複数のプロパティを列挙する場合は、カンマ(,)で区切ります。

そして、transition-durationプロパティで、変化にかける時間を指定しています。単位sは「秒」で、0.8秒かけて各プロパティを、ノーマル時の値からオーバー時の値へ変化させることになります。時間の単位には、千分の1秒を表すミリ秒(ms)も使用できます。

ですから、各値は、数値的に連続した変化を持たせられるものでなければなりません。たとえば内側の白いドロップシャドウの場合、ノーマル時がinset 0px 8px 12px rgba(255,255,255,0)、オーバー時がinset 0px 8px 12px rgba(255,255,255,0.6)ですが、色の不透明度が0から0.6へ徐々に変化することになります。

transitionによる値の変化
transitionによる値変化の例

実はこれが、ノーマル時に、不透明度0の見えもしない白い影を指定した理由です。変化後の値には、それと対になる変化前の値が必要だったのです。

こうした変化ですから、たとえばdiplay:none(非表示)とdisplay:block(ブロックレベル表示)の間で、値を遷移させることはできません。これらの値は二者択一であり、連続した中間状態は存在しないからです。非表示と表示を遷移させるなら、opacityプロパティで不透明度を0~1へ変化させることになります。

その他のtransition関連プロパティ

transitionには、この他、以下のプロパティがあります。

transition
関連プロパティの一括指定用
transition-delay
開始の遅延時間をミリ秒(ms)もしくは秒(s)で指定
transition-timing-function
変化に対するイージング効果を指定。値は以下の表と図を参照
transition-timing-functionの値①
ease 減速→等速→減速(デフォルト値)
linear 等速
ease-in 減速→等速
ease-out 等速→減速
ease-in-out 減速→等速(持続時間なし)→減速
cubic-bezier
(始点制御点X座標, 始点制御点Y座標,終点制御点X座標, 終点制御点Y座標)
cubic-bezier関数。トーンカーブと似たグラフのベジェ曲線の形状で速度変化を指定。下図参照
cubic-bezier概念図
transition-timing-functionの値②
step-start steps(1, start)と同等
step-end steps(1, end)と同等
steps
(数値, start/end)
steps関数。第一引数で1以上の数値、第二引数でstarもしくはendを指定。再生開始後(start)もしくは終了前(end)のタイミングで、再生が第一引数の数値でコマ送りになる。
steps概念図

ベンダー接頭辞の必要性

ところで、transition-durationプロパティではベンダー接頭辞を使っていないのに、なぜtransition-propertyではChrome用に-webkit-を付けているのでしょう。Chrome 26は、実際にはtransitionの各プロパティに、ベンダー接頭辞無しで対応しています。

しかし、transition-propertyに使った値のうち、transformにはベンダー接頭辞が必要なのです。これを、ベンダー接頭辞無しのtransition-propertyに入れた場合、なおかつその後ろにtransformがあると、-webkit-transformは打ち消されてしまうのか、Chromeでは動作しなくなります。


transition-property:color, background-color, box-shadow, -webkit-transform, transform;

これらの順序を逆にすれば、実際にはChromeでも他のブラウザーでも問題なく動作しますが、接頭辞無しの次に接頭辞付のものが読み込まれるというのは、ベンダー接頭辞の使い方としては間違っているように思えます。


transition-property:color, background-color, box-shadow, transform, -webkit-transform;

このため、transition-propertyについては、-webkit-付きのものも、現状では併記しているわけです。面倒な話ですね。

まとめ

以上が、トップページのナビゲーションボタンに与えた、CSS3効果の全貌です。基本的な配置やサイズはCSS2の既存のプロパティで行い、視覚的に強調する効果を、主としてCSS3のbox-shadowと透明色で適用しています。角丸を含め、こうした見栄えであれば、画像で表現する必要はほとんどなくなりました。

そして、ロールオーバー時にtransitionプロパティで、一種のアニメーション効果も付与しました。transitionは、事実上、hover“イベント”でのみ有効ですが、JavaScriptに頼らなくても、それよりも簡単に、動的変化を表すことができるのです。

krzm.jp:not(so-called mobile friendly)