[譯] 如何禁用連接:從入門到放棄

禁用鏈接:從入門到放棄

有一天,我在工做中產生了關於如何禁用連接的思考。不知爲什麼,去年我無心添加了一個「disabled」錨點樣式。但有一個問題:你沒法在 HTML 中真正禁用 <a> 連接(擁有合法 href 屬性)。更況且,你爲何要禁用它呢?連接是 Web 的基礎。css

某種意義上,個人同事看起來並不打算接受這個事實,因此我開始思考如何真正實現它。我知道這將付出不少努力,因此我想證實爲了這種非傳統的交互並不值得付出努力和代碼。但我擔憂一旦被證實這是能夠實現的,他們將無視個人警告繼續作相似的嘗試。這尚未動搖我,不過我以爲咱們能夠開始看個人研究了。html

第一:前端

不要這樣作。

一個被禁用的連接不能稱做一個連接,它只是一段文本。若是須要禁用一個連接的話,你須要從新思考你的設計。html5

Bootstrap 有一個爲錨點標籤添加 .disabled 類的例子,我很討厭這點。雖然他們至少說起了這個類只提供了一個禁用 樣式,但這仍然是一種誤導。若是你真的想禁用一個連接,你須要作更多的工做而不是隻是讓它 看起來 被禁用了。node

萬無一失的辦法:移除 href 屬性

若是你決定無視個人警告嘗試禁用一個連接,那麼 移除 href 屬性是我所知的最好的辦法android

官方解釋 Hyperlink specios

aarea 元素的 href 屬性不是必要的;當這些元素沒有 href 屬性時,它們將不會解釋成超連接。git

一個更易理解的定義 MDNgithub

這個屬性能夠被忽略(從 HTML5 開始支持)以建立一個佔位符連接。佔位符連接相似傳統的超連接,但它不會跳轉到任何地方。後端

下面是用來設置和移除 href 屬性的基本 JavaScript 代碼:

/* 
 * 用你習慣的方式選擇一個連接
 *
 * document.getElementById('MyLink');
 * document.querySelector('.link-class');
 * document.querySelector('[href="https://unfetteredthoughts.net"]');
 */
// 經過移除 href 屬性來「禁用」一個連接。
link.href = '';
// 經過設置 href 屬性啓用連接
link.href = 'https://unfetteredthoughts.net';
複製代碼

爲這些連接設置 CSS 樣式一樣很是簡單:

a {
  /* 已禁用的連接樣式 */
}
a:link, a:visited { /* or a[href] */
  /* 可訪問的連接樣式 */
}
複製代碼

這就是你所要作的所有!

這是不夠的,我想要更復雜的東西讓我看起來更聰明!

若是你不得不爲了某些極端狀況過分設計,這裏有些事情須要考慮。但願你注意而且意識到我將爲你展現的東西並不值得爲之努力。

首先,咱們須要爲連接添加樣式,讓它看起來被禁用了。

.isDisabled {
  color: currentColor;
  cursor: not-allowed;
  opacity: 0.5;
  text-decoration: none;
}
複製代碼
<a class="isDisabled" href="https://unfetteredthoughts.net">Disabled Link</a>
複製代碼

color 設置成 currentColor 將把字體顏色重置爲普通的非連接文本的顏色。同時把鼠標懸停設置爲 not-allowed,這樣鼠標懸停時就會顯示禁用的標識。咱們遺漏掉了那些不使用鼠標的用戶,他們主要使用觸摸和鍵盤,因此並不會獲得這個指示。接下來,將透明度減至 0.5。根據 WCAG,禁用的元素不須要知足顏色對比指南。我認爲這是很危險的,由於這基本上是純文本,減小透明度至 0.5 將使視弱用戶難以閱讀,這是我討厭禁用連接的另外一個緣由。最後,文本的下劃線被移除了,由於它一般是一個連接的最佳標識。如今,這 看起來 是一個被禁用的連接了!

但它並無被真正禁用!用戶仍然能夠點擊、觸摸這個連接。我聽到你在尖叫 pointer-events

.isDisabled {
  ...
  pointer-events: none;
}
複製代碼

如今,咱們完成了全部工做!禁用一個連接已經大功告成!雖然這只是對鼠標用戶和觸屏用戶 真正地 禁用了連接。那麼對於不支持 pointer-events 的瀏覽器怎麼辦呢?根據 caniuse,Opera Mini 以及 IE 11 如下版本都不支持這個屬性。IE 11 以及 Edge 實際上也不支持 pointer-events,除非 display 設置成 block 或者 inline-block。並且,將 pointer-events 設置成 none 將覆蓋咱們 not-allowed 的指針樣式,因此如今鼠標用戶將不會獲得這個額外的視覺指示,代表連接被禁用。這已經開始崩潰了。如今咱們不得不更改咱們的標記和 CSS。

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.isDisabled > a {
  color: currentColor;
  display: inline-block;  /* 爲了 IE11/ MS Edge 的 bug */
  pointer-events: none;
  text-decoration: none;
}
複製代碼
<span class="isDisabled"><a href="https://unfetteredthoughts.net">Disabled Link</a></span>
複製代碼

將一個連接包裹在 <span> 標籤中並添加 isDisabled 類給了咱們一半禁用視覺樣式。一個很好的效果是這個 isDisabled 類是通用的,能夠用在其餘元素上,例如按鈕和表單元素。實際的錨點標籤如今有設置爲 nonepointer-eventstext-decoration 屬性。

那麼鍵盤用戶呢?鍵盤用戶會使用回車鍵激活連接。pointer-events 只用於光標,沒有鍵盤事件。咱們還須要防止不支持 pointer-events 的舊瀏覽器激活連接,如今咱們將介紹一些 JavaScript。

引入 JavaScript

// 在用經常使用方法獲取連接以後
link.addEventListener('click', function (event) {
  if (this.parentElement.classList.contains('isDisabled')) {
    event.preventDefault();
  }
});
複製代碼

如今咱們的連接 看起來 被禁用了並且不會響應點擊、觸摸以及回車鍵。可是咱們還沒完成!屏幕閱讀器用戶沒法知道這個連接已經被禁用了。咱們須要將這個連接描述爲被禁用。disabled 屬性在連接上不合法,但咱們可使用 aria-disabled="true"

<span class="isDisabled"><a href="https://unfetteredthoughts.net" aria-disabled="true">Disabled Link</a></span>
複製代碼

如今我將利用這個機會根據 aria-disabled 屬性設置連接樣式。我喜歡使用 ARIA 屬性做爲 CSS 的鉤子,由於擁有不正確的樣式的元素能夠表現出重要的可訪問缺失。

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
a[aria-disabled="true"] {
  color: currentColor;
  display: inline-block;  /* 爲了 IE11/ MS Edge 的 bug */
  pointer-events: none;
  text-decoration: none;
}
複製代碼

如今咱們的連接 看起來 被禁用, 表現起來 被禁用, 並且被 描述 成被禁用.

不幸的是,即使連接被描述成被禁用,一些屏幕閱讀器(JAWS)仍將宣稱這些連接是可點擊的。任何一個有點擊事件監聽器的元素都是這樣。這是由於開發者傾向於將非交互元素如 divspan 添加事件監聽器從而當作僞交互元素使用。對此咱們無能爲力。咱們爲了去除一個連接的全部特徵所作的努力都被咱們想要愚弄的輔助技術所挫敗,諷刺的是,咱們以前就想騙過它了。

不過,若是咱們將監聽器移動到 body 呢?

document.body.addEventListener('click', function (event) {
  // 過濾掉其餘元素的點擊事件
  if (event.target.nodeName == 'A' && event.target.getAttribute('aria-disabled') == 'true') {
    event.preventDefault();
  }
});
複製代碼

咱們完成了嗎?其實並無。有的時候咱們須要啓用這些連接,因此咱們須要添加額外的代碼來切換這些狀態或行爲。

function disableLink(link) {
// 1\. 爲父級 span 添加 isDisabled 類
  link.parentElement.classList.add('isDisabled');
// 2\. 保存 href 以便之後添加
  link.setAttribute('data-href', link.href);
// 3\. 移除 href
  link.href = '';
// 4\. 設置 aria-disabled 爲 'true'
  link.setAttribute('aria-disabled', 'true');
}
function enableLink(link) {
// 1\. 將父級 span 的 'isDisabled' 類移除
  link.parentElement.classList.remove('isDisabled');
// 2\. 設置 href
  link.href = link.getAttribute('data-href');
// 3\. 移除 'aria-disabled' 屬性,比將其設爲 false 更好
  link.removeAttribute('aria-disabled');
}
複製代碼

就是這樣。咱們如今從視覺上、功能上以及語義上爲全部的用戶禁用了連接。它只用了 10 行 CSS,15 行 JavaScript(包括 body 上的一個監聽器)以及 2 個 HTML 元素。

說真的,不要作這樣的嘗試。


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

相關文章
相關標籤/搜索