CSSだけで「loading・読み込み中」を飾る8つの方法

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

CSSだけでloadingを作る方法の6回目です。
過去に矢印ボールが回転するloadingloadingバーその他の回転系その他のバータイプと紹介してきました。
toolの方でまとめる予定でしたが、作業中にテキスト型のloadingがないことに気付きましたので、1から作成してみました。
PCブラウザではIE11・IE10・Chrome・Safari・Firefox、スマホではiOSのSafari・Android標準ブラウザ・Chrome・Firefoxに対応しています。

尻尾タイプ

Loading
読み込み中

「loading」や「読み込み中」の後に点々が続く、かなり良く見かけるタイプです。
HTMLは次のようになります。
<span class="loading">Loading<span></span></span>
CSSは以下です。 

span.loading {
    display: inline-block;
    white-space: nowrap;
}
    span.loading span {
        display: inline-block;
        width: 100px;
        height: 2px;
        vertical-align: middle;

        background-position: 0 0;
        background-repeat: repeat-x;
        background-size: 4px 100%;

        background-image:-webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.5, transparent), color-stop(0.5, #000), to(#000) );
        background-image:-webkit-linear-gradient(left,transparent 2px,#000 4px);
        background-image: linear-gradient(to right,transparent 2px,#000 4px);

        -webkit-animation: animation 1.5s linear infinite;
        animation: animation 1.5s linear infinite;
    }

@-webkit-keyframes animation {
    0% {
        width: 0;
    }
    100% {
        width: 100%;
    }
}

@keyframes animation {
    0% {
        width: 0;
    }
    100% {
        width: 100%;
    }
} 

解説

loading要素の中にspanを設置し、このspanでgradientを利用して点線風のラインを描写し、animationでサイズを変化させています。
尚、span要素を設置せずに疑似要素でやれそうですが、一部のwebkit系ブラウザでは疑似要素に設定したanimationが動かないためできません。
また、dottedのborderでやれそうですが、点線がスライドしているように見えてしまうため却下しました。解決策がある可能性はありますが今回はgradientを採用しました。

バウンドタイプ

Loading

Loadingが左からタイミングをずらしてバウンドします。Loadingには限らず、良く利用される装飾方法かと思います。
HTMLは全てのテキストを1文字ずつspanで囲みます。
<span class="loading"><span>L</span><span>o</span><span>a</span><span>d</span><span>i</span><span>n</span><span>g</span></span>
CSSは以下です。 

span.loading {
    display: inline-block;
    white-space: nowrap;
}
    span.loading span {
        display: inline-block;
        vertical-align: middle;
    }
    span.loading span:nth-of-type(1) {
        -webkit-animation: animation 2s ease 0s infinite;
        animation: animation 2s ease 0s infinite;
    }
    span.loading span:nth-of-type(2) {
        -webkit-animation: animation 2s ease 0.1s infinite;
        animation: animation 2s ease 0.1s infinite;
    }
    span.loading span:nth-of-type(3) {
        -webkit-animation: animation 2s ease 0.2s infinite;
        animation: animation 2s ease 0.2s infinite;
    }
    span.loading span:nth-of-type(4) {
        -webkit-animation: animation 2s ease 0.3s infinite;
        animation: animation 2s ease 0.3s infinite;
    }
    span.loading span:nth-of-type(5) {
        -webkit-animation: animation 2s ease 0.4s infinite;
        animation: animation 2s ease 0.4s infinite;
    }
    span.loading span:nth-of-type(6) {
        -webkit-animation: animation 2s ease 0.5s infinite;
        animation: animation 2s ease 0.5s infinite;
    }
    span.loading span:nth-of-type(7) {
        -webkit-animation: animation 2s ease 0.6s infinite;
        animation: animation 2s ease 0.6s infinite;
    }

@-webkit-keyframes animation {
    0% {
        margin-top: 0;
    }
    5% {
        margin-top: -1em;
    }
    10% {
        margin-top: 0;
    }
    13% {
        margin-top: -0.5em;
    }
    16% {
        margin-top: 0;
    }
    18% {
        margin-top: -0.2em;
    }
    20% {
        margin-top: 0;
    }
}

@keyframes animation {
    0% {
        margin-top: 0;
    }
    5% {
        margin-top: -1em;
    }
    10% {
        margin-top: 0;
    }
    13% {
        margin-top: -0.5em;
    }
    16% {
        margin-top: 0;
    }
    18% {
        margin-top: -0.2em;
    }
    20% {
        margin-top: 0;
    }
} 

解説

文字数分だけnth-of-type(1)といった具合に各1つ文字を指定して、それぞれにanimationを設定しています。animation-delayプロパティを0.1秒ずつずらして定義することで左側波打つようにanimationが実行されます。
animationの中身では、バウンドを意識してmargin-topを変化させています。厳密な計算でパーセントとmarginの量を変化させれば、よりリアルなバウンドを再現できますが、バウンド対象が複数あり、比較的スピードのあるバウンドのため、減衰を少なめにして「バウンド感」を演出すること優先された方が良いと思われます。
尚、例では「Loading」「読み込み中」の各7・5文字のテキストにしていますが、これ以上の場合はnth-of-typeを増やしてください。

振り子タイプ

Loading

こちらもloadingに限らずよく見る装飾です。ボキャブラリーが足らず「振り子」と名付けました。
HTMLは上のバウンドと同じく1文字ずつspanで囲みます。
<span class="loading"><span>L</span><span>o</span><span>a</span><span>d</span><span>i</span><span>n</span><span>g</span></span>
CSSは以下です。 

span.loading {
    display: inline-block;
    white-space: nowrap;
}
    span.loading span {
        display: inline-block;
        vertical-align: middle;
    }
    span.loading span:nth-of-type(1) {
        -webkit-animation: animation 2s ease 0s infinite;
        animation: animation 2s ease 0s infinite;
    }
    span.loading span:nth-of-type(2) {
        -webkit-animation: animation 2s ease 0.1s infinite;
        animation: animation 2s ease 0.1s infinite;
    }
    span.loading span:nth-of-type(3) {
        -webkit-animation: animation 2s ease 0.2s infinite;
        animation: animation 2s ease 0.2s infinite;
    }
    span.loading span:nth-of-type(4) {
        -webkit-animation: animation4 2s ease 0.3s infinite;
        animation: animation 2s ease 0.3s infinite;
    }
    span.loading span:nth-of-type(5) {
        -webkit-animation: animation 2s ease 0.4s infinite;
        animation: animation 2s ease 0.4s infinite;
    }
    span.loading span:nth-of-type(6) {
        -webkit-animation: animation 2s ease 0.5s infinite;
        animation: animation 2s ease 0.5s infinite;
    }
    span.loading span:nth-of-type(7) {
        -webkit-animation: animation 2s ease 0.6s infinite;
        animation: animation 2s ease 0.6s infinite;
    }

@-webkit-keyframes animation {
    0% {
        -webkit-transform: rotate(-45deg);
    }
    5% {
        -webkit-transform: rotate(45deg);
    }
    10% {
        -webkit-transform: rotate(-23deg);
    }
    13% {
        -webkit-transform: rotate(23deg);
    }
    16% {
        -webkit-transform: rotate(-12deg);
    }
    18% {
        -webkit-transform: rotate(12deg);
    }
    20% {
        -webkit-transform: rotate(0);
    }
}

@keyframes animation {
    0% {
        transform: rotate(-45deg);
    }
    5% {
        transform: rotate(45deg);
    }
    10% {
        transform: rotate(-23deg);
    }
    13% {
        transform: rotate(23deg);
    }
    16% {
        transform: rotate(-12deg);
    }
    18% {
        transform: rotate(12deg);
    }
    20% {
        transform: rotate(0);
    }
} 

解説

基本構造はバウンドタイプと同一なのでそちらをご参照ください。
animation内では、transform:rotateを使って文字を交互に左右に傾けています。傾きを減衰させることで、垂直に戻る力が働いているような錯覚を生んでいます。

さざ波タイプ

Loading

今回紹介する8種類の中で唯一、IEでのみ見た目が異なり、左から右へ向けて文字がキラキラと反射しているように見えます。その他では、浜辺に置かれた文字がたゆたっているように見えます。
<span class="loading"><span>L</span><span>o</span><span>a</span><span>d</span><span>i</span><span>n</span><span>g</span></span>
CSSは以下です。 

span.loading {
    display: inline-block;
    white-space: nowrap;
}
    span.loading span {
        display: inline-block;
        vertical-align: middle;
    }
    span.loading span:nth-of-type(1) {
        -webkit-animation: animation 2s ease 0s infinite;
        animation: animation 2s ease 0s infinite;
    }
    span.loading span:nth-of-type(2) {
        -webkit-animation: animation 2s ease 0.1s infinite;
        animation: animation 2s ease 0.1s infinite;
    }
    span.loading span:nth-of-type(3) {
        -webkit-animation: animation 2s ease 0.2s infinite;
        animation: animation 2s ease 0.2s infinite;
    }
    span.loading span:nth-of-type(4) {
        -webkit-animation: animation 2s ease 0.3s infinite;
        animation: animation 2s ease 0.3s infinite;
    }
    span.loading span:nth-of-type(5) {
        -webkit-animation: animation 2s ease 0.4s infinite;
        animation: animation 2s ease 0.4s infinite;
    }
    span.loading span:nth-of-type(6) {
        -webkit-animation: animation 2s ease 0.5s infinite;
        animation: animation 2s ease 0.5s infinite;
    }
    span.loading span:nth-of-type(7) {
        -webkit-animation: animation 2s ease 0.6s infinite;
        animation: animation 2s ease 0.6s infinite;
    }

@-webkit-keyframes animation {
    20% {
        -webkit-text-shadow: rgba(0, 0, 0, 1) 5px 0 0;
        color: transparent;
    }
}

@keyframes animation {
    20% {
        text-shadow: rgba(0, 0, 0, 1) 5px 0 0;
        color: transparent;
    }
} 

解説

基本構造はバウンドタイプと同一です。
animation内で、文字色を透明化し、かつ左側に5pxずらしたtext-shadowを設定しています。これにより、元の文字が左にゆったりと5pxズレて戻る効果が得られます。
IEではanimation内でtext-shadowが効かないため、文字色の効果のみが表現されます。IEとその他を統一したい場合は、animation内のtext-shadowを消してください。
同一の表現をすべくtext-indentやmargin-leftなどで試してみましたが、color:transparentとtext-shadowの組み合わせが最も波っぽかったので採用しました。

ぶるぶるタイプ

Loading
読み込み中

文字列が一時的にぶるぶると動いて目立ちます。ボタンにマウスを重ねた際や、「NEW」アイコンなどを目立たせるためなど、様々に利用される手法です。
「応答していない」のではなく、しっかり「読み込み中」であることを強く伝えることができます。
HTMLはspanのみでシンプルです。
<span class="loading">Loading</span>
CSSは以下です。 

span.loading {
    position: relative;
    left: 0;
    top: 0;
    display: inline-block;
    white-space: nowrap;

    -webkit-animation: animation 2s infinite;
    animation: animation 2s infinite;
}

@-webkit-keyframes animation {
    4% {
        top: -12px;
        left: -12px;
    }
    8% {
        top: 11px;
        left: 11px;
    }
    12% {
        top: -10px;
        left: -10px;
    }
    16% {
        top: 9px;
        left: 9px;
    }
    18% {
        top: -8px;
        left: -8px;
    }
    20% {
        top: 7px;
        left: 7px;
    }
    22% {
        top: -6px;
        left: -6px;
    }
    24% {
        top: 5px;
        left: 5px;
    }
    25% {
        top: -4px;
        left: -4px;
    }
    26% {
        top: 3px;
        left: 3px;
    }
    27% {
        top: -2px;
        left: -2px;
    }
    28% {
        top: 1px;
        left: 1px;
    }
    29% {
        top: 0;
        left: 0;
    }
}

@keyframes animation {
    4% {
        top: -12px;
        left: -12px;
    }
    8% {
        top: 11px;
        left: 11px;
    }
    12% {
        top: -10px;
        left: -10px;
    }
    16% {
        top: 9px;
        left: 9px;
    }
    18% {
        top: -8px;
        left: -8px;
    }
    20% {
        top: 7px;
        left: 7px;
    }
    22% {
        top: -6px;
        left: -6px;
    }
    24% {
        top: 5px;
        left: 5px;
    }
    25% {
        top: -4px;
        left: -4px;
    }
    26% {
        top: 3px;
        left: 3px;
    }
    27% {
        top: -2px;
        left: -2px;
    }
    28% {
        top: 1px;
        left: 1px;
    }
    29% {
        top: 0;
        left: 0;
    }
} 

解説

position:relativeにし、animation内でtopとleftを変化させることで、文字が揺れている感じを表現しています。
パーセントの間隔を減らすことで減衰を表現していますが、厳密な計算は行っていません。
loadingに限らず他の場面でも利用できると思います。例えば、a:hoverに設定することで、動きのあるボタンを簡単に作れます。

動く点線タイプ

Loading
読み込み中

下線を移動させることで、控えめに読込中を表現しています。
HTMLはspan内に空のspanを設置し、これで下線を表現しています。
<span class="loading">Loading<span></span></span>
CSSは以下です。 

span.loading {
    position: relative;
    display: inline-block;
}
    span.loading span {
        position: absolute;
        display: inline-block;
        left: 0;
        right: 0;
        top: 100%;
        height: 2px;

        background-position: 0 0;
        background-repeat: repeat-x;
        background-size: 10px 100%;

        background-image:-webkit-gradient(linear, left top, right top, from(transparent), color-stop(0.9, transparent), color-stop(0.9, #000), to(#000) );
        background-image:-webkit-linear-gradient(left,transparent 5px,#000 5px,#000 10px);
        background-image: linear-gradient(to right,transparent 5px,#000 5px,#000 10px);

        -webkit-animation: animation 0.5s linear infinite;
        animation: animation 0.5s linear infinite;
    }

@-webkit-keyframes animation {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: 10px 0;
    }
}

@keyframes animation {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: 10px 0;
    }
} 

解説

中のspanにgradientでストライプを表現し、animationでbackground-positionを変化させることでストライプを移動させています。過去に紹介したloadingバーに似ています。
はじめに紹介した尻尾タイプと同様、borderのdottedやdashedでは表現できなかったためgradientを採用しています。
尚、background-sizeの10pxと、keyframes内のbackground-positionの10pxがずれると、滑らかな動作になりませんので、点線の間隔などを変更する際はご注意下さい。

バー伸長タイプ

Loading
読み込み中

上の動く点線タイプと同じ構造です。こちらもかなり控えめに見えます。
HTMLも上と同じく、spanを内部に設置します。
<span class="loading">Loading<span></span></span>
CSSは以下です。 

span.loading {
    position: relative;
    display: inline-block;
}
    span.loading span {
        position: absolute;
        display: inline-block;
        left: 0;
        top: 100%;
        width: 100%;
        height: 2px;

        background-position: 0 0;

        background-image:-webkit-gradient(linear, left top, right top, from(#000), to(transparent) );
        background-image:-webkit-linear-gradient(left,#000,transparent);
        background-image: linear-gradient(to right,#000,transparent);

        -webkit-animation: animation 2s linear infinite;
        animation: animation 2s linear infinite;
    }

@-webkit-keyframes animation {
    0% {
        width: 0;
        background-color: transparent;
    }
    40% {
        width: 100%;
        background-color: transparent;
    }
    80% {
        width: 100%;
        background-color: #000;
    }
    100% {
        width: 100%;
        background-color: #000;
    }
}

@keyframes animation {
    0% {
        width: 0;
        background-color: transparent;
    }
    40% {
        width: 100%;
        background-color: transparent;
    }
    80% {
        width: 100%;
        background-color: #000;
    }
    100% {
        width: 100%;
        background-color: #000;
    }
} 

解説

中のspanで設置したバーには、gradientで単純なグラデーションを設定しています。これをanimationで、widthを変化させることで、目盛が上昇するようなイメージを表現しています。
width:100%となった時点で、文字列と同じサイズのグラデーションが設置されます。これ以降は、backgroundの色を変化させて、グラデーションを1色で塗りつぶしています。以上により、100%まで目盛が達しているように見せています。

ボックスタイプ

Loading
読み込み中

これはオリジナルなアイディアです。文字列を囲む線が上から時計回りに展開されて、最終的にボックスに囲まれます。
paddingを設定して、もう少し大きな文字で使用すると、まずまず使えるかと思います。
HTMLはspanを中に設定します。
<span class="loading">Loading<span></span></span>
CSSは以下です。 

span.loading {
    position: relative;
    display: inline-block;

    border-top: 1px solid transparent;
    border-right: 1px solid transparent;
    border-bottom: 1px solid transparent;
    border-left: 1px solid transparent;

    -webkit-animation: animation 5s linear infinite;
    animation: animation 5s linear infinite;
}
    span.loading span {
        position: absolute;
        display: inline-block;

        left: -1px;
        top: -1px;
        width: 1px;
        height: 1px;

        background-color: #000;

        -webkit-animation: animation2 5s linear infinite;
        animation: animation2 5s linear infinite;
    }

@-webkit-keyframes animation {
    20% {
        border-top: 1px solid #000;
        border-right: 1px solid transparent;
        border-bottom: 1px solid transparent;
        border-left: 1px solid transparent;
    }
    40% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid transparent;
        border-left: 1px solid transparent;
    }
    60% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid #000;
        border-left: 1px solid transparent;
    }
    80% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid #000;
        border-left: 1px solid #000;
    }
    100% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid #000;
        border-left: 1px solid #000;
    }
}
@keyframes animation {
    20% {
        border-top: 1px solid #000;
        border-right: 1px solid transparent;
        border-bottom: 1px solid transparent;
        border-left: 1px solid transparent;
    }
    40% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid transparent;
        border-left: 1px solid transparent;
    }
    60% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid #000;
        border-left: 1px solid transparent;
    }
    80% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid #000;
        border-left: 1px solid #000;
    }
    100% {
        border-top: 1px solid #000;
        border-right: 1px solid #000;
        border-bottom: 1px solid #000;
        border-left: 1px solid #000;
    }
}

@-webkit-keyframes animation2 {
    0% {
        left: -1px;
        top: -1px;
    }

    2% {
        left: 100%;
        top: -1px;
    }
    20% {
        left: 100%;
        top: -1px;
    }

    22% {
        left: 100%;
        top: 100%;
    }
    40% {
        left: 100%;
        top: 100%;
    }

    42% {
        left: -1px;
        top: 100%;
    }
    60% {
        left: -1px;
        top: 100%;
    }

    62% {
        left: -1px;
        top: -1px;
    }
    80% {
        left: -1px;
        top: -1px;
    }
}

@keyframes animation2 {
    0% {
        left: -1px;
        top: -1px;
    }

    2% {
        left: 100%;
        top: -1px;
    }
    20% {
        left: 100%;
        top: -1px;
    }

    22% {
        left: 100%;
        top: 100%;
    }
    40% {
        left: 100%;
        top: 100%;
    }

    42% {
        left: -1px;
        top: 100%;
    }
    60% {
        left: -1px;
        top: 100%;
    }

    62% {
        left: -1px;
        top: -1px;
    }
    80% {
        left: -1px;
        top: -1px;
    }
} 

解説

animationを2つ使用しています。
1つ目は外側のspanで、時計回りにborder-colorを設定して色付けすることで、文字を囲む線を増やしています。
中のspanでは、1x1pxのドットを、左上から時計回りに移動させています。
外側のspanのみの場合は、枠線が順番に浮かび上がるように見えますが、これと並行して1x1pxのドットを移動させることで、枠線全体が同時に浮かび上がるのではなく、一端から一端へと線を引くように見せています。

カスタマイズ

font-size、font-familyなどは自由に設定できます。
上の解説をご理解いただける場合は、色やその他の変更も必要に応じてお試しください。
現在、loadingの色などを設定できるページをツールのページにオープン予定です。

IE9以下の対策

今回紹介したloadingの対応ブラウザは初めに書きましたが、主な未対応ブラウザはIE9以下です。
これまで紹介したloadingでは、条件付きコメント(if lte IE 9)で対応しておりましたが、幸い今回のloadingは全てテキスト表記があるため、animationが動作しなくても意味を伝えることが可能です。よって、特に対策はしておりません。

2015/8/21