矢印がグルグル回転するloadingをCSSだけで作る方法

Loadingアイコンメーカーはじめました(2015年9月3日)

前回、「一定時間のマウスオーバーで表示されるポップアップをCSSだけで実装する方法」を紹介しましたが、「CSSだけで」繋がりで今回はloadingを作ってみたいと思います。

今回は、下記のような矢印がグルグル回転するloadingを作ってみます(テストページはこちら)。

HTMLは非常にシンプルで、
<span class="loading"></span>
です。
CSSは次のようになります。

span.loading {
    position: relative;
    display: inline-block;
    width: 100px;
    height: 100px;
    border: 5px solid #000;

    border-radius: 55px;
}

    /*輪の区切り*/
    span.loading:before {
        position: absolute;
        display: inline-block;
        content: " ";
        left: 100%;
        top: 50%;
        margin-top: -15px;
        margin-left:-10px;
        width: 20px;
        height: 30px;
        background-color: #fff;
    }

    /*矢印*/
    span.loading:after {
        position: absolute;
        display: inline-block;
        content: " ";
        left: 100%;
        top: 50%;
        margin-top: -20px;
        margin-left:-10px;
        border: 10px solid transparent;
        border: 10px solid rgba(0, 0, 0, 0);
        border-top: 20px solid #000;
    }

span.loading要素に:before/:afterの疑似要素を設置し、一方は円の区切れを表現するブロックを、一方は矢印を表示しています。
背景が白以外の場合は、円の区切れを表現する部分をその背景色に設定する必要があります。そのため、背景が画像であったり、グラデーションが掛かっている場合は使えません。
ここまででで、このような回転しない丸い矢印が作れます。

大きさや色を調整する

まずspan.loadingのwidth/heightを希望のサイズに変更しましょう。width=heightが必須です。
次に、span.loadingのborderサイズと色を調整しましょう。
span.loadingのwidth/height/borderを変更した場合は、border-radius=width/2+borderとしましょう。ただ、2000pxなど大きい値にしても大丈夫なようです。

次に、輪の区切りはmargin-left=width/2*-1、margin-top=height/2*-1を守りつつ調整しましょう。背景が白以外の場合は個々のbackground-colorを変更します。

最後に、矢印の横幅はborder: 10pxの2行を同値にして変更、矢印の高さはbroder-top:20pxを調整します。ずれた場合は、margin-top/margin-leftで調整しましょう。span.loadingのborderの色を変えた場合は、矢印の色の変更も忘れずに。

animationを加える

次にanimationを追加します。
span.loadingに
    -webkit-animation: rotating 2s linear infinite;
    animation: rotating 2s linear infinite;
を追加し、keyframesを定義します。animationの2sは2秒を意味しますが、この数字を変えることで回転速度が変わります。
CSSは以下です。

span.loading {
    position: relative;
    display: inline-block;
    width: 100px;
    height: 100px;
    border: 5px solid #000;

    border-radius: 55px;
 
    -webkit-animation: rotating 2s linear infinite;
    animation: rotating 2s linear infinite;
}

    /*輪の区切り*/
    span.loading:before {
        position: absolute;
        display: inline-block;
        content: " ";
        left: 100%;
        top: 50%;
        margin-top: -15px;
        margin-left:-10px;
        width: 20px;
        height: 30px;
        background-color: #fff;
    }

    /*矢印*/
    span.loading:after {
        position: absolute;
        display: inline-block;
        content: " ";
        left: 100%;
        top: 50%;
        margin-top: -20px;
        margin-left:-10px;
        border: 10px solid transparent;
        border: 10px solid rgba(0, 0, 0, 0);
        border-top: 20px solid #000;
    }

    /*回転*/
    @-webkit-keyframes rotating {
        0% {
            -webkit-transform: rotate(0deg);
        }
        100% {
            -webkit-transform: rotate(360deg);
        }
    }
    @keyframes rotating {
        0% {
            transform: rotate(0deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }

クロスブラウザ対策

以上を正しく表示できるのは、Chrome、Firefox、Safari、IE10以上です。
IE9以下に対応するために、最後に以下を追加します。

<!--[if lte IE 9 ]>
<style type="text/css">
    /*非表示*/
    span.loading:before {
        display: none;
    }

    /*loading*/
    span.loading:after {
        content: "loading";
        border: none;
        left: 0;
        right: 0;
        top: 50%;
        margin-top: 0;
        margin-left: 0;
        text-align: center;
        line-height: 0;
    }
</style>
<![endif]-->

回転のアニメーションはありませんが、「loading」の文字が表示されます。IE9・IE8に対応しており、IE8以上であればloadingの意図を伝えることができます。

「CSSだけで」で出来るメリット

「CSSだけで」出来るメリットは、思いつくところで下記の3点が挙げられます。

  • 導入・カスタマイズが楽
  • ベクターのため高解像ディスプレイでもきれいに表示可
  • 背景透過

loadingをGIFアニメーションで設置した場合との比較を前提に説明してみます。
まず1は、例えばサイズや色を変える場合に、画像を作り直す必要がなく、CSSの一部を書き換えるだけでOKなのでとても楽です。
また2ですが、CSSで表示する要素はベクター画像のため、スマホやRetina Displayなど普及が進んでいる高解像ディスプレイでも「ギザギザ」せずに見ることができます。
最後に3は1に似ていますが、背景が透過なので場所を選ばず設置出来ます(ただし今回のものは一部が非透過なので要CSS設定)。

2015年6月18日)ベンダーprefixの検証結果を反映し、一部内容を修正しました。

2015/4/24