1. 前端優(yōu)秀實踐不完全指南【追求極致用戶體驗】

        共 21949字,需瀏覽 44分鐘

         ·

        2021-03-05 12:59

        本文略長,耐下心好好讀讀,應(yīng)該會有所收獲~

        其實標(biāo)題應(yīng)該叫,Web 用戶體驗設(shè)計提升指南。

        一個 Web 頁面,一個 APP,想讓別人用的爽,也就是所謂的良好的用戶體驗,我覺得他可能包括但不限于:

        • 急速的打開速度
        • 眼前一亮的 UI 設(shè)計
        • 酷炫的動畫效果
        • 豐富的個性化設(shè)置
        • 便捷的操作
        • 貼心的細(xì)節(jié)
        • 關(guān)注殘障人士,良好的可訪問性
        • ...

        所謂的用戶體驗設(shè)計,其實是一個比較虛的概念,是秉承著以用戶為中心的思想的一種設(shè)計手段,以用戶需求為目標(biāo)而進(jìn)行的設(shè)計。設(shè)計過程注重以用戶為中心,用戶體驗的概念從開發(fā)的最早期就開始進(jìn)入整個流程,并貫穿始終。

        良好的用戶體驗設(shè)計,是產(chǎn)品每一個環(huán)節(jié)共同努力的結(jié)果。

        除去一些很難一蹴而就的,本文將就頁面展示、交互細(xì)節(jié)、可訪問性三個方面入手,羅列一些在實際的開發(fā)過程中,積攢的一些有益的經(jīng)驗。通過本文,你將能收獲到:

        1. 了解到一些小細(xì)節(jié)是如何影響用戶體驗的
        2. 了解到如何在盡量小的開發(fā)改動下,提升頁面的用戶體驗
        3. 了解到一些優(yōu)秀的交互設(shè)計細(xì)節(jié)
        4. 了解基本的無障礙功能及頁面可訪問性的含義
        5. 了解基本的提升頁面可訪問性的方法

        頁面展示

        就整個頁面的展示,頁面內(nèi)容的呈現(xiàn)而言,有一些小細(xì)節(jié)是需要我們注意的。

        整體布局

        先來看看一些布局相關(guān)的問題。

        對于大部分 PC 端的項目,我們首先需要考慮的肯定是最外層的一層包裹。假設(shè)就是 .g-app-wrapper

        <div class="g-app-wrapper">
            <!-- 內(nèi)部內(nèi)容 -->
        </div>

        首先,對于 .g-app-wrapper,有幾點,是我們在項目開發(fā)前必須弄清楚的:

        1. 項目是全屏布局還是定寬布局?
        2. 對于全屏布局,需要適配的最小的寬度是多少?

        對于定寬布局,就比較方便了,假設(shè)定寬為 1200px,那么:

        .g-app-wrapper {
            width1200px;
            margin0 auto;
        }

        利用 margin: 0 auto 實現(xiàn)布局的水平居中。在屏幕寬度大于 1200px 時,兩側(cè)留白,當(dāng)然屏幕寬度小于 1200px 時,則出現(xiàn)滾動條,保證內(nèi)部內(nèi)容不亂。

        對于現(xiàn)代布局,更多的是全屏布局。其實現(xiàn)在也更提倡這種布局,即使用可隨用戶設(shè)備的尺寸和能力而變化的自適應(yīng)布局。

        通常而言是左右兩欄,左側(cè)定寬,右側(cè)自適應(yīng)剩余寬度,當(dāng)然,會有一個最小的寬度。那么,它的布局應(yīng)該是這樣:

        <div class="g-app-wrapper">
            <div class="g-sidebar"></div>
            <div class="g-main"></div>
        </div>
        .g-app-wrapper {
            display: flex;
            min-width1200px;
        }
        .g-sidebar {
            flex-basis250px;
            margin-right10px;
        }
        .g-main {
            flex-grow1;
        }

        利用了 flex 布局下的 flex-grow: 1,讓 .main 進(jìn)行伸縮,占滿剩余空間,利用 min-width 保證了整個容器的最小寬度。

        當(dāng)然,這是最基本的自適應(yīng)布局。對于現(xiàn)代布局,我們應(yīng)該盡可能的考慮更多的場景。做到:

        底部 footer

        下面一種情形也是非常常見的一個情景。

        頁面存在一個 footer 頁腳部分,如果整個頁面的內(nèi)容高度小于視窗的高度,則 footer 固定在視窗底部,如果整個頁面的內(nèi)容高度大于視窗的高度,則 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 {
            height100vh;
            display: flex;
            flex-direction: column;
        }

        .g-footer {
            margin-top: auto;
            flex-shrink0;
            height30px;
            background: deeppink;
        }

        Codepen Demo -- sticky footer by flex margin auto[1]

        當(dāng)然,實現(xiàn)它的方法有很多,這里僅給出一種推薦的解法。

        處理動態(tài)內(nèi)容 - 文本超長

        對于所有接收后端接口字段的文本展示類的界面。都需要考慮全面(防御性編程:所有的外部數(shù)據(jù)都是不可信的),正常情況如下,是沒有問題的。

        但是我們是否考慮到了文本會超長?超長了會折行還是換行?

        對于單行文本,使用單行省略:

        {
            width200px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        當(dāng)然,目前對于多行文本的超長省略,兼容性也已經(jīng)非常好了:

        {
            width200px;
            overflow : hidden;
            text-overflow: ellipsis;
            display: -webkit-box;
            -webkit-line-clamp2;
            -webkit-box-orient: vertical;
        }

        處理動態(tài)內(nèi)容 - 保護(hù)邊界

        對于一些動態(tài)內(nèi)容,我們經(jīng)常使用 min/max-widthmin/max-height 對容器的高寬限度進(jìn)行合理的控制。

        在使用它們的時候,也有一些細(xì)節(jié)需要考慮到。

        譬如經(jīng)常會使用 min-width 控制按鈕的最小寬度:

        .btn {
            ...
            min-width120px;
        }

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

        這里就需要配合 padding 一起:

        .btn {
            ...
            min-width88px;
            padding0 16px
        }

        借用Min and Max Width/Height in CSS[2]中一張非常好的圖,作為釋義:

        0 內(nèi)容展示

        這個也是一個常常被忽略的地方。

        頁面經(jīng)常會有列表搜索,列表展示。那么,既然存在有數(shù)據(jù)的正常情況,當(dāng)然也會存在搜索不到結(jié)果或者列表無內(nèi)容可展示的情形。

        對于這種情況,一定要注意 0 結(jié)果頁面的設(shè)計,同時也要知道,這也是引導(dǎo)用戶的好地方。對于 0 結(jié)果頁面,分清楚:

        • 數(shù)據(jù)為空:其中又可能包括了用戶無權(quán)限、搜索無結(jié)果、篩選無結(jié)果、頁面無數(shù)據(jù)
        • 異常狀態(tài):其中又可能包括了網(wǎng)絡(luò)異常、服務(wù)器異常、加載失敗等待

        不同的情況可能對應(yīng)不同的 0 結(jié)果頁面,附帶不同的操作引導(dǎo)。

        譬如網(wǎng)絡(luò)異常:

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

        關(guān)于 0 結(jié)果頁面設(shè)計,可以詳細(xì)看看這篇文章:如何設(shè)計產(chǎn)品的空白頁面?[3]

        小小總結(jié)一下,上述比較長的篇幅一直都在闡述一個道理,開發(fā)時,不能僅僅關(guān)注正?,F(xiàn)象,要多考慮各種異常情況,思考全面。做好各種可能情況的處理。

        圖片相關(guān)

        圖片在我們的業(yè)務(wù)中應(yīng)該是非常的常見了。有一些小細(xì)節(jié)是需要注意的。

        給圖片同時設(shè)置高寬

        有的時候和產(chǎn)品、設(shè)計會商定,只能使用固定尺寸大小的圖片,我們的布局可能是這樣:

        對應(yīng)的布局:

        <ul class="g-container">
            <li>
                <img src="http://placehold.it/150x100">
                <p>圖片描述</p>
            </li>
        </ul>
        ul li img {
            width150px;
        }

        當(dāng)然,萬一假設(shè)后端接口出現(xiàn)一張非正常大小的圖片,上述不加保護(hù)的布局就會出問題:

        所以對于圖片,我們總是建議同時寫上高和寬,避免因為圖片尺寸錯誤帶來的布局問題:

        ul li img {
            width150px;
            height100px;
        }

        同時,給 <img> 標(biāo)簽同時寫上高寬,可以在圖片未加載之前提前占住位置,避免圖片從未加載狀態(tài)到渲染完成狀態(tài)高寬變化引起的重排問題。

        object-fit

        當(dāng)然,限制高寬也會出現(xiàn)問題,譬如圖片被拉伸了,非常的難看:

        這個時候,我們可以借助 object-fit,它能夠指定可替換元素的內(nèi)容(也就是圖片)該如何適應(yīng)它的父容器的高寬。

        ul li img {
            width150px;
            height100px;
            object-fit: cover;
        }

        利用 object-fit: cover,使圖片內(nèi)容在保持其寬高比的同時填充元素的整個內(nèi)容框。

        object-fit 還有一個配套屬性 object-position,它可以控制圖片在其內(nèi)容框中的位置。(類似于 background-position),m默認(rèn)是 object-position: 50% 50%,如果你不希望圖片居中展示,可以使用它去改變圖片實際展示的 position 。

        ul li img {
            width150px;
            height100px;
            object-fit: cover;
            object-position50% 100%;
        }

        像是這樣,object-position: 100% 50% 指明從底部開始展示圖片。這里有一個很好的 Demo 可以幫助你理解 object-position。

        CodePen Demo -- Object position[4]

        考慮屏幕 dpr -- 響應(yīng)式圖片

        正常情況下,圖片的展示應(yīng)該沒有什么問題了。但是對于有圖片可展示的情況下,我們還可以做的更好。

        在移動端或者一些高清的 PC 屏幕(蘋果的 MAC Book),屏幕的 dpr 可能大于 1。這種時候,我們可能還需要考慮利用多倍圖去適配不同 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)然,這是比較舊的寫法,srcset 新增了新的 w 寬度描述符,需要配合 sizes 一起使用,所以更好的寫法是:

        <img 
                src = "photo.png" 
                sizes = “(min-width: 600px600px300px
                srcset = [email protected] 300w,
                               photo@2x.png 600w,
                               photo@3x.png 1200w,
        >

        利用 srcset,我們可以給不同 dpr 的屏幕,提供最適合的圖片。

        上述出現(xiàn)了一些概念,dpr,圖片的 srcset ,sizes 屬性,不太了解的可以移步 前端基礎(chǔ)知識概述[5]

        圖片丟失

        好了,當(dāng)圖片鏈接沒問題時,已經(jīng)處理好了。接下來還需要考慮,當(dāng)圖片鏈接掛了,應(yīng)該如何處理。

        處理的方式有很多種。最好的處理方式,是我最近在張鑫旭老師的這篇文章中 -- 圖片加載失敗后CSS樣式處理最佳實踐[6] 看到的。這里簡單講下:

        1. 利用圖片加載失敗,觸發(fā) <img> 元素的 onerror 事件,給加載失敗的 <img> 元素新增一個樣式類
        2. 利用新增的樣式類,配合 <img> 元素的偽元素,展示默認(rèn)兜底圖的同時,還能一起展示 <img> 元素的 alt 信息
        <img src="test.png" alt="圖片描述" onerror="this.classList.add('error');">
        img.error {
            position: relative;
            display: inline-block;
        }

        img.error::before {
            content"";
            /** 定位代碼 **/
            backgroundurl(error-default.png);
        }

        img.error::after {
            contentattr(alt);
            /** 定位代碼 **/
        }

        我們利用偽元素 before ,加載默認(rèn)錯誤兜底圖,利用偽元素 after,展示圖片的 alt 信息:

        image

        OK,到此,完整的對圖片的處理就算完成了,完整的 Demo 你可以戳這里看看:

        CodePen Demo -- 圖片處理[7]

        交互設(shè)計優(yōu)化

        接下來一個大環(huán)節(jié)是關(guān)于一些交互的細(xì)節(jié)。對于交互設(shè)計,一些比較通用的準(zhǔn)則:

        • Don’t make me think
        • 符合用戶的習(xí)慣與預(yù)期
        • 操作便利
        • 做適當(dāng)?shù)奶嵝?/section>
        • 不強(qiáng)迫用戶

        過渡與動畫

        在我們的交互過程中,適當(dāng)?shù)脑黾舆^渡與動畫,能夠很好的讓用戶感知到頁面的變化

        譬如我們頁面上隨處可見 loading 效果,其實就是這樣一種作用,讓用戶感知頁面正在加載,或者正在處理某些事務(wù)。

        滾動優(yōu)化

        滾動也是操作網(wǎng)頁中非常重要的一環(huán)??纯从心男┛梢詢?yōu)化的點:

        滾動平滑:使用 scroll-behavior: smooth 讓滾動絲滑

        使用 scroll-behavior: smooth,可以讓滾動框?qū)崿F(xiàn)平穩(wěn)的滾動,而不是突兀的跳動??纯葱Ч?,假設(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,是突兀的跳動切換:

        給可滾動容器添加 scroll-behavior: smooth,實現(xiàn)平滑滾動:

        {
            scroll-behavior: smooth;
        }
        scroll2

        使用 scroll-snap-type 優(yōu)化滾動效果

        sroll-snap-type 可能算得上是新的滾動規(guī)范里面最核心的一個屬性樣式。

        scroll-snap-type[8]:屬性定義在滾動容器中的一個臨時點(snap point)如何被嚴(yán)格的執(zhí)行。

        光看定義有點難理解,簡單而言,這個屬性規(guī)定了一個容器是否對內(nèi)部滾動動作進(jìn)行捕捉,并且規(guī)定了如何去處理滾動結(jié)束狀態(tài)。讓滾動操作結(jié)束后,元素停止在適合的位置。

        看個簡單示例:

        當(dāng)然,scroll-snap-type 用法非常多,可控制優(yōu)化的點很多,限于篇幅無法一一展開,具體更詳細(xì)的用法可以看看我的另外一篇文章 -- 使用 sroll-snap-type 優(yōu)化滾動[9]

        控制滾動層級,避免頁面大量重排

        這個優(yōu)化可能稍微有一點難理解。需要了解 CSS 渲染優(yōu)化的相關(guān)知識。

        先說結(jié)論,控制滾動層級的意思是盡量讓需要進(jìn)行 CSS 動畫(可以是元素的動畫,也可以是容器的滾動)的元素的 z-index 保持在頁面最上方,避免瀏覽器創(chuàng)建不必要的圖形層(GraphicsLayer),能夠很好的提升渲染性能

        這一點怎么理解呢,一個元素觸發(fā)創(chuàng)建一個 Graphics Layer 層的其中一個因素是:

        • 元素有一個 z-index 較低且包含一個復(fù)合層的兄弟元素

        根據(jù)上述這點,我們對滾動性能進(jìn)行優(yōu)化的時候,需要注意兩點:

        1. 通過生成獨立的 GraphicsLayer,利用 GPU 加速,提升滾動的性能
        2. 如果本身滾動沒有性能問題,不需要獨立的 GraphicsLayer,也要注意滾動容器的層級,避免因為層級過高而被其他創(chuàng)建了 GraphicsLayer 的元素合并,被動的生成一個 Graphics Layer ,影響頁面整體的渲染性能

        如果你對這點還有點懵,可以看看這篇文章 -- 你所不知道的 CSS 動畫技巧與細(xì)節(jié)[10]

        點擊交互優(yōu)化

        在用戶點擊交互方面,也有一些有意思的小細(xì)節(jié)。

        優(yōu)化手勢 -- 不同場景應(yīng)用不同 cursor

        對于不同的內(nèi)容,最好給與不同的 cursor 樣式,CSS 原生提供非常多種常用的手勢。

        在不同的場景使用不同的鼠標(biāo)手勢,符合用戶的習(xí)慣與預(yù)期,可以很好的提升用戶的交互體驗。

        首先對于按鈕,就至少會有 3 種不同的 cursor,分別是可點擊,不可點擊,等待中:

        {
            cursor: pointer;    // 可點擊
            cursor: not-allowed;    // 不可點擊
            cursor: wait;    // loading
        }

        除此之外,還有一些常見的,對于一些可輸入的 Input 框,使用 cursor: text,對于提示 Tips 類使用 cursor: help,放大縮小圖片 zoom-inzoom-out 等等:

        一些常用的簡單列一列:

        • 按鈕可點擊: cursor: pointer
        • 按鈕禁止點擊: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)然,實際 cursor 還支持非常多種,可以在 MDN[11] 或者下面這個 CodePen Demo 中查看這里看完整的列表:

        CodePen Demo -- Cursor Demo[12]

        點擊區(qū)域優(yōu)化 -- 偽元素擴(kuò)大點擊區(qū)域

        按鈕是我們網(wǎng)頁設(shè)計中十分重要的一環(huán),而按鈕的設(shè)計也與用戶體驗息息相關(guān)。

        考慮這樣一個場景,在搖晃的車廂上或者是單手操作著屏幕,有的時候一個按鈕,死活也點不到。

        讓用戶更容易的點擊到按鈕無疑能很好的增加用戶體驗及可提升頁面的訪問性,尤其是在移動端,按鈕通常都很小,但是受限于設(shè)計稿或者整體 UI 風(fēng)格,我們不能直接去改變按鈕元素的高寬。

        那么這個時候有什么辦法在不改變按鈕原本大小的情況下去增加他的點擊熱區(qū)呢?

        這里,偽元素也是可以代表其宿主元素來響應(yīng)的鼠標(biāo)交互事件的。借助偽元素可以輕松幫我們實現(xiàn),我們可以這樣寫:

        .btn::befoer{
          content:"";
          position:absolute;
          top:-10px;
          right:-10px;
          bottom:-10px;
          left:-10px;
        }

        當(dāng)然,在 PC 端下這樣子看起來有點奇怪,但是合理的用在點擊區(qū)域較小的移動端則能取到十分好的效果,效果如下:

        608782-20160527112625428-906375003

        在按鈕的偽元素沒有其它用途的時候,這個方法確實是個很好的提升用戶體驗的點。

        快速選擇優(yōu)化 -- user-select: all

        操作系統(tǒng)或者瀏覽器通常會提供一些快速選取文本的功能,看看下面的示意圖:

        快速單擊兩次,可以選中單個單詞,快速單擊三次,可以選中一整行內(nèi)容。但是如果有的時候我們的核心內(nèi)容,被分隔符分割,或者潛藏在一整行中的一部分,這個時候選取起來就比較麻煩。

        利用 user-select: all,可以將需要一次選中的內(nèi)容進(jìn)行包裹,用戶只需要點擊一次,就可以選中該段信息:

        .g-select-all {
            user-select: all
        }

        給需要一次選中的信息,加上這個樣式后的效果,這個細(xì)節(jié)作用在一些需要復(fù)制粘貼的場景,非常好用:

        CodePen -- user-select: all 示例[13]

        選中樣式優(yōu)化 -- ::selection

        當(dāng)然,如果你想更進(jìn)一步,CSS 還有提供一個 ::selection 偽類,可以控制選中的文本的樣式(只能控制color, background, text-shadow),進(jìn)一步加深效果。

        CodePen -- user-select: all && ::selection 控制選中樣式[14]

        添加禁止選擇 -- user-select: none

        有快速選擇,也就會有它的對立面 -- 禁止選擇。

        對于一些可能頻繁操作的按鈕,可能出現(xiàn)如下尷尬的場景:

        • 文本按鈕的快速點擊,觸發(fā)了瀏覽器的雙擊快速選擇,導(dǎo)致文本被選中:
        • 翻頁按鈕的快速點擊,觸發(fā)了瀏覽器的雙擊快速選擇:

        [](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/da77c284cd0f4aafb183a5667c5cf32c~tplv-k3u1fbpfcp-watermark.image "" "")

        對于這種場景,我們需要把不可被選中元素設(shè)置為不可被選中,利用 CSS 可以快速的實現(xiàn)這一點:

        {
            -webkit-user-select: none; /* Safari */
            -ms-user-select: none; /* IE 10 and IE 11 */
            user-select: none; /* Standard syntax */
        }

        這樣,無論點擊的頻率多快,都不會出現(xiàn)尷尬的內(nèi)容選中:

        跳轉(zhuǎn)優(yōu)化

        現(xiàn)階段,單頁應(yīng)用(Single Page Application)的應(yīng)用非常廣泛,Vue 、React 等框架大行其道。但是一些常見的寫法,也容易衍生一些小問題。

        譬如,點擊按鈕、文本進(jìn)行路由跳轉(zhuǎn)。譬如,經(jīng)常會出現(xiàn)這種代碼:

        <template>
        ...
        <button @click="gotoDetail">
        Detail
        </button>
        ...
        <template>
        ...
        gotoDetail() {
        this.$router.push({
        name: 'xxxxx',
        });
        }

        大致邏輯就是給按鈕添加一個事件,點擊之后,跳轉(zhuǎn)到另外一個路由。當(dāng)然,本身這個功能是沒有任何問題的,但是沒有考慮到用戶實際使用的場景。

        實際使用的時候,由于是一個頁面跳轉(zhuǎn),很多時候,用戶希望能夠保留當(dāng)前頁面的內(nèi)容,同時打開一個新的窗口,這個時候,他會嘗試下的鼠標(biāo)右鍵,選擇在新標(biāo)簽頁中打開頁面,遺憾的是,上述的寫法是不支持鼠標(biāo)右鍵打開新頁面的。

        原因在于瀏覽器是通過讀取 <a> 標(biāo)簽的 href 屬性,來展示類似在新標(biāo)簽頁中打開頁面這種選項,對于上述的寫法,瀏覽器是無法識別它是一個可以跳轉(zhuǎn)的鏈接。簡單的示意圖如下:

        所以,對于所有路由跳轉(zhuǎn)按鈕,建議都使用 <a> 標(biāo)簽,并且內(nèi)置 href 屬性,填寫跳轉(zhuǎn)的路由地址。實際渲染出來的 DOM 可能是需要類似這樣:

        <a href="/xx/detail">Detail</a>

        易用性

        易用性也是交互設(shè)計中需要考慮的一個非常重要的環(huán)節(jié),能做的有非常多。簡單的羅列一下:

        • 注意界面元素的一致性,降低用戶學(xué)習(xí)成本
        • 延續(xù)用戶日常的使用習(xí)慣,而不是重新創(chuàng)造
        • 給下拉框增加一些預(yù)設(shè)值,降低用戶填寫成本
        • 同類的操作合并在一起,降低用戶的認(rèn)知成本
        • 任何操作之后都要給出反饋,讓用戶知道操作已經(jīng)生效

        先探索,后表態(tài)

        這一點非常的有意思,什么叫先探索后表態(tài)呢?就是我們不要一上來就強(qiáng)迫用戶去做一些事情,譬如登錄。

        想一想一些常用網(wǎng)站的例子:

        • 類似虎牙、Bilibili 等視頻網(wǎng)站,可以先觀看體驗,一定觀看時間后才會要求登錄(登錄享受藍(lán)光)
        • 電商網(wǎng)站,只有到付款的時候,才需要登錄

        上述易用性先探索,后表態(tài)的內(nèi)容,部分來源于:Learn From What Leading Companies A/B Test[15],可以好好讀一讀。

        字體優(yōu)化

        字體的選擇與使用其實是非常有講究的。

        如果網(wǎng)站沒有強(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 能夠自動選擇本操作系統(tǒng)下的默認(rèn)系統(tǒng)字體。

        默認(rèn)使用特定操作系統(tǒng)的系統(tǒng)字體可以提高性能,因為瀏覽器或者 webview 不必去下載任何字體文件,而是使用已有的字體文件。font-family: system-ui 字體設(shè)置的優(yōu)勢之處在于它與當(dāng)前操作系統(tǒng)使用的字體相匹配,對于文本內(nèi)容而言,它可以得到最恰當(dāng)?shù)恼故尽?/p>

        舉兩個例子,天貓的字體定義與 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;

        簡單而言,它們總體遵循了這樣一個基本原則:

        1、盡量使用系統(tǒng)默認(rèn)字體

        使用系統(tǒng)默認(rèn)字體的主要原因是性能,并且系統(tǒng)字體的優(yōu)點在于它與當(dāng)前操作系統(tǒng)使用的相匹配,因此它的文本展示必然也是一個讓人舒適展示效果。

        2、兼顧中西,西文在前,中文在后

        中文或者西文(英文)都要考慮到。由于大部分中文字體也是帶有英文部分的,但是英文部分又不怎么好看,但是英文字體中大多不包含中文。通常會先進(jìn)行英文字體的聲明,選擇最優(yōu)的英文字體,這樣不會影響到中文字體的選擇,中文字體聲明則緊隨其次。

        3、兼顧多操作系統(tǒng)

        選擇字體的時候要考慮多操作系統(tǒng)。例如 MAC OS 下的很多中文字體在 Windows 都沒有預(yù)裝,為了保證 MAC 用戶的體驗,在定義中文字體的時候,先定義 MAC 用戶的中文字體,再定義 Windows 用戶的中文字體;

        4、兼顧舊操作系統(tǒng),以字體族系列 serif 和 sans-serif 結(jié)尾

        當(dāng)使用一些非常新的字體時,要考慮向下兼容,兼顧到一些極舊的操作系統(tǒng),使用字體族系列 serif 和 sans-serif 結(jié)尾總歸是不錯的選擇。

        對于上述的一些字體可能會有些懵,譬如 -apple-system, BlinkMacSystemFont,這是因為不同瀏覽器廠商對規(guī)范的實現(xiàn)有所不同,對于字體定義更多的相關(guān)細(xì)節(jié),可以再看看這篇文章 -- Web 字體 font-family 再探秘[19]

        可訪問性(A11Y)

        可訪問性,在我們的網(wǎng)站中,屬于非常重要的一環(huán),但是大部分前端(其實應(yīng)該是設(shè)計、前端、產(chǎn)品)同學(xué)都會忽視它。

        我潛伏在一個叫無障礙設(shè)計小組的群里,其中包含了很多無障礙設(shè)計師以及患有一定程度視覺、聽力、行動障礙的用戶,他們在群里經(jīng)常會表達(dá)出一個觀點,就是國內(nèi)的大部分 Web 網(wǎng)站及 APP 基本沒有考慮過殘障人士的使用(或者可訪問性做的非常差),非常的令人揪心。

        尤其在我們一些重交互、重邏輯的網(wǎng)站中,我們需要考慮用戶的使用習(xí)慣、使用場景,從高可訪問性的角度考慮,譬如假設(shè)用戶沒有鼠標(biāo),僅僅使用鍵盤,能否順暢的使用我們的網(wǎng)站?

        假設(shè)用戶沒有鼠標(biāo),這個真不一定是針對殘障人士,很多情況下,用戶拿鼠標(biāo)的手可能在干其他事情,比如在吃東西,又或者在 TO B 類的業(yè)務(wù),如超市收銀、倉庫收貨,很可能用戶拿鼠標(biāo)的手操作著其他設(shè)備(掃碼槍)等等。

        本文不會專門闡述無障礙設(shè)計的方方面面,只是從一些我覺得前端工程師需要關(guān)注的,并且僅需要花費少量代價就能做好的一些無障礙設(shè)計細(xì)節(jié)。記住,無障礙設(shè)計對所有人都更友善。

        色彩對比度

        顏色,也是我們天天需要打交道的屬性。對于大部分視覺正常的用戶,可能對頁面的顏色敏感度還沒那么高。但是對于一小部分色弱、色盲用戶,他們對于網(wǎng)站的顏色會更加敏感,不好的設(shè)計會給他們訪問網(wǎng)站帶來極大的不便。

        什么是色彩對比度

        是否曾關(guān)心過頁面內(nèi)容的展示,使用的顏色是否恰當(dāng)?色弱、色盲用戶能否正??辞鍍?nèi)容?良好的色彩使用,在任何時候都是有益的,而且不僅僅局限于對于色弱、色盲用戶。在戶外用手機(jī)、陽光很強(qiáng)看不清,符合無障礙標(biāo)準(zhǔn)的高清晰度、高對比度文字就更容易閱讀。

        這里就有一個概念 -- 顏色對比度,簡單地說,描述就是兩種顏色在亮度(Brightness)上的差別。運用到我們的頁面上,大多數(shù)的情況就是背景色(background-color)與內(nèi)容顏色(color)的對比差異。

        最權(quán)威的互聯(lián)網(wǎng)無障礙規(guī)范 —— WCAG AA[20]規(guī)范規(guī)定,所有重要內(nèi)容的色彩對比度需要達(dá)到 4.5:1 或以上(字號大于18號時達(dá)到 3:1 或以上),才算擁有較好的可讀性。

        借用一張圖 -- 知乎 -- 助你輕松做好無障礙的15個UI設(shè)計工具推薦[21]

        很明顯,上述最后一個例子,文字已經(jīng)非常的不清晰了,正常用戶都已經(jīng)很難看得清了。

        檢查色彩對比度的工具

        Chrome 瀏覽器從很早開始,就已經(jīng)支持檢查元素的色彩對比度了。以我當(dāng)前正在寫作的頁面為例子,Github Issues 編輯頁面的兩個按鈕:

        審查元素,分別可以看到兩個按鈕的色彩對比度:

        可以看到,綠底白字按鈕的色彩對比度是沒有達(dá)到標(biāo)準(zhǔn)的,也被用黃色的嘆號標(biāo)識了出來。

        除此之外,在審查元素的 Style 界面的取色器,改變顏色,也能直觀的看到當(dāng)前的色彩對比度:

        焦點響應(yīng)

        類似百度、谷歌的首頁,進(jìn)入頁面后會默認(rèn)讓輸入框獲得焦點:

        并非所有的有輸入框的頁面,都需要進(jìn)入頁面后進(jìn)行聚焦,但是焦點能夠讓用戶非常明確的知道,當(dāng)前自己在哪,需要做些什么。尤其是對于無法操作鼠標(biāo)的用戶。

        頁面上可以聚焦的元素,稱為可聚焦元素,獲得焦點的元素,則會觸發(fā)該元素的 focus 事件,對應(yīng)的,也就會觸發(fā)該元素的 :focus 偽類。

        瀏覽器通常會使用元素的 :focus 偽類,給元素添加一層邊框,告訴用戶,當(dāng)前的獲焦元素在哪里。

        我們可以通過鍵盤的 Tab 鍵,進(jìn)行焦點的切換,而獲焦元素則可以通過元素的 :focus 偽類的樣式,告訴用戶當(dāng)前焦點位置。

        當(dāng)然,除了 Tab 鍵之外,對于一些多輸入框、選擇框的表單頁面,我們也應(yīng)該想著如何簡化用戶的操作,譬如用戶按回車鍵時自動前進(jìn)到下一字段。一般而言,用戶必須執(zhí)行的觸按越少,體驗越佳。:thumbsup:

        下面的截圖,完全由鍵盤操作完成

        通過元素的 :focus 偽類以及鍵盤 Tab 鍵切換焦點,用戶可以非常順暢的在脫離鼠標(biāo)的情況下,對頁面的焦點切換及操作。

        然而,在許多 reset.css 中,經(jīng)常能看到這樣一句 CSS 樣式代碼,為了樣式的統(tǒng)一,消除了可聚焦元素的 :focus 偽類:

        :focus {
            outline0;
        }

        我們給上述操作的代碼。也加上這樣一句代碼,全程再用鍵盤操作一下

        除了在 input 框有光標(biāo)提示,當(dāng)使用 Tab 進(jìn)行焦點切換到 select 或者到 button 時,由于沒有了 :focus 樣式,用戶將完全懵逼,不知道頁面的焦點現(xiàn)在處于何處。

        保證非鼠標(biāo)用戶體驗,合理運用 :focus-visible

        當(dāng)然,造成上述結(jié)果很重要的一個原因在于。:focus 偽類不論用戶在使用鼠標(biāo)還是使用鍵盤,只要元素獲焦,就會觸發(fā)。

        而其本身的默認(rèn)樣式又不太能被產(chǎn)品或者設(shè)計接受,導(dǎo)致了很多人會在焦點元素觸發(fā) :focus 偽類時,通過改變 border 的顏色或者其他一些方式替代或者直接禁用。而這樣做,從可訪問性的角度來看,對于非鼠標(biāo)用戶,無疑是災(zāi)難性的。

        基于此,在W3 CSS selectors-4 規(guī)范[22] 中,新增了一個非常有意思的 :focus-visible 偽類。

        :focus-visible:這個選擇器可以有效地根據(jù)用戶的輸入方式(鼠標(biāo) vs 鍵盤)展示不同形式的焦點。

        有了這個偽類,就可以做到,當(dāng)用戶使用鼠標(biāo)操作可聚焦元素時,不展示 :focus 樣式或者讓其表現(xiàn)較弱,而當(dāng)用戶使用鍵盤操作焦點時,利用 :focus-visible,讓可獲焦元素獲得一個較強(qiáng)的表現(xiàn)樣式。

        看個簡單的 Demo:

        <button>Test 1</button>
        button:active {
          background#eee;
        }
        button:focus {
          outline2px solid red;
        }

        使用鼠標(biāo)點擊:

        可以看到,使用鼠標(biāo)點擊的時候,觸發(fā)了元素的 :active 偽類,也觸發(fā)了 :focus偽類,不太美觀。但是如果設(shè)置了 outline: none 又會使鍵盤用戶的體驗非常糟糕。嘗試使用 :focus-visible 偽類改造一下:

        button:active {
          background#eee;
        }
        button:focus {
          outline2px solid red;
        }
        button:focus:not(:focus-visible) {
          outline: none;
        }

        看看效果,分別是在鼠標(biāo)點擊 Button 和使用鍵盤控制焦點點擊 Button:

        CodePen Demo -- :focus-visible example[23]

        可以看到,使用鼠標(biāo)點擊,不會觸發(fā) :foucs,只有當(dāng)鍵盤操作聚焦元素,使用 Tab 切換焦點時,outline: 2px solid red 這段代碼才會生效。

        這樣,我們就既保證了正常用戶的點擊體驗,也保證了一批無法使用鼠標(biāo)的用戶的焦點管理體驗。

        值得注意的是,有同學(xué)會疑惑,這里為什么使用了 :not 這么繞的寫法而不是直接這樣寫呢:

        button:focus {
          outline: unset;
        }
        button:focus-visible {
          outline2px solid red;
        }

        為的是兼容不支持 :focus-visible 的瀏覽器,當(dāng) :focus-visible 不兼容時,還是需要有 :focus 偽類的存在。

        使用 WAI-ARIA 規(guī)范增強(qiáng)語義 -- div 等非可獲焦元素模擬獲焦元素

        還有一個非常需要注意的點。

        現(xiàn)在很多前端同學(xué)在前端開發(fā)的過程中,喜歡使用非可獲焦元素模擬獲焦元素,譬如:

        • 使用 div 模擬 button 元素
        • 使用 ul 模擬下拉列表 select 等等

        當(dāng)下很多組件庫都是這樣做的,譬如 element-ui 和 ant-design。

        在使用非可獲焦元素模擬獲焦元素的時候,一定要注意,不僅僅只是外觀長得像就完事了,其行為表現(xiàn)也需要符合原本的 button、select 等可聚焦元素的性質(zhì),能夠體現(xiàn)元素的語義,能夠被聚焦,能夠通過 Tab 切換等等。

        基于大量類似的場景,有了 WAI-ARIA 標(biāo)準(zhǔn)[24],WAI-ARIA是一個為殘疾人士等提供無障礙訪問動態(tài)、可交互Web內(nèi)容的技術(shù)規(guī)范。

        簡單來說,它提供了一些屬性,增強(qiáng)標(biāo)簽的語義及行為:

        • 可以使用 tabindex 屬性控制元素是否可以聚焦,以及它是否/在何處參與順序鍵盤導(dǎo)航
        • 可以使用 role 屬性,來標(biāo)識元素的語義及作用,譬如使用 <div id="saveChanges" tabindex="0" role="button">Save</div> 來模擬一個按鈕
        • 還有大量的 aria-* 屬性,表示元素的屬性或狀態(tài),幫助我們進(jìn)一步地識別以及實現(xiàn)元素的語義化,優(yōu)化無障礙體驗

        使用工具查看標(biāo)簽的語義

        我們來看看 Github 頁面是如何定義一個按鈕的,以 Github Issues 頁面的 Edit 按鈕為例子:

        這一塊,清晰的描述了這個按鈕在可訪問性相關(guān)的一些特性,譬如 Contrast 色彩對比度,按鈕的描述,也就是 Name,是給屏幕閱讀器看到的,Role 標(biāo)識是這個元素的屬性,它是一個按鈕,Keyboard focusable 則表明他能否被鍵盤的 Tab 按鈕給捕獲。

        分析使用非可聚焦元素模擬的按鈕

        這里,我隨便選取了我們業(yè)務(wù)中一個使用 span 模擬按鈕的場景,是一個面包屑導(dǎo)航,點擊可進(jìn)行跳轉(zhuǎn),發(fā)現(xiàn)慘不忍睹:

        HTML 代碼:

        <span class="ssc-breadcrumb-item-link"> Inbound </span>
        image

        基本上可訪問性為 0,作為一個按鈕,它不可被聚焦,無法被鍵盤用戶選中,沒有具體的語義,色彩對比度太低,可能視障用戶無法看清。并且,作為一個能進(jìn)行頁面跳轉(zhuǎn)的按鈕,它沒有不是 a 標(biāo)簽,沒有 href 屬性。

        即便對于面包屑導(dǎo)航,我們可以不將它改造成 <a> 標(biāo)簽,也需要做到最基本的一些可訪問性改造:

        <span role="button" aria-label="goto inbound page" tabindex="0" class="ssc-breadcrumb-item-link"> Inbound </span>

        不要忘了再改一下顏色,達(dá)到最低色彩對比度以上,再看看:

        OK,這樣,一個最最最基本的,滿足最低可訪問性需求的按鈕算是勉強(qiáng)達(dá)標(biāo),當(dāng)然,這個按鈕可以再更進(jìn)一步進(jìn)行改造,涉及了更深入的可訪問性知識,本文不深入展開。

        分析組件庫的 A11Y

        最后,在我們比較常用的 Vue - element-ui[25]、React - ant-design[26] 中,我們來看看 ant-design 在提升可訪問性相關(guān)的一些功能。

        以 Select 選擇框組件為例,ant-design 利用了大量的 WAI-ARIA 屬性,使得用 div 模擬的下拉框不僅僅在表現(xiàn)上符合一個下拉框,在語義、行為上都符合一個下拉框,簡單的一個例子:

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

        再看看在交互體驗上:

        上述操作全是在鍵盤下完成,看著平平無奇,實際上組件庫在正常響應(yīng)可獲焦元素切換的同時,給用 div 模擬的 select 加了很多鍵盤事件的響應(yīng),可以利用回車,上下鍵等對可選項進(jìn)行選擇。其實是下了很多功夫。

        對于 A11Y 相關(guān)的內(nèi)容,篇幅及內(nèi)容非常之多,本文無法一一展開,感興趣的可以通讀下下列文章:

        • WAI-ARIA basics[27]
        • WAI-ARIA 1.1[28]
        • Web中的焦點管理[29]
        • 無障礙功能[30]
        • 提升Web用戶體驗的71個設(shè)計要點[31]
        • 公眾號 -- 無障礙設(shè)計小組[32]

        總結(jié)一下

        本文從頁面展示交互細(xì)節(jié)、可訪問性三個大方面入手,羅列一些在實際的開發(fā)過程中,積攢的一些有益的經(jīng)驗。雖然不夠全面,不過從一開始也就沒想著大而全,主要是一些可能有用但是容易被忽視的點,也算是一個不錯的查缺補(bǔ)漏小指南。

        當(dāng)然,很多都是我個人的觀點想法,可能有一些理解存在一些問題,一些概念沒有解讀到位,也希望大家?guī)兔χ赋觥?/p>

        最后

        本文到此結(jié)束,希望對你有幫助 :)

        如果還有什么疑問或者建議,可以多多交流,原創(chuàng)文章,文筆有限,才疏學(xué)淺,文中若有不正之處,萬望告知。

        參考資料

        [1]

        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è)計產(chǎn)品的空白頁面?: http://www.woshipm.com/pd/3742114.html

        [4]

        CodePen Demo -- Object position: https://codepen.io/robinrendle/pen/raGOOJ

        [5]

        前端基礎(chǔ)知識概述: https://github.com/chokcoco/cnblogsArticle/issues/25

        [6]

        圖片加載失敗后CSS樣式處理最佳實踐: 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)化滾動: https://github.com/chokcoco/iCSS/issues/74

        [10]

        你所不知道的 CSS 動畫技巧與細(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]

        知乎 -- 助你輕松做好無障礙的15個UI設(shè)計工具推薦: 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中的焦點管理: https://www.w3cplus.com/a11y/focus-for-web.html

        [30]

        無障礙功能: https://developers.google.com/web/fundamentals/accessibility?hl=zh-cn

        [31]

        提升Web用戶體驗的71個設(shè)計要點: https://www.shejidaren.com/71-good-ui-tips.html

        [32]

        公眾號 -- 無障礙設(shè)計小組: https://werss.app/accounts/NTI1NTUwNTg1ODU0NTM=

        瀏覽 66
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
          
          

            1. 99精品福利| 麻豆免费完整版欧美 | 免费看美女逼 | 天天干天天干天天干 | 日韩黄色免费观看 |