読み込みバー コンポーネントの作成

<progress> 要素を使用して、カラー アダプティブでアクセス可能な読み込みバーを作成する方法について、基本的な概要を示します。

この投稿では、カラー アダプティブ バナーを実装する方法についての考え方をご紹介します。 <progress> 要素を使用して、アクセス可能な読み込みバーを作成します。 デモ ソースをご覧ください。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Chrome でライトとダーク、不確定、増加、完了のデモを行います。

動画で視聴したい場合は、この投稿の YouTube バージョンをご利用ください。

概要

<progress> 要素により、完了を視覚的および音声でユーザーに知らせます。この 次のようなシナリオで役立ちます。 ダウンロードやアップロードに関する情報が表示され 進行状況の量は不明ですが、作業はまだ有効です。

この GUI チャレンジでは、 ユーザー補助の労力を軽減するために、既存の HTML <progress> 要素を使用します。「 色とレイアウトにより、組み込み要素のカスタマイズの限界がなくなるため、 コンポーネントをモダナイズして 設計システムに適合するようにします

<ph type="x-smartling-placeholder">
</ph> 各ブラウザのライトタブとダークタブで、 
    アダプティブ アイコンの概要(上から下): 
    Safari、Firefox、Chrome。 <ph type="x-smartling-placeholder">
</ph> Firefox、Safari、iOS Safari で表示されるデモ Chrome、Android Chrome をライト モードとダーク スキームで表示されます。

マークアップ

<progress> 要素を <label> では、 明示的な関係属性を省略して、暗黙的な関係属性を優先することもできます。 できます。 読み込み状態の影響を受ける親要素にもラベルを付けたので、画面 その情報をユーザーに中継できます。

<progress></progress>

value がない場合、要素の進行状況は 不確定max 属性はデフォルトで 1 に設定されているため、進行状況は 0 ~ 1 の間になります。max の設定 範囲を 0 ~ 100 に設定します。0 の範囲に収めることにしました と 1 つの制限で、進行状況の値を 0.5 または 50% に変換します。

ラベルラップの進行状況

暗黙的な関係では、progress 要素は次のようなラベルでラップされます。

<label>Loading progress<progress></progress></label>

このデモでは、スクリーン リーダーのラベルを含めることにしました。 のみ。 そのためには、ラベルのテキストを <span> でラップし、いくつかのスタイルを適用します。 効果的に画面外に表示できます

<label>
  <span class="sr-only">Loading progress</span>
  <progress></progress>
</label>

WebAIM の次の関連 CSS がある場合:

.sr-only {
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

screen Ready のみの要素が表示されている devtools のスクリーンショット。

読み込みの進行状況の影響を受ける領域

健康な視力があれば、達成状況を示す指標を簡単に関連付けることができます。 関連要素とページ領域が含まれていますが、視覚障がいのあるユーザーには 明確です。この問題を改善するには、 aria-busy 属性を、読み込み完了時に変更される最上位の要素に指定します。 さらに、進行状況と読み込みゾーンの関係を示します。 aria-describedby

<main id="loading-zone" aria-busy="true">
  …
  <progress aria-describedby="loading-zone"></progress>
</main>

JavaScript から、タスクの開始時に aria-busytrue に切り替えて、 終了したら、false

Aria 属性の追加

<progress> 要素の暗黙的なロールは、 progressbar さん、明確にしました 暗黙的なロールがないブラウザでは使用しません。属性も追加しました。 indeterminate: 要素を明示的に不明な状態にします。 value が設定されていない要素を監視するよりも明確です。

<label>
  Loading 
  <progress 
    indeterminate 
    role="progressbar" 
    aria-describedby="loading-zone"
    tabindex="-1"
  >unknown</progress>
</label>

使用 tabindex="-1" progress 要素を JavaScript からフォーカス可能にすることができます。これは スクリーン リーダーの技術です。進行状況の変化に応じて進行状況にフォーカスできるため、 は、更新された進捗状況がユーザーに通知されます。

スタイル

進行状況の要素は、スタイル設定において少し扱いにくい部分があります。組み込み HTML 要素には特別な隠れた部分があり、選択が難しく、 設定可能なプロパティ セットしか提供されません。

レイアウト

レイアウト スタイルは、処理をある程度柔軟に行えるようにすることを目的としています。 要素のサイズとラベルの位置を指定します。追加される特別な完了状態は、 便利ですが、必須ではありません。

<progress> レイアウト

進行状況要素の幅は、縮小および拡大できるようにそのままにします。 設計に必要なスペースを確保します。組み込みのスタイルは appearancebordernone に設定します。これは、要素を ブラウザごとに独自のスタイルがあるため、ブラウザ間で正規化されます。 要素です。

progress {
  --_track-size: min(10px, 1ex);
  --_radius: 1e3px;

  /*  reset  */
  appearance: none;
  border: none;

  position: relative;
  height: var(--_track-size);
  border-radius: var(--_radius);
  overflow: hidden;
}

_radius1e3px の値には科学数を使用する 表記を使用して、任意の文字列を 大きな値になるため、border-radius は常に四捨五入されます。これは、次と同等です。 1000px。これを使いたいのは 設定した後は忘れてしまえば、書き込む時間は 1000px より短くなります。また、 必要に応じてさらに大きくすることもできます。3 を 4 に変更すると、1e4px になります。 10000px と同等です。

overflow: hidden が使用されており、そのスタイルは議論の余地があるものです。データは数多くあります。 たとえば、border-radius 値を関数に渡して 塗りつぶし要素のトラッキングとトラッキングそれは 進歩の子プロセスや 要素の外側に存在する可能性があります。このカスタム進行状況に対する別のイテレーション overflow: hidden がなくても要素を実行でき、その場合、 コンプリート状態を改善できます。

処理が完了しました

ここでは CSS セレクタが、最大値と値を比較して手間のかかる作業を行います。これらのセレクタが一致すると、処理は完了です。完了すると疑似要素が生成され、progress 要素の最後に追加されます。これにより、完了を視覚的にわかりやすく示すことができます。

progress:not([max])[value="1"]::before,
progress[max="100"][value="100"]::before {
  content: "";
  
  position: absolute;
  inset-block: 0;
  inset-inline: auto 0;
  display: flex;
  align-items: center;
  padding-inline-end: max(calc(var(--_track-size) / 4), 3px);

  color: white;
  font-size: calc(var(--_track-size) / 1.25);
}

読み込みバーが 100% で、最後にチェックマークが表示されている状態のスクリーンショット。

ブラウザでは進行状況の要素が独自の色で表示されます。また、 1 つの CSS プロパティを持たせることができます。これをベースにいくつかの ブラウザ固有の特別なセレクタを使用できます。

ライトとダークのブラウザ スタイル

サイトでダーク / ライト アダプティブ <progress> 要素にオプトインするには: 必須となるのは color-scheme だけです。

progress {
  color-scheme: light dark;
}

単一プロパティの進捗の塗りつぶしの色

<progress> 要素の色合いを調整するには、accent-color を使用します。

progress {
  accent-color: rebeccapurple;
}

設定によって、トラックの背景色が明るいから暗に accent-color。ブラウザでは適切なコントラストが確保されており、非常にきれいです。

ライトカラーとダークカラーをフルにカスタマイズ

<progress> 要素に、トラックの色用の 2 つのカスタム プロパティを設定します。 もう 1 つはトラックの進行状況の色ですGoogle の prefers-color-scheme メディアクエリでは、トラックの新しい色値とトラックの進行状況を指定します。

progress {
  --_track: hsl(228 100% 90%);
  --_progress: hsl(228 100% 50%);
}

@media (prefers-color-scheme: dark) {
  progress {
    --_track: hsl(228 20% 30%);
    --_progress: hsl(228 100% 75%);
  }
}

フォーカス スタイル

先ほど、プログラムによって操作できるように、要素に負のタブ インデックスを指定しました。 できます。使用 :focus-visible~ フォーカスをカスタマイズして、よりスマートなフォーカス リング スタイルにオプトインできます。これをクリックすると クリックしてフォーカスを当ててもフォーカス リングは表示されず、キーボードをクリックすると表示されます。「 これについては YouTube 動画で詳しく説明しています。 確認することをおすすめします

progress:focus-visible {
  outline-color: var(--_progress);
  outline-offset: 5px;
}

フォーカス リングが表示された読み込みバーのスクリーンショット。すべての色が一致しています。

ブラウザをまたいだカスタム スタイル

スタイルをカスタマイズするには、<progress> 要素のそれぞれについて、 表示されます。progress 要素の使用は単一のタグですが、 CSS 疑似セレクタを介して公開される少数の子要素があります。Chrome DevTools 設定を有効にすると、これらの要素が表示されます。

  1. ページを右クリックして [要素を検証] を選択すると、DevTools が表示されます。
  2. [DevTools] ウィンドウの右上にある設定の歯車アイコンをクリックします。
  3. [Elements] の見出しで、[ユーザー エージェント シャドウを表示] を見つけて有効にします。 DOM] チェックボックスをオンにします。

ユーザー エージェント Shadow DOM の公開を DevTools で有効にしている場所を示すスクリーンショット

Safari と Chromium のスタイル

Safari や Chromium などの WebKit ベースのブラウザでは、 ::-webkit-progress-bar::-webkit-progress-value: 使用する CSS。現時点では、カスタム プロパティを使用して background-color を設定します。 光と暗に適応します。

/*  Safari/Chromium  */
progress[value]::-webkit-progress-bar {
  background-color: var(--_track);
}

progress[value]::-webkit-progress-value {
  background-color: var(--_progress);
}

進行状況要素の内部要素を示すスクリーンショット

Firefox のスタイル

Firefox では、::-moz-progress-bar 疑似セレクタのみが <progress> 要素。また、トラックの色合いを直接調整することもできません。

/*  Firefox  */
progress[value]::-moz-progress-bar {
  background-color: var(--_progress);
}

Firefox のスクリーンショットと、progress 要素が表示される場所

Safari、iOS Safari、ブラウザが開いている [デバッグ] コーナーのスクリーンショット 
  Firefox、Chrome、Android の Chrome で読み込みバーが動作している。

iOS Safari では Firefox では accent-color からトラック色が設定されていますが、 水色のトラックがありますダークモードでも同じです。Firefox にはダークトラックがありますが、 設定済みのカスタム色ではなく、Webkit ベースのブラウザで動作します。

アニメーション

ブラウザの組み込み疑似セレクタを使用する場合、 使用できる CSS プロパティのセットです。

トラックをいっぱいにまでアニメーション化する

画面遷移を inline-size / 進行状況要素は Chromium では動作しますが、Safari では動作しません。Firefox では、 ::-moz-progress-bar で遷移プロパティを使用していない。

/*  Chromium Only 😢  */
progress[value]::-webkit-progress-value {
  background-color: var(--_progress);
  transition: inline-size .25s ease-out;
}

:indeterminate 状態のアニメーション化

アニメーションを追加できるように、もう少しクリエイティブな表現にします。疑似要素 作成されて、グラデーションが再び表示されます。このグラデーションは、 3 つのブラウザですべて更新しました。

カスタム プロパティ

カスタム プロパティは多くのことに役立ちますが、私のお気に入りの一つは、 魔法のように見える CSS 値に名前を付けます。次はかなり 複雑 linear-gradient 良い名前にしますその目的とユースケースを明確に理解できる。

progress {
  --_indeterminate-track: linear-gradient(to right,
    var(--_track) 45%,
    var(--_progress) 0%,
    var(--_progress) 55%,
    var(--_track) 0%
  );
  --_indeterminate-track-size: 225% 100%;
  --_indeterminate-track-animation: progress-loading 2s infinite ease;
}

カスタム プロパティはコードの DRY 状態を保つのにも役立ちます。繰り返しになりますが、 グループ化する必要があります

キーフレーム

前後に繰り返す無限のアニメーションが目標です。開始と終了 CSS で設定されます中央のキーフレームに必要なのは 1 つのキーフレームのみです 50% に移動し、開始位置、終了位置、終了位置に戻るアニメーションを作成します。 もう一度!

@keyframes progress-loading {
  50% {
    background-position: left; 
  }
}

各ブラウザをターゲットに設定

すべてのブラウザで <progress> に疑似要素を作成できるわけではありません。 進行状況バーをアニメーション化することもできます。対応ブラウザの追加 トラックをアニメーション化するという目的なので、擬似要素からアップグレードします。 アニメーションバーを作成できます

Chromium 疑似要素

Chromium では、カバーする位置で疑似要素 ::after を使用できます。 必要があります。不確定のカスタム プロパティが使用され、 4 つ目のアニメーションは 非常に効果的です

progress:indeterminate::after {
  content: "";
  inset: 0;
  position: absolute;
  background: var(--_indeterminate-track);
  background-size: var(--_indeterminate-track-size);
  background-position: right; 
  animation: var(--_indeterminate-track-animation);
}
Safari の進行状況バー

Safari の場合は、カスタム プロパティとアニメーションが 疑似要素の進行状況バー:

progress:indeterminate::-webkit-progress-bar {
  background: var(--_indeterminate-track);
  background-size: var(--_indeterminate-track-size);
  background-position: right; 
  animation: var(--_indeterminate-track-animation);
}
Firefox の進行状況バー

Firefox では、カスタム プロパティとアニメーションも 疑似要素の進行状況バー:

progress:indeterminate::-moz-progress-bar {
  background: var(--_indeterminate-track);
  background-size: var(--_indeterminate-track-size);
  background-position: right; 
  animation: var(--_indeterminate-track-animation);
}

JavaScript

JavaScript は、<progress> 要素において重要な役割を果たします。制御 要素に渡され、十分な情報が スクリーン リーダーです。

const state = {
  val: null
}

デモには、進行状況を制御するためのボタンがあります。state.val を更新します 次に、更新するための関数を呼び出します。 DOM

document.querySelector('#complete').addEventListener('click', e => {
  state.val = 1
  setProgress()
})

setProgress()

この関数で UI/UX オーケストレーションが行われます。まずは setProgress() 関数を使用します。アクセス権があるため、パラメータは必要ありません。 state オブジェクト、進行状況要素、<main> ゾーンです。

const setProgress = () => {
  
}

<main> ゾーンの読み込みステータスの設定

進行状況が完了したかどうかに応じて、関連する <main> 更新する必要があります。 aria-busy 属性:

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)
}

読み込み量が不明な場合は属性をクリアしてください

値が不明または設定されていない場合、この使用方法で null は、value を削除します。 aria-valuenow 属性。これにより、<progress> が不確定になります。

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }
}

JavaScript の小数数学の問題を解決する

進行状況はデフォルトの最大値である 1 のままにしているので、 インクリメント関数とデクリメント関数では、小数の計算を使用します。JavaScript などの 生成 AI は、 できます。 次の roundDecimals() 関数では、計算の余分な部分を除去します。 結果:

const roundDecimals = (val, places) =>
  +(Math.round(val + "e+" + places)  + "e-" + places)

読みやすく、表示できるように値を丸めます。

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }

  const val = roundDecimals(state.val, 2)
  const valPercent = val * 100 + "%"
}

スクリーン リーダーとブラウザの状態の値を設定する

この値は DOM の 3 つの場所で使用されます。

  1. <progress> 要素の value 属性。
  2. aria-valuenow 属性。
  3. <progress> 内部テキスト コンテンツ。
const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }

  const val = roundDecimals(state.val, 2)
  const valPercent = val * 100 + "%"

  progress.value = val
  progress.setAttribute('aria-valuenow', valPercent)
  progress.innerText = valPercent
}

進捗に焦点を当てる

値を更新すると、視力のあるユーザーには進行状況の変化が表示されますが、 読者には変更のお知らせがまだ通知されません。焦点を絞る <progress> 要素が含まれていると、ブラウザが更新を通知します。

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }

  const val = roundDecimals(state.val, 2)
  const valPercent = val * 100 + "%"

  progress.value = val
  progress.setAttribute('aria-valuenow', valPercent)
  progress.innerText = valPercent

  progress.focus()
}

Mac OS 版 Voice Over アプリのスクリーンショット 
  読み込みバーの進行状況をユーザーに表示します。

まとめ

どのようにやり方をしたかわかったので、どのように感じますか? ‽ 🙂?

機会があれば少しだけ変更したい点がございます。現在のコンポーネントをクリーンアップする余地と、<progress> 要素の疑似クラスのスタイル制限なしで構築を試みる余地があると思います。ぜひお試しください。

アプローチを多様化して、ウェブで構築するすべての方法を学びましょう。

デモを作成し、ツイートしてリンクを送ってください 下の [コミュニティリミックス]セクションに アクセスしてください

コミュニティ リミックス