今回のお題は、メニュー項目にポインタを重ねると数字が飛び出してくるバーだ(サンプル1 ) 。「 Hop Over Notification Badge 」のデザインとアニメーションにもとづいて、コードはわかりやすく組み立て直した。ちょっとした動きとはいえ、アニメーションを魅力的に見せる工夫がある。あまり手が混みすぎていないところも好ましい。
サンプル1 CSS3: Hop over notification badge
メニューバーのインタラクション
<body>
要素に加えるメニューバーは、つぎのようにul
要素(class
属性"menu")のリストで組み立てる。<li>
要素に含めた<a>
要素には、data-
グローバル属性(data-bubble)で表示する数字が定めてある。<a>
要素にひとつだけclass
属性が与えてあるのは、あとで数字の背景色を変えるためだ。なおいつもどおり、-prefix-freeをCDNから読み込んでおくものとする(第16回の「水平に並べた要素に静的なスタイルを割り当てる 」参照) 。
<body>要素
<ul class="menu">
<li><a href="#" data- bubble="117">Messages</a></li>
<li><a href="#" data- bubble="4">New Posts</a></li>
<li><a class="gold" href="#" data- bubble="1">Hidden Coins</a></li>
</ul>
このHTMLのコードにつぎの<style>
要素のようにCSSを定めると、インタラクションを加える前のメニューバーができ上がる(図1 ) 。メニュー項目を区切る垂直の仕切りは左右の境界線(border-left
とborder-right
)の明暗で凹凸を表し、右下の影はぼけなしのbox-shadow
プロパティにより加えた。なお、テキストにはtext-shadow
プロパティで下方向に明るい影をつけて、凹んでいるように見せている。
<style>要素
body {
padding: 1em 2em;
font: 100%/1.5 "Helvetica Neue", sans-serif;
color: #eee;
background: #485258;
}
.menu {
display: inline-block;
box-shadow : 0.12em 0.12em 0 rgba(40, 40, 40, 0.2);
list-style-type: none;
padding: 0;
}
.menu li {
float:left;
border-left:0.063em solid #a6c6cd;
border-right:0.063em solid #6ca1ac;
}
.menu a {
display: block;
padding: 0 1em;
line-height: 2.5em;
position:relative;
font-weight: bold;
text-decoration: none;
color: #364652;
background-color: #86B2BB;
text-shadow : 0 0.063em 0 #a6c6cd;
}
図1 インタラクションを加える前のメニューバー
メニュー項目にマウスポインタを重ねたとき、テキストの表現を変える(図2 ) 。擬似クラス:hover
と:active
および:focus
で、テキストの色と影をつぎのように定めた。色は白に近くし、右下に暗い影を落とすことで、浮き上がって見える。ここまでのCSSの定めを、以下のコード1 にまとめた。
.menu a:hover,
.menu a:active,
.menu a:focus {
color: #eee;
text-shadow : 0.063em 0.063em 0 #547177;
}
図2 マウスポインタを重ねるとテキストの表現が変わる
コード1 マウスポインタを重ねた項目の表現が変わるメニューバー
body {
padding: 1em 2em;
font: 100%/1.5 "Helvetica Neue", sans-serif;
color: #eee;
background: #485258;
}
.menu {
display: inline-block;
box-shadow : 0.12em 0.12em 0 rgba(40, 40, 40, 0.2);
list-style-type: none;
padding: 0;
}
.menu li {
float:left;
border-left:0.063em solid #a6c6cd;
border-right:0.063em solid #6ca1ac;
}
.menu a {
display: block;
padding: 0 1em;
line-height: 2.5em;
position:relative;
font-weight: bold;
text-decoration: none;
color: #364652;
background-color: #86B2BB;
text-shadow : 0 0.063em 0 #a6c6cd;
}
.menu a:hover,
.menu a:active,
.menu a:focus {
color: #eee;
text-shadow : 0.063em 0.063em 0 #547177;
}
マウスポインタを重ねた項目に数字を示す
つぎは、今回の肝となる数字、インターフェイスではバッジと呼ばれる部品だ。つぎのように、data-
グローバル属性(data-bubble)の与えられた<a>
要素を属性セレクタ[]
で選んで、::after
擬似要素を加える。表示する数字は、前述のとおりdata-
グローバル属性からattr()
式 でcontent
プロパティに与えた。border-radius
プロパティで背景の角に丸みをつけ、文字と角丸背景にそれぞれ影を加えている。これが、インタラクションを加える前の数字(バッジ)のスタイルになる(図3 ) 。
.menu a[data-bubble]:after {
content: attr (data-bubble);
position: absolute;
top: 0;
right: 0.5em;
line-height: 1.5em;
padding: 0 0.46em;
text-shadow : 0 0.063em 0 rgba(0, 0, 0, 0.2);
background-color: #eee;
color: #364652;
box-shadow : 0 0.063em 0.063em rgba(0, 0, 0, 0.2);
border-radius : 4em;
}
図3 擬似要素で数字を示す
擬似要素(::after
)の数字に、つぎのような基本的なインタラクションを加える。z-index
プロパティで、初めはメニューバーの背後に隠しておく(-1) 。マウスポインタを重ねたら(:hover
と:active
および:focus
)手前に出し(1) 、top
プロパティで上に持ち上げた[1] 。これで、マウスポインタを重ねたメニュー項目には、数字が示されることになる(図4 ) 。ここまでのCSSの定めを、以下のコード2 にまとめておこう。
.menu a[data-bubble]::after {
z-index: -1;
transform : translateZ (0);
}
.menu a:hover[data-bubble]::after,
.menu a:active[data-bubble]::after,
.menu a:focus[data-bubble]::after {
top: -1.25em;
z-index: 1;
}
図4 マウスポインタを重ねたメニュー項目に数字が示される
コード2 マウスポインタを重ねると数字が示されるメニューバー
body {
padding: 1em 2em;
font: 100%/1.5 "Helvetica Neue", sans-serif;
color: #eee;
background: #485258;
}
.menu {
display: inline-block;
box-shadow : 0.12em 0.12em 0 rgba(40, 40, 40, 0.2);
list-style-type: none;
padding: 0;
}
.menu li {
float:left;
border-left:0.063em solid #a6c6cd;
border-right:0.063em solid #6ca1ac;
}
.menu a {
display: block;
padding: 0 1em;
line-height: 2.5em;
position:relative;
font-weight: bold;
text-decoration: none;
color: #364652;
background-color: #86B2BB;
text-shadow : 0 0.063em 0 #a6c6cd;
}
.menu a:hover,
.menu a:active,
.menu a:focus {
color: #eee;
text-shadow : 0.063em 0.063em 0 #547177;
}
.menu a[data-bubble]::after {
content: attr (data-bubble);
position: absolute;
top: 0;
right: 0.5em;
line-height: 1.5em;
padding: 0 0.46em;
text-shadow : 0 0.063em 0 rgba(0, 0, 0, 0.2);
background-color: #eee;
color: #364652;
box-shadow : 0 0.063em 0.063em rgba(0, 0, 0, 0.2);
border-radius : 4em;
z-index: -1;
transform : translateZ (0);
}
.menu a:hover[data-bubble]::after,
.menu a:active[data-bubble]::after,
.menu a:focus[data-bubble]::after {
top: -1.25em;
z-index: 1;
}
[1] z-index
をマイナスからプラスに切り替えたとき、環境によっては背景がちらつく。transform
プロパティでtranslateZ()
関数を定めたのは、それを避けるための記述だ。
.menu a[data-bubble]::after {
transform : translateZ (0);
}
数字に飛び出すようなアニメーションを加える
いよいよ数字の擬似要素に、飛び出すようなアニメーションを加えて仕上げよう。animation
プロパティと@keyframes
規則を以下のように加える。これらの定めだけ見ると、transform
プロパティでtranslateY()
関数により、垂直位置を上げ下げしているだけと捉えるかもしれない。しかも、アニメーションの終わる位置は、始まりより下がる。しかし、@keyframes
規則をよくよく眺めると、top
プロパティが含まれている。この値は、マウスポインタを重ねたとき(:hover
と:active
および:focus
) 、少し上に持ち上げられているのだ。表1 のようにこれらが組み合わさって、バーの裏から飛び出して、半分持ち上がった位置に降りるアニメーションになっている。なお、animation-fill-mode
プロパティ はboth
とした。
表1 数字要素の垂直位置のアニメーション
キーフレーム transform top
0% 0 0
50% -12px -
100% 6px -1.25em
.menu a:hover[data-bubble]::after,
.menu a:active[data-bubble]::after,
.menu a:focus[data-bubble]::after {
animation : bubbleover 0.4s;
animation-fill-mode : both;
top: -1.25em;
z-index: 1;
}
@keyframes bubbleover {
0% {
top: 0;
transform : translateY (0);
z-index: -1;
}
50% {
transform : translateY (-12px);
z-index: -1
}
100% {
transform : translateY (6px);
z-index: 1;
}
}
あとおまけとして、3つめのメニュー項目(class
属性"gold")だけ数字の背景色が違う。CSSには以下の定めが加えてある。書き上がったCSSの記述は、以下のコード3 にまとめたとおりだ。
<ul class="menu">
<li><a class="gold" href="#" data-bubble="1">Hidden Coins</a></li>
</ul>
a.gold[data-bubble]::after {
background-color: gold;
}
コード3 マウスポインタを重ねると数字が飛び出すメニューバー
body {
padding: 1em 2em;
font: 100%/1.5 "Helvetica Neue", sans-serif;
color: #eee;
background: #485258;
}
.menu {
display: inline-block;
box-shadow : 0.12em 0.12em 0 rgba(40, 40, 40, 0.2);
list-style-type: none;
padding: 0;
}
.menu li {
float:left;
border-left:0.063em solid #a6c6cd;
border-right:0.063em solid #6ca1ac;
}
.menu a {
display: block;
padding: 0 1em;
line-height: 2.5em;
position:relative;
font-weight: bold;
text-decoration: none;
color: #364652;
background-color: #86B2BB;
text-shadow : 0 0.063em 0 #a6c6cd;
}
.menu a:hover,
.menu a:active,
.menu a:focus {
color: #eee;
text-shadow : 0.063em 0.063em 0 #547177;
}
.menu a[data-bubble]::after {
content: attr (data-bubble);
position: absolute;
top: 0;
right: 0.5em;
line-height: 1.5em;
padding: 0 0.46em;
text-shadow : 0 0.063em 0 rgba(0, 0, 0, 0.2);
background-color: #eee;
color: #364652;
box-shadow : 0 0.063em 0.063em rgba(0, 0, 0, 0.2);
border-radius : 4em;
z-index: -1;
transform : translateZ (0);
}
a.gold[data-bubble]::after {
background-color: gold;
}
.menu a:hover[data-bubble]::after,
.menu a:active[data-bubble]::after,
.menu a:focus[data-bubble]::after {
animation : bubbleover 0.4s;
animation-fill-mode : both;
top: -1.25em;
z-index: 1;
}
@keyframes bubbleover {
0% {
top: 0;
transform : translateY (0);
z-index: -1;
}
50% {
transform : translateY (-12px);
z-index: -1
}
100% {
transform : translateY (6px);
z-index: 1;
}
}