巧用 display: contents 增強頁面語義

2021-02-14 前端大學

(給前端大學加星標,提升前端技能.)

作者:chokcoco

https://github.com/chokcoco/iCSS/issues/79

display: contents 是一個比較陌生的屬性,雖然屬於 display 這個基本上是最常見的 CSS 屬性,但是 contents 這個取值基本不會用到。但是它早在 2016 年就已經得到了 Firefox 的支持。

本文將深入一下這個有意思的屬性值。

基本用法

根據 W3C 對 display: contents 的定義。

The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes and text runs as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced in the element tree by its contents (including both its source-document children and its pseudo-elements, such as ::before and ::after pseudo-elements, which are generated before/after the element’s children as normal).

簡單翻譯一下即是,將設置了該屬性值的元素本身將不會產生任何盒子,但是它的從保留其子代元素的正常展示。

看個簡單的例子。有如下簡單三層結構:

<div class="container">

<div class="wrap">

<div class="inner"></div>

</div>

</div>

簡單的 CSS 如下:

.container {

width: 200px;

height: 200px;

background: #bbb;

}

.wrap {

border: 2px solid red;

padding: 20px;

box-sizing: border-box;

}

.inner {

border: 2px solid green;

padding: 20px;

box-sizing: border-box;

}

表現如下:

這個非常好理解,但是如果,我們給中間層的容器添加上 display: contents,再看看效果:

<div class="container">

<div class="wrap" style="display: contents">

<div class="inner"></div>

</div>

</div>

可以看到,沒有了中間層的 border: 2px solid red 的紅色邊框,整個 .wrap div 好像不存在一樣,但是它的子元素卻是正常的渲染了。

重點,設置了display: contents的元素本身不會被渲染,但是其子元素能夠正常被渲染。

這個屬性我一直在思考有什麼非常適合的使用點。

總結來說,這個屬性適用於那些充當遮罩(wrapper)的元素,這些元素本身沒有什麼作用,可以被忽略的一些布局場景。

充當無語義的包裹框

最近寫 React、Vue 的時候,發現這個屬性在寫 JSX 的時候能有很好的作用,並且也非常符合這個屬性本身的定位。

我們在寫 React、RN 時,經常需要輸出一段模板。

return (

<div class="wrap">

<h2>Title</h2>

<div>...</div>

</div>

)

我們只是想輸出 .wrap div 內的內容,但是由於框架要求,輸出的 JSX 模板必須包含在一個父元素之下,所以不得已,需要添加一個 .wrap 進行包裹,但是這個 .wrap 本身是沒有任何樣式的。

如果輸出的元素是要放在其他 display: flex、display: grid 容器之下,加了一層無意義的 .wrap 之後,整個布局又需要重新進行調整,麻煩。

一種方法是使用框架提供的容器 <React.Fragment>,它不會向頁面插入任何多餘節點。

在 Vue 中類似的是 <template> 元素, <template> 也是不會被渲染在 DOM 樹中,查看頁面結構也無法看到,但是 display: contents 是存在於頁面結構中的,只是沒有生成任何盒子。

這個多出來的父元素其實是沒必要的。這個時候,我們也可以添加上 display: contents,像是這樣:

return (

<div class="wrap" style="display: contents">

<h2>Title</h2>

<div>...</div>

</div>

)

這樣,它既起到了包裹的作用,但是在實際渲染中,這個 div 其實沒有生成任何盒子,一舉兩得。並且像一些 flex 布局、grid 布局,也不會受到影響。

讓代碼更加符合語義化

考慮這個非常實際的場景,現在我們的頁面上充斥了大量的可點擊按鈕,或者點擊觸發相應功能的文字等元素。但是,從語義上而言,它們應該是一個一個的 <button>,但是實際上,更多時候我們都是使用了 <p>、 <div>、 <a> 等標籤進行了模擬,給他們加上了相應的點擊事情而已。

像是下面這樣,雖然沒什麼問題,但是相對而言不那麼符合語義化:

<p class="button">

Button

</p>

<p class="button">

Click Me

</p>

.button {

width: 120px;

line-height: 64px;

text-align: center;

background-color: #ddd;

border: 2px solid #666;

}

我們不使用 <button> 的原因有很多, <button> 相對 div 而言沒那麼好控制,且會引入很多默認樣式。但是,有了 display: contents,我們可以讓我們的代碼既符合語義化,同時不需要去解決 <button> 帶來的一些樣式問題:

<p class="button">

<button style="display: contents">

Button

</button>

</p>

<p class="button">

<button style="display: contents">

Click Me

</button>

</p>

添加了 <buttonstyle="display:contents">Click Me</button> 的包裹,不會對樣式帶來什麼影響,button 也不會實際渲染在頁面結構中,但是頁面的結構語義上好了不少。

對於對頁面結構、語義化有強迫症的一些同學而言,靈活運用這個屬性可以解決很多問題。

在替換元素及表單元素中一些有意思的現象

display: contents 並非在所有元素下的表現都一致。

對於可替換元素及大部分表單元素,使用 display: contents 的作用類似於 display: none。也就是說對於一些常見的可替換元素、表單元素:

<br>

<canvas>

<object>

<audio>

<iframe>

<img>

<video>

<frame>

<input>

<textarea>

<select>

作用了 display: contents 相當於使用了 display: none ,元素的整個框和內容都沒有繪製在頁面上。

<button> 的一些異同

與其他表單元素不一樣,正常而言,添加了 display: contents 相當於被隱藏,不會被渲染。但是實際運用過程中發現,如果包裹了內容,其一些可繼承樣式還是會被子內容繼承。這個實際使用的過程中需要注意一下。

對 A11Y 的影響

在一些外文文檔中有一些討論是關於 display: contents 的使用會影響到頁面的可訪問性。例如作用了 display: contents 的容器及列表,會對頁面的可訪問性帶來一些意外結果。

這個我看暫時沒有明確的結論,如果你的頁面對可訪問性的要求很高,具體使用的此屬性的話也是需要注意一下這一點。

CSS 中類似的一些影響布局的屬性

CSS 本身其實也在一直在努力,增加了各種屬性去讓我們在布局上有更多的空間與控制權。總而言之給我的感受是讓 CSS 更加的像是一個完整的工程而不僅僅只是展現樣式。

類似的一些有意思的屬性:https://github.com/chokcoco/iCSS/issues/23

CAN I USE

看看兼容性。

不算太慘澹,但也不算全面普及。考慮用在一些漸進增強的場景當中。

參考

分享前端好文,點亮 在看 

相關焦點

  • 如何理解CSS的display屬性
    這有一組display值允許你的元素表現類似於HTML表格。新加坡的開發人員Colin Toh寫了一篇優秀的有關於display為表格屬性的文章,你應該認真看一下。雖然我們大多數的人都不在使用基於表格的布局,display: table在一定的情況下還是十分有用的。如: 如果你想要在更廣泛的布局上使用表格,但是在在較小寬度上保持典型的塊布局。
  • display的32種寫法
    display: ruby;ruby這個取值對於我們亞洲人來說其實是非常有用的一個東西,但是目前除了Firefox以外其它瀏覽器對它的支持都不太好。簡而言之,display: ruby;的作用就是可以做出下面這樣的東西:
  • display 的 32 種寫法
    display: table-cell;詳情參考display: table;。這個屬性有必要詳細說說,因為它完全可以單獨應用,用在高度不固定元素的垂直居中上,詳情請見張鑫旭的這篇文章。效果如下圖所示:
  • CSS Display屬性的雙值寫法
    我們只需要將display屬性的值設置為display: grid或display: flex就可以實現這兩種布局。當display屬性改變後,其子元素才變成了flex或者grid元素,從而對一些特性進行響應。display: grid和display: flex對一個元素的產生了對外和對內兩方面的影響。
  • HTML頁面指定符號,使該符號內的內容當做PHP代碼。
    php /** * 把一個指定的HTML頁面顯示。如果有頁面中有放PHP代碼的地方就執行PHP代碼。* 放置PHP代碼的地方都有$fuhao1和$fuhao2 * @param unknown_type $filename * @param unknown_type $fuhao1 * @param unknown_type $fuhao2 */ function display2($filename,$fuhao1,$fuhao2,$xiandingarr){ $filestr
  • 關於CSS中display的32種寫法
    的傢伙搞出來的鬼東西,實際使用極少,效果就是這樣:看,你用能實現的效果,他可以用實現出來,就是這個作用。display: table-cell;詳情參考display: table;。這個屬性有必要詳細說說,因為它完全可以單獨應用,用在高度不固定元素的垂直居中上,詳情請見張鑫旭的這篇文章。
  • CSS : Visibility 和 Display 屬性的比較
    在頁面元素可見性改變時你如何應對?Visibility 和 Display 屬性的區別這裡有個 Demo 可以比較 visibility: hidden 和 display: none 的區別。點擊頁面上部的連結,頁面裡綠色的 Div 將會進行相應的改變。
  • 【進階】實現頁面靜態化,PHP是如何實現的,你又是如何實現的
    抖音號:startphp用短視頻和大家分享PHP學習方法,學習技巧與經驗分享,功能實例歡迎關注抖音號:startphp隨著網站的內容的增多和用戶訪問量的增多,無可避免的是網站加載會越來越慢,受限於帶寬和伺服器同一時間的請求次數的限制
  • WordPress插件 Table of Contents Plus 文章目錄索引/層級輸出所有分類、頁面及使用教程
    這款WordPress插件和昨天推薦的插件easy table of contents具有相同的功能:文章目錄索引。
  • CSS中display屬性的妙用
    CSS中display屬性的妙用 CSS中visibility屬性隱藏元素但保持元素的浮動位置,而display實際上是設置元素的浮動特徵,這裡就向大家描述一下display屬性的具體使用,希望對你有所幫助。
  • 用於半監督語義分割的基於掩碼的數據增強
    特別是,CutMix和ClassMix等數據增強技術從現有的標記數據生成額外的訓練數據。在本文中,作者提出了一種新的數據增強方法,稱為ComplexMix,它結合了CutMix和ClassMix的特性,提高了性能。所提議的方法能夠控制增強數據的複雜性,同時嘗試實現語義正確,並解決複雜性和正確性之間的權衡。
  • CSS中 display 與 visibility 的區別
    問題:之間複製以前文字滾動的效果代碼(文字滾動時無錯誤),結果發現頁面被拉長了一倍,也就是隱藏的層。解決:查CSS手冊後發現了隱藏內容原來是有區別的,一種是保留對象的物理空間,一種是不保留。-display:noneCSS1 隱藏對象。
  • CSS Display屬性與盒模型
    點擊上面「天碼營」,加入我們,快速成長~「內容簡介」因為HTML流式文檔的特性,頁面布局往往是新手最為頭疼的問題之一
  • 到底用content還是contents,大部分國人都蒙圈,你清楚嗎?
    A.常用contents的情況:1.指包、袋、箱子、容器等裡面的物體(the contents of a box,bag,bottle,building,room,etc.)時,一般用contents。
  • 詞彙辨析 10 content 和 contents
    【解答】此字通常是用複數,意為:(1)內面所有的東西、內容、囊中物,例如:the contents of a room(房間裡面的東西),the contents of a box(箱子裡的東西),the contents of a bag(囊中物),the contents of
  • 對外新聞傳播策略:增強軟實力 善用「巧實力」
    增強軟實力 善用「巧實力」     ——對當前我國對外新聞傳播策略的思考     鄭保衛     一、「軟實力」、「巧實力」與新聞傳播     「軟實力」    在新聞傳播領域,「軟實力」競爭的焦點在於如何提升新聞媒介的信息傳播力和輿論引導力,並以此來擴大新聞媒介自身的影響力,最終達到增強國家軟實力的目標。     新聞媒介所具有的信息傳播和輿論引導的功能,使它成為體現和增強國家「軟實力」的一種重要手段和有效工具。
  • 神奇的 display
    在復盤 Flex 布局和 Grid 布局之前,先復盤一下display。何為 display複雜的定義不做贅述,把display 看成一個轉接頭就好,之前有幾篇文章有提到或者用到過 TA。用 HTML + CSS 做個簡單的小玩意加了display:none 後今天案例中的「我是玖柒後」就隱藏了,但是 TA 的代碼是已經加載出來了的。
  • 2019 語義分割指南
    這種分割在計算對象數量的應用程式中非常有用,例如計算商城的行人流量。它的一些主要應用是在自動駕駛、人機互動、機器人和照片編輯/創意工具中。例如,語義分割在汽車自動駕駛和機器人技術中是至關重要的,因為對於一個模型來說,了解其所處環境中的語義信息是非常重要的。
  • WordPress插件 easy table of contents 文章目錄索引及使用教程
    今天給大家推薦的WordPress插件是easy table of contents,可以在文章頁自動創建目錄索引,讓閱讀者一目了然。
  • ASP.NET定製簡單的錯誤處理頁面
    首頁 > 語言 > 關鍵詞 > asp最新資訊 > 正文 ASP.NET定製簡單的錯誤處理頁面