原文連接:Hiding Elements On The Web,by Ahmad Shadeedjavascript
在平時的開發工做中,有時會有隱藏元素的需求。好比,一個按鈕,須要在桌面端隱藏,在手機端顯示;一個導航欄,須要在手機端隱藏,在桌面端顯示。「隱藏」不是字面上展現的這樣簡單,它還包含幾層意思:css
經過本篇文章,你將會學到利用 HTML/CSS 隱藏元素的方法,內容涵蓋了可訪問性、動畫和使用案例。咱們一塊兒來看看吧!html
hidden
屬性這是在 HTML 標籤上使用的一個布爾值屬性。在瀏覽器加載頁面的時候,使用 hidden
屬性修飾的元素,渲染效果與 display: none
相似。固然,若是使用 CSS 手動重寫了 hidden
屬性的話,就另當別論了。java
來看下面的例子:web
這部分包含了一個標題、圖片和描述信息。圖片只會在視口寬度大於 400px
的時候才顯示。這裏我給 <img>
加了一個 hidden
屬性。瀏覽器
我寫了一段 CSS 代碼,讓 hidden
屬性修飾的圖片在視口寬度大於 400px
的時候顯示。svg
img[hidden] {
display: none;
}
@media (min-width: 400px) {
img[hidden] {
display: block;
}
}
複製代碼
下面是在大視口(大於 400px
)下的渲染效果。工具
Demo學習
你可能要問了,爲何不直接使用 display: none
呢?好問題。圖片使用 hidden 屬性控制帶來的好處是——即便 CSS 因爲某種緣由沒有加載成功,圖片也會隱藏。測試
hidden
屬性對可訪問性的影響hidden
會將元素徹底從頁面隱藏,因此屏幕閱讀器是沒法訪問。若是隻是出於視覺表現的目的,必定要避免使用。
display
屬性每一個元素都有一個默認的 display
值,多是 inline-block
、block
、table
等等。咱們使用 display: none
就能達到隱藏元素的效果,而且該元素的全部後代都和它一塊兒隱藏了。
與上面代碼相似,不過此次咱們使用了 display: none
:
img {
display: none;
}
@media (min-width: 400px) {
img {
display: block;
}
}
複製代碼
display: none
會將元素從文檔流中移除,屏幕閱讀器也是沒法訪問到。那麼,什麼是文檔流?咱們能夠用下面的圖片來生動地描述它:
咱們把藍皮書用 display: none
隱藏了,最後發現它從這摞書裏徹底消失了,就好像被抽走了同樣。藍皮書原來佔據的空間不存在了。HTML 於此相似,說明文檔流被改變了。
下面的動畫,展現了藍皮書被移除時的情況:
會的。舉個例子,<img>
默認使用 CSS 隱藏,咱們將它設置在某個斷點處顯示。咱們打開 DevTools,檢查 networks 選項卡,仍是發現圖像被加載了,即便沒有顯示。
<style>
元素值得一提的是,某些元素默認就是 display: none
的。好比 <style>
。咱們能夠把插入到 HTML 頁面中的 <style>
的 display
值設置爲 block
,這樣就能看見它了。
<body>
<style> .title { color: #000; } </style>
</body>
複製代碼
style {
display: block;
}
複製代碼
這事若是在讓樣式塊(style block)變得可編輯,就更有趣了。能夠經過爲 <style>
添加 contenteditable
屬性來實現。
Demo(譯註:在 Firefox 中能看到上面的效果,而在 Chrome 裏是看不到的)
display:none
對可訪問性的影響跟 hidden
屬性同樣,display: none
元素也是從頁面中徹底隱藏的,屏幕閱讀器也沒法訪問。
opacity
元素設置 opacity
後,包括後代都會被隱藏,這不是由於繼承的緣由。然而,這只是視覺上的隱藏。還要注意的是,opacity
值小於 1
的元素會建立一個 層疊上下文。
上圖裏,藍皮書只是在視覺上隱藏了。它所佔據的空間仍然保留,與 display: none
效果比較的話,這一摞書的順序沒有發生變化。
img {
opacity: 0;
}
複製代碼
咱們把最開始的例子,用 opacity: 0
從新改寫下,結果會是這樣的:
圖片從視覺上隱藏了,但它佔據空間依然是在的。
Dusan Milovanovic 指出,pointer-events: none | auto
能夠用來禁用使用 opacity: 0
隱藏的元素上的鼠標事件。這仍是很重要的,若是一個元素看不見了,但依然能響應用戶的點擊、懸停或選擇文本的行爲,勘定是很奇怪的。
opacity: 0
對可訪問性的影響使用 opacity: 0
隱藏的元素依然能被屏幕閱讀器訪問,也能被鍵盤聚焦。
visibility
使用 visibility: hidden
的隱藏元素與使用 opacity: 0
的元素相似,不影響視覺上的文檔流表現。
請注意,藍皮書從可視流中隱藏了,但並無影響這摞書的順序。
有一點,若是 visibility: hidden
是在父元素身上使用,那麼它及其它的後代默認都是看不見的。可是,若是有一個子元素上使用了 visibility: hidden
,那麼這子元素將是可見的。
<article>
<h1>Spring is on the way</h1>
<img src="landscape.jpg" alt="">
<p><!-- Desc --></p>
</article>
複製代碼
article {
visibility: hidden;
}
img {
visibility: visible;
}
複製代碼
上例中,<article>
使用了 visibility: hidden
,而子元素 <img>
是 visibility: visible
的,結果圖片依然是顯示的。也就是說,子元素是能夠重寫父元素的 visibility
屬性的。
visibility: hidden
對可訪問性的影響若是一個元素 visibility: hidden
了,那麼它以及它的全部後代元素都會從訪問樹(accessibility tree)中刪除,不會被屏幕閱讀器讀到。
position
屬性使用 position
屬性將隱藏元素的原理,就是把元素移動到屏幕以外,設置其尺寸爲 0 (寬和高)。好比,網頁裏 跳過導航(skip navigation) 連接:
爲了讓連接定位到屏幕以外,咱們能夠這麼作:
.skip-link {
position: absolute;
top: -100%;
}
複製代碼
-100% 會將元素網上推出一個視口高度的距離。結果,連接就被徹底隱藏了。當連接被鍵盤聚焦時,則能夠這樣設置:
.skip-link:focus {
position: absolute;
top: 0;
}
複製代碼
position: absolute | fixed
對可訪問性的影響元素能夠被屏幕閱讀器讀到,被鍵盤聚焦。只是移動到視口以外了而已。
clip-path
clip-path
屬性用來建立一個裁剪區域,只有在這個區域內的元素內容纔是可見的,其餘部分則是隱藏的。
爲了用更直觀的方式演示,我使用 clippy 工具來解釋。在下面的 GIF 圖中,我定義了以下的 clip-path
:
img {
clip-path: polygon(0 0, 0 0, 0 0, 0 0);
}
複製代碼
將多邊形每一個點的座標設置爲 (0, 0)
,則裁剪區域變爲 0。結果,圖像不會顯示了。一樣,還能夠用一個圓(circle)來代替這裏的多邊形(polygon):
img {
clip-path: circle(0 at 50% 50%);
}
複製代碼
使用 clip-path
實現的隱形效果只是視覺上的,屏幕閱讀器依然能夠訪問,鍵盤也能聚焦。
color
和 font-size
儘管這兩種技術並不像咱們前面討論的那樣廣泛,但在某些場景下比較有用。
color: transparent
將文本設置成透明色(transparent),只是視覺上隱藏了。這比較適合僅帶圖標的按鈕。
font-size: 0
將文字大小設置爲 0
也是視覺上的隱藏。
來看一個包含以下結構的按鈕:
<button>
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="false" focusable="false">
<!-- Path data -->
</svg>
<span>Like</span>
</button>
複製代碼
咱們的目標是以一種能被訪問的方式隱藏文本。爲此,我使用了下面的 CSS:
.button span {
color: transparent;
font-size: 0;
}
複製代碼
文本隱藏了。
aria-hidden
當爲元素添加 aria-hidden
後,就會從訪問樹中刪除,這能夠用來提高屏幕閱讀器用戶的體驗。須要注意的是,元素依然是視覺可見的。
<button>
Menu
<svg aria-hidden="true"><!-- --></svg>
</button>
複製代碼
這裏是一個帶 label 和圖表的菜單按鈕。爲了讓 svg 對屏幕閱讀器隱藏,這裏添加了 aria-hidden
。
根據 MDN 文檔,aria-hidden
的使用場景包括:
aria-hidden
是爲屏幕閱讀器設計的,所以它僅對屏幕閱讀器隱藏內容。可是,內容對於視覺用戶仍然可見,而且也支持鍵盤聚焦。
在咱們開始示例以前,我想帶你們回顧一下前面提到的屬性,我從 CSS-tricks 上的 這篇文章 得到了靈感,作了下面的一張速查表,方便你們在使用時根據須要選擇合適的方法。
當咱們想對隱藏元素使用動畫的時候。好比,顯示隱藏的移動導航,須要以一種可訪問的方式來實現。爲了得到訪問性體驗,咱們將探索一些值得學習的好例子,以及一些很差的例子,避免犯錯誤,從而給屏幕閱讀器用戶帶來更好的體驗。
咱們有一個菜單,在展開時使用一個劃入的動畫。最簡單的作法是使用下面的方法:
ul {
opacity: 0;
transform: translateX(100%);
transition: 0.3s ease-out;
}
ul.active {
opacity: 1;
transform: translateX(0);
}
複製代碼
根據這種方法,菜單在添加 .active 類的時候顯示,不然摺疊。這個類是經過 JavaScript 添加的,以下所示。
menuToggle.addEventListener('click', function(e){
e.preventDefault();
navMenu.classList.toggle('active');
});
複製代碼
結果看起來不錯,但它有一個大問題。使用 opacity: 0
的方式不會將導航從訪問樹中刪除 。即使導航在視覺上隱藏了,可它仍然能被鍵盤聚焦,並且也能被屏幕閱讀器讀到。
下面是來自 Chrome DevTools 的訪問樹截圖:
下面的截圖,則是 Mac OS 上的訪問工具 VoiceOver 看到的頁面內容。跟上面同樣,
簡而言之,訪問樹是屏幕閱讀器用戶能夠訪問的全部內容的列表。在咱們的例子中,包含一個導航列表,雖然它視覺上是隱藏的,但仍是出如今了訪問樹中。所以,隱藏菜單時咱們須要解決兩個問題:
爲了解決上面的文問題,咱們須要在菜單導航上使用 visibility: hidden
。這確保菜單不只在視覺上是隱藏的,屏幕閱讀器也沒法訪問。
ul {
visibility: hidden;
opacity: 0;
transform: translateX(100%);
transition: 0.3s ease-out;
}
ul.active {
visibility: visible;
opacity: 1;
transform: translateX(0);
}
複製代碼
添加後,如今菜單對屏幕閱讀器也是隱藏的了。讓咱們再來測試一下 VoiceOver 的結果:
默認的複選框設計很難自定義。所以,咱們須要爲複選框設計自定義樣式。通常會這麼作:
<p class="c-checkbox">
<input class="sr-only" type="checkbox" name="" id="c1">
<label class="c-checkbox__label" for="c1">Custom checkbox</label>
</p>
複製代碼
要自定義複選框,須要以可訪問的方式隱藏輸入框。爲此,須要藉助 position
等其餘屬性來實現。有一個常見的CSS 類,稱爲 sr-only
或 visual-hidden
,用來在視覺上隱藏一個元素,但鍵盤和屏幕閱讀器依然能訪問。
.sr-only {
border: 0;
clip: rect(0 0 0 0);
-webkit-clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}
複製代碼
這樣,就能夠訪問自定義複選框。若是你想了解更多,我寫了關於這個主題的 一篇文章。
在標題中,我使用了一個表情符號。若是隱藏,那麼屏幕閱讀器會使用下面的方式閱讀:
Hiding On The Web grinning face with open mouth
每一個表情符號都有一個對應的特定描述,屏幕閱讀器閱讀時會使用這個描述。想象你如今正在瀏覽一個網頁,忽然聽到這個標題,讀到後面,可能就有點懵逼了。爲了不這種混淆,可使用 aria-hidden
,把表情包設定爲對屏幕閱讀器隱藏。
<h1>Hiding On The Web <span aria-hidden="true">😃</span></h1>
複製代碼
小故事,大道理小改變,大勝利!
在 Twitter 上,有一個名爲「See New Tweets」的按鈕,默認使用 aria-hidden 對屏幕閱讀器隱藏,只在有新推文可纔會顯示。
用戶 ID 和日期之間的點是裝飾性的。所以,使用了 aria-hidden="true"
避免被屏幕閱讀器讀到。
display: none;
, but don’t(完)
廣告時間(長期有效)
我有一位好朋友開了一間貓舍,在此幫她宣傳一下。如今貓舍裏養的都是布偶貓。若是你也是個愛貓人士而且有須要的話,不妨掃一掃她的【閒魚】二維碼。不買也沒關係,看看也行。
瞄~