<progress> 元素是表示工作完成進度的語意方式,例如下載或上傳資訊,或完成多步驟程序的一部分。使用原生元素有助於提升無障礙程度,因為螢幕閱讀器具有隱含的 role="progressbar",可以讀出值。
本指南會實作完全自訂樣式的水平進度列。
進度列或進度環?
- 如果空間有限或偏好正方形顯示比例,建議使用圓形進度列 (進度環):進度環
- 在大多數不確定進度的情況下,建議使用旋轉圖示 (載入旋轉圖示)。如果進度不確定狀態只是暫時性,且很快就會由確定進度列取代,請使用不確定進度列 (例如等待上傳相關中繼資料,才能顯示進度百分比)
標記
- 使用原生
<progress>元素:提供內建無障礙功能和平台一致的行為。 - 如需使用預設 0-1 以外的評分系統,請使用
max。 - 如要設定特定進度值,請設定
value屬性。如要表示不確定狀態 (例如在開始提供更具體的回饋之前),請省略value。 - 使用
<label for="...">、aria-labelledby或aria-label,將進度元素與標籤建立關聯。
需要哪種自訂功能?
如要進行有限的樣式設定,下列屬性就足夠:
accent-color:變更進度列的顏色width/inline-size:變更進度列寬度height/block-size套用方式不一致,請先測試writing-mode: vertical-lr:垂直長條。- 繪製後套用的效果:
opacity、filter、clip-path、遮罩、轉換、box-shadow等。
如果有限的樣式設定已足夠,請略過下一節。
警告:某些屬性 (例如 border-radius、background、border) 會在不顯示任何訊息的情況下,停用預設進度列樣式。如果需要上述屬性以外的樣式,請按照下一節的說明,實作完全自訂的樣式。請勿套用更多樣式,以免「只是碰巧有效」。
完全自訂樣式
1. 基本設定
- 必要:使用
appearance: none啟用自訂樣式。 - 使用
border: 0 solid重設通用 Analytics 邊界 - 如要將有效長條裁剪至元素的 border-radius,請使用
overflow: clip,或將相同的border-radius套用至長條。請勿在列上使用border-radius: inherit,這取決於 Shadow DOM 中元素的特定結構。
progress {
/* Reset default browser styles */
appearance: none;
border: 0 solid;
/* Clip bar to element’s border-radius */
overflow: clip;
}
2. 樣式
- 在
progress元素本身設定軌道樣式。 - 使用適當的瀏覽器指定虛擬元素,指定進度列本身:WebKit/Blink 使用
::-webkit-progress-value,Firefox 使用::-moz-progress-bar。 - 強制規定:請勿在同一規則中將
-webkit-和-moz-虛擬元素分組。系統會將規則視為無效並忽略。:is()和:where()不支援虛擬元素,因此無法解決這個問題。 - 每個瀏覽器指定的虛擬元素只能出現一次。特定狀態的自訂項目 (例如不確定區隔大小和動畫) 應透過
progress元素本身設定的自訂屬性進行轉送。 - 選用:在填滿時轉換
inline-size,讓確定值變更時顯示動畫,而不是跳轉。Firefox 會調整版面配置中的填滿大小,並忽略該屬性,這不會造成任何影響。
progress {
--progress-bar-radius: 1e5px;
border-radius: var(--progress-bar-radius);
/* Apply color for custom progress track (background) */
background: var(--progress-bar-track, var(--color-neutral-90));
/* Subtle depth on the empty part of the track */
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);
}
/* Let <progress> styling show through */
progress::-webkit-progress-bar {
background: transparent;
}
/* Webkit, Chrome */
progress::-webkit-progress-value {
background: var(--progress-bar-fill, var(--accent-color));
border-radius: var(--progress-bar-radius);
transition: inline-size 0.3s;
}
/* Firefox */
progress::-moz-progress-bar {
background: var(--progress-bar-fill, var(--accent-color));
border-radius: var(--progress-bar-radius);
transition: inline-size 0.3s;
}
3. 不確定狀態樣式
為不確定狀態新增自訂動畫:將填滿虛擬元素轉換為短片段,並沿著軌道滑動。
- 請設定填滿效果本身的樣式,不要在
progress上重新建立為背景。 - 不確定填滿效果只會透過動畫呈現:主要畫面格會使用實際的
inline-size設定長度 (這會覆寫 Chromium 的 UA 內嵌inline-size),並使用translate移動。請勿使用scale做為長度,否則會扭曲填滿區域上繪製的任何圖案。 translate百分比會根據填滿寬度解析,因此請改用軌道單位表示位置:將progress設為內嵌大小容器,並在主要畫面格中使用cqi。在from, to中加入margin-right: auto,這樣 Chromium 在 RTL 模式下也會將填滿效果放在實際左側。- 請使用轉換 (而非邊界) 移動填滿。
- 轉換會將動畫保留在合成器中 (除非
inline-size也正在動畫中) - 邊界在 RTL 中會中斷,原因有兩個:
- Firefox 只會使用實體左側邊界來定位不確定填滿,因此
margin-inline-start在 RTL 中不會產生任何效果,且填滿永遠不會移動。 - 在 Chromium 和 WebKit 中,填滿會以一般區塊的形式呈現,一旦邊界將填滿推到軌道末端,邊界就會加總超過軌道。標準 CSS 會在 RTL 中忽略
margin-left,因此區隔會跳到邊緣,而不是滑出邊緣。 translate會在版面配置後套用,因此不會發生上述問題。
- 轉換會將動畫保留在合成器中 (除非
- 如要鏡像翻轉 RTL 的動作 (就像 Chrome 的原生列一樣),請反轉
:dir(rtl)下方的動畫:
progress:dir(rtl) {
--progress-bar-indeterminate-animation: progress-bar-indeterminate var(--progress-bar-indeterminate-animation-duration) infinite linear reverse;
}
- 在
progress上定義公開--progress-bar-indeterminate-*屬性 (其名稱已將其範圍限定為狀態),讓消費者可以覆寫這些屬性,而不需要知道:indeterminate。 - 如要改變線段長度 (例如前緣向前移動,後緣跟上),請將
--progress-bar-indeterminate-animation設為兩個並行動畫:一個動畫的主要畫面格在cqi(位置) 中為translate加上動畫效果,另一個動畫的主要畫面格則為inline-size(長度) 加上動畫效果,這樣每個動畫都有自己的主要畫面格和加/減速。請勿嘗試在單一主要畫面格清單中設定兩邊的形狀;每個主要畫面格的animation-timing-function會套用至該主要畫面格中的每個屬性。 --progress-bar-animation適用於這兩種狀態,可用於確定閃爍等效果。revert-rule僅用於在設定時覆寫,以盡可能提高可組合性。- 請勿停用不確定動畫 (
animation: none會在 Chromium 中留下零寬度的填滿)。如要減少動態效果,請放慢速度。
progress {
/* Lets the fill position itself in track units (cqi) */
container-type: inline-size;
/* Segment length relative to the track */
--progress-bar-indeterminate-size: 30%;
--progress-bar-indeterminate-animation-duration: 1.5s;
/* Respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
--progress-bar-indeterminate-animation-duration: 10s;
}
}
progress:indeterminate {
--progress-bar-animation: var(
--progress-bar-indeterminate-animation,
progress-bar-indeterminate var(--progress-bar-indeterminate-animation-duration) infinite linear
);
}
/* Add to the existing pseudo-element rules */
progress::-webkit-progress-value {
animation: var(--progress-bar-animation, revert-rule);
}
progress::-moz-progress-bar {
animation: var(--progress-bar-animation, revert-rule);
}
/* Physical: left to right regardless of direction (reverse under :dir(rtl) to mirror). */
@keyframes progress-bar-indeterminate {
from, to {
inline-size: var(--progress-bar-indeterminate-size);
/* Pin to the physical left; Chromium would otherwise lay the fill out at the inline start */
margin-right: auto;
}
from { translate: -100%; } /* Own width: fully outside the left edge */
to { translate: 100cqi; } /* Track width: fully outside the right edge */
}
其他無障礙功能注意事項
除了上述規範外,請注意下列事項:
- 宣布完成,但不搶走焦點:請勿在
<progress>上設定tabindex或呼叫.focus(),因為這不是互動式元素,將焦點移至該元素會干擾鍵盤使用者。如要在背景工作完成時發出通知,請更新禮貌狀態元素 (role="status"或aria-live="polite")。 - 請勿在
<progress>內加入備用文字:新式瀏覽器會忽略<progress>內的文字,輔助技術也不會使用。 - 避免在未標示的一般
<div>上使用aria-busy+aria-describedby。aria-busy的螢幕閱讀器支援功能不一致,且輔助技術會忽略未命名<div>上的aria-describedby,且沒有角色。如果載入時區域內容尚未準備就緒,請使用hidden或aria-hidden="true"隱藏。 - 建議:新增自訂樣式時,請確保進度列和軌道之間有適當的對比。
- 考慮使用其他方式表示不確定狀態:與其他內容並列顯示的不確定進度列動畫,可能會干擾部分使用者。
備用策略
accent-color 的備用方案和瀏覽器支援
accent-color 屬性是漸進增強。不支援這項屬性的瀏覽器會忽略該屬性,並使用預設的使用者介面顏色。
如果系統不支援 accent-color,且需要設定進度列樣式,請使用自訂樣式方法,將偏好的樣式套用至進度列。
revert-rule 的備用方案和瀏覽器支援
如果不支援 revert-rule,animation: var(--progress-bar-animation, revert-rule) 會在未設定 --progress-bar-animation 時,改用 animation-name: revert-rule,並採用 0s 持續時間,如果沒有 @keyframes revert-rule,則會是無害的無作業。