本文其實應該叫,Web 用戶體驗設計提升指南。
一個 Web 頁面,一個 APP,想讓別人用的爽,也就是所謂的良好的用戶體驗,我覺得他可能包括但不限于:
所謂的用戶體驗設計,其實是一個比較虛的概念,是秉承著以用戶為中心的思想的一種設計手段,以用戶需求為目標而進行的設計。設計過程注重以用戶為中心,用戶體驗的概念從開發的最早期就開始進入整個流程,并貫穿始終。
良好的用戶體驗設計,是產品每一個環節共同努力的結果。
除去一些很難一蹴而就的,本文將就頁面展示、交互細節、可訪問性三個方面入手,羅列一些在實際的開發過程中,積攢的一些有益的經驗。通過本文,你將能收獲到:
就整個頁面的展示,頁面內容的呈現而言,有一些小細節是需要我們注意的。
先來看看一些布局相關的問題。
對于大部分 PC 端的項目,我們首先需要考慮的肯定是最外層的一層包裹。假設就是 .g-app-wrapper
。
<div class="g-app-wrapper">
div>
復制代碼
首先,對于 .g-app-wrapper
,有幾點,是我們在項目開發前必須弄清楚的:
對于定寬布局,就比較方便了,假設定寬為 1200px
,那么:
.g-app-wrapper {
width: 1200px;
margin: 0 auto;
}
復制代碼
利用 margin: 0 auto
實現布局的水平居中。在屏幕寬度大于 1200px
時,兩側留白,當然屏幕寬度小于 1200px
時,則出現滾動條,保證內部內容不亂。
">
對于現代布局,更多的是全屏布局。其實現在也更提倡這種布局,即使用可隨用戶設備的尺寸和能力而變化的自適應布局。
通常而言是左右兩欄,左側定寬,右側自適應剩余寬度,當然,會有一個最小的寬度。那么,它的布局應該是這樣:
<div class="g-app-wrapper">
<div class="g-sidebar">div>
<div class="g-main">div>
div>
復制代碼
.g-app-wrapper {
display: flex;
min-width: 1200px;
}
.g-sidebar {
flex-basis: 250px;
margin-right: 10px;
}
.g-main {
flex-grow: 1;
}
復制代碼
">
利用了 flex 布局下的 flex-grow: 1
,讓 .main
進行伸縮,占滿剩余空間,利用 min-width
保證了整個容器的最小寬度。
當然,這是最基本的自適應布局。對于現代布局,我們應該盡可能的考慮更多的場景。做到:
">
下面一種情形也是非常常見的一個情景。
頁面存在一個 footer 頁腳部分,如果整個頁面的內容高度小于視窗的高度,則 footer 固定在視窗底部,如果整個頁面的內容高度大于視窗的高度,則 footer 正常流排布(也就是需要滾動到底部才能看到 footer)。
看看效果:
">
嗯,這個需求如果能夠使用 flex 的話,使用 justify-content: space-between
可以很好的解決,同理使用 margin-top: auto
也非常容易完成:
<div class="g-container">
<div class="g-real-box">
...
div>
<div class="g-footer">div>
div>
復制代碼
.g-container {
height: 100vh;
display: flex;
flex-direction: column;
}
.g-footer {
margin-top: auto;
flex-shrink: 0;
height: 30px;
background: deeppink;
}
復制代碼
Codepen Demo -- sticky footer by flex margin auto
當然,實現它的方法有很多,這里僅給出一種推薦的解法。
對于所有接收后端接口字段的文本展示類的界面。都需要考慮全面(防御性編程:所有的外部數據都是不可信的),正常情況如下,是沒有問題的。
">
但是我們是否考慮到了文本會超長?超長了會折行還是換行?
">
對于單行文本,使用單行省略:
{
width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
復制代碼
">
當然,目前對于多行文本的超長省略,兼容性也已經非常好了:
{
width: 200px;
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
復制代碼
">
對于一些動態內容,我們經常使用 min/max-width
或 min/max-height
對容器的高寬限度進行合理的控制。
在使用它們的時候,也有一些細節需要考慮到。
譬如經常會使用 min-width
控制按鈕的最小寬度:
.btn {
...
min-width: 120px;
}
復制代碼
當內容比較少的時候是沒問題的,但是當內容比較長,就容易出現問題。使用了 min-width
卻沒考慮到按鈕的過長的情況:
這里就需要配合 padding 一起:
.btn {
...
min-width: 88px;
padding: 0 16px
}
復制代碼
借用Min and Max Width/Height in CSS中一張非常好的圖,作為釋義:
">
這個也是一個常常被忽略的地方。
頁面經常會有列表搜索,列表展示。那么,既然存在有數據的正常情況,當然也會存在搜索不到結果或者列表無內容可展示的情形。
對于這種情況,一定要注意 0 結果頁面的設計,同時也要知道,這也是引導用戶的好地方。對于 0 結果頁面,分清楚:
不同的情況可能對應不同的 0 結果頁面,附帶不同的操作引導。
譬如網絡異常:
">
或者確實是 0 結果:
">
關于 0 結果頁面設計,可以詳細看看這篇文章:如何設計產品的空白頁面?
小小總結一下,上述比較長的篇幅一直都在闡述一個道理,開發時,不能僅僅關注正?,F象,要多考慮各種異常情況,思考全面。做好各種可能情況的處理。
圖片在我們的業務中應該是非常的常見了。有一些小細節是需要注意的。
有的時候和產品、設計會商定,只能使用固定尺寸大小的圖片,我們的布局可能是這樣:
">
對應的布局:
<ul class="g-container">
<li>
<img src="http://placehold.it/150x100">
<p>圖片描述p>
li>
ul>
復制代碼
ul li img {
width: 150px;
}
復制代碼
當然,萬一假設后端接口出現一張非正常大小的圖片,上述不加保護的布局就會出問題:
">
所以對于圖片,我們總是建議同時寫上高和寬,避免因為圖片尺寸錯誤帶來的布局問題:
ul li img {
width: 150px;
height: 100px;
}
復制代碼
同時,給
標簽同時寫上高寬,可以在圖片未加載之前提前占住位置,避免圖片從未加載狀態到渲染完成狀態高寬變化引起的重排問題。
object-fit
當然,限制高寬也會出現問題,譬如圖片被拉伸了,非常的難看:
">
這個時候,我們可以借助 object-fit
,它能夠指定可替換元素的內容(也就是圖片)該如何適應它的父容器的高寬。
ul li img {
width: 150px;
height: 100px;
object-fit: cover;
}
復制代碼
利用 object-fit: cover
,使圖片內容在保持其寬高比的同時填充元素的整個內容框。
">
object-fit
還有一個配套屬性 object-position
,它可以控制圖片在其內容框中的位置。(類似于 background-position
),m默認是 object-position: 50% 50%
,如果你不希望圖片居中展示,可以使用它去改變圖片實際展示的 position 。
ul li img {
width: 150px;
height: 100px;
object-fit: cover;
object-position: 50% 100%;
}
復制代碼
">
像是這樣,object-position: 100% 50%
指明從底部開始展示圖片。這里有一個很好的 Demo 可以幫助你理解 object-position
。
CodePen Demo -- Object position
正常情況下,圖片的展示應該沒有什么問題了。但是對于有圖片可展示的情況下,我們還可以做的更好。
在移動端或者一些高清的 PC 屏幕(蘋果的 MAC Book),屏幕的 dpr 可能大于 1。這種時候,我們可能還需要考慮利用多倍圖去適配不同 dpr 的屏幕。
正好,
標簽是有提供相應的屬性 srcset
讓我們進行操作的。
<img src='photo@1x.png'
srcset='photo@1x.png 1x,
photo@2x.png 2x,
photo@3x.png 3x'
/>
復制代碼
當然,這是比較舊的寫法,srcset
新增了新的 w 寬度描述符,需要配合 sizes
一起使用,所以更好的寫法是:
<img
src = "photo.png"
sizes = “(min-width: 600px) 600px, 300px"
srcset = “photo@1x.png 300w,
photo@2x.png 600w,
photo@3x.png 1200w,
>
復制代碼
利用 srcset
,我們可以給不同 dpr 的屏幕,提供最適合的圖片。
上述出現了一些概念,dpr,圖片的 srcset ,sizes 屬性,不太了解的可以移步 前端基礎知識概述
好了,當圖片鏈接沒問題時,已經處理好了。接下來還需要考慮,當圖片鏈接掛了,應該如何處理。
處理的方式有很多種。最好的處理方式,是我最近在張鑫旭老師的這篇文章中 -- 圖片加載失敗后CSS樣式處理最佳實踐 看到的。這里簡單講下:
![]()
元素的 onerror
事件,給加載失敗的 ![]()
元素新增一個樣式類![]()
元素的偽元素,展示默認兜底圖的同時,還能一起展示 ![]()
元素的 alt
信息<img src="test.png" alt="圖片描述" onerror="this.classList.add('error');">
復制代碼
img.error {
position: relative;
display: inline-block;
}
img.error::before {
content: "";
/** 定位代碼 **/
background: url(error-default.png);
}
img.error::after {
content: attr(alt);
/** 定位代碼 **/
}
復制代碼
我們利用偽元素 before
,加載默認錯誤兜底圖,利用偽元素 after
,展示圖片的 alt
信息:
">
OK,到此,完整的對圖片的處理就算完成了,完整的 Demo 你可以戳這里看看:
接下來一個大環節是關于一些交互的細節。對于交互設計,一些比較通用的準則:
在我們的交互過程中,適當的增加過渡與動畫,能夠很好的讓用戶感知到頁面的變化。
譬如我們頁面上隨處可見 loading 效果,其實就是這樣一種作用,讓用戶感知頁面正在加載,或者正在處理某些事務。
">
滾動也是操作網頁中非常重要的一環??纯从心男┛梢詢灮狞c:
scroll-behavior: smooth
讓滾動絲滑使用 scroll-behavior: smooth
,可以讓滾動框實現平穩的滾動,而不是突兀的跳動??纯葱Ч?,假設如下結構:
<div class="g-container">
<nav>
<a href="#1">1a>
<a href="#2">2a>
<a href="#3">3a>
nav>
<div class="scrolling-box">
<section id="1">First sectionsection>
<section id="2">Second sectionsection>
<section id="3">Third sectionsection>
div>
div>
復制代碼
不使用 scroll-behavior: smooth
,是突兀的跳動切換:
">
給可滾動容器添加 scroll-behavior: smooth
,實現平滑滾動:
{
scroll-behavior: smooth;
}
復制代碼
scroll-snap-type
優化滾動效果sroll-snap-type
可能算得上是新的滾動規范里面最核心的一個屬性樣式。
scroll-snap-type:屬性定義在滾動容器中的一個臨時點(snap point)如何被嚴格的執行。
光看定義有點難理解,簡單而言,這個屬性規定了一個容器是否對內部滾動動作進行捕捉,并且規定了如何去處理滾動結束狀態。讓滾動操作結束后,元素停止在適合的位置。
看個簡單示例:
當然,scroll-snap-type
用法非常多,可控制優化的點很多,限于篇幅無法一一展開,具體更詳細的用法可以看看我的另外一篇文章 -- 使用 sroll-snap-type 優化滾動
這個優化可能稍微有一點難理解。需要了解 CSS 渲染優化的相關知識。
先說結論,控制滾動層級的意思是盡量讓需要進行 CSS 動畫(可以是元素的動畫,也可以是容器的滾動)的元素的 z-index 保持在頁面最上方,避免瀏覽器創建不必要的圖形層(GraphicsLayer),能夠很好的提升渲染性能。
這一點怎么理解呢,一個元素觸發創建一個 Graphics Layer 層的其中一個因素是:
根據上述這點,我們對滾動性能進行優化的時候,需要注意兩點:
如果你對這點還有點懵,可以看看這篇文章 -- 你所不知道的 CSS 動畫技巧與細節
在用戶點擊交互方面,也有一些有意思的小細節。
cursor
對于不同的內容,最好給與不同的 cursor
樣式,CSS 原生提供非常多種常用的手勢。
在不同的場景使用不同的鼠標手勢,符合用戶的習慣與預期,可以很好的提升用戶的交互體驗。
首先對于按鈕,就至少會有 3 種不同的 cursor,分別是可點擊,不可點擊,等待中:
{
cursor: pointer; // 可點擊
cursor: not-allowed; // 不可點擊
cursor: wait; // loading
}
復制代碼
除此之外,還有一些常見的,對于一些可輸入的 Input 框,使用 cursor: text
,對于提示 Tips 類使用 cursor: help
,放大縮小圖片 zoom-in
、zoom-out
等等:
">
一些常用的簡單列一列:
cursor: pointer
cursor: not-allowed
cursor: wait
當然,實際 cursor
還支持非常多種,可以在 MDN 或者下面這個 CodePen Demo 中查看這里看完整的列表:
按鈕是我們網頁設計中十分重要的一環,而按鈕的設計也與用戶體驗息息相關。
考慮這樣一個場景,在搖晃的車廂上或者是單手操作著屏幕,有的時候一個按鈕,死活也點不到。
讓用戶更容易的點擊到按鈕無疑能很好的增加用戶體驗及可提升頁面的訪問性,尤其是在移動端,按鈕通常都很小,但是受限于設計稿或者整體 UI 風格,我們不能直接去改變按鈕元素的高寬。
那么這個時候有什么辦法在不改變按鈕原本大小的情況下去增加他的點擊熱區呢?
這里,偽元素也是可以代表其宿主元素來響應的鼠標交互事件的。借助偽元素可以輕松幫我們實現,我們可以這樣寫:
.btn::befoer{
content:"";
position:absolute;
top:-10px;
right:-10px;
bottom:-10px;
left:-10px;
}
復制代碼
當然,在 PC 端下這樣子看起來有點奇怪,但是合理的用在點擊區域較小的移動端則能取到十分好的效果,效果如下:
">
在按鈕的偽元素沒有其它用途的時候,這個方法確實是個很好的提升用戶體驗的點。
user-select: all
操作系統或者瀏覽器通常會提供一些快速選取文本的功能,看看下面的示意圖:
">
快速單擊兩次,可以選中單個單詞,快速單擊三次,可以選中一整行內容。但是如果有的時候我們的核心內容,被分隔符分割,或者潛藏在一整行中的一部分,這個時候選取起來就比較麻煩。
利用 user-select: all
,可以將需要一次選中的內容進行包裹,用戶只需要點擊一次,就可以選中該段信息:
.g-select-all {
user-select: all
}
復制代碼
給需要一次選中的信息,加上這個樣式后的效果,這個細節作用在一些需要復制粘貼的場景,非常好用:
">
CodePen -- user-select: all 示例
::selection
當然,如果你想更進一步,CSS 還有提供一個 ::selection
偽類,可以控制選中的文本的樣式(只能控制color
, background
, text-shadow
),進一步加深效果。
">
CodePen -- user-select: all && ::selection 控制選中樣式
user-select: none
有快速選擇,也就會有它的對立面 -- 禁止選擇。
對于一些可能頻繁操作的按鈕,可能出現如下尷尬的場景:
">
對于這種場景,我們需要把不可被選中元素設置為不可被選中,利用 CSS 可以快速的實現這一點:
{
-webkit-user-select: none; /* Safari */
-ms-user-select: none; /* IE 10 and IE 11 */
user-select: none; /* Standard syntax */
}
復制代碼
這樣,無論點擊的頻率多快,都不會出現尷尬的內容選中:
">
現階段,單頁應用(Single Page Application)的應用非常廣泛,Vue 、React 等框架大行其道。但是一些常見的寫法,也容易衍生一些小問題。
譬如,點擊按鈕、文本進行路由跳轉。譬如,經常會出現這種代碼:
...
...
...
gotoDetail() {
this.$router.push({
name: 'xxxxx',
});
}
復制代碼
大致邏輯就是給按鈕添加一個事件,點擊之后,跳轉到另外一個路由。當然,本身這個功能是沒有任何問題的,但是沒有考慮到用戶實際使用的場景。
實際使用的時候,由于是一個頁面跳轉,很多時候,用戶希望能夠保留當前頁面的內容,同時打開一個新的窗口,這個時候,他會嘗試下的鼠標右鍵,選擇在新標簽頁中打開頁面,遺憾的是,上述的寫法是不支持鼠標右鍵打開新頁面的。
原因在于瀏覽器是通過讀取 標簽的
href
屬性,來展示類似在新標簽頁中打開頁面這種選項,對于上述的寫法,瀏覽器是無法識別它是一個可以跳轉的鏈接。簡單的示意圖如下:
">
所以,對于所有路由跳轉按鈕,建議都使用 標簽,并且內置
href
屬性,填寫跳轉的路由地址。實際渲染出來的 DOM 可能是需要類似這樣:
<a href="/xx/detail">Detaila>
復制代碼
易用性也是交互設計中需要考慮的一個非常重要的環節,能做的有非常多。簡單的羅列一下:
這一點非常的有意思,什么叫先探索后表態呢?就是我們不要一上來就強迫用戶去做一些事情,譬如登錄。
想一想一些常用網站的例子:
上述易用性和先探索,后表態的內容,部分來源于:Learn From What Leading Companies A/B Test,可以好好讀一讀。
字體的選擇與使用其實是非常有講究的。
如果網站沒有強制必須使用某些字體。最新的規范建議我們更多的去使用系統默認字體。也就是 CSS Fonts Module Level 4 -- Generic font families 中新增的 font-family: system-ui
關鍵字。
font-family: system-ui
能夠自動選擇本操作系統下的默認系統字體。
默認使用特定操作系統的系統字體可以提高性能,因為瀏覽器或者 webview 不必去下載任何字體文件,而是使用已有的字體文件。 font-family: system-ui
字體設置的優勢之處在于它與當前操作系統使用的字體相匹配,對于文本內容而言,它可以得到最恰當的展示。
舉兩個例子,天貓的字體定義與 Github 的字體定義:
font-family: "PingFang SC",miui,system-ui,-apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,sans-serif;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
簡單而言,它們總體遵循了這樣一個基本原則:
使用系統默認字體的主要原因是性能,并且系統字體的優點在于它與當前操作系統使用的相匹配,因此它的文本展示必然也是一個讓人舒適展示效果。
中文或者西文(英文)都要考慮到。由于大部分中文字體也是帶有英文部分的,但是英文部分又不怎么好看,但是英文字體中大多不包含中文。通常會先進行英文字體的聲明,選擇最優的英文字體,這樣不會影響到中文字體的選擇,中文字體聲明則緊隨其次。
選擇字體的時候要考慮多操作系統。例如 MAC OS 下的很多中文字體在 Windows 都沒有預裝,為了保證 MAC 用戶的體驗,在定義中文字體的時候,先定義 MAC 用戶的中文字體,再定義 Windows 用戶的中文字體;
當使用一些非常新的字體時,要考慮向下兼容,兼顧到一些極舊的操作系統,使用字體族系列?serif?和?sans-serif?結尾總歸是不錯的選擇。
對于上述的一些字體可能會有些懵,譬如 -apple-system
, BlinkMacSystemFont
,這是因為不同瀏覽器廠商對規范的實現有所不同,對于字體定義更多的相關細節,可以再看看這篇文章 -- Web 字體 font-family 再探秘
可訪問性,在我們的網站中,屬于非常重要的一環,但是大部分前端(其實應該是設計、前端、產品)同學都會忽視它。
我潛伏在一個叫無障礙設計小組的群里,其中包含了很多無障礙設計師以及患有一定程度視覺、聽力、行動障礙的用戶,他們在群里經常會表達出一個觀點,就是國內的大部分 Web 網站及 APP 基本沒有考慮過殘障人士的使用(或者可訪問性做的非常差),非常的令人揪心。
尤其在我們一些重交互、重邏輯的網站中,我們需要考慮用戶的使用習慣、使用場景,從高可訪問性的角度考慮,譬如假設用戶沒有鼠標,僅僅使用鍵盤,能否順暢的使用我們的網站?
假設用戶沒有鼠標,這個真不一定是針對殘障人士,很多情況下,用戶拿鼠標的手可能在干其他事情,比如在吃東西,又或者在 TO B 類的業務,如超市收銀、倉庫收貨,很可能用戶拿鼠標的手操作著其他設備(掃碼槍)等等。
本文不會專門闡述無障礙設計的方方面面,只是從一些我覺得前端工程師需要關注的,并且僅需要花費少量代價就能做好的一些無障礙設計細節。記住,無障礙設計對所有人都更友善。
顏色,也是我們天天需要打交道的屬性。對于大部分視覺正常的用戶,可能對頁面的顏色敏感度還沒那么高。但是對于一小部分色弱、色盲用戶,他們對于網站的顏色會更加敏感,不好的設計會給他們訪問網站帶來極大的不便。
是否曾關心過頁面內容的展示,使用的顏色是否恰當?色弱、色盲用戶能否正??辞鍍热??良好的色彩使用,在任何時候都是有益的,而且不僅僅局限于對于色弱、色盲用戶。在戶外用手機、陽光很強看不清,符合無障礙標準的高清晰度、高對比度文字就更容易閱讀。
這里就有一個概念 -- 顏色對比度,簡單地說,描述就是兩種顏色在亮度(Brightness)上的差別。運用到我們的頁面上,大多數的情況就是背景色(background-color)與內容顏色(color)的對比差異。
最權威的互聯網無障礙規范 —— WCAG AA規范規定,所有重要內容的色彩對比度需要達到 4.5:1 或以上(字號大于18號時達到 3:1 或以上),才算擁有較好的可讀性。
借用一張圖 -- 知乎 -- 助你輕松做好無障礙的15個UI設計工具推薦:
">
很明顯,上述最后一個例子,文字已經非常的不清晰了,正常用戶都已經很難看得清了。
Chrome 瀏覽器從很早開始,就已經支持檢查元素的色彩對比度了。以我當前正在寫作的頁面為例子,Github Issues
編輯頁面的兩個按鈕:
">
審查元素,分別可以看到兩個按鈕的色彩對比度:
">
可以看到,綠底白字按鈕的色彩對比度是沒有達到標準的,也被用黃色的嘆號標識了出來。
除此之外,在審查元素的 Style 界面的取色器,改變顏色,也能直觀的看到當前的色彩對比度:
">
類似百度、谷歌的首頁,進入頁面后會默認讓輸入框獲得焦點:
">
并非所有的有輸入框的頁面,都需要進入頁面后進行聚焦,但是焦點能夠讓用戶非常明確的知道,當前自己在哪,需要做些什么。尤其是對于無法操作鼠標的用戶。
頁面上可以聚焦的元素,稱為可聚焦元素,獲得焦點的元素,則會觸發該元素的 focus
事件,對應的,也就會觸發該元素的 :focus
偽類。
瀏覽器通常會使用元素的 :focus
偽類,給元素添加一層邊框,告訴用戶,當前的獲焦元素在哪里。
我們可以通過鍵盤的 Tab
鍵,進行焦點的切換,而獲焦元素則可以通過元素的 :focus
偽類的樣式,告訴用戶當前焦點位置。
當然,除了
Tab
鍵之外,對于一些多輸入框、選擇框的表單頁面,我們也應該想著如何簡化用戶的操作,譬如用戶按回車鍵時自動前進到下一字段。一般而言,用戶必須執行的觸按越少,體驗越佳。:thumbsup:
下面的截圖,完全由鍵盤操作完成:
">
通過元素的 :focus
偽類以及鍵盤 Tab 鍵切換焦點,用戶可以非常順暢的在脫離鼠標的情況下,對頁面的焦點切換及操作。
然而,在許多 reset.css
中,經常能看到這樣一句 CSS 樣式代碼,為了樣式的統一,消除了可聚焦元素的 :focus
偽類:
:focus {
outline: 0;
}
復制代碼
我們給上述操作的代碼。也加上這樣一句代碼,全程再用鍵盤操作一下:
">
除了在 input
框有光標提示,當使用 Tab 進行焦點切換到 select
或者到 button
時,由于沒有了 :focus
樣式,用戶將完全懵逼,不知道頁面的焦點現在處于何處。
:focus-visible
當然,造成上述結果很重要的一個原因在于。:focus
偽類不論用戶在使用鼠標還是使用鍵盤,只要元素獲焦,就會觸發。
而其本身的默認樣式又不太能被產品或者設計接受,導致了很多人會在焦點元素觸發 :focus
偽類時,通過改變 border 的顏色或者其他一些方式替代或者直接禁用。而這樣做,從可訪問性的角度來看,對于非鼠標用戶,無疑是災難性的。
基于此,在W3 CSS selectors-4 規范 中,新增了一個非常有意思的 :focus-visible
偽類。
:focus-visible
:這個選擇器可以有效地根據用戶的輸入方式(鼠標 vs 鍵盤)展示不同形式的焦點。
有了這個偽類,就可以做到,當用戶使用鼠標操作可聚焦元素時,不展示 :focus
樣式或者讓其表現較弱,而當用戶使用鍵盤操作焦點時,利用 :focus-visible
,讓可獲焦元素獲得一個較強的表現樣式。
看個簡單的 Demo:
<button>Test 1button>
復制代碼
button:active {
background: #eee;
}
button:focus {
outline: 2px solid red;
}
復制代碼
使用鼠標點擊: