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

第7回追加情報をアニメーションで表示するボタン

今回のお題は、アニメーションするボタンだ。マウスポインタを重ねると追加情報が現れるサンプル1⁠。Animated Buttonsの表現を参考にした。例によって、HTMLとCSSの構成はわかりやすく改め、コードも絞り込んである。

サンプル1 CSS3: Animatied buttons

ボタンの静的なデザイン

<body>要素に書くコードは以下のように構成した。各ボタンを<a>要素class属性"btn")として<div>要素class属性"container")の中に納めた。ボタンの<a>要素は、それぞれ3つの<span>要素class属性"btn-text"と"btn-slide-text"および"btn-icon")をパーツとして含んでいる図1⁠。3つめの<span>要素の中には、さらに空の<span>要素が加えてあり、CSSで矢印を背景画像として与える。

図1 すべてが表示されたボタンと構成要素のクラス名
図1 すべてが表示されたボタンと構成要素のクラス名
<div class="container">
    <a href="#" class="btn">
        <span class="btn-text">Simple interface</span> 
        <span class="btn-slide-text">CSS3</span>
        <span class="btn-icon"><span></span></span>
    </a>
    <a href="#" class="btn">
        <span class="btn-text">Dynamic contents</span>
        <span class="btn-slide-text">CreateJS</span>
        <span class="btn-icon"><span></span></span>
    </a>
    <a href="#" class="btn">
        <span class="btn-text">3D contents</span>
        <span class="btn-slide-text">Away3D</span>
        <span class="btn-icon"><span></span></span>
    </a>
</div>

この<body>要素の記述に対して、つぎのような<style>要素を与える。各ボタンはすべてが表示され、まだアニメーションもマウスインタラクションもない(前掲図1⁠。なお、CSSにベンダープレフィックスを付けなくて済むように、<script>要素で-prefix-freeを読み込んでいる(第1回のベンダープレフィックスと-prefix-freeの項参照⁠⁠。また、Google FontsのOswaldを使った(第5回のGoogle Fontsと回り込みの解除参照⁠⁠。

<script src="lib/prefixfree.min.js" type="text/javascript"></script>
<link href="http://fonts.googleapis.com/css?family=Oswald" rel="stylesheet" type="text/css" />
<style>
body {
    margin:0;
    padding:0;
    background: aliceblue;
    font-family: 'Oswald', Arial, sans-serif;
}
.container {
    width: 320px;
    margin: 0 auto;
    padding: 20px 0;
}
.btn {
    background: linear-gradient(to bottom, lightsteelblue, steelblue);
    padding-left: 20px;
    padding-right: 180px;
    height: 38px;
    position: relative;
    border: 1px solid slategray;
    box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8) inset,
        1px 1px 3px rgba(0, 0, 0, 0.2),
        0px 0px 0px 4px rgba(188, 188, 188, 0.5);
    border-radius: 20px;
    float: left;
    clear: both;
    margin: 10px 0px;
    color: white;
    text-decoration: none;
}
.btn-text,
.btn-slide-text {
    font-size: 18px;
    white-space: nowrap;
}
.btn-text {
    padding-top: 5px;
    display: block;
    text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.3);
    color: midnightblue;
}
.btn-slide-text {
    position: absolute;
    top: 0px;
    right: 52px;
    width: 100px;
    background: dimgray;
    text-shadow: 0px -1px 1px black;
    color: white;
    text-transform: uppercase;
    text-indent: 10px;
    overflow: hidden;
    line-height: 38px;
    box-shadow: -1px 0px 1px rgba(255, 255, 255, 0.4),
        1px 1px 2px rgba(0, 0, 0, 0.2) inset;
}
.btn-icon {
    position: absolute;
    right: 0px;
    top: 0px;
    height: 100%;
    width: 52px;
    border-left: 1px solid slategray;
    box-shadow: 1px 0px 1px rgba(255, 255, 255, 0.4) inset;
}
.btn-icon span {
    width: 38px;
    height: 38px;
    opacity: 0.7;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -20px 0px 0px -20px;
    background: url(images/arrow_right.png) no-repeat 50% 55%;
}
</style>

ボタンの凹凸の表現

アニメーションに取りかかる前に、前掲CSSで定めた、ボタンの凹凸の表現の仕方について確かめておく。グラデーションとボーダーおよびシャドウを組み合わせて立体風に見せている図2⁠。

図2 立体のように凹凸が表現されたボタン
図2 立体のように凹凸が表現されたボタン

まず、ボタン全体の<a>要素class属性"btn")は、backgroundプロパティに定めたlinear-gradient()関数で背景を線形のグラデーションで塗るとともに、borderプロパティにより外枠を与えた(第2回のメニューに角の丸みと影を加える参照⁠⁠。また、border-radiusプロパティが角を丸くしている。そして、box-shadowプロパティの構文はつぎのとおりだ。普通に影をつけるだけでなく、insetキーワードで内側に光や影を加えれば、凹凸が表せる(第1回の影でボタンを立体的に見せる参照⁠⁠。さらに、ぼけ幅を0にすることで、ボーダーのような縁をつけることも可能だ。

box-shadow: [inset] 水平のずれ 垂直のずれ ぼけ幅 カラー

ボタン全体class属性"btn")は、内側上部に白を与えて膨らみを表した。そして、右下の影に加え、グレーで太めの縁を加えた。2番目のパーツclass属性"btn-slide-text")の左端には白を与えることで初めのパーツを膨らませ、内側左上の影で凹みを表している。3番目のパーツclass属性"btn-icon")は内側左端に白を与えて膨らませた。さらに、border-leftプロパティで左のパーツ右端に凹みを加えた。

.btn {
    background: linear-gradient(to bottom, lightsteelblue, steelblue);

    border: 1px solid slategray;
    box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8) inset,
        1px 1px 3px rgba(0, 0, 0, 0.2),
        0px 0px 0px 4px rgba(188, 188, 188, 0.5);
    border-radius: 20px;

}

.btn-slide-text {

    box-shadow: -1px 0px 1px rgba(255, 255, 255, 0.4),
        1px 1px 2px rgba(0, 0, 0, 0.2) inset;

}
.btn-icon {

    border-left: 1px solid slategray;
    box-shadow: 1px 0px 1px rgba(255, 255, 255, 0.4) inset;
}

ボタンにポインタを重ねたら追加情報を示す

ボタンの追加情報を初めは隠しておき、マウスポインタを重ねたら表示しよう。まず、ボタン全体の要素class属性"btn")の幅は、padding-rightプロパティで初めは縮めておき、マウスポインタが重なったら:hover擬似クラスでもとに戻す。つぎに、追加情報の要素class属性"btn-slide-text")widthプロパティの値を初めは0とし、やはりマウスポインタが重なったときに戻せばよい。これでマウスポインタを重ねたボタンの追加情報が示される。

.btn {

    /*padding-right: 180px;*/
    padding-right: 80px;

}

.btn-slide-text {

    /*width: 100px;*/
    width: 0px;

}

.btn:hover {
    padding-right: 180px;

}
.btn:hover .btn-slide-text {
    width: 100px;
}

アニメーションに効果を加える

ボタンのアニメーションにもう少し効果を加えよう。ボタン全体の要素class属性"btn")には、transitionプロパティを定める。タイミング関数は、変化が一定のlinearを用いた。また、マウスポインタを重ねたとき:hover⁠、box-shadowプロパティで加えた太い縁は外している。そして、3番目のパーツ(class属性"btn-icon")の中の矢印の背景画像を与えたspan要素は、半透明にしてあったopacityプロパティの値を1にした。これで、ボタンにマウスポインタを重ねると、効果のともなったアニメーションで追加情報が示される図3⁠。ここまでのCSSの定めを以下のコード1にまとめた。

.btn {

    transition: 0.3s linear;

}

.btn:hover {

    box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8) inset,
        1px 1px 3px rgba(0, 0, 0, 0.2);
}


.btn:hover .btn-icon span {
    opacity: 1;
}
図3 ボタンにマウスポインタを重ねると追加情報がアニメーションで示される
図3 ボタンにマウスポインタを重ねると追加情報がアニメーションで示される
コード1 マウスポインタを重ねるとアニメーションで追加情報が示されるボタン
body {
    margin:0;
    padding:0;
    background: aliceblue;
    font-family: 'Oswald', Arial, sans-serif;
}
.container {
    width: 320px;
    margin: 0 auto;
    padding: 20px 0;
}
.btn {
    background: linear-gradient(to bottom, lightsteelblue, steelblue);
    padding-left: 20px;
    padding-right: 80px;
    height: 38px;
    position: relative;
    border: 1px solid slategray;
    box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8) inset,
        1px 1px 3px rgba(0, 0, 0, 0.2),
        0px 0px 0px 4px rgba(188, 188, 188, 0.5);
    border-radius: 20px;
    float: left;
    clear: both;
    margin: 10px 0px;
    transition: 0.3s linear;
    color: white;
    text-decoration: none;
}
.btn-text,
.btn-slide-text {
    font-size: 18px;
    white-space: nowrap;
}
.btn-text {
    padding-top: 5px;
    display: block;
    text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.3);
    color: midnightblue;
}
.btn-slide-text {
    position: absolute;
    top: 0px;
    right: 52px;
    width: 0px;
    background: dimgray;
    text-shadow: 0px -1px 1px black;
    color: white;
    text-transform: uppercase;
    text-indent: 10px;
    overflow: hidden;
    line-height: 38px;
    box-shadow: -1px 0px 1px rgba(255, 255, 255, 0.4),
        1px 1px 2px rgba(0, 0, 0, 0.2) inset;
}
.btn-icon {
    position: absolute;
    right: 0px;
    top: 0px;
    height: 100%;
    width: 52px;
    border-left: 1px solid slategray;
    box-shadow: 1px 0px 1px rgba(255, 255, 255, 0.4) inset;
}
.btn-icon span {
    width: 38px;
    height: 38px;
    opacity: 0.7;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -20px 0px 0px -20px;
    background: url(images/arrow_right.png) no-repeat 50% 55%;
}
.btn:hover {
    padding-right: 180px;
    box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8) inset,
        1px 1px 3px rgba(0, 0, 0, 0.2);
}
.btn:hover .btn-slide-text {
    width: 100px;
}
.btn:hover .btn-icon span {
    opacity: 1;
}

ボタンのパーツのアニメーションを仕上げる

前傾コード1のアニメーションはまだ不完全だ。ボタンはアニメーションで幅が広がるのに、追加情報の幅はただちに変わるのでボタンのテキストに重なってしまう図4⁠。そこで、以下に抜き書きしたCSSのように、ボタンの中の3つの要素(class属性"btn-text"と"btn-slide-text"および"btn-icon")にも、transitionプロパティを定める。また、ボタンにマウスポインタを重ねたとき、テキストと影その影の色を変えた。さらに、ボタンを押した場合:active擬似クラス)のスタイルも新たに加える。これで、マウスポインタを重ねると細かな効果の加わったアニメーションで追加情報が示されるボタンのできあがりだ。CSSの定めと合わせて<body>要素の記述も、以下のコード2にまとめた。

図4 ボタンにポインタを重ねたとき追加情報が重なって現れる
図4 ボタンにポインタを重ねたとき追加情報が重なって現れる
.btn-text {

    transition: 0.2s linear;
}
.btn-slide-text {

    transition: 0.3s linear;
}

.btn-icon span {

    transition: 0.3s linear;
}

.btn:hover .btn-text {
    text-shadow: 0px 1px 1px slategray;
    color: white;
}

.btn:active {
    top: 1px;
    background: steelblue;
    box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4) inset;
    border-color: lightsteelblue;
}
コード2 マウスポインタを重ねると細かな効果の加わったアニメーションで追加情報が示されるボタン
<div class="container">
    <a href="#" class="btn">
        <span class="btn-text">Simple interface</span> 
        <span class="btn-slide-text">CSS3</span>
        <span class="btn-icon"><span></span></span>
    </a>
    <a href="#" class="btn">
        <span class="btn-text">Dynamic contents</span>
        <span class="btn-slide-text">CreateJS</span>
        <span class="btn-icon"><span></span></span>
    </a>
    <a href="#" class="btn">
        <span class="btn-text">3D contents</span>
        <span class="btn-slide-text">Away3D</span>
        <span class="btn-icon"><span></span></span>
    </a>
</div>
body {
    margin:0;
    padding:0;
    background: aliceblue;
    font-family: 'Oswald', Arial, sans-serif;
}
.container {
    width: 320px;
    margin: 0 auto;
    padding: 20px 0;
}
.btn {
    background: linear-gradient(to bottom, lightsteelblue, steelblue);
    padding-left: 20px;
    padding-right: 80px;
    height: 38px;
    position: relative;
    border: 1px solid slategray;
    box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8) inset,
        1px 1px 3px rgba(0, 0, 0, 0.2),
        0px 0px 0px 4px rgba(188, 188, 188, 0.5);
    border-radius: 20px;
    float: left;
    clear: both;
    margin: 10px 0px;
    transition: 0.3s linear;
    color: white;
    text-decoration: none;
}
.btn-text,
.btn-slide-text {
    font-size: 18px;
    white-space: nowrap;
}
.btn-text {
    padding-top: 5px;
    display: block;
    text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.3);
    color: midnightblue;
    transition: 0.2s linear;
}
.btn-slide-text {
    position: absolute;
    top: 0px;
    right: 52px;
    width: 0px;
    background: dimgray;
    text-shadow: 0px -1px 1px black;
    color: white;
    text-transform: uppercase;
    text-indent: 10px;
    overflow: hidden;
    line-height: 38px;
    box-shadow: -1px 0px 1px rgba(255, 255, 255, 0.4),
        1px 1px 2px rgba(0, 0, 0, 0.2) inset;
    transition: 0.3s linear;
}
.btn-icon {
    position: absolute;
    right: 0px;
    top: 0px;
    height: 100%;
    width: 52px;
    border-left: 1px solid slategray;
    box-shadow: 1px 0px 1px rgba(255, 255, 255, 0.4) inset;
}
.btn-icon span {
    width: 38px;
    height: 38px;
    opacity: 0.7;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -20px 0px 0px -20px;
    background: url(images/arrow_right.png) no-repeat 50% 55%;
    transition: 0.3s linear;
}
.btn:hover {
    padding-right: 180px;
    box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.8) inset,
        1px 1px 3px rgba(0, 0, 0, 0.2);
}
.btn:hover .btn-text {
    text-shadow: 0px 1px 1px slategray;
    color: white;
}
.btn:hover .btn-slide-text {
    width: 100px;
}
.btn:hover .btn-icon span {
    opacity: 1;
}
.btn:active {
    top: 1px;
    background: steelblue;
    box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4) inset;
    border-color: lightsteelblue;
}

おすすめ記事

記事・ニュース一覧