CSSでつくるローディング(スピナーとバー)
読み込み中です
40パーセント終わりました
動く色と残りの色の差は 7.53対1 です。3対1 以上あるので、どこが動いているか見分けられます。
✓ 入っています。書き出す CSS には、@media (prefers-reduced-motion: reduce) の段落が必ず付きます。つねに入ったままです。
この端末の設定は、画面がついた直後に読み取ります。
先に、CSS を書かない作り方
HTML には進み具合の棒がもともと入っています。 下の1行だけで、この棒が出ます(見た目はブラウザまかせです)。
<!-- 中の文字は、この要素を描けない古い道具のための控えです --> <progress value="40" max="100">40パーセント</progress>
value を書かないと「不定」になります。終わりが見えない読み込みは、この形です。
くるくる回る輪のコード
この CSS が、上のプレビューをそのまま動かしています。画像は0個、JavaScript は0行です(1302文字・2208バイト)。
/* くるくる回る輪。画像ファイルは0個、JavaScript は0行です。 */
.pt-spinner {
box-sizing: border-box;
width: 48px;
height: 48px;
/* 半分だけ丸めると、正方形が円になります */
border-radius: 50%;
border: 6px solid #d0d5dd;
/* ⭐ 4辺のうち上の1辺だけ色を変える。これが回っている正体です */
border-top-color: #0017c1;
animation: pt-spin 1s linear infinite;
}
/* 1周(360度)だけ書けば、あとはずっと繰り返してくれます */
@keyframes pt-spin {
to {
transform: rotate(360deg);
}
}
/* この段落を消さないでください。
「動きを減らしたい」と機械に伝えている人がいます。
ぐるぐる回る絵で目が回ったり、気分が悪くなったりする人がいるからです。
その設定のときだけ、ここが効いて動きが止まります。 */
@media (prefers-reduced-motion: reduce) {
.pt-spinner {
/* 回るのをやめる。輪は残るので「待っているところ」は伝わります */
animation: none;
}
}<!-- 待っている絵。role="progressbar" で「進み具合の表示」だと伝えます --> <!-- 終わりが分からないので aria-valuenow は書きません --> <div class="pt-spinner" role="progressbar" aria-label="読み込み中"></div> <!-- 絵だけにしない。文字でも言います --> <p>読み込み中です</p>
進み具合のバーのコード
変えているのは、中の帯の幅だけです。
/* 進み具合のバー。外側が「ぜんぶ」、内側が「進んだぶん」です。 */
.pt-bar {
box-sizing: border-box;
width: 100%;
height: 14px;
background: #d0d5dd;
border-radius: 7px;
/* 中の帯を、丸めた角の内側に収める */
overflow: hidden;
}
.pt-bar-fill {
height: 100%;
background: #0017c1;
border-radius: inherit;
/* ⭐ 進んだぶん。ここだけ書き換えれば、バーが伸びます */
width: 40%;
/* 数が変わったとき、いきなり飛ばずに 0.3秒かけて伸びます */
transition: width 0.3s linear;
}
/* この段落を消さないでください。
「動きを減らしたい」と機械に伝えている人がいます。
ぐるぐる回る絵で目が回ったり、気分が悪くなったりする人がいるからです。
その設定のときだけ、ここが効いて動きが止まります。 */
@media (prefers-reduced-motion: reduce) {
.pt-bar-fill {
/* 伸びるのも「動き」です。設定に合わせて、すぐ切り替わるようにします */
transition: none;
}
}<!-- aria-valuemin と aria-valuemax は省いています。
書かないと 0 と 100 として扱う、と ARIA が決めているからです -->
<div class="pt-bar" role="progressbar" aria-label="読み込みの進み具合"
aria-valuenow="40">
<div class="pt-bar-fill"></div>
</div>
<p>40パーセント終わりました</p>長い行は、この枠の中だけ横に動かせます(キーボードでも動きます)。
よくある質問
ローディングのくるくるは、CSSだけで作れますか?
作れます。正方形の枠線を border-radius: 50% で円にして、4つの辺のうち1辺だけ色を変え、その円を回すだけです。画像ファイルは0個、JavaScriptは0行で足ります。画像で作ると、待たせている最中にその画像を取りに行くことになり、待っている絵のためにもう一度待つことになります。CSSなら、そのページの中に書いた文字だけで絵が動きます。
progress要素とCSSで作るバーは、どちらを使えばいいですか?
見た目を変えないなら progress 要素が短く済みます。1行書くだけで棒が出て、進み具合の意味もブラウザが分かってくれます。ただし見た目の変え方がブラウザごとに違い、思ったとおりに塗るのが難しいので、細かく作りたいときは自分でバーを組むことになります。そのときも、値の扱い方は progress 要素の決まりをそのまま真似るのが安全です。
終わりが分からないとき、aria-valuenowに0と書いてもいいですか?
いけません。0は「まだ進んでいない」という意味になり、「どこまで進んだか分からない」とは別のことです。WAI-ARIAは、値が分からないときはaria-valuenowを書かないこと、と決めています。書かないこと自体が「分からない」という情報になっていて、読み上げの道具はそこを読み分けます。標準のprogress要素も同じ考え方で、valueを書かなければ不定になります。
prefers-reduced-motionは必ず書かないといけませんか?
決まりの文言としては「読み込み中の動きは欠かせないものに当たるので、止めるボタンは要らない」となっています(WCAG 2.2.2の注記4)。ですが、ぐるぐる回る絵で目が回ったり気分が悪くなったりする人は実際にいて、その人は機械の設定で「動きを減らしたい」と申告しています。申告があるのに無視する理由がないので、このサイトでは書き出すCSSに必ず入れています。
スピナーはどれくらいの速さで回すのがいいですか?
1周1秒前後が読みやすい速さです。速くしすぎると、色の違う1辺が点滅しているように見えてきます。WCAG 2.3.1は、1秒に3回を超える点滅を禁じています。発作の引き金になりうるからです。この道具では、いちばん速い設定でも1周0.4秒(1秒に2.5回)までにして、その手前で止めてあります。
progress要素とmeter要素は何が違いますか?
progressは「終わりに向かって進んでいく作業」、meterは「決まった範囲の中のいまの値」です。HTMLの仕様は、ディスクの使用量をprogressで表すのは不適切で、そこはmeterを使うように、と名指しで書いています。ダウンロードの進み具合はprogress、電池の残りやテストの点数はmeterです。同じ棒に見えても、意味が違います。
くるくる回る絵と、進み具合のバー。画像もJavaScriptも要りません。 つまみを動かすと、そのまま貼れるCSSが出ます。
回っているのは、枠線の1辺だけです
くるくる回る絵の正体は、枠線の1辺だけ色を変えた円です。 まず正方形に枠線を引き、border-radius: 50%で角を半分まで丸めると、 正方形は円になります。その枠線のうち上の1辺だけを別の色にして、 円ごとぐるぐる回しているだけです。
回っているのは色ではなく、円そのものです。 色の違う1辺が円といっしょに動くので、目には「光っているところが回っている」ように見えます。 止めてよく見ると、ただの1か所だけ色の違う輪だと分かります。
ここが大事なところです。この絵のために取りに行くファイルが1つもありません。 待たせている最中に絵を取りに行く作りだと、待っている絵を出すために、もう一度待つことになります。 通信が遅いときほど、その絵が出てきません。いちばん必要なときにいちばん出ない、という困った形です。 CSSで描いた輪は、ページの文字の中にすでにあるので、その心配がありません。
動く色と残りの色は、はっきり違う色にします
輪のどこが動いているのか見分けられなければ、待っていることが伝わりません。 WCAG SC 1.4.11 は「内容を理解するのに必要な絵の部分」に3対1以上の差を求めています。ここが当てはまると考えて、この道具は 2つの色の差を測って、足りなければ画面に出すようにしました。見本の「見分けにくい色」を押すと、足りないときの見え方が分かります。
HTMLには、もともと進み具合の棒があります
CSSで作る前に知っておきたいことがあります。HTMLにはprogressという要素がもとから入っています。1行書くだけで棒が出て、しかもその棒が何を表しているかを ブラウザと読み上げの道具が分かってくれます。
面白いのは値を書かなかったときです。仕様には「To make an indeterminate progress bar, remove the value attribute.(不定の進み具合にするには、value属性を取り除く)」と書かれています。つまり書かないことが指定になっているわけです。 値が無い棒は「不定」── 終わりが見えない読み込みを表します。
どれくらい進んだかを数で聞くと、不定の棒は−1を返します。 仕様が「For an indeterminate progress bar, returns −1.」と決めているからです。 0でも空でもなく−1なのは、0が「まだ進んでいない」という別の意味を持っているからです。
もうひとつ、progressには使ってはいけない場面があります。 仕様は「ディスクの使用量を progress で表すのは不適切」と名指しで書き、 そこはmeterを使うように、と続けています。progressは「終わりに向かって進む作業」、meterは「決まった範囲の中のいまの値」。 同じ棒に見えても、意味が違います。
動きは止められるようにします。ここは外せません
ぐるぐる回る絵を見ると目が回る・気分が悪くなる人がいます。 乗り物に酔うのと似た仕組みで、本人の気の持ちようではありません。 だから機械(パソコンやスマホ)には「動きを減らしてほしい」と申告しておく設定があります。
CSSは、その申告を読み取れます。仕様の言葉では「the user has requested the system minimize the amount of non-essential motion it uses(欠かせないものではない動きを、できるだけ減らしてほしいと利用者が求めている)」を見分ける仕組みで、書き方は@media (prefers-reduced-motion: reduce)です。 この道具が書き出すCSSには、この段落が必ず入ります。外すつまみは置いていません。
なぜ外せないようにしたのか。申告をしているのは利用者本人で、こちらはそれを受け取る側だからです。 受け取るかどうかを作る人の好みで決められるようにすると、設定した人の申告が、作る人の気分で消えることになります。 色や速さは好みで決めていいところですが、ここは違います。
止めるときも輪は残します。回転だけをやめて、 1か所だけ色の違う輪をそのまま置いておきます。 終わりが分からないバーは、帯を真ん中あたりで止めます── 端に寄せて止めると「まだ始まっていない」「もう終わった」に見えてしまうからです。
この画面自身も、その設定に従っています。上のプレビューは、書き出しているCSSそのもので動いています。 だから「動きを減らす」設定の端末では、このページでも回りません。 自分のページで無視していたら、書いてあることを信じてもらえません。
止めるボタンは付けなくていいのですか
WCAG(ウェブのアクセシビリティの決まり)の SC 2.2.2 は、 自動で始まって5秒より長く動くものに止める手立てを求めています。 ただし「欠かせないもの」は例外で、注記4に「読み込みの最中の動きは、その間なにも操作できず、進んでいることを示さないと 止まったと勘違いされるなら、欠かせないものとみなせる」という趣旨が書かれています。だから止めるボタンは要りません。 そのぶん、機械の設定を尊重するほうが筋の通ったやり方になります。
速さにも決まりが効いています。輪は1か所だけ色が違うので、 速く回すほど点滅に近づきます。 SC 2.3.1 は1秒に3回を超える点滅を禁じています。 発作の引き金になりうるからです。だからこの道具は、いちばん速い設定でも1周0.4秒(1秒に2.5回)までにしてあります。
待っている絵には、名前と役割を付けます
丸い絵が回っていることは、目で見ている人にしか分かりません。 読み上げの道具に伝えるには、role="progressbar"と書いて「これは進み具合の表示です」と教え、aria-labelで名前を付けます。
ここでいちばん間違えやすいところがあります。 進み具合が分からないとき、aria-valuenowは書きません。WAI-ARIAは「値が分からないときは書かないこと」と決めています。書かないこと自体が「分からない」という情報だからです。 ここに0と書いてしまうと「まだ1つも進んでいない」と伝わり、 別のことを言ったことになります。
逆に、aria-valueminとaria-valuemaxは書かなくてもかまいません。書かなかったときは0と100として扱う、とWAI-ARIAが決めているからです。 パーセントで表すなら、その2つはもう決まっているわけです。
読み込んでいる場所そのものにも、しるしを付けられます。WAI-ARIAは、読み込み中の場所にaria-busyを付けて、終わったら外すことを勧めています。「ここはいま作りかえている最中です」と伝えるしるしです。
決まりの出どころ:HTML Standard 4.10.13 The progress element(新しいタブで開きます)、Media Queries Level 5(prefers-reduced-motion)(新しいタブで開きます)、WAI-ARIA 1.2(progressbar)(新しいタブで開きます)、WCAG 2.2(新しいタブで開きます)(2.2.2 の注記4・2.3.1・1.4.11)。すべて原文にあたって確かめています。 貼り付けた文字やえらんだ色はどこにも送っていません。 この画面の中だけで組み立てています。