前端優(yōu)秀實(shí)踐不完全指南
本文略長(zhǎng),耐下心好好讀讀,應(yīng)該會(huì)有所收獲~
其實(shí)標(biāo)題應(yīng)該叫,Web 用戶(hù)體驗(yàn)設(shè)計(jì)提升指南。
一個(gè) Web 頁(yè)面,一個(gè) APP,想讓別人用的爽,也就是所謂的良好的用戶(hù)體驗(yàn),我覺(jué)得他可能包括但不限于:
急速的打開(kāi)速度 眼前一亮的 UI 設(shè)計(jì) 酷炫的動(dòng)畫(huà)效果 豐富的個(gè)性化設(shè)置 便捷的操作 貼心的細(xì)節(jié) 關(guān)注殘障人士,良好的可訪問(wèn)性 ...
所謂的用戶(hù)體驗(yàn)設(shè)計(jì),其實(shí)是一個(gè)比較虛的概念,是秉承著以用戶(hù)為中心的思想的一種設(shè)計(jì)手段,以用戶(hù)需求為目標(biāo)而進(jìn)行的設(shè)計(jì)。設(shè)計(jì)過(guò)程注重以用戶(hù)為中心,用戶(hù)體驗(yàn)的概念從開(kāi)發(fā)的最早期就開(kāi)始進(jìn)入整個(gè)流程,并貫穿始終。
良好的用戶(hù)體驗(yàn)設(shè)計(jì),是產(chǎn)品每一個(gè)環(huán)節(jié)共同努力的結(jié)果。
除去一些很難一蹴而就的,本文將就頁(yè)面展示、交互細(xì)節(jié)、可訪問(wèn)性三個(gè)方面入手,羅列一些在實(shí)際的開(kāi)發(fā)過(guò)程中,積攢的一些有益的經(jīng)驗(yàn)。通過(guò)本文,你將能收獲到:
了解到一些小細(xì)節(jié)是如何影響用戶(hù)體驗(yàn)的 了解到如何在盡量小的開(kāi)發(fā)改動(dòng)下,提升頁(yè)面的用戶(hù)體驗(yàn) 了解到一些優(yōu)秀的交互設(shè)計(jì)細(xì)節(jié) 了解基本的無(wú)障礙功能及頁(yè)面可訪問(wèn)性的含義 了解基本的提升頁(yè)面可訪問(wèn)性的方法
頁(yè)面展示
就整個(gè)頁(yè)面的展示,頁(yè)面內(nèi)容的呈現(xiàn)而言,有一些小細(xì)節(jié)是需要我們注意的。
整體布局
先來(lái)看看一些布局相關(guān)的問(wèn)題。
對(duì)于大部分 PC 端的項(xiàng)目,我們首先需要考慮的肯定是最外層的一層包裹。假設(shè)就是 .g-app-wrapper。
<div class="g-app-wrapper">
<!-- 內(nèi)部?jī)?nèi)容 -->
</div>
首先,對(duì)于 .g-app-wrapper,有幾點(diǎn),是我們?cè)陧?xiàng)目開(kāi)發(fā)前必須弄清楚的:
項(xiàng)目是全屏布局還是定寬布局? 對(duì)于全屏布局,需要適配的最小的寬度是多少?
對(duì)于定寬布局,就比較方便了,假設(shè)定寬為 1200px,那么:
.g-app-wrapper {
width: 1200px;
margin: 0 auto;
}
利用 margin: 0 auto 實(shí)現(xiàn)布局的水平居中。在屏幕寬度大于 1200px 時(shí),兩側(cè)留白,當(dāng)然屏幕寬度小于 1200px 時(shí),則出現(xiàn)滾動(dòng)條,保證內(nèi)部?jī)?nèi)容不亂。

對(duì)于現(xiàn)代布局,更多的是全屏布局。其實(shí)現(xiàn)在也更提倡這種布局,即使用可隨用戶(hù)設(shè)備的尺寸和能力而變化的自適應(yīng)布局。
通常而言是左右兩欄,左側(cè)定寬,右側(cè)自適應(yīng)剩余寬度,當(dāng)然,會(huì)有一個(gè)最小的寬度。那么,它的布局應(yīng)該是這樣:
<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 進(jìn)行伸縮,占滿剩余空間,利用 min-width 保證了整個(gè)容器的最小寬度。
當(dāng)然,這是最基本的自適應(yīng)布局。對(duì)于現(xiàn)代布局,我們應(yīng)該盡可能的考慮更多的場(chǎng)景。做到:

底部 footer
下面一種情形也是非常常見(jiàn)的一個(gè)情景。
頁(yè)面存在一個(gè) footer 頁(yè)腳部分,如果整個(gè)頁(yè)面的內(nèi)容高度小于視窗的高度,則 footer 固定在視窗底部,如果整個(gè)頁(yè)面的內(nèi)容高度大于視窗的高度,則 footer 正常流排布(也就是需要滾動(dòng)到底部才能看到 footer)。
看看效果:

嗯,這個(gè)需求如果能夠使用 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[1]
當(dāng)然,實(shí)現(xiàn)它的方法有很多,這里僅給出一種推薦的解法。
處理動(dòng)態(tài)內(nèi)容 - 文本超長(zhǎng)
對(duì)于所有接收后端接口字段的文本展示類(lèi)的界面。都需要考慮全面(防御性編程:所有的外部數(shù)據(jù)都是不可信的),正常情況如下,是沒(méi)有問(wèn)題的。

但是我們是否考慮到了文本會(huì)超長(zhǎng)?超長(zhǎng)了會(huì)折行還是換行?

對(duì)于單行文本,使用單行省略:
{
width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

當(dāng)然,目前對(duì)于多行文本的超長(zhǎng)省略,兼容性也已經(jīng)非常好了:
{
width: 200px;
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}

處理動(dòng)態(tài)內(nèi)容 - 保護(hù)邊界
對(duì)于一些動(dòng)態(tài)內(nèi)容,我們經(jīng)常使用 min/max-width 或 min/max-height 對(duì)容器的高寬限度進(jìn)行合理的控制。
在使用它們的時(shí)候,也有一些細(xì)節(jié)需要考慮到。
譬如經(jīng)常會(huì)使用 min-width 控制按鈕的最小寬度:
.btn {
...
min-width: 120px;
}

當(dāng)內(nèi)容比較少的時(shí)候是沒(méi)問(wèn)題的,但是當(dāng)內(nèi)容比較長(zhǎng),就容易出現(xiàn)問(wèn)題。使用了 min-width 卻沒(méi)考慮到按鈕的過(guò)長(zhǎng)的情況:

這里就需要配合 padding 一起:
.btn {
...
min-width: 88px;
padding: 0 16px
}
借用Min and Max Width/Height in CSS[2]中一張非常好的圖,作為釋義:

0 內(nèi)容展示
這個(gè)也是一個(gè)常常被忽略的地方。
頁(yè)面經(jīng)常會(huì)有列表搜索,列表展示。那么,既然存在有數(shù)據(jù)的正常情況,當(dāng)然也會(huì)存在搜索不到結(jié)果或者列表無(wú)內(nèi)容可展示的情形。
對(duì)于這種情況,一定要注意 0 結(jié)果頁(yè)面的設(shè)計(jì),同時(shí)也要知道,這也是引導(dǎo)用戶(hù)的好地方。對(duì)于 0 結(jié)果頁(yè)面,分清楚:
數(shù)據(jù)為空:其中又可能包括了用戶(hù)無(wú)權(quán)限、搜索無(wú)結(jié)果、篩選無(wú)結(jié)果、頁(yè)面無(wú)數(shù)據(jù) 異常狀態(tài):其中又可能包括了網(wǎng)絡(luò)異常、服務(wù)器異常、加載失敗等待
不同的情況可能對(duì)應(yīng)不同的 0 結(jié)果頁(yè)面,附帶不同的操作引導(dǎo)。
譬如網(wǎng)絡(luò)異常:

或者確實(shí)是 0 結(jié)果:

關(guān)于 0 結(jié)果頁(yè)面設(shè)計(jì),可以詳細(xì)看看這篇文章:如何設(shè)計(jì)產(chǎn)品的空白頁(yè)面?[3]
小小總結(jié)一下,上述比較長(zhǎng)的篇幅一直都在闡述一個(gè)道理,開(kāi)發(fā)時(shí),不能僅僅關(guān)注正常現(xiàn)象,要多考慮各種異常情況,思考全面。做好各種可能情況的處理。
圖片相關(guān)
圖片在我們的業(yè)務(wù)中應(yīng)該是非常的常見(jiàn)了。有一些小細(xì)節(jié)是需要注意的。
給圖片同時(shí)設(shè)置高寬
有的時(shí)候和產(chǎn)品、設(shè)計(jì)會(huì)商定,只能使用固定尺寸大小的圖片,我們的布局可能是這樣:

對(duì)應(yīng)的布局:
<ul class="g-container">
<li>
<img src="http://placehold.it/150x100">
<p>圖片描述</p>
</li>
</ul>
ul li img {
width: 150px;
}
當(dāng)然,萬(wàn)一假設(shè)后端接口出現(xiàn)一張非正常大小的圖片,上述不加保護(hù)的布局就會(huì)出問(wèn)題:

所以對(duì)于圖片,我們總是建議同時(shí)寫(xiě)上高和寬,避免因?yàn)閳D片尺寸錯(cuò)誤帶來(lái)的布局問(wèn)題:
ul li img {
width: 150px;
height: 100px;
}
同時(shí),給 <img> 標(biāo)簽同時(shí)寫(xiě)上高寬,可以在圖片未加載之前提前占住位置,避免圖片從未加載狀態(tài)到渲染完成狀態(tài)高寬變化引起的重排問(wèn)題。
object-fit
當(dāng)然,限制高寬也會(huì)出現(xiàn)問(wèn)題,譬如圖片被拉伸了,非常的難看:

這個(gè)時(shí)候,我們可以借助 object-fit,它能夠指定可替換元素的內(nèi)容(也就是圖片)該如何適應(yīng)它的父容器的高寬。
ul li img {
width: 150px;
height: 100px;
object-fit: cover;
}
利用 object-fit: cover,使圖片內(nèi)容在保持其寬高比的同時(shí)填充元素的整個(gè)內(nèi)容框。

object-fit 還有一個(gè)配套屬性 object-position,它可以控制圖片在其內(nèi)容框中的位置。(類(lèi)似于 background-position),m默認(rèn)是 object-position: 50% 50%,如果你不希望圖片居中展示,可以使用它去改變圖片實(shí)際展示的 position 。
ul li img {
width: 150px;
height: 100px;
object-fit: cover;
object-position: 50% 100%;
}

像是這樣,object-position: 100% 50% 指明從底部開(kāi)始展示圖片。這里有一個(gè)很好的 Demo 可以幫助你理解 object-position。
CodePen Demo -- Object position[4]
考慮屏幕 dpr -- 響應(yīng)式圖片
正常情況下,圖片的展示應(yīng)該沒(méi)有什么問(wèn)題了。但是對(duì)于有圖片可展示的情況下,我們還可以做的更好。
在移動(dòng)端或者一些高清的 PC 屏幕(蘋(píng)果的 MAC Book),屏幕的 dpr 可能大于 1。這種時(shí)候,我們可能還需要考慮利用多倍圖去適配不同 dpr 的屏幕。
正好,<img> 標(biāo)簽是有提供相應(yīng)的屬性 srcset 讓我們進(jìn)行操作的。
<img src='[email protected]'
srcset='[email protected] 1x,
[email protected] 2x,
[email protected] 3x'
/>
當(dāng)然,這是比較舊的寫(xiě)法,srcset 新增了新的 w 寬度描述符,需要配合 sizes 一起使用,所以更好的寫(xiě)法是:
<img
src = "photo.png"
sizes = “(min-width: 600px) 600px, 300px"
srcset = “[email protected] 300w,
photo@2x.png 600w,
photo@3x.png 1200w,
>
利用 srcset,我們可以給不同 dpr 的屏幕,提供最適合的圖片。
上述出現(xiàn)了一些概念,dpr,圖片的 srcset ,sizes 屬性,不太了解的可以移步 前端基礎(chǔ)知識(shí)概述[5]
圖片丟失
好了,當(dāng)圖片鏈接沒(méi)問(wèn)題時(shí),已經(jīng)處理好了。接下來(lái)還需要考慮,當(dāng)圖片鏈接掛了,應(yīng)該如何處理。
處理的方式有很多種。最好的處理方式,是我最近在張?chǎng)涡窭蠋煹倪@篇文章中 -- 圖片加載失敗后CSS樣式處理最佳實(shí)踐[6] 看到的。這里簡(jiǎn)單講下:
利用圖片加載失敗,觸發(fā) <img>元素的onerror事件,給加載失敗的<img>元素新增一個(gè)樣式類(lèi)利用新增的樣式類(lèi),配合 <img>元素的偽元素,展示默認(rèn)兜底圖的同時(shí),還能一起展示<img>元素的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 ,加載默認(rèn)錯(cuò)誤兜底圖,利用偽元素 after,展示圖片的 alt 信息:

OK,到此,完整的對(duì)圖片的處理就算完成了,完整的 Demo 你可以戳這里看看:
CodePen Demo -- 圖片處理[7]
交互設(shè)計(jì)優(yōu)化
接下來(lái)一個(gè)大環(huán)節(jié)是關(guān)于一些交互的細(xì)節(jié)。對(duì)于交互設(shè)計(jì),一些比較通用的準(zhǔn)則:
Don’t make me think 符合用戶(hù)的習(xí)慣與預(yù)期 操作便利 做適當(dāng)?shù)奶嵝?/section> 不強(qiáng)迫用戶(hù)
過(guò)渡與動(dòng)畫(huà)
在我們的交互過(guò)程中,適當(dāng)?shù)脑黾舆^(guò)渡與動(dòng)畫(huà),能夠很好的讓用戶(hù)感知到頁(yè)面的變化。
譬如我們頁(yè)面上隨處可見(jiàn) loading 效果,其實(shí)就是這樣一種作用,讓用戶(hù)感知頁(yè)面正在加載,或者正在處理某些事務(wù)。

滾動(dòng)優(yōu)化
滾動(dòng)也是操作網(wǎng)頁(yè)中非常重要的一環(huán)??纯从心男┛梢?xún)?yōu)化的點(diǎn):
滾動(dòng)平滑:使用 scroll-behavior: smooth 讓滾動(dòng)絲滑
使用 scroll-behavior: smooth,可以讓滾動(dòng)框?qū)崿F(xiàn)平穩(wěn)的滾動(dòng),而不是突兀的跳動(dòng)。看看效果,假設(shè)如下結(jié)構(gòu):
<div class="g-container">
<nav>
<a href="#1">1</a>
<a href="#2">2</a>
<a href="#3">3</a>
</nav>
<div class="scrolling-box">
<section id="1">First section</section>
<section id="2">Second section</section>
<section id="3">Third section</section>
</div>
</div>
不使用 scroll-behavior: smooth,是突兀的跳動(dòng)切換:

給可滾動(dòng)容器添加 scroll-behavior: smooth,實(shí)現(xiàn)平滑滾動(dòng):
{
scroll-behavior: smooth;
}

使用 scroll-snap-type 優(yōu)化滾動(dòng)效果
sroll-snap-type 可能算得上是新的滾動(dòng)規(guī)范里面最核心的一個(gè)屬性樣式。
scroll-snap-type[8]:屬性定義在滾動(dòng)容器中的一個(gè)臨時(shí)點(diǎn)(snap point)如何被嚴(yán)格的執(zhí)行。
光看定義有點(diǎn)難理解,簡(jiǎn)單而言,這個(gè)屬性規(guī)定了一個(gè)容器是否對(duì)內(nèi)部滾動(dòng)動(dòng)作進(jìn)行捕捉,并且規(guī)定了如何去處理滾動(dòng)結(jié)束狀態(tài)。讓滾動(dòng)操作結(jié)束后,元素停止在適合的位置。
看個(gè)簡(jiǎn)單示例:

當(dāng)然,scroll-snap-type 用法非常多,可控制優(yōu)化的點(diǎn)很多,限于篇幅無(wú)法一一展開(kāi),具體更詳細(xì)的用法可以看看我的另外一篇文章 -- 使用 sroll-snap-type 優(yōu)化滾動(dòng)[9]
控制滾動(dòng)層級(jí),避免頁(yè)面大量重排
這個(gè)優(yōu)化可能稍微有一點(diǎn)難理解。需要了解 CSS 渲染優(yōu)化的相關(guān)知識(shí)。
先說(shuō)結(jié)論,控制滾動(dòng)層級(jí)的意思是盡量讓需要進(jìn)行 CSS 動(dòng)畫(huà)(可以是元素的動(dòng)畫(huà),也可以是容器的滾動(dòng))的元素的 z-index 保持在頁(yè)面最上方,避免瀏覽器創(chuàng)建不必要的圖形層(GraphicsLayer),能夠很好的提升渲染性能。
這一點(diǎn)怎么理解呢,一個(gè)元素觸發(fā)創(chuàng)建一個(gè) Graphics Layer 層的其中一個(gè)因素是:
元素有一個(gè) z-index 較低且包含一個(gè)復(fù)合層的兄弟元素
根據(jù)上述這點(diǎn),我們對(duì)滾動(dòng)性能進(jìn)行優(yōu)化的時(shí)候,需要注意兩點(diǎn):
通過(guò)生成獨(dú)立的 GraphicsLayer,利用 GPU 加速,提升滾動(dòng)的性能 如果本身滾動(dòng)沒(méi)有性能問(wèn)題,不需要獨(dú)立的 GraphicsLayer,也要注意滾動(dòng)容器的層級(jí),避免因?yàn)閷蛹?jí)過(guò)高而被其他創(chuàng)建了 GraphicsLayer 的元素合并,被動(dòng)的生成一個(gè) Graphics Layer ,影響頁(yè)面整體的渲染性能
如果你對(duì)這點(diǎn)還有點(diǎn)懵,可以看看這篇文章 -- 你所不知道的 CSS 動(dòng)畫(huà)技巧與細(xì)節(jié)[10]
點(diǎn)擊交互優(yōu)化
在用戶(hù)點(diǎn)擊交互方面,也有一些有意思的小細(xì)節(jié)。
優(yōu)化手勢(shì) -- 不同場(chǎng)景應(yīng)用不同 cursor
對(duì)于不同的內(nèi)容,最好給與不同的 cursor 樣式,CSS 原生提供非常多種常用的手勢(shì)。
在不同的場(chǎng)景使用不同的鼠標(biāo)手勢(shì),符合用戶(hù)的習(xí)慣與預(yù)期,可以很好的提升用戶(hù)的交互體驗(yàn)。
首先對(duì)于按鈕,就至少會(huì)有 3 種不同的 cursor,分別是可點(diǎn)擊,不可點(diǎn)擊,等待中:
{
cursor: pointer; // 可點(diǎn)擊
cursor: not-allowed; // 不可點(diǎn)擊
cursor: wait; // loading
}

除此之外,還有一些常見(jiàn)的,對(duì)于一些可輸入的 Input 框,使用 cursor: text,對(duì)于提示 Tips 類(lèi)使用 cursor: help,放大縮小圖片 zoom-in、zoom-out 等等:

一些常用的簡(jiǎn)單列一列:
按鈕可點(diǎn)擊: cursor: pointer按鈕禁止點(diǎn)擊: cursor: not-allowed等待 Loading 狀態(tài): cursor: wait輸入框:cursor: text; 圖片查看器可放大可縮?。?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">cursor: zoom-in/ zoom-out 提示:cursor: help;
當(dāng)然,實(shí)際 cursor 還支持非常多種,可以在 MDN[11] 或者下面這個(gè) CodePen Demo 中查看這里看完整的列表:
CodePen Demo -- Cursor Demo[12]
點(diǎn)擊區(qū)域優(yōu)化 -- 偽元素?cái)U(kuò)大點(diǎn)擊區(qū)域
按鈕是我們網(wǎng)頁(yè)設(shè)計(jì)中十分重要的一環(huán),而按鈕的設(shè)計(jì)也與用戶(hù)體驗(yàn)息息相關(guān)。
考慮這樣一個(gè)場(chǎng)景,在搖晃的車(chē)廂上或者是單手操作著屏幕,有的時(shí)候一個(gè)按鈕,死活也點(diǎn)不到。
讓用戶(hù)更容易的點(diǎn)擊到按鈕無(wú)疑能很好的增加用戶(hù)體驗(yàn)及可提升頁(yè)面的訪問(wèn)性,尤其是在移動(dòng)端,按鈕通常都很小,但是受限于設(shè)計(jì)稿或者整體 UI 風(fēng)格,我們不能直接去改變按鈕元素的高寬。
那么這個(gè)時(shí)候有什么辦法在不改變按鈕原本大小的情況下去增加他的點(diǎn)擊熱區(qū)呢?
這里,偽元素也是可以代表其宿主元素來(lái)響應(yīng)的鼠標(biāo)交互事件的。借助偽元素可以輕松幫我們實(shí)現(xiàn),我們可以這樣寫(xiě):
.btn::befoer{
content:"";
position:absolute;
top:-10px;
right:-10px;
bottom:-10px;
left:-10px;
}
當(dāng)然,在 PC 端下這樣子看起來(lái)有點(diǎn)奇怪,但是合理的用在點(diǎn)擊區(qū)域較小的移動(dòng)端則能取到十分好的效果,效果如下:

在按鈕的偽元素沒(méi)有其它用途的時(shí)候,這個(gè)方法確實(shí)是個(gè)很好的提升用戶(hù)體驗(yàn)的點(diǎn)。
快速選擇優(yōu)化 -- user-select: all
操作系統(tǒng)或者瀏覽器通常會(huì)提供一些快速選取文本的功能,看看下面的示意圖:

快速單擊兩次,可以選中單個(gè)單詞,快速單擊三次,可以選中一整行內(nèi)容。但是如果有的時(shí)候我們的核心內(nèi)容,被分隔符分割,或者潛藏在一整行中的一部分,這個(gè)時(shí)候選取起來(lái)就比較麻煩。
利用 user-select: all,可以將需要一次選中的內(nèi)容進(jìn)行包裹,用戶(hù)只需要點(diǎn)擊一次,就可以選中該段信息:
.g-select-all {
user-select: all
}
給需要一次選中的信息,加上這個(gè)樣式后的效果,這個(gè)細(xì)節(jié)作用在一些需要復(fù)制粘貼的場(chǎng)景,非常好用:

CodePen -- user-select: all 示例[13]
選中樣式優(yōu)化 -- ::selection
當(dāng)然,如果你想更進(jìn)一步,CSS 還有提供一個(gè) ::selection 偽類(lèi),可以控制選中的文本的樣式(只能控制color, background, text-shadow),進(jìn)一步加深效果。

CodePen -- user-select: all && ::selection 控制選中樣式[14]
添加禁止選擇 -- user-select: none
有快速選擇,也就會(huì)有它的對(duì)立面 -- 禁止選擇。
對(duì)于一些可能頻繁操作的按鈕,可能出現(xiàn)如下尷尬的場(chǎng)景:
文本按鈕的快速點(diǎn)擊,觸發(fā)了瀏覽器的雙擊快速選擇,導(dǎo)致文本被選中:

翻頁(yè)按鈕的快速點(diǎn)擊,觸發(fā)了瀏覽器的雙擊快速選擇:
[](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/da77c284cd0f4aafb183a5667c5cf32c~tplv-k3u1fbpfcp-watermark.image "" "")
對(duì)于這種場(chǎng)景,我們需要把不可被選中元素設(shè)置為不可被選中,利用 CSS 可以快速的實(shí)現(xiàn)這一點(diǎn):
{
-webkit-user-select: none; /* Safari */
-ms-user-select: none; /* IE 10 and IE 11 */
user-select: none; /* Standard syntax */
}
這樣,無(wú)論點(diǎn)擊的頻率多快,都不會(huì)出現(xiàn)尷尬的內(nèi)容選中:

跳轉(zhuǎn)優(yōu)化
現(xiàn)階段,單頁(yè)應(yīng)用(Single Page Application)的應(yīng)用非常廣泛,Vue 、React 等框架大行其道。但是一些常見(jiàn)的寫(xiě)法,也容易衍生一些小問(wèn)題。
譬如,點(diǎn)擊按鈕、文本進(jìn)行路由跳轉(zhuǎn)。譬如,經(jīng)常會(huì)出現(xiàn)這種代碼:
<template>
...
<button @click="gotoDetail">
Detail
</button>
...
<template>
...
gotoDetail() {
this.$router.push({
name: 'xxxxx',
});
}
大致邏輯就是給按鈕添加一個(gè)事件,點(diǎn)擊之后,跳轉(zhuǎn)到另外一個(gè)路由。當(dāng)然,本身這個(gè)功能是沒(méi)有任何問(wèn)題的,但是沒(méi)有考慮到用戶(hù)實(shí)際使用的場(chǎng)景。
實(shí)際使用的時(shí)候,由于是一個(gè)頁(yè)面跳轉(zhuǎn),很多時(shí)候,用戶(hù)希望能夠保留當(dāng)前頁(yè)面的內(nèi)容,同時(shí)打開(kāi)一個(gè)新的窗口,這個(gè)時(shí)候,他會(huì)嘗試下的鼠標(biāo)右鍵,選擇在新標(biāo)簽頁(yè)中打開(kāi)頁(yè)面,遺憾的是,上述的寫(xiě)法是不支持鼠標(biāo)右鍵打開(kāi)新頁(yè)面的。
原因在于瀏覽器是通過(guò)讀取 <a> 標(biāo)簽的 href 屬性,來(lái)展示類(lèi)似在新標(biāo)簽頁(yè)中打開(kāi)頁(yè)面這種選項(xiàng),對(duì)于上述的寫(xiě)法,瀏覽器是無(wú)法識(shí)別它是一個(gè)可以跳轉(zhuǎn)的鏈接。簡(jiǎn)單的示意圖如下:

所以,對(duì)于所有路由跳轉(zhuǎn)按鈕,建議都使用 <a> 標(biāo)簽,并且內(nèi)置 href 屬性,填寫(xiě)跳轉(zhuǎn)的路由地址。實(shí)際渲染出來(lái)的 DOM 可能是需要類(lèi)似這樣:
<a href="/xx/detail">Detail</a>
易用性
易用性也是交互設(shè)計(jì)中需要考慮的一個(gè)非常重要的環(huán)節(jié),能做的有非常多。簡(jiǎn)單的羅列一下:
注意界面元素的一致性,降低用戶(hù)學(xué)習(xí)成本 延續(xù)用戶(hù)日常的使用習(xí)慣,而不是重新創(chuàng)造 給下拉框增加一些預(yù)設(shè)值,降低用戶(hù)填寫(xiě)成本 同類(lèi)的操作合并在一起,降低用戶(hù)的認(rèn)知成本 任何操作之后都要給出反饋,讓用戶(hù)知道操作已經(jīng)生效
先探索,后表態(tài)
這一點(diǎn)非常的有意思,什么叫先探索后表態(tài)呢?就是我們不要一上來(lái)就強(qiáng)迫用戶(hù)去做一些事情,譬如登錄。
想一想一些常用網(wǎng)站的例子:
類(lèi)似虎牙、Bilibili 等視頻網(wǎng)站,可以先觀看體驗(yàn),一定觀看時(shí)間后才會(huì)要求登錄(登錄享受藍(lán)光) 電商網(wǎng)站,只有到付款的時(shí)候,才需要登錄
上述易用性和先探索,后表態(tài)的內(nèi)容,部分來(lái)源于:Learn From What Leading Companies A/B Test[15],可以好好讀一讀。
字體優(yōu)化
字體的選擇與使用其實(shí)是非常有講究的。
如果網(wǎng)站沒(méi)有強(qiáng)制必須使用某些字體。最新的規(guī)范建議我們更多的去使用系統(tǒng)默認(rèn)字體。也就是 CSS Fonts Module Level 4 -- Generic font families[16] 中新增的 font-family: system-ui 關(guān)鍵字。
font-family: system-ui 能夠自動(dòng)選擇本操作系統(tǒng)下的默認(rèn)系統(tǒng)字體。
默認(rèn)使用特定操作系統(tǒng)的系統(tǒng)字體可以提高性能,因?yàn)闉g覽器或者 webview 不必去下載任何字體文件,而是使用已有的字體文件。font-family: system-ui 字體設(shè)置的優(yōu)勢(shì)之處在于它與當(dāng)前操作系統(tǒng)使用的字體相匹配,對(duì)于文本內(nèi)容而言,它可以得到最恰當(dāng)?shù)恼故尽?/p>
舉兩個(gè)例子,天貓的字體定義與 Github 的字體定義:
天貓[17]: font-family: "PingFang SC",miui,system-ui,-apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,sans-serif;Github[18]: font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
簡(jiǎn)單而言,它們總體遵循了這樣一個(gè)基本原則:
1、盡量使用系統(tǒng)默認(rèn)字體
使用系統(tǒng)默認(rèn)字體的主要原因是性能,并且系統(tǒng)字體的優(yōu)點(diǎn)在于它與當(dāng)前操作系統(tǒng)使用的相匹配,因此它的文本展示必然也是一個(gè)讓人舒適展示效果。
2、兼顧中西,西文在前,中文在后
中文或者西文(英文)都要考慮到。由于大部分中文字體也是帶有英文部分的,但是英文部分又不怎么好看,但是英文字體中大多不包含中文。通常會(huì)先進(jìn)行英文字體的聲明,選擇最優(yōu)的英文字體,這樣不會(huì)影響到中文字體的選擇,中文字體聲明則緊隨其次。
3、兼顧多操作系統(tǒng)
選擇字體的時(shí)候要考慮多操作系統(tǒng)。例如 MAC OS 下的很多中文字體在 Windows 都沒(méi)有預(yù)裝,為了保證 MAC 用戶(hù)的體驗(yàn),在定義中文字體的時(shí)候,先定義 MAC 用戶(hù)的中文字體,再定義 Windows 用戶(hù)的中文字體;
4、兼顧舊操作系統(tǒng),以字體族系列 serif 和 sans-serif 結(jié)尾
當(dāng)使用一些非常新的字體時(shí),要考慮向下兼容,兼顧到一些極舊的操作系統(tǒng),使用字體族系列 serif 和 sans-serif 結(jié)尾總歸是不錯(cuò)的選擇。
對(duì)于上述的一些字體可能會(huì)有些懵,譬如 -apple-system, BlinkMacSystemFont,這是因?yàn)椴煌瑸g覽器廠商對(duì)規(guī)范的實(shí)現(xiàn)有所不同,對(duì)于字體定義更多的相關(guān)細(xì)節(jié),可以再看看這篇文章 -- Web 字體 font-family 再探秘[19]
可訪問(wèn)性(A11Y)
可訪問(wèn)性,在我們的網(wǎng)站中,屬于非常重要的一環(huán),但是大部分前端(其實(shí)應(yīng)該是設(shè)計(jì)、前端、產(chǎn)品)同學(xué)都會(huì)忽視它。
我潛伏在一個(gè)叫無(wú)障礙設(shè)計(jì)小組的群里,其中包含了很多無(wú)障礙設(shè)計(jì)師以及患有一定程度視覺(jué)、聽(tīng)力、行動(dòng)障礙的用戶(hù),他們?cè)谌豪锝?jīng)常會(huì)表達(dá)出一個(gè)觀點(diǎn),就是國(guó)內(nèi)的大部分 Web 網(wǎng)站及 APP 基本沒(méi)有考慮過(guò)殘障人士的使用(或者可訪問(wèn)性做的非常差),非常的令人揪心。
尤其在我們一些重交互、重邏輯的網(wǎng)站中,我們需要考慮用戶(hù)的使用習(xí)慣、使用場(chǎng)景,從高可訪問(wèn)性的角度考慮,譬如假設(shè)用戶(hù)沒(méi)有鼠標(biāo),僅僅使用鍵盤(pán),能否順暢的使用我們的網(wǎng)站?
假設(shè)用戶(hù)沒(méi)有鼠標(biāo),這個(gè)真不一定是針對(duì)殘障人士,很多情況下,用戶(hù)拿鼠標(biāo)的手可能在干其他事情,比如在吃東西,又或者在 TO B 類(lèi)的業(yè)務(wù),如超市收銀、倉(cāng)庫(kù)收貨,很可能用戶(hù)拿鼠標(biāo)的手操作著其他設(shè)備(掃碼槍?zhuān)┑鹊取?/p>
本文不會(huì)專(zhuān)門(mén)闡述無(wú)障礙設(shè)計(jì)的方方面面,只是從一些我覺(jué)得前端工程師需要關(guān)注的,并且僅需要花費(fèi)少量代價(jià)就能做好的一些無(wú)障礙設(shè)計(jì)細(xì)節(jié)。記住,無(wú)障礙設(shè)計(jì)對(duì)所有人都更友善。
色彩對(duì)比度
顏色,也是我們天天需要打交道的屬性。對(duì)于大部分視覺(jué)正常的用戶(hù),可能對(duì)頁(yè)面的顏色敏感度還沒(méi)那么高。但是對(duì)于一小部分色弱、色盲用戶(hù),他們對(duì)于網(wǎng)站的顏色會(huì)更加敏感,不好的設(shè)計(jì)會(huì)給他們?cè)L問(wèn)網(wǎng)站帶來(lái)極大的不便。
什么是色彩對(duì)比度
是否曾關(guān)心過(guò)頁(yè)面內(nèi)容的展示,使用的顏色是否恰當(dāng)?色弱、色盲用戶(hù)能否正常看清內(nèi)容?良好的色彩使用,在任何時(shí)候都是有益的,而且不僅僅局限于對(duì)于色弱、色盲用戶(hù)。在戶(hù)外用手機(jī)、陽(yáng)光很強(qiáng)看不清,符合無(wú)障礙標(biāo)準(zhǔn)的高清晰度、高對(duì)比度文字就更容易閱讀。
這里就有一個(gè)概念 -- 顏色對(duì)比度,簡(jiǎn)單地說(shuō),描述就是兩種顏色在亮度(Brightness)上的差別。運(yùn)用到我們的頁(yè)面上,大多數(shù)的情況就是背景色(background-color)與內(nèi)容顏色(color)的對(duì)比差異。
最權(quán)威的互聯(lián)網(wǎng)無(wú)障礙規(guī)范 —— WCAG AA[20]規(guī)范規(guī)定,所有重要內(nèi)容的色彩對(duì)比度需要達(dá)到 4.5:1 或以上(字號(hào)大于18號(hào)時(shí)達(dá)到 3:1 或以上),才算擁有較好的可讀性。
借用一張圖 -- 知乎 -- 助你輕松做好無(wú)障礙的15個(gè)UI設(shè)計(jì)工具推薦[21]:

很明顯,上述最后一個(gè)例子,文字已經(jīng)非常的不清晰了,正常用戶(hù)都已經(jīng)很難看得清了。
檢查色彩對(duì)比度的工具
Chrome 瀏覽器從很早開(kāi)始,就已經(jīng)支持檢查元素的色彩對(duì)比度了。以我當(dāng)前正在寫(xiě)作的頁(yè)面為例子,Github Issues 編輯頁(yè)面的兩個(gè)按鈕:

審查元素,分別可以看到兩個(gè)按鈕的色彩對(duì)比度:

可以看到,綠底白字按鈕的色彩對(duì)比度是沒(méi)有達(dá)到標(biāo)準(zhǔn)的,也被用黃色的嘆號(hào)標(biāo)識(shí)了出來(lái)。
除此之外,在審查元素的 Style 界面的取色器,改變顏色,也能直觀的看到當(dāng)前的色彩對(duì)比度:

焦點(diǎn)響應(yīng)
類(lèi)似百度、谷歌的首頁(yè),進(jìn)入頁(yè)面后會(huì)默認(rèn)讓輸入框獲得焦點(diǎn):

并非所有的有輸入框的頁(yè)面,都需要進(jìn)入頁(yè)面后進(jìn)行聚焦,但是焦點(diǎn)能夠讓用戶(hù)非常明確的知道,當(dāng)前自己在哪,需要做些什么。尤其是對(duì)于無(wú)法操作鼠標(biāo)的用戶(hù)。
頁(yè)面上可以聚焦的元素,稱(chēng)為可聚焦元素,獲得焦點(diǎn)的元素,則會(huì)觸發(fā)該元素的 focus 事件,對(duì)應(yīng)的,也就會(huì)觸發(fā)該元素的 :focus 偽類(lèi)。
瀏覽器通常會(huì)使用元素的 :focus 偽類(lèi),給元素添加一層邊框,告訴用戶(hù),當(dāng)前的獲焦元素在哪里。
我們可以通過(guò)鍵盤(pán)的 Tab 鍵,進(jìn)行焦點(diǎn)的切換,而獲焦元素則可以通過(guò)元素的 :focus 偽類(lèi)的樣式,告訴用戶(hù)當(dāng)前焦點(diǎn)位置。
當(dāng)然,除了
Tab鍵之外,對(duì)于一些多輸入框、選擇框的表單頁(yè)面,我們也應(yīng)該想著如何簡(jiǎn)化用戶(hù)的操作,譬如用戶(hù)按回車(chē)鍵時(shí)自動(dòng)前進(jìn)到下一字段。一般而言,用戶(hù)必須執(zhí)行的觸按越少,體驗(yàn)越佳。:thumbsup:
下面的截圖,完全由鍵盤(pán)操作完成:

通過(guò)元素的 :focus 偽類(lèi)以及鍵盤(pán) Tab 鍵切換焦點(diǎn),用戶(hù)可以非常順暢的在脫離鼠標(biāo)的情況下,對(duì)頁(yè)面的焦點(diǎn)切換及操作。
然而,在許多 reset.css 中,經(jīng)常能看到這樣一句 CSS 樣式代碼,為了樣式的統(tǒng)一,消除了可聚焦元素的 :focus 偽類(lèi):
:focus {
outline: 0;
}
我們給上述操作的代碼。也加上這樣一句代碼,全程再用鍵盤(pán)操作一下:

除了在 input 框有光標(biāo)提示,當(dāng)使用 Tab 進(jìn)行焦點(diǎn)切換到 select 或者到 button 時(shí),由于沒(méi)有了 :focus 樣式,用戶(hù)將完全懵逼,不知道頁(yè)面的焦點(diǎn)現(xiàn)在處于何處。
保證非鼠標(biāo)用戶(hù)體驗(yàn),合理運(yùn)用 :focus-visible
當(dāng)然,造成上述結(jié)果很重要的一個(gè)原因在于。:focus 偽類(lèi)不論用戶(hù)在使用鼠標(biāo)還是使用鍵盤(pán),只要元素獲焦,就會(huì)觸發(fā)。
而其本身的默認(rèn)樣式又不太能被產(chǎn)品或者設(shè)計(jì)接受,導(dǎo)致了很多人會(huì)在焦點(diǎn)元素觸發(fā) :focus 偽類(lèi)時(shí),通過(guò)改變 border 的顏色或者其他一些方式替代或者直接禁用。而這樣做,從可訪問(wèn)性的角度來(lái)看,對(duì)于非鼠標(biāo)用戶(hù),無(wú)疑是災(zāi)難性的。
基于此,在W3 CSS selectors-4 規(guī)范[22] 中,新增了一個(gè)非常有意思的 :focus-visible 偽類(lèi)。
:focus-visible:這個(gè)選擇器可以有效地根據(jù)用戶(hù)的輸入方式(鼠標(biāo) vs 鍵盤(pán))展示不同形式的焦點(diǎn)。
有了這個(gè)偽類(lèi),就可以做到,當(dāng)用戶(hù)使用鼠標(biāo)操作可聚焦元素時(shí),不展示 :focus 樣式或者讓其表現(xiàn)較弱,而當(dāng)用戶(hù)使用鍵盤(pán)操作焦點(diǎn)時(shí),利用 :focus-visible,讓可獲焦元素獲得一個(gè)較強(qiáng)的表現(xiàn)樣式。
看個(gè)簡(jiǎn)單的 Demo:
<button>Test 1</button>
button:active {
background: #eee;
}
button:focus {
outline: 2px solid red;
}
使用鼠標(biāo)點(diǎn)擊:

可以看到,使用鼠標(biāo)點(diǎn)擊的時(shí)候,觸發(fā)了元素的 :active 偽類(lèi),也觸發(fā)了 :focus偽類(lèi),不太美觀。但是如果設(shè)置了 outline: none 又會(huì)使鍵盤(pán)用戶(hù)的體驗(yàn)非常糟糕。嘗試使用 :focus-visible 偽類(lèi)改造一下:
button:active {
background: #eee;
}
button:focus {
outline: 2px solid red;
}
button:focus:not(:focus-visible) {
outline: none;
}
看看效果,分別是在鼠標(biāo)點(diǎn)擊 Button 和使用鍵盤(pán)控制焦點(diǎn)點(diǎn)擊 Button:

CodePen Demo -- :focus-visible example[23]
可以看到,使用鼠標(biāo)點(diǎn)擊,不會(huì)觸發(fā) :foucs,只有當(dāng)鍵盤(pán)操作聚焦元素,使用 Tab 切換焦點(diǎn)時(shí),outline: 2px solid red 這段代碼才會(huì)生效。
這樣,我們就既保證了正常用戶(hù)的點(diǎn)擊體驗(yàn),也保證了一批無(wú)法使用鼠標(biāo)的用戶(hù)的焦點(diǎn)管理體驗(yàn)。
值得注意的是,有同學(xué)會(huì)疑惑,這里為什么使用了 :not 這么繞的寫(xiě)法而不是直接這樣寫(xiě)呢:
button:focus {
outline: unset;
}
button:focus-visible {
outline: 2px solid red;
}
為的是兼容不支持 :focus-visible 的瀏覽器,當(dāng) :focus-visible 不兼容時(shí),還是需要有 :focus 偽類(lèi)的存在。
使用 WAI-ARIA 規(guī)范增強(qiáng)語(yǔ)義 -- div 等非可獲焦元素模擬獲焦元素
還有一個(gè)非常需要注意的點(diǎn)。
現(xiàn)在很多前端同學(xué)在前端開(kāi)發(fā)的過(guò)程中,喜歡使用非可獲焦元素模擬獲焦元素,譬如:
使用 div模擬button元素使用 ul模擬下拉列表select等等
當(dāng)下很多組件庫(kù)都是這樣做的,譬如 element-ui 和 ant-design。
在使用非可獲焦元素模擬獲焦元素的時(shí)候,一定要注意,不僅僅只是外觀長(zhǎng)得像就完事了,其行為表現(xiàn)也需要符合原本的 button、select 等可聚焦元素的性質(zhì),能夠體現(xiàn)元素的語(yǔ)義,能夠被聚焦,能夠通過(guò) Tab 切換等等。
基于大量類(lèi)似的場(chǎng)景,有了 WAI-ARIA 標(biāo)準(zhǔn)[24],WAI-ARIA是一個(gè)為殘疾人士等提供無(wú)障礙訪問(wèn)動(dòng)態(tài)、可交互Web內(nèi)容的技術(shù)規(guī)范。
簡(jiǎn)單來(lái)說(shuō),它提供了一些屬性,增強(qiáng)標(biāo)簽的語(yǔ)義及行為:
可以使用 tabindex屬性控制元素是否可以聚焦,以及它是否/在何處參與順序鍵盤(pán)導(dǎo)航可以使用 role屬性,來(lái)標(biāo)識(shí)元素的語(yǔ)義及作用,譬如使用<div id="saveChanges" tabindex="0" role="button">Save</div>來(lái)模擬一個(gè)按鈕還有大量的 aria-*屬性,表示元素的屬性或狀態(tài),幫助我們進(jìn)一步地識(shí)別以及實(shí)現(xiàn)元素的語(yǔ)義化,優(yōu)化無(wú)障礙體驗(yàn)
使用工具查看標(biāo)簽的語(yǔ)義
我們來(lái)看看 Github 頁(yè)面是如何定義一個(gè)按鈕的,以 Github Issues 頁(yè)面的 Edit 按鈕為例子:

這一塊,清晰的描述了這個(gè)按鈕在可訪問(wèn)性相關(guān)的一些特性,譬如 Contrast 色彩對(duì)比度,按鈕的描述,也就是 Name,是給屏幕閱讀器看到的,Role 標(biāo)識(shí)是這個(gè)元素的屬性,它是一個(gè)按鈕,Keyboard focusable 則表明他能否被鍵盤(pán)的 Tab 按鈕給捕獲。
分析使用非可聚焦元素模擬的按鈕
這里,我隨便選取了我們業(yè)務(wù)中一個(gè)使用 span 模擬按鈕的場(chǎng)景,是一個(gè)面包屑導(dǎo)航,點(diǎn)擊可進(jìn)行跳轉(zhuǎn),發(fā)現(xiàn)慘不忍睹:

HTML 代碼:
<span class="ssc-breadcrumb-item-link"> Inbound </span>

基本上可訪問(wèn)性為 0,作為一個(gè)按鈕,它不可被聚焦,無(wú)法被鍵盤(pán)用戶(hù)選中,沒(méi)有具體的語(yǔ)義,色彩對(duì)比度太低,可能視障用戶(hù)無(wú)法看清。并且,作為一個(gè)能進(jìn)行頁(yè)面跳轉(zhuǎn)的按鈕,它沒(méi)有不是 a 標(biāo)簽,沒(méi)有 href 屬性。
即便對(duì)于面包屑導(dǎo)航,我們可以不將它改造成 <a> 標(biāo)簽,也需要做到最基本的一些可訪問(wèn)性改造:
<span role="button" aria-label="goto inbound page" tabindex="0" class="ssc-breadcrumb-item-link"> Inbound </span>
不要忘了再改一下顏色,達(dá)到最低色彩對(duì)比度以上,再看看:

OK,這樣,一個(gè)最最最基本的,滿足最低可訪問(wèn)性需求的按鈕算是勉強(qiáng)達(dá)標(biāo),當(dāng)然,這個(gè)按鈕可以再更進(jìn)一步進(jìn)行改造,涉及了更深入的可訪問(wèn)性知識(shí),本文不深入展開(kāi)。
分析組件庫(kù)的 A11Y
最后,在我們比較常用的 Vue - element-ui[25]、React - ant-design[26] 中,我們來(lái)看看 ant-design 在提升可訪問(wèn)性相關(guān)的一些功能。
以 Select 選擇框組件為例,ant-design 利用了大量的 WAI-ARIA 屬性,使得用 div 模擬的下拉框不僅僅在表現(xiàn)上符合一個(gè)下拉框,在語(yǔ)義、行為上都符合一個(gè)下拉框,簡(jiǎn)單的一個(gè)例子:

看看使用 div 模擬下拉框的 DOM 部分:

再看看在交互體驗(yàn)上:

上述操作全是在鍵盤(pán)下完成,看著平平無(wú)奇,實(shí)際上組件庫(kù)在正常響應(yīng)可獲焦元素切換的同時(shí),給用 div 模擬的 select 加了很多鍵盤(pán)事件的響應(yīng),可以利用回車(chē),上下鍵等對(duì)可選項(xiàng)進(jìn)行選擇。其實(shí)是下了很多功夫。
對(duì)于 A11Y 相關(guān)的內(nèi)容,篇幅及內(nèi)容非常之多,本文無(wú)法一一展開(kāi),感興趣的可以通讀下下列文章:
WAI-ARIA basics[27] WAI-ARIA 1.1[28] Web中的焦點(diǎn)管理[29] 無(wú)障礙功能[30] 提升Web用戶(hù)體驗(yàn)的71個(gè)設(shè)計(jì)要點(diǎn)[31] 公眾號(hào) -- 無(wú)障礙設(shè)計(jì)小組[32]
總結(jié)一下
本文從頁(yè)面展示、交互細(xì)節(jié)、可訪問(wèn)性三個(gè)大方面入手,羅列一些在實(shí)際的開(kāi)發(fā)過(guò)程中,積攢的一些有益的經(jīng)驗(yàn)。雖然不夠全面,不過(guò)從一開(kāi)始也就沒(méi)想著大而全,主要是一些可能有用但是容易被忽視的點(diǎn),也算是一個(gè)不錯(cuò)的查缺補(bǔ)漏小指南。
當(dāng)然,很多都是我個(gè)人的觀點(diǎn)想法,可能有一些理解存在一些問(wèn)題,一些概念沒(méi)有解讀到位,也希望大家?guī)兔χ赋觥?/p>
最后
本文到此結(jié)束,希望對(duì)你有幫助 :)
如果還有什么疑問(wèn)或者建議,可以多多交流,原創(chuàng)文章,文筆有限,才疏學(xué)淺,文中若有不正之處,萬(wàn)望告知。
參考資料
Codepen Demo -- sticky footer by flex margin auto: https://codepen.io/Chokcoco/pen/pmrbWX
[2]Min and Max Width/Height in CSS: https://ishadeed.com/article/min-max-css/
[3]如何設(shè)計(jì)產(chǎn)品的空白頁(yè)面?: http://www.woshipm.com/pd/3742114.html
[4]CodePen Demo -- Object position: https://codepen.io/robinrendle/pen/raGOOJ
[5]前端基礎(chǔ)知識(shí)概述: https://github.com/chokcoco/cnblogsArticle/issues/25
[6]圖片加載失敗后CSS樣式處理最佳實(shí)踐: https://www.zhangxinxu.com/wordpress/2020/10/css-style-image-load-fail/
[7]CodePen Demo -- 圖片處理: https://codepen.io/Chokcoco/pen/WNGgNqv?editors=1100
[8]scroll-snap-type: https://developer.mozilla.org/zh-CN/docs/Web/CSS/scroll-snap-type
[9]使用 sroll-snap-type 優(yōu)化滾動(dòng): https://github.com/chokcoco/iCSS/issues/74
[10]你所不知道的 CSS 動(dòng)畫(huà)技巧與細(xì)節(jié): https://github.com/chokcoco/iCSS/issues/27
[11]MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
[12]CodePen Demo -- Cursor Demo: https://codepen.io/Chokcoco/pen/poEBLqr
[13]CodePen -- user-select: all 示例: https://codepen.io/Chokcoco/pen/LYRBmEJ
[14]CodePen -- user-select: all && ::selection 控制選中樣式: https://codepen.io/Chokcoco/pen/RwGYWNj
[15]Learn From What Leading Companies A/B Test: https://goodui.org/
[16]CSS Fonts Module Level 4 -- Generic font families: https://www.w3.org/TR/css-fonts-4/#generic-font-families
[17]天貓: https://www.tmall.com/
[18]Github: https://github.com
[19]Web 字體 font-family 再探秘: https://github.com/chokcoco/iCSS/issues/69
[20]WCAG AA: https://www.w3.org/Translations/WCAG21-zh/
[21]知乎 -- 助你輕松做好無(wú)障礙的15個(gè)UI設(shè)計(jì)工具推薦: https://zhuanlan.zhihu.com/p/349761993
[22]W3 CSS selectors-4 規(guī)范: https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo
[23]CodePen Demo -- :focus-visible example: https://codepen.io/Chokcoco/pen/abBbPrE
[24]WAI-ARIA 標(biāo)準(zhǔn): https://www.w3.org/TR/wai-aria-1.1/
[25]element-ui: https://element.eleme.io/#/zh-CN/component/select
[26]ant-design: https://ant.design/components/select-cn/
[27]WAI-ARIA basics: https://developer.mozilla.org/zh-CN/docs/learn/Accessibility/WAI-ARIA_basics
[28]WAI-ARIA 1.1: https://www.w3.org/TR/wai-aria-1.1/
[29]Web中的焦點(diǎn)管理: https://www.w3cplus.com/a11y/focus-for-web.html
[30]無(wú)障礙功能: https://developers.google.com/web/fundamentals/accessibility?hl=zh-cn
[31]提升Web用戶(hù)體驗(yàn)的71個(gè)設(shè)計(jì)要點(diǎn): https://www.shejidaren.com/71-good-ui-tips.html
[32]公眾號(hào) -- 無(wú)障礙設(shè)計(jì)小組: https://werss.app/accounts/NTI1NTUwNTg1ODU0NTM=
