摘要:鍵盤訪問(wèn)的升級(jí)提供快捷方式不過(guò),在訪問(wèn)網(wǎng)格時(shí),通過(guò)鍵盤進(jìn)行兩個(gè)方向的移動(dòng)會(huì)不會(huì)更好呢使用一點(diǎn)做漸進(jìn)增強(qiáng),我們做到了,可以使用鼠標(biāo)或方向鍵訪問(wèn)網(wǎng)格。在本例總共,查找表名字是。
厚著臉做推廣,個(gè)人網(wǎng)站 http://www.wemlion.com/。
本文轉(zhuǎn)載自:眾成翻譯
譯者:文藺
鏈接:http://www.zcfy.cc/article/1179
原文:https://www.christianheilmann.com/2016/08/15/better-keyboard-navigation-with-progressive-enhancement/
創(chuàng)建界面時(shí)很重要的一點(diǎn)是,要考慮到那些只依賴鍵盤來(lái)使用產(chǎn)品的用戶。這對(duì)可訪問(wèn)性來(lái)說(shuō)是基本要求,在多數(shù)情況下,通過(guò)鍵盤操作訪問(wèn)也并非難事。這意味著首先,也是最重要的,是使用鍵盤可訪問(wèn)元素進(jìn)行交互。
如果希望用戶跳轉(zhuǎn)到其他地方,使用帶有有效的 href 屬性的錨點(diǎn)連接
如果希望用戶執(zhí)行你自己的代碼,并在當(dāng)前文檔中停留,使用按鈕
通過(guò)流動(dòng) tabIndex 技術(shù)幾乎可以使所有內(nèi)容都能通過(guò)鍵盤訪問(wèn),不過(guò),既然已經(jīng)有 HTML 元素可以做同樣的事情,又何必再麻煩呢。
效果可視化不過(guò),使用恰當(dāng)?shù)脑夭⒉荒敲春?jiǎn)單;用戶鍵盤在元素集合中所處的位置,也要顯眼一些。給激活的元素加上輪廓(outline),瀏覽器解決了這個(gè)問(wèn)題。這雖然超有用,但卻是一些人的眼中釘,他們希望由自己控制所有交互的視覺展現(xiàn)。在 CSS 中將 outline 屬性設(shè)置為 none,就能移除這個(gè)視覺輔助功能;不過(guò)這會(huì)帶來(lái)不小的可訪問(wèn)性問(wèn)題,除非你提供一個(gè)別的替代。
使用最顯眼的 HTML 元素;加上一些 CSS,確保除 hover 之外 focus 狀態(tài)同樣也被定義。這樣就可以使用戶在列表中的一個(gè)個(gè)項(xiàng)目間,輕松地通過(guò) tab 來(lái)切換了。Shift + Tab 允許回退。可以看下 demo,HTML 挺簡(jiǎn)單粗暴的。
使用列表,為我們的元素賦予了層次結(jié)構(gòu),以及普通瀏覽器所沒(méi)有的可訪問(wèn)性技術(shù)的導(dǎo)航方式。它還帶來(lái)很多 HTML 元素,我們可以自己添加樣式。通過(guò)一點(diǎn)樣式,我們可以將其轉(zhuǎn)換為網(wǎng)格,占用更少的垂直空間,容納更多內(nèi)容。
ul, li { margin: 0; padding: 0; list-style: none; } button { border: none; display: block; background: goldenrod; color: white; width: 90%; height: 30px; margin: 5%; transform: scale(0.8); transition: 300ms; } button:hover, button:focus { transform: scale(1); outline: none; background: powderblue; color: #333; } li { float: left; } /* grid magic by @heydonworks https://codepen.io/heydon/pen/bcdrl */ li { width: calc(100% / 4); } li:nth-child(4n+1):nth-last-child(1) { width: 100%; } li:nth-child(4n+1):nth-last-child(1) ~ li { width: 100%; } li:nth-child(4n+1):nth-last-child(2) { width: 50%; } li:nth-child(4n+1):nth-last-child(2) ~ li { width: 50%; } li:nth-child(4n+1):nth-last-child(3) { width: calc(100% / 4); } li:nth-child(4n+1):nth-last-child(3) ~ li { width: calc(100% / 4); }
結(jié)果看起來(lái)非常棒,在查看列表的過(guò)程中,我們能清楚地看到自己所處的位置。
鍵盤訪問(wèn)的升級(jí) —— 提供快捷方式不過(guò),在訪問(wèn)網(wǎng)格時(shí),通過(guò)鍵盤進(jìn)行兩個(gè)方向的移動(dòng)會(huì)不會(huì)更好呢?
使用一點(diǎn) JavaScript 做漸進(jìn)增強(qiáng),我們做到了,可以使用鼠標(biāo)或方向鍵訪問(wèn)網(wǎng)格。
不過(guò)記著,這僅僅只是一個(gè)增強(qiáng)。假設(shè) JavaScript 因?yàn)楦鞣N可能的原因執(zhí)行失敗,依然可以通過(guò) tab 來(lái)訪問(wèn)列表,我們失去的只是便利,但至少還有可用的界面。
我將這個(gè)打包成了一個(gè)小巧、無(wú)依賴的開源 JavaScript 項(xiàng)目 gridnav,可以在 GitHub 上獲取代碼。你要做的就是調(diào)用腳本,傳給它一個(gè)選擇器以獲取元素列表。
通過(guò)列表元素的 data- 屬性,可以自己定義每行元素的數(shù)量以及鍵盤可訪問(wèn)的元素。這些是可選的,但設(shè)置之后會(huì)讓代碼更快,出錯(cuò)可能性更小。README 文件更詳細(xì)地解釋了如何使用。
工作原理開始考慮如何做的時(shí)候,像任何開發(fā)者一樣,抓到了最復(fù)雜的方式。我以為,需要對(duì)父節(jié)點(diǎn)、兄弟節(jié)點(diǎn)的大量定位比較,使用上 getBoundingClientRect,進(jìn)行大量的 DOM 訪問(wèn)。
之后我往回走了一步,意識(shí)到如何展示列表并不重要。最終不過(guò)是一個(gè)列表,我們要訪問(wèn)它而已。甚至不需要訪問(wèn) DOM,因?yàn)槲覀兯龅牟贿^(guò)是從一堆按鈕或錨點(diǎn)連接中的一個(gè)切換到另一個(gè)。我們要做的就是:
找到當(dāng)前所在元素(event.target)。
獲取按下的鍵。
根據(jù)鍵向前向后移動(dòng),或跳過(guò)一些元素到下一行。
就像這樣(點(diǎn)擊這里試試看):
我們需要跳過(guò)的元素?cái)?shù)量是由每行的元素?cái)?shù)量決定的。向上等同于向前 n 個(gè)元素,向下相當(dāng)于向后 n 個(gè)元素。
使用一些小技巧,完整代碼非常簡(jiǎn)短:
(function(){ var list = document.querySelector("ul"); var items = list.querySelectorAll("button"); var amount = Math.floor( list.offsetWidth / list.firstElementChild.offsetWidth ); var codes = { 38: -amount, 40: amount, 39: 1, 37: -1 }; for (var i = 0; i < items.length; i++) { items[i].index = i; } function handlekeys(ev) { var keycode = ev.keyCode; if (codes[keycode]) { var t = ev.target; if (t.index !== undefined) { if (items[t.index + codes[keycode]]) { items[t.index + codes[keycode]].focus(); } } } } list.addEventListener("keyup", handlekeys); })();
這里發(fā)生了什么?
首先我們獲取到了列表元素,并緩存所有可通過(guò)鍵盤訪問(wèn)的元素:
var list = document.querySelector("ul"); var items = list.querySelectorAll("button");
計(jì)算每次上下移動(dòng)需要跳過(guò)的元素?cái)?shù)量,將列表的寬度除以列表第一個(gè)子元素(本例中是 LI)的寬度即可:
var amount = Math.floor( list.offsetWidth / list.firstElementChild.offsetWidth );
相較于 switch 語(yǔ)句或者大量的 if 判斷,我更樂(lè)意使用查找表。在本例總共,查找表名字是 codes。向上鍵值為 38,向下 40,向左 37,向右 39。假如我們拿到了 codes[37],值為 -1,也就是我們要在列表中移動(dòng)的數(shù)量:
var codes = { 38: -amount, 40: amount, 39: 1, 37: -1 };
可以使用 event.target 獲取按下鍵盤時(shí)列表中的選中元素,但我們不知道它在列表中的位置。為避免重復(fù)遍歷列表,一次性遍歷所有按鈕,將它們?cè)诹斜碇械乃饕鎯?chǔ)在按鈕自身的 index 屬性中。
for (var i = 0; i < items.length; i++) { items[i].index = i; }
handlekeys() 完成剩余工作。讀取所按按鍵的鍵值,然后到 codes 中查找。所以,我們只針對(duì)方向鍵做出響應(yīng)。接著獲取當(dāng)前的元素,檢查其是否有 index 屬性。如果有,則檢查我們將要移到的位置是否有元素存在。如果元素存在,則獲得焦點(diǎn)。
function handlekeys(ev) { var keycode = ev.keyCode; if (codes[keycode]) { var t = ev.target; if (t.index !== undefined) { if (items[t.index + codes[keycode]]) { items[t.index + codes[keycode]].focus(); } } } }
給列表綁定一個(gè) keyup 事件監(jiān)聽器,搞定 :)
list.addEventListener("keyup", handlekeys);
如果你想看真實(shí)效果,這有一個(gè)講述各個(gè)細(xì)節(jié)的快速視頻教程。
視頻在最后的代碼部分有點(diǎn) bug,因?yàn)槲覜](méi)將 count 屬性和 undefined 對(duì)比,所以在第一個(gè)元素上,鍵盤功能沒(méi)法正常工作(0 是 falsy)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/111492.html
摘要:這里使用到的最多的中的屬性,即媒體查詢響應(yīng)式設(shè)計(jì)實(shí)踐原則漸進(jìn)增強(qiáng)漸進(jìn)增強(qiáng)英語(yǔ)是網(wǎng)頁(yè)設(shè)計(jì)的一種策略,強(qiáng)調(diào)可訪問(wèn)性,語(yǔ)義標(biāo)記,外部樣式表和腳本技術(shù)。 1、響應(yīng)式設(shè)計(jì)關(guān)鍵點(diǎn)在于: 媒體查詢、流動(dòng)網(wǎng)格、彈性圖片,而不是flex布局或者是自適應(yīng)布局 響應(yīng)式和自適應(yīng)的最直觀的區(qū)別是:自適應(yīng)是為了解決如何才能在不同大小的設(shè)備上呈現(xiàn)同樣的網(wǎng)頁(yè),直觀地來(lái)看就是盒子會(huì)根據(jù)屏幕分辨率的大小進(jìn)行伸縮變換。所以...
摘要:前言本篇文章是基礎(chǔ)知識(shí)的篇,如果前面的基礎(chǔ)知識(shí)入門篇看完了,現(xiàn)在就可以學(xué)習(xí)了?;靖拍罘譃槿齻€(gè)部分。在這個(gè)基礎(chǔ)上使用一些新特性,高級(jí)瀏覽器支持,低級(jí)瀏覽器不支持。在對(duì)象中的屬性是一個(gè)布爾值,只有和。 showImg(https://segmentfault.com/img/remote/1460000012581493?w=1920&h=1080); DOM 前言 本篇文章是JavaS...
摘要:最后,我們必須調(diào)用函數(shù)來(lái)檢查所有的漸進(jìn)式圖片容器在首次運(yùn)行時(shí)是否在頁(yè)面上可見。我們還必須在滾動(dòng)頁(yè)面或調(diào)整瀏覽器大小時(shí)調(diào)用函數(shù),在一些舊的瀏覽器主要指可以非常迅速地對(duì)這些事件作出回應(yīng),所以我們需要限制回調(diào),以確保它不能在毫秒內(nèi)被再一次調(diào)用。 你可以在Facebook和Medium上遇到過(guò)漸進(jìn)式圖片,當(dāng)頁(yè)面滾動(dòng)到視圖時(shí),模糊的低分辨率圖像會(huì)被清晰的全分辨率版本替換。 showImg(htt...
摘要:小蘿卜滬江前端開發(fā)工程師本文原創(chuàng)翻譯,有不當(dāng)?shù)牡胤綒g迎指出。簡(jiǎn)稱就非常擅長(zhǎng)做這些,事實(shí)這也是它們的宗旨。通過(guò)它精心設(shè)計(jì)的規(guī)則能保證優(yōu)先顯示頁(yè)面的主要內(nèi)容。原創(chuàng)新書移動(dòng)前端高效開發(fā)實(shí)戰(zhàn)已在亞馬遜京東當(dāng)當(dāng)開售。 小蘿卜(滬江前端開發(fā)工程師)本文原創(chuàng)翻譯,有不當(dāng)?shù)牡胤綒g迎指出。轉(zhuǎn)載請(qǐng)指明出處。 如果你在過(guò)去幾個(gè)月一直關(guān)注web開發(fā)社區(qū),你很可能已經(jīng)閱讀了 progressive web ap...
摘要:原文鏈接原作者利用原生方法替換實(shí)現(xiàn)性能提升現(xiàn)在我們正在用實(shí)現(xiàn)一個(gè)具有郵件收發(fā)和即時(shí)聊天功能的客戶端工具。為了防止用戶感覺卡頓,所有的動(dòng)作都需要在毫秒級(jí)完成。然而理想是豐滿的,現(xiàn)實(shí)是殘酷的。。。 原文鏈接 https://medium.com/missive-ap...原作者Philippe Lehoux 利用js原生方法替換react component實(shí)現(xiàn)性能提升 現(xiàn)在我們正在用Re...
閱讀 2871·2021-10-11 10:57
閱讀 2434·2021-08-27 16:20
閱讀 1414·2019-08-30 13:03
閱讀 1587·2019-08-30 12:50
閱讀 3373·2019-08-29 14:16
閱讀 1588·2019-08-29 11:12
閱讀 1641·2019-08-28 17:53
閱讀 2920·2019-08-27 10:58