[譯] 如何讓你的 CSS Grid 佈局有良好的可訪問性

CSS Grid 能夠將元素放入有行和列的網格中,從而讓建立二維佈局成爲可能。有了它,你能夠自定義網格的任何形態,例如網格寬高、網格範圍、或者網格之間的間隙。可是,CSS Grid 可能會有訪問性不佳的問題,尤爲是對於那些使用屏幕閱讀器和僅使用鍵盤的用戶。本篇教程將會幫助你避免此類問題。css

源順序獨立性

「源順序獨立性」是 CSS Grid 強大優點之一。這意味着你不須要像使用 float 或者表格佈局那樣,在 HTML 中定義佈局結構。你可使用 CSS Grid 的排序和網格位置屬性改變 HTML 呈現的視覺效果。html

W3C 的 CSS Grid 文檔中的重排序和可訪問性章節,將源順序獨立性定義爲:前端

「經過將網格佈局與媒體查詢相結合,開發者可使用相同的語義標記,可是元素佈局的從新排列是脫離源代碼順序而獨立存在的,這樣就能夠同時在源代碼順序和渲染出的視覺效果兩個方面實現須要的佈局。」android

使用 CSS Grid,你能夠將邏輯順序和視覺順序解耦。源順序獨立性在不少時候都很是有用,可是它也有可能會破壞代碼的可訪問性。使用屏幕閱讀器和鍵盤的用戶都只能看到你 HTML 文件的代碼邏輯順序,可是沒法看到經過 CSS Grid 建立出來的視覺順序。ios

若是你的文檔很簡單,這一般不是什麼大問題,由於這時候源代碼邏輯順序和視覺順序基本是一致的。可是,比較複雜、不對稱、零散,或者使用了其餘創意佈局的文件一般就會對使用屏幕閱讀器或者鍵盤的用戶形成困惑。git

能改變視覺順序的屬性

CSS Grid 有不少能夠改變文檔視覺順序的屬性:github

若是你想知道更多關於網格位置屬性的使用方法,能夠看看咱們以前關於網格區域的文章。如今,讓咱們看看視覺重排序是如何形成代碼可訪問性的問題的。web

視覺效果與邏輯的重排序

這是一個簡單的網格佈局,只有幾個簡單的連接,因此你可使用鍵盤測試代碼:後端

<div class="container">
    <div class="item-1"><a href="#">Link 1</a></div>
    <div class="item-2"><a href="#">Link 2</a></div>
    <div class="item-3"><a href="#">Link 3</a></div>
    <div class="item-4"><a href="#">Link 4</a></div>
    <div class="item-5"><a href="#">Link 5</a></div>
    <div class="item-6"><a href="#">Link 6</a></div>
</div>
複製代碼

如今咱們再加入一些樣式。下面的 CSS 代碼將網格元素放入了三個寬度相同的列中。使用 grid-row 屬性,第一個元素被移動到了第二行的開始。ide

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 0.625rem;
}
 
.item-1 {
  grid-row: 2;
}
複製代碼

在下面這個圖中,你能夠看到最終的視覺效果,其中 Link 1 被加上了一些特殊樣式以便突出說明。普通的用戶將會首先看到 Link 2,可是使用屏幕閱讀器的用戶將會從 Link 1 開始,由於他們聽從的是 HTML 代碼中定義的邏輯順序。

對於純鍵盤使用者,使用 tab 鍵瀏覽頁面也一樣困難,由於這樣依舊會從 Link 1 開始,也就是頁面的左下角(你能夠本身嘗試一下)。

image

解決方案

解決方案很是簡單優雅。不要改變視覺順序,你只須要將 Link 1 移動到 HTML 文件的下面。這樣,源代碼順序和視覺順序就一致了。

<div class="container">
  <div class="item-2"><a href="#">Link 2</a></div>
  <div class="item-3"><a href="#">Link 3</a></div>
  <div class="item-4"><a href="#">Link 4</a></div>
  <div class="item-1"><a href="#">Link 1</a></div>
  <div class="item-5"><a href="#">Link 5</a></div>
  <div class="item-6"><a href="#">Link 6</a></div>
</div>
複製代碼

你不須要在 CSS 中爲 .item-1 添加任何關於 Grid 的屬性。由於你也不用改變默認的源代碼順序了,那麼你只須要爲網格容器定義屬性便可。

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 0.625rem;
}
複製代碼

看,儘管這個例子最終結果和之前同樣,如今它的可訪問性更高了。使用 tab 或者屏幕閱讀器都會從 Link 2 開始,邏輯上也遵循源代碼順序。

image

如何讓佈局的可訪問性更好

這裏有幾個通用的佈局模版,你可讓使用 CSS Grid 重排序屬性的代碼可訪問性更高。例如,「聖盃佈局」就是這樣一種模式。它包括一個頭部,一個主要內容區域,一個頁腳,還有兩個固定寬度的側邊欄,它們倆一個在左一個在右。

左邊欄佈局可能會爲使用屏幕閱讀器的用戶形成困惑。由於左邊欄在源代碼順序要要比主要內容區域靠前,而它則是使用屏幕閱讀器的用戶最早看到的內容。可是,一般狀況下,使用屏幕閱讀器的用戶開始閱讀的位置最好是主要內容。特別是當左邊欄主要包括的實際上是廣告,博客目錄,標籤雲,或者其餘一些不相關的內容。

CSS Grid 容許你改變 HTML 文件的源代碼順序,並將主要內容放在兩個側邊欄前面

<div class="container">
    <header>Header</header>
    <main>Main content</main>
    <aside class="left-sidebar">Left sidebar</aside>
    <aside class="right-sidebar">Right sidebar</aside>
    <footer>Footer</footer>
</div>
複製代碼

還有一些其餘可用的解決方案,來使用 CSS Grid 定義視覺順序的改變。大部分教程都會使用命名的網格區域,並使用 grid-template-areas 屬性對它們進行重排列。

下面的代碼是最簡單的解決方案,由於它只是爲視覺順序和源代碼順序不一樣的元素添加了幾個額外的規則。CSS Grid 有優秀的自動排列功能,可以把餘下的網格元素搞定。

.container {
  display: grid;
  grid-template-columns: 9.375rem 1fr 9.375rem;
  grid-gap: 0.625rem;
}
header, 
footer {
  grid-column: 1 / span 3;
}
.left-sidebar {
  grid-area: 2 / 1;
}
複製代碼

這樣,grid-column<header> 和 <footer> 區域橫跨整個屏幕(三列),而後 grid-areagrid-row 和 grid-column 的簡寫)固定了左邊欄的位置。以下就是使用這些樣式後的樣子:

image

儘管聖盃佈局是一個相對簡單的佈局,你還可使用相同的邏輯來完成一些更復雜的佈局。要始終牢記頁面的哪一個部分是最重要的,哪部分是使用屏幕閱讀器的用戶在看到其餘內容以前可能最想看的。

語義丟失怎麼辦

某些狀況下,CSS Grid 也會對語義形成破壞;這也是影響可訪問性的一個方面。因爲 display: grid; 佈局僅被元素的直接子元素繼承,網格元素的子元素其實就不是網格佈局的一部分了。爲了節省工做量,開發者也許認爲將佈局扁平化是一個不錯的解決方案,因此他們就將全部但願包括在網格佈局內的元素都做爲網格容器的直接子元素。可是,若是一個佈局被認爲的扁平化了,文件的語義一般也就丟失了。

加入你想要建立一個元素展覽牆(好比圖片牆),在這裏,元素按照網格排列並被一個頭部和一個頁腳包圍。以下是帶語義的標籤寫法:

<section class="container">
    <header>Header</header>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
        <li>Item 4</li>
        <li>Item 5</li>
        <li>Item 6</li>
    </ul>
    <footer>Footer</footer>
</section>
複製代碼

可是若是你想要使用 CSS Grid,<section> 應該做爲網格容器,<h1><h2><ul> 是網格元素。可是,列表內的元素不被包括在網格內,由於他們是網格容器子元素的子元素

因此,若是你想要快速的完成工做,將佈局結構扁平化也許是一個不錯的主意,也就是讓全部的元素都做爲網格容器的子元素:

<section class="container">
    <header>Header</header>
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <footer>Footer</footer>
</section>
複製代碼

如今,你就能夠很輕鬆地使用 CSS Grid 建立出想要的佈局:

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 0.625rem;
}
header,
footer {
    grid-column: 1 / span 3;
}
複製代碼

image

一切看上去都很是好,可是文檔已經丟失了它最初的語義,因此:

  • 使用屏幕閱讀器的用戶沒法知道元素之間的關係,也沒法知道它們實際上是列表的一部分(大部分的屏幕閱讀器都會通知用戶列表元素的數量);
  • 被破壞的語義也會讓搜索引擎很難明白你的內容;
  • 若是用戶在禁用 CSS 的時候訪問你的內容(例如,網速不佳的時候),在瀏覽頁面時可能會很困惑,由於他們只看到一系列不相關的 div。

最重要的規則是,你絕對不能爲了看上去好看而放棄語義。

解決方案

目前的解決方案經過爲未排序的列表添加了 CSS 規則,建立出了嵌套的網格。

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 0.625rem;
}
.container > * {
    grid-column: 1 / span 3;
}
ul {
    display: inherit;
    grid-template-columns: inherit;
    grid-gap: inherit;
}
複製代碼

在以下例子中,你能夠看到嵌套的網格和父級網格是如何關聯的。元素按照指望的樣子排列出來了,可是此時,文檔始終保留着它的語義。

image

總結

簡單的 CSS Grid 佈局可能不會致使可訪問性的問題。可是當你想要改變視覺順序或者建立多層網格的時候,問題就可能暴露出來。解決這些問題一般不會很麻煩,因此這樣作來修復那些可訪問性問題是很值得的,由於這樣你可以讓那些使用輔助工具的用戶更易讀懂你的內容。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索