--- title: 漫談無障礙網頁設計-5 tags: 網頁設計, 無障礙 description: --- # 漫談無障礙網頁設計-5 {%hackmd 7SwuI8Z_SCugN0SHT5LxVw %} 上一篇文章最後提到表格使用的 HTML tag `<table>`,實務上 `<table>` 可說是應用方式相對複雜一種元件類型,因此這裡會再花一點篇幅來深入說明。 ## 表格的使用 網際網路剛推出,網站內容還沒有這麼多豐富變化,甚至 CSS 還沒推出之前[^1],`<table>` 是用來形塑網站結構的主要工具,有接觸過 Frontpage 、 Dreamweaver 等工具的讀者大概都不陌生,過去網站所有的內容可以用一層一層的 table 架構完畢(現存的經典案例必須要提 [阿部寬的官網](http://abehiroshi.la.coocan.jp/) XD)。 [^1]: 講古小知識!HTML 在 1990 問世,當時的樣式表(style sheet)還沒有統一規範,直到 1996 年 CSS 才推出,而且一開始還不怎麼流行。`<div>` + CSS 的排版方式是 2000 年後才逐漸把 `<table>` 排版取代的。 如果有在處理 EDM (Electronic Direct Mail,也就是電子報),也不可避免需要大量使用 `<table>` 。這是因為 email 的用戶端非常多── Outlook 就有好幾版,iOS、iPadOS、Apple Mail、Yahoo! Mail、Gmail……族繁不及備載,而這些用戶端對 HTML、CSS 的支援度幾乎都比瀏覽器差,針對 email 甚至有一個獨立的 [Can I email...](https://www.caniemail.com/features/) 網站,可見一斑。  從上圖可以看到幾個主流用戶端對語義化 HTML tag 的支援度都未臻完整,更別提右邊畫面外還有超過十個以上的其他用戶端支援度參差不一。 說了這麼多,就是要表達瞭解如何使用 `<table>` 也是很重要的!關於表格,有三種常見的使用情境: 1. Data Table 資料表格 - 使用 `<table>` 的 HTML 結構來呈現二維資料,即原生的寫法。 2. Layout Table 排版表格 - 因為排版需求,用 `<table>` 來排版,實際內容並非表格資料;如上面提到 EDM、維護更新古早網站或任何用 `<table>` 切版較快的情形。 3. 模擬表格 - 與資料表格接近,有表格的外觀和二維特性,但用 `<div>` 或 `<ul>` 、 `<li>` 搭配 CSS 來呈現表格資料。 下面分別介紹這三種情境的實作方式: ### 1. Data Table 資料表格 上一篇有提到語義化表格會使用到的 HTML tag: - `<table>` - `<caption>` - `<tbody>` 、 `<thead>` 、 `<tfoot>` - `<tr>` - `<th>` - `<td>` 一個完整使用到所有結構的表格大概會像這裡的範例一: <iframe height="300" style="width: 100%;" scrolling="no" title="表格結構範例" src="https://codepen.io/judyshyu/embed/wvjWyrX?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/judyshyu/pen/wvjWyrX"> 表格結構範例</a> by J (<a href="https://codepen.io/judyshyu">@judyshyu</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> <br><br> 如果已經有一定的 HTML 基礎,應該都對如何使用表格結構不陌生,初學者則可以漸進式地加強你的表格結構: #### A. 正確使用 `<tr>` 、 `<th>` 、 `<td>` `<tr>` 代表的是 table row,`<th>` 代表的是 table header,`<td>` 則是 table data 。表格是二維的資料呈現方式,基本的表格由橫向的 row 和直行的 column 構成,橫向的 row 由 `<tr>` 來表示,而表格的每格單位則由 `<th>` 和 `<td>` 組成。所有的 `<th>` 、 `<td>` 都必須被包含在 `<tr>` 中。 正確使用 `<th>` 相當重要,因為在沒有其他額外屬性標示的情況下,螢幕閱讀器只能藉由 HTML 結構判斷哪些 table data 屬於哪個 table header。 #### B. 加入`<caption>` (和 summary) 無障礙表格可以帶有標題,這裡指的標題並不是 `<h1>` ~ `<h6>` ,而是專門用來描述表格標題的 `<caption>` 。與提供 `<figure>` 標題的 `<figcaption>` 用法類似,不同的是 `<caption>` 必須放在 `<table>` 內的第一個元件,不能是最後一個(視覺上則可以藉由 CSS 來把標題的位置移到表格下方)。 若表格內容複雜,可以補充摘要(summary)來加強說明表格內容,summary 的寫法比較靈活,可以: 1. 直接在 `<caption>` 裡塞一個子元素( `<span>` …等)來放說明文字; 2. 在 `<table>` 鄰近用別的元素撰寫 summary (要帶 `id`),並在 `<table>` 上加入 `aria-describedby="{id}"` 來關聯兩者; 3. 把 `<table>` 包在 `<figure>` 裡,利用 `<figcaption>` 來撰寫 summary。 ※ 注意不要使用`summary` 屬性,這個已經不支援了。 #### C. 加入 `<tbody>` 、 `<thead>` 、 `<tfoot>` 其實就算程式碼裡沒有寫 `<tbody>` ,瀏覽器在產生 `<table>` 的 DOM 時也會加上。 如果你的表格結構帶有表頭 row 、匯總 row ,那麼就可以用 `<thead>` 、 `<tfoot>` 將 `<tr>` 包起來,清楚表達結構。不過這幾個 HTML tag 有比較多使用順序上的規範: 1. 一個 `<table>` 中, `<thead>` 、 `<tfoot>` 只能有一個,`<tbody>` 則可以有多個,用來區別複雜資料的區段; 2. 如果自行撰寫 `<tbody>` , `<table>` 內就不能有直屬的 `<tr>` 元素,所有的 `<tr>` 都必須被放在 `<tbody>` 、 `<thead>` 或 `<tfoot>` 中; 3. `<tbody>` 、 `<thead>` 、 `<tfoot>` 內都必須有至少一個 `<tr>` ; 4. `<thead>` 必須放在 `<table>` 內的 `<caption>` 或 `<colgroup>` 之後,並在 `<tbody>` 、 `<tfoot>` 之前; 5. 相反地, `<tfoot>` 必須放在 `<caption>` 、 `<colgroup>` 、 `<thead>` 、 `<tbody>` 之後。 #### D. 加入屬性 加入屬性的目的是闡明資料之間的關聯,能讓螢幕閱讀器知道應該用怎樣的順序來閱讀表格,其中最重要也比較容易實作的屬性有[^2]: [^2]: 參照 [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th) - `scope`: - 只能用在 `<th>` ,用來定義與其相關的資料內容的方向性,`scope` 可以有的值有: - `row`:表示同一個橫向 row 的 `td` 與其相關 - `col`:表示同一個直排 column 的 `td` 與其相關 - `rowgroup`:表示多個 row 的 `td` 與其相關,通常會搭配排版使用的 `rowspan` 屬性使用 - `colgroup`:表示多個 column 的 `td` 與其相關,通常會搭配排版使用的 `colspan` 屬性使用 - `headers`: - 可用在 `<th>` 、 `<td>` ,表達這個元素屬於哪個 `<th>` ,其值為所屬 `<th>` 的 `id` (只能是 `<th>` 的 `id` ,不過可以同時有多個,用空白區隔) 看看實際的應用範例能更快理解: <iframe height="300" style="width: 100%;" scrolling="no" title="Untitled" src="https://codepen.io/judyshyu/embed/wvjWyrX?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/judyshyu/pen/wvjWyrX"> Untitled</a> by J (<a href="https://codepen.io/judyshyu">@judyshyu</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> <br><br> 上面的範例為求清楚,將兩種屬性分開成兩個表格舉例,實際使用時`scope` 和 `headers` 可以同時並存[^3]。 [^3]: 更多範例可以參考:[Tables Tutorial | Web Accessibility Initiative (WAI) | W3C](https://www.w3.org/WAI/tutorials/tables/) #### E. 優化複雜表格 表格內容太多時,經常會有超出螢幕畫面不滾動就閱讀不到的情形,雖然直接把格子間距或文字縮小很直覺,但這樣反而會導致閱讀性不佳,遇到這種情況,複雜表格可以藉由幾種方式處理: 1. 精簡表格內容 2. 拆分成多個表格 3. 根據表格類型,甚至可以直接將表格內容整個設計成互動性的查詢功能頁 其中,要注意表格內容在簡化或拆分後是否還能正確表達原本要呈現的資訊。而第三種方式雖然整體成本較高,但對使用者來說會方便很多,例如下面這個郵資一覽表:  觀察其內容其實是有公式可循的,使用者使用這張表的目的是查詢資費,那麼使用查詢表式就更直覺了:  ### 2. Layout Table 排版表格 單純使用表格當作排版工具是非常不建議的,除了前面提到歷史因素和 EDM 的狀況以外都應該盡量避免。若因不可抗力必須要用 `<table>` 來排版,也應該注意: 1. `<table>` 內除了 `<td>` 以外不要使用任何其他上述的 HTML tag,以免造成更多語義上的混亂; 2. 在 `<table>` 加上 `role="presentation"` ,表明這是裝飾性的內容,不需要被讀出; 3. 不要把這種表格放在資料表格內,會造成資料表格的閱讀困難。 ### 3. 模擬表格 如非必要,也應避免使用這種方式來撰寫表格。與其使用一大堆 ARIA 標籤,不如盡量使用原生的語義化 HTML tag ,對使用者更友善。`role="table"` 算是較新的 ARIA 內容,要注意瀏覽器、輔具,尤其是觸控裝置對它的支援度尚未完全普及。 模擬表格有資料表格的外觀和陣列特性,但因為排版需求不使用 `<table>` 的 HTML 結構,而是採用 `<div>` 或 `<ul>` 、 `<li>` 搭配 CSS 來呈現表格資料,這種情形需要搭配 `role` 來表明其表格結構;通常用在有特殊排版或 RWD 不同尺寸樣式變化巨大的表格。 模擬表格的整體結構會跟原生 `<table>` 差不多,藉由利用 role 屬性來標示對應的角色,能使用的 role 屬性和 HTML tag 其實都有對應,觀察下面 [WAI](https://www.w3.org/WAI/ARIA/apg/example-index/table/table.html) 提供的撰寫範例,就能發現基本的 role 屬性都是能夠對應 HTML tag 的: <iframe height="300" style="width: 100%;" scrolling="no" title="table" src="https://codepen.io/judyshyu/embed/gOzMXQV?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/judyshyu/pen/gOzMXQV"> table</a> by J (<a href="https://codepen.io/judyshyu">@judyshyu</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ## 具備互動性的 HTML 元素 ### `<button>` 和 `<a>` `<button>` 和 `<a>` 是網頁裡最常見的互動元件。`<button>` 和具備 `href` 屬性的 `<a>` 可以被滑鼠點擊,也可以用鍵盤的 <kbd>Tab</kbd> 鍵選取(focusable),並用 <kbd>Enter</kbd> 或 <kbd>Space</kbd> 鍵觸發。 `<button>` 在互動後仍會停留在原本的頁面位置,而 `<a>` 在互動後會將使用者引導至其他區塊(即 anchor ,前往錨點的行為)或引導至其他頁面(即 link ,前往連結的行為)。也就是說,即使視覺上元件的外觀長得像顆按鈕,只要操作行為是導引使用者到另一個頁面,那就應該要使用 `<a>` 來撰寫。正確區辨兩者能夠幫助使用者預期互動後會有什麼結果! [登入按鈕,其實是連結] `<a>` 最重要的屬性是 `href` ,但要注意 `<a>` 並不等同於 link, `href` 並不是必要的,沒有 `href` 的 `<a>` 的意義轉為 placeholder(佔位),表達的是「此處可能有一個已被移除的連結」 [^5]。 [^5]: [HTML spec](https://html.spec.whatwg.org/#the-a-element);這篇的討論也有相當詳細的說明 [Valid to use \<a> (anchor tag) without href attribute?](https://stackoverflow.com/questions/10510191/valid-to-use-a-anchor-tag-without-href-attribute) tab-index focus order https://web.dev/dom-order-matters/
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up