巧用 display: contents 增強頁面語義

来源:https://www.cnblogs.com/coco1s/archive/2020/05/28/12980682.html
-Advertisement-
Play Games

display: contents 是一個比較陌生的屬性,雖然屬於 display 這個基本上是最常見的 CSS 屬性,但是 contents 這個取值基本不會用到。但是它早在 2016 年就已經得到了 Firefox 的支持。 本文將深入一下這個有意思的屬性值。 基本用法 根據 W3C 對 dis ...


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;
}

表現如下:

image

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

<div class="container">
    <div class="wrap" style="display: contents">
        <div class="inner"></div>
    </div>
</div> 

image

可以看到,沒有了中間層的 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: flexdisplay: 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 佈局,也不會受到影響。

Codepen Demo -- display: contents | display: flex 的穿透影響

 

讓代碼更加符合語義化

考慮這個非常實際的場景,現在我們的頁面上充斥了大量的可點擊按鈕,或者點擊觸發相應功能的文字等元素。但是,從語義上而言,它們應該是一個一個的 <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>

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

CodePen Demo -- Button with display: contents

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

  

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

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

對於可替換元素及大部分表單元素,使用 display: contents 的作用類似於 display: none

也就是說對於一些常見的可替換元素、表單元素:

  • <br>
  • <canvas>
  • <object>
  • <audio>
  • <iframe>
  • <img>
  • <video>
  • <frame>
  • <input>
  • <textarea>
  • <select>

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

<button> 的一些異同

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

 

對 A11Y 的影響

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

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

 

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

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

類似的一些有意思的屬性:

 

CAN I USE

看看相容性

 image

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

 

參考

 

最後

好了,本文到此結束,希望對你有幫助 :)

更多精彩 CSS 技術文章彙總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。

更多精彩有趣的 CSS 效果,歡迎來這裡看看 CSS 靈感 -- 在這裡找到寫 CSS 的靈感

如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在本文中,您將找到針對高級開發人員的iOS面試問題和解答。 當您準備進行技術性的iOS面試時,重要的是要瞭解您可能會被問到的話題以及經驗豐富的iOS開發人員的期望。這些問題被許多公司用來衡量iOS候選人的經驗水平。它們涵蓋了iOS開發的各個方面,旨在接觸對該平臺的廣泛瞭解。畢竟,高級開發人員有望能夠 ...
  • # 3.柵格系統 介紹的是 4.5.x版本 一行最多放12列 - class類介紹 最外層容器: 1.container-fluid:寬度100%,和body的寬度一樣 2.container:寬度是一個具體數值,但是會根據用戶屏幕大小來改變 行類 1.row:分行 列類: 5個響應層 後面的*表示 ...
  • 引言 在nuxt中使用Vuex,以模塊方式引用——計數器為例 計數器示例 目錄結構 目錄結構 js模塊寫法 // user.js // state為一個函數, 註意箭頭函數寫法 const state = () => ({ counter: 6 }) // mutations為一個對象 const ...
  • 什麼是前端? 前端,也稱web前端、web客戶端、通常是指網站的前臺部分,運行在PC端、移動端等瀏覽器上展現給用戶瀏覽的網頁,包括網站的表現層和結構層,通俗點就是用戶可以看到的部分,前端與後端(服務端)相對應,前端調取後端(服務端)的數據展現給用戶。 前端開發做什麼? 前端工程師,又叫web前端開發 ...
  • 學習目標:能夠說出為什麼需要對象 能夠使用字面量創建對象 能夠使用構造函數創建對象 能夠說出new的執行過程 能夠遍歷對象 1.對象 1.1萬物皆對象,對象是一個具體的事物 在程式裡面,一個伺服器,一張網頁,一個遠程伺服器的連接也可以是對象。 Javascript中對象是一組無序的相關屬性和方法的集 ...
  • <script> //數組排序(冒泡排序) //冒泡排序是一種演算法,把一系列的數據按照一定的循序進行排列顯示(從小到大或從大到小) //把數組[5,4,3,2,1]換成[1,2,3,4,5] var arr = [5,4,3,2,1]; var temp; for(i=0;i<arr.length- ...
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document< ...
  • 摘要 在之前的文章中有講過保留兩位小數的實現,最近在開發在開發活動頁面時,依舊是展示參賽作品的點贊數。當點贊數過萬時,顯示三位有效數字來展示點贊數,例如:1.56萬、23.1萬等。經過探索,找到了toPrecision() 方法,在MDN中是這樣概述該方法的:toPrecision() 方法以指定的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...