CSS3アニメーションでつくるインターフェイス表現

第18回飛び出す数字のアニメーション

今回のお題は、メニュー項目にポインタを重ねると数字が飛び出してくるバーだサンプル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-leftborder-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 インタラクションを加える前のメニューバー
図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 マウスポインタを重ねるとテキストの表現が変わる
図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 擬似要素で数字を示す
図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 マウスポインタを重ねたメニュー項目に数字が示される
図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;
}

数字に飛び出すようなアニメーションを加える

いよいよ数字の擬似要素に、飛び出すようなアニメーションを加えて仕上げよう。animationプロパティと@keyframes規則を以下のように加える。これらの定めだけ見ると、transformプロパティでtranslateY()関数により、垂直位置を上げ下げしているだけと捉えるかもしれない。しかも、アニメーションの終わる位置は、始まりより下がる。しかし、@keyframes規則をよくよく眺めると、topプロパティが含まれている。この値は、マウスポインタを重ねたとき:hover:activeおよび:focus⁠ 、少し上に持ち上げられているのだ。表1のようにこれらが組み合わさって、バーの裏から飛び出して、半分持ち上がった位置に降りるアニメーションになっている。なお、animation-fill-modeプロパティbothとした。

表1 数字要素の垂直位置のアニメーション
キーフレームtransformtop
0%00
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;
    }
}

おすすめ記事

記事・ニュース一覧