概略說明如何建構滑桿和核取方塊的設定元件。
在本文中,我想分享如何替回應式網頁建構設定元件,支援多種裝置輸入內容,並且能夠在各種瀏覽器中運作。試試示範。
如果您偏好播放影片,或是希望在 UI/使用者體驗預覽我們正在建構的內容,請參考以下的 YouTube 逐步操作說明:
總覽
我們將各項元件分為以下幾個部分:
版面配置
這是第一個將所有 CSS Grid 的 GUI 挑戰示範影片!以下是每個使用 Chrome 開發人員工具的格狀檢視畫面:
只是要間隔一段時間
最常見的版面配置:
foo {
display: grid;
gap: var(--something);
}
我將這個版面配置稱為「僅限間隔」,因為它只會使用格線在區塊之間加入間隔。
五個版面配置都使用這項策略,如下所示:
fieldset
元素包含每個輸入群組 (.fieldset-item
),使用 gap: 1px
在元素之間建立髮線框線。沒有棘手的邊框解決方案!
.grid { display: grid; gap: 1px; background: var(--bg-surface-1); & > .fieldset-item { background: var(--bg-surface-2); } }
.grid { display: grid; & > .fieldset-item { background: var(--bg-surface-2); &:not(:last-child) { border-bottom: 1px solid var(--bg-surface-1); } } }
自然網格包裝
最複雜的版面配置最後成為巨集版面配置,也就是 <main>
和 <form>
之間的邏輯版面配置系統。
將內容置中
Flexbox 和格線都能為 align-items
或 align-content
提供功能,而在處理包裝元素時,content
版面配置對齊方式則會以群組的形式將空間分配給子項。
main {
display: grid;
gap: var(--space-xl);
place-content: center;
}
主要元素使用 place-content: center
對齊捷徑,因此子項在一欄和兩欄版面配置中會垂直和水平置中。
請觀看上方的影片,瞭解即使已進行包裝,「內容」會保持置中。
重複自動調整最小值
<form>
會針對每個區段使用自動調整式格線版面配置。這個版面配置會根據可用空間,從 1 欄切換為 2 欄。
form {
display: grid;
gap: var(--space-xl) var(--space-xxl);
grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
align-items: flex-start;
max-width: 89vw;
}
此格線的 row-gap
(--space-xl) 與 column-gap
(--space-xxl) 的值不同,這樣才能將自訂觸控加入回應式版面配置。我們希望能在欄堆疊時取得較大的間隔,但不會像在寬螢幕上一樣大。
grid-template-columns
屬性使用 3 種 CSS 函式:repeat()
、minmax()
和 min()
。Una Kravets 有提供有關此問題的優質版面配置網誌文章,稱為 RAM。
與 Una 的比較,版面配置有 3 項特殊新增功能:
- 我們會傳遞額外的
min()
函式。 - 我們指定
align-items: flex-start
。 - 後面有
max-width: 89vw
樣式。
Evan Minto 曾在自己的網誌上充分描述額外的 min()
函式,詳情請參閱「Intrinsically 回應式 CSS Grid with minmax() 和 min() 一文。因此,建議您提供一讀。flex-start
對齊校正是為了移除預設的延展效果,因此此版面配置的子項不需要相同的高度,可以使用自然的內建高度。這部 YouTube 影片會簡單介紹一下上述的調整方法。
因此,max-width: 89vw
值得深入分析。
讓我為您顯示套用及未套用該樣式的版面配置:
為什麼會這樣?如果指定 max-width
,系統會為 auto-fit
版面配置演算法提供背景資訊、明確大小調整或確定大小,以便瞭解自身可放入空間中的重複次數。雖然空間看起來似乎是「完整寬度」,但根據 CSS 格線規格,您必須提供明確的大小或大小上限。我提供了大小上限。
那麼,為何要選擇 89vw
?因為我的版面配置是「能夠正常運作」。我和其他幾位 Chrome 團隊正在調查為何更合理的值,例如 100vw
不足,且這實際上是錯誤。
間距
這個版面配置的組合大多來自間距有限的調色盤,7 為確切值。
:root {
--space-xxs: .25rem;
--space-xs: .5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
--space-xxl: 6rem;
}
與格狀檢視、CSS @nest 和 @media 的第 5 級語法相輔相成,能夠確實運用這些流程。以下為完整的 <main>
版面配置組合範例。
main {
display: grid;
gap: var(--space-xl);
place-content: center;
padding: var(--space-sm);
@media (width >= 540px) {
& {
padding: var(--space-lg);
}
}
@media (width >= 800px) {
& {
padding: var(--space-xl);
}
}
}
根據預設,含有置中內容的格線 (例如在行動裝置上)但隨著可視區域空間增加,邊框間距就會分散。2021 年 CSS 看起來很棒!
還記得先前的版面配置「只是要填空嗎?」?以下提供這類元件在元件中的完整外觀:
header {
display: grid;
gap: var(--space-xxs);
}
section {
display: grid;
gap: var(--space-md);
}
顏色
採用控制顏色的運用方式,讓設計脫穎而出,因此顯得與眾不同。我這麼做:
:root {
--surface1: lch(10 0 0);
--surface2: lch(15 0 0);
--surface3: lch(20 0 0);
--surface4: lch(25 0 0);
--text1: lch(95 0 0);
--text2: lch(75 0 0);
}
我要使用數字來為介面和文字顏色命名,而不是使用 surface-dark
和 surface-darker
這類名稱,因為在媒體查詢中,我會翻兩,而淺色和深色則沒有意義。
我在偏好設定媒體查詢中翻轉,如下所示:
:root {
...
@media (prefers-color-scheme: light) {
& {
--surface1: lch(90 0 0);
--surface2: lch(100 0 0);
--surface3: lch(98 0 0);
--surface4: lch(85 0 0);
--text1: lch(20 0 0);
--text2: lch(40 0 0);
}
}
}
請務必在深入瞭解色彩語法的詳細資料之前,先快速瞭解整體概況和策略。不過,我有更早點了 我來先備份
倫敦、
在不深入研究色彩理論的情況下,LCH 是一種以人為本的語法,主要規範我們如何看待色彩,而不是使用數學 (例如 255) 測量色彩的方式。這是一項明顯的優勢,因為人類可以更輕鬆地寫字,而其他人類也能受到這些調整影響。
![pod.link/csspodcast 網頁的螢幕截圖,顯示「顏色 2:Perception」劇集](https://web.dev/static/articles/building/a-settings-component/image/a-screenshot-podlinkcs-a40f130bf81b8.png?authuser=7&hl=zh-tw)
在這個示範中,我們來看一下語法 和要轉動的黑暗值我們來看看 1 個介面和 1 種文字顏色:
:root {
--surface1: lch(10 0 0);
--text1: lch(95 0 0);
@media (prefers-color-scheme: light) {
& {
--surface1: lch(90 0 0);
--text1: lch(40 0 0);
}
}
}
--surface1: lch(10 0 0)
會轉譯為 10%
亮度、0 色點和 0 色調:深深的無色灰色。接著,在淺色模式的媒體查詢中,亮度會透過 --surface1: lch(90 0 0);
翻轉為 90%
。這正是策略重點請先變更 2 個主題之間的亮度,維持設計呼叫的對比度或能維持無障礙設計的項目。
此處使用 lch()
的好處是,光度是人為導向,而我們對 %
做出的變更十分滿意,因此能夠公正且一致地呈現 %
的差異。例如 hsl()
不可靠。
若想瞭解色彩空間和 lch()
功能,請參閱這篇文章。即將推出!
CSS 目前完全無法存取這些顏色。我再重複一次:Google 並無法存取大多數現代監視器的三分之一顏色。這些顏色不單只是任何顏色,而是螢幕可以顯示最鮮明的色彩。我們的網站連線速度比 CSS 規格和瀏覽器導入作業更快,因此網站運作速度較慢。
Lea Verou
使用色彩配置自動調整表單控制項
許多瀏覽器都會提供深色主題控制項 (目前為 Safari 和 Chromium),但您必須在設計時使用的 CSS 或 HTML 中加以指定。
以上是示範在開發人員工具的「樣式」面板中的屬性效果。示範會使用 HTML 標記,我認為通常更佳的位置:
<meta name="color-scheme" content="dark light">
如要瞭解詳細資訊,請參閱 Thomas Steiner 的 color-scheme
文章。核取方塊輸入值外,還有許多功能等您來發掘!
CSS accent-color
表單元素上的 accent-color
最近活動屬於單一 CSS 樣式,可變更瀏覽器輸入元素中使用的色調顏色。詳情請參閱 GitHub。讓我把元件加入元件的樣式中隨著瀏覽器支援這項功能,核取方塊會聚焦於帶有粉紅色和紫色的彈出主題。
input[type="checkbox"] {
accent-color: var(--brand);
}
固定漸層和焦點內部的抽色
在使用一段時間後,顏色最為理想。我喜歡的其中一種方式是透過彩色的 UI 互動。
上方影片有許多層次的使用者介面意見回饋和互動,有助於提供個人專屬的互動體驗:
- 凸顯上下文。
- 提供使用者介面意見回饋,說明值是否落在範圍內。
- 針對欄位接受輸入,提供 UI 回饋。
為了在與元素互動時提供意見回饋,CSS 會使用 :focus-within
虛擬類別變更各種元素的外觀,讓我們細分 .fieldset-item
,其的優點如下:
.fieldset-item {
...
&:focus-within {
background: var(--surface2);
& svg {
fill: white;
}
& picture {
clip-path: circle(50%);
background: var(--brand-bg-gradient) fixed;
}
}
}
當此元素的某個子項聚焦在內時:
- 已在
.fieldset-item
背景指派較高的對比度表面顏色。 - 巢狀
svg
會填滿白色,提高對比度。 - 巢狀
<picture>
clip-path
會展開為完整圓形,背景則會填滿亮的固定漸層。
自訂範圍
以下列 HTML 輸入元素為例,我會示範如何自訂外觀:
<input type="range">
我們需要自訂這個元素並分為 3 個部分:
範圍元素樣式
input[type="range"] {
/* style setting variables */
--track-height: .5ex;
--track-fill: 0%;
--thumb-size: 3ex;
--thumb-offset: -1.25ex;
--thumb-highlight-size: 0px;
appearance: none; /* clear styles, make way for mine */
display: block;
inline-size: 100%; /* fill container */
margin: 1ex 0; /* ensure thumb isn't colliding with sibling content */
background: transparent; /* bg is in the track */
outline-offset: 5px; /* focus styles have space */
}
CSS 的前幾行是樣式的自訂部分,希望清楚標示這些部分對您有所幫助。其餘樣式大多都會重設樣式,以提供一致的基礎讓您建構元件上複雜的部分。
軌道樣式
input[type="range"]::-webkit-slider-runnable-track {
appearance: none; /* clear styles, make way for mine */
block-size: var(--track-height);
border-radius: 5ex;
background:
/* hard stop gradient:
- half transparent (where colorful fill we be)
- half dark track fill
- 1st background image is on top
*/
linear-gradient(
to right,
transparent var(--track-fill),
var(--surface1) 0%
),
/* colorful fill effect, behind track surface fill */
var(--brand-bg-gradient) fixed;
}
秘訣就是「揭開」鮮豔的填滿色彩。方法是以頂端的強制停止漸層效果來完成。漸層在填滿百分比前會保持透明,其後則會使用未填滿的軌跡表面顏色。未填滿的介面後方是完整寬度顏色,等待透明度顯示。
追蹤填滿樣式
我的設計需要使用 JavaScript 來維持填滿樣式。但只有 CSS 供應商可採用這類策略,但拇指元素必須與軌道高度相同,所以我無法在這些限制範圍內找到一致。
/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')
/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
const max = slider.getAttribute('max') || 10;
const percent = slider.value / max * 100;
return `${parseInt(percent)}%`;
};
/* on page load, set the fill amount */
sliders.forEach(slider => {
slider.style.setProperty('--track-fill', rangeToPercent(slider));
/* when a slider changes, update the fill prop */
slider.addEventListener('input', e => {
e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
})
})
我認為這可以帶來更好的視覺體驗。滑桿在沒有 JavaScript 的情況下也能運作,不需要使用 --track-fill
屬性,只是不會有填滿樣式 (如果不存在)。如果有可用的 JavaScript,請填入自訂屬性,同時觀察任何使用者變更,將自訂屬性與值同步處理。
歡迎參閱 Ana Tudor 發布的 CSS-Tricks 文章,瞭解如何運用 CSS 解決方案填滿曲目。我也發現這個 range
元素很不錯。
拇指樣式
input[type="range"]::-webkit-slider-thumb {
appearance: none; /* clear styles, make way for mine */
cursor: ew-resize; /* cursor style to support drag direction */
border: 3px solid var(--surface3);
block-size: var(--thumb-size);
inline-size: var(--thumb-size);
margin-top: var(--thumb-offset);
border-radius: 50%;
background: var(--brand-bg-gradient) fixed;
}
這些樣式大多都是建立精美的圓形。如您所見,您會看到固定背景漸層,可用於統一縮圖、音軌和相關 SVG 元素的動態色彩。我將互動的樣式區隔開來,藉此找出懸停醒目顯示使用的 box-shadow
技巧:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
::-webkit-slider-thumb {
…
/* shadow spread is initally 0 */
box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
/* if motion is OK, transition the box-shadow change */
@media (--motionOK) {
& {
transition: box-shadow .1s ease;
}
}
/* on hover/active state of parent, increase size prop */
@nest input[type="range"]:is(:hover,:active) & {
--thumb-highlight-size: 10px;
}
}
希望可以輕鬆管理並以動畫方式醒目顯示使用者意見。使用方塊陰影,就能避免以效果觸發版面配置。方法是建立未經模糊處理的陰影,而且與拇指元素的圓形形狀相符。接著變更並轉換遊標懸停在尺寸上。
如果勾選了醒目顯示特效,那麼勾選
跨瀏覽器選取器
我發現我需要這些 -webkit-
和 -moz-
選取器,才能達到跨瀏覽器一致性:
input[type="range"] {
&::-webkit-slider-runnable-track {}
&::-moz-range-track {}
&::-webkit-slider-thumb {}
&::-moz-range-thumb {}
}
自訂核取方塊
以下列 HTML 輸入元素為例,我會示範如何自訂外觀:
<input type="checkbox">
我們需要自訂這個元素並分為 3 個部分:
核取方塊元素
input[type="checkbox"] {
inline-size: var(--space-sm); /* increase width */
block-size: var(--space-sm); /* increase height */
outline-offset: 5px; /* focus style enhancement */
accent-color: var(--brand); /* tint the input */
position: relative; /* prepare for an absolute pseudo element */
transform-style: preserve-3d; /* create a 3d z-space stacking context */
margin: 0;
cursor: pointer;
}
transform-style
和 position
樣式可用於準備我們稍後推出的虛擬元素,以便設定醒目顯示的樣式。否則大多是我意見小的風格我喜歡遊標指向指標,就像外框偏移,預設核取方塊也過小,而如果 accent-color
是支援,請將這些核取方塊加入品牌色彩配置。
核取方塊標籤
提供核取方塊的標籤有 2 個原因。其一是核取方塊值的用途,回答「開或關」的原因。其次是針對使用者體驗,網頁使用者習慣透過相關聯的標籤與核取方塊互動。
<input type="checkbox" id="text-notifications" name="text-notifications" >
<label for="text-notifications"> <h3>Text Messages</h3> <small>Get notified about all text messages sent to your device</small> </label>
在標籤中加入 for
屬性,使其指向由 ID 勾選的核取方塊:<label for="text-notifications">
。在核取方塊上將名稱和 ID 都加倍,確保透過各種工具和技術 (例如滑鼠或螢幕閱讀器) 找到這些資訊:<input type="checkbox" id="text-notifications" name="text-notifications">
。在連線期間免費使用 :hover
、:active
等產品,可以增加表單的互動方式。
核取方塊醒目顯示功能
我想維持介面的一致性,而且滑桿元素會顯示醒目的縮圖,以便與核取方塊搭配使用。縮圖可以使用 box-shadow
,而 spread
屬性來縮放陰影的上下比例。不過,由於核取方塊為正方形,「而且應該」是正方形,因此效果不彰。
我能透過虛擬元素達到相同的視覺效果,但幸運的 CSS 卻變得更加困難:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
input[type="checkbox"]::before {
--thumb-scale: .01; /* initial scale of highlight */
--thumb-highlight-size: var(--space-xl);
content: "";
inline-size: var(--thumb-highlight-size);
block-size: var(--thumb-highlight-size);
clip-path: circle(50%); /* circle shape */
position: absolute; /* this is why position relative on parent */
top: 50%; /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
left: 50%;
background: var(--thumb-highlight-color);
transform-origin: center center; /* goal is a centered scaling circle */
transform: /* order here matters!! */
translateX(-50%) /* counter balances left: 50% */
translateY(-50%) /* counter balances top: 50% */
translateZ(-1px) /* PUTS IT BEHIND THE CHECKBOX */
scale(var(--thumb-scale)) /* value we toggle for animation */
;
will-change: transform;
@media (--motionOK) { /* transition only if motion is OK */
& {
transition: transform .2s ease;
}
}
}
/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
--thumb-scale: 1;
}
建立圓形虛擬元素並不容易,但要放在其連接的元素後方會比較困難。以下是我修正的錯誤:
這當然是微互動,但我想維持視覺的一致性,對我來說很重要。動畫縮放技巧跟往其他地方一樣。我們將自訂屬性設為新的值,讓 CSS 根據動作偏好設定進行轉換。這裡的主要功能是 translateZ(-1px)
。父項建立了 3D 空間,而這個虛擬元素子項透過將自己稍微放回 z 空間內,使其輕觸此空間。
無障礙功能
對於這個設定元件的滑鼠、鍵盤和螢幕閱讀器互動操作,YouTube 影片非常有效果。我會在這裡說明部分細節
HTML 元素選項
<form>
<header>
<fieldset>
<picture>
<label>
<input>
以上每個項目都包含了使用者瀏覽工具的提示和提示。有些元素可提供互動提示、部分連結互動功能,以及構成螢幕閱讀器瀏覽的無障礙樹狀結構。
HTML 屬性
我們可以隱藏螢幕閱讀器不需要的元素。在這種情況下,您可以隱藏滑桿旁邊的圖示:
<picture aria-hidden="true">
在以上影片中,您可以看到 Mac OS 的螢幕閱讀器流程,請留意輸入焦點如何從滑桿移到下一個滑桿。這是因為我們在下一個滑桿時,隱藏了可能停下的圖示。如果沒有這個屬性,使用者就必須先停止、監聽並擺脫看不見的圖片。
可擴充向量圖形具有大量的數學能力,因此我們要新增 <title>
元素,以便提供免費的滑鼠懸停標題,以及使用者可理解的數學註解:
<svg viewBox="0 0 24 24">
<title>A note icon</title>
<path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>
除此之外,我們也使用清楚標示的 HTML 程式碼,讓表單能夠針對滑鼠、鍵盤、電玩遊戲控制器和螢幕閱讀器進行良好的測試。
JavaScript
我已說明如何透過 JavaScript 管理曲目填滿顏色,因此現在要看 <form>
的相關 JavaScript:
const form = document.querySelector('form');
form.addEventListener('input', event => {
const formData = Object.fromEntries(new FormData(form));
console.table(formData);
})
每次表單與表單互動或變更時,主控台都會將表單記錄為資料表,方便檢查後再提交至伺服器。
結論
現在你知道我怎麼做,你會怎麼做?這樣可以達到一些有趣的元件架構!誰將建構第 1 版,並在最喜歡的架構中使用運算單元?🙂
讓我們帶您更多元的方法,並瞭解運用網路打造網站的所有方式。 建立示範並透過 Twitter 推文連結,我就會把連結新增至下方的「社群重混」部分!