基本總覽:如何使用 <progress>
元素建構可自動調整顏色且可存取的載入列。
在這篇文章中,我想分享一些想法,包括如何打造自動調整色彩及
含有 <progress>
元素的可存取載入列。試試
示範及觀看
資料來源!
如果您喜歡看影片,請參考這篇文章的 YouTube 版本:
總覽
<progress>
敬上
元素提供視覺和音訊意見回饋,讓使用者知道應用程式已完成。這個
視覺回饋適用於各種情境,例如填寫表單、
或顯示下載或上傳資訊
進度金額不明,但作業仍在執行中。
這項 GUI 挑戰
現有的 HTML <progress>
元素,節省一些無障礙功能的工作。
色彩和版面配置,突破了內建元素自訂的極限,
翻新元件,讓元件與設計系統相輔相成。
標記
我選擇將 <progress>
元素納入
<label>
,則適用
我可以略過明確關聯屬性,以隱含
關係。
我也為受載入狀態影響的父項元素加上標籤
以便將資訊轉發給使用者。
<progress></progress>
如果沒有 value
,表示元素的進度
未確定。
max
屬性預設為 1,因此進度介於 0 到 1 之間。正在設定max
例如設為 100,就會將範圍設為 0-100。我選擇維持在 0 以內
和 1 項限制,請將進度值轉譯為 0.5 或 50%。
標籤包裝進度
在隱含關係中,進度元素會用標籤包裝,如下所示:
<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;
}
受載入進度影響的區域
如果視力健康,也可輕鬆連結進度指標
與相關元素和網頁區域合作,但對視障使用者來說
清楚易懂為達成此目的,指派合適的
aria-busy
敬上
屬性設為最頂端的元素,會在載入完成後變更。
此外,指出進度與載入區域之間的關係
同時
aria-describedby
。
<main id="loading-zone" aria-busy="true">
…
<progress aria-describedby="loading-zone"></progress>
</main>
透過 JavaScript,請在工作開始時將 aria-busy
切換為 true
,以及
完成後 false
。
新增 Aria 屬性
<progress>
元素的隱含角色
progressbar
,我已將這項內容設為煽情露骨內容
針對缺乏隱含角色的瀏覽器
我們也新增了
indeterminate
:明確將元素設為不明狀態,
而不是觀察元素未設定 value
。
<label>
Loading
<progress
indeterminate
role="progressbar"
aria-describedby="loading-zone"
tabindex="-1"
>unknown</progress>
</label>
使用
tabindex="-1"
敬上
讓進度元素可以從 JavaScript 聚焦。這很重要
螢幕閱讀器技術會隨著進度改變而著重閱讀進度
只會在更新進度達標時通知使用者。
樣式
在設定樣式時,進度元素有點棘手。內建 HTML 元素包含特殊的隱藏部分,可能難以選取, 只提供幾項房源可以設定
版面配置
版面配置樣式的目的是讓進度保有一些彈性 元素的大小和標籤位置系統會新增特殊的完成狀態, 提示是實用,但不是必要 額外的視覺提示
<progress>
版面配置
進度元素的寬度維持不變,方便縮小並放大
達成設計所需的空間內建的樣式會由
正在將 appearance
和 border
設為 none
。如此一來,元素即可
由於每個瀏覽器都有自己的樣式
元素。
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;
}
_radius
的 1e3px
值使用科學數字
表示方式
大數值,因此 border-radius
一律會四捨五入。等同於
1000px
。我之所以喜歡這項功能,是因為我希望輸入夠大的值
我可以設定但直接忘記 (寫入時間比 1000px
短)。這個
視需要輕鬆放大:只要 3 為 4 的 ,1e4px
就會是
相當於 10000px
。
使用的是 overflow: hidden
,而且是一種內容風格。有幾個
例如不必將 border-radius
值向下傳遞至
追蹤及追蹤填充元素但這也意味著進度不一的子項
可能住在元素之外再次執行這個自訂進度
則可在沒有 overflow: hidden
的情況下完成,且可能會開啟
產生動畫或更好的完成狀態
進度完成
CSS 選取器會比較最大值與值,如果兩者相符,就表示進度已完成。完成後,系統會產生虛擬元素並附加至進度元素的結尾,為完成動作提供額外視覺提示。
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);
}
顏色
瀏覽器會為進度元素顯示專屬顏色,並且會根據 只需要一項 CSS 屬性的淺色和深色。我們可以透過一些 特殊的瀏覽器專用選取器
淺色和深色瀏覽器樣式
如要選擇為網站採用深色和淺色的自動調整 <progress>
元素,請按照下列步驟操作:
您只需要提供 color-scheme
即可,
progress {
color-scheme: light dark;
}
單一屬性進度填滿顏色
如要為 <progress>
元素設定色調,請使用 accent-color
。
progress {
accent-color: rebeccapurple;
}
請注意,軌跡的背景顏色從淺色變成深色,具體取決於
accent-color
。瀏覽器可確保對比鮮明,呈現最完美的色彩。
完全自訂的淺色和深色
在 <progress>
元素上設定兩個自訂屬性,一個用於軌跡顏色
另類則用於追蹤進度顏色內部
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>
元素的各個部分來自訂樣式
。使用進度元素是單一標記,但這個標記是由
只有少數幾個透過 CSS 虛擬選取器公開的子元素。Chrome 開發人員工具
如果啟用設定,畫面上就會顯示這些元素:
- 在頁面上按一下滑鼠右鍵,然後選取「檢查元素」開啟開發人員工具。
- 按一下開發人員工具視窗右上角的「設定」齒輪。
- 在「元素」Elements標題下方,找到並啟用「顯示使用者代理程式陰影」 DOM」核取方塊。
Safari 和 Chromium 樣式
以 WebKit 為基礎的瀏覽器,例如 Safari 和 Chromium 公開
::-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);
}
請注意,當 iOS Safari 顯示 Firefox 時,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
狀態加上動畫效果
這裡會有太多創意,讓我加入動畫。虛擬元素 就會為 Chromium 的背景 。
自訂屬性
自訂屬性的用途很多
但我最喜歡的功能之一
為另一個神奇的 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 中設定,只需要一個主要畫面格,中間的主要畫面格
於 50%
建立動畫,回到動畫開頭、結尾
又回來了!
@keyframes progress-loading {
50% {
background-position: left;
}
}
指定每個瀏覽器
並非所有瀏覽器都允許在 <progress>
上建立虛擬元素
元素本身也可以建立進度列的動畫效果。支援更多瀏覽器
為軌道建立動畫效果,而不是建立虛擬元素。因此,我將虛擬元素升級
把底座和動畫長條組成動畫
Chromium 虛擬元素
Chromium 允許這個虛擬元素:::after
搭配要覆蓋的位置
元素。使用指定的自訂屬性,以及返回和
但第四個動畫的表現都非常好
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/使用者體驗自動化調度管理。請先建立
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 等
因此,不一定每次都支援這項功能
。
以下 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 中的三個位置:
<progress>
元素的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
}
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()
}
結論
現在你知道我怎麼了,這樣會如何 🙂?
假如再有一次機會,我一定會進行一些變更。我認為還有空間清除目前的元件,並且有空間嘗試在沒有 <progress>
元素虛擬類別樣式限制的情況下,建構一個元件。值得一探究竟!
讓我們來體驗多元的方法,瞭解透過網路建立內容的所有方式。
建立示範、將 Twitter 推文連結,我們就會為您新增 前往下方的社群重混專區!