display: contents 是一个比较陌生的属性,虽然属于 display 这个基本上是最常见的 CSS 属性,但是 contents 这个取值基本不会用到。但是它早在 2016 年就已经得到了 Firefox 的支持。,本文将深入一下这个有意思的属性值。,根据 W3C[1] 对 display: contents 的定义。,简单翻译一下即是,设置了该属性值的元素本身将不会产生任何盒子,但是它保留其子代元素的正常展示。,看个简单的例子。有如下简单三层结构:,简单的 CSS 如下:,表现如下:,这个非常好理解,但是如果,我们给中间层的容器添加上 display: contents,再看看效果:,可以看到,没有了中间层的 border: 2px solid red 的红色边框,整个 .wrap div 好像不存在一样,但是它的子元素却是正常的渲染了。,重点,设置了display: contents的元素本身不会被渲染,但是其子元素能够正常被渲染。,这个属性我一直在思考有什么非常适合的使用点。,总结来说,这个属性适用于那些充当遮罩(wrapper)的元素,这些元素本身没有什么作用,可以被忽略的一些布局场景。也就是幽灵 DOM 节点。,最近写 React、Vue 的时候,发现这个属性在写 JSX 的时候能有很好的作用,并且也非常符合这个属性本身的定位。,我们在写 DOM 结构时,经常需要输出一段模板,或者需要一些无语义的幽灵节点。,我们只是想输出 .wrap div 内的内容,但是由于框架要求,输出的 JSX 模板必须包含在一个父元素之下,所以不得已,需要添加一个 .wrap 进行包裹,但是这个 .wrap 本身是没有任何样式的。,如果输出的元素是要放在其他 display: flex、display: grid 容器之下,加了一层无意义的 .wrap 之后,整个布局又需要重新进行调整,麻烦。,一种方法是使用框架提供的容器 <React.Fragment>,它不会向页面插入任何多余节点。,这个多出来的父元素其实是没必要的。这个时候,我们也可以添加上 display: contents,像是这样:,这样,它既起到了包裹的作用,但是在实际渲染中,这个 div 其实没有生成任何盒子,一举两得。并且像一些 flex 布局、grid 布局,也不会受到影响。,Codepen Demo -- display: contents | display: flex 的穿透影响[2]。,考虑这个非常实际的场景,现在我们的页面上充斥了大量的可点击按钮,或者点击触发相应功能的文字等元素。但是,从语义上而言,它们应该是一个一个的 <button>,但是实际上,更多时候我们都是使用了 <p>、<div>、<a> 等标签进行了模拟,给他们加上了相应的点击事情而已。,像是下面这样,虽然没什么问题,但是相对而言不那么符合语义化:,我们不使用 <button> 的原因有很多,<button> 相对 div 而言没那么好控制,且会引入很多默认样式。但是,有了 display: contents,我们可以让我们的代码既符合语义化,同时不需要去解决 <button> 带来的一些样式问题:,添加了 <button style="display: contents">Click Me</button> 的包裹,不会对样式带来什么影响,button 也不会实际渲染在页面结构中,但是页面的结构语义上好了不少。,CodePen Demo -- Button with display: contents[3]。,对于对页面结构、语义化有强迫症的一些同学而言,灵活运用这个属性可以解决很多问题。,display: contents 并非在所有元素下的表现都一致。,对于可替换元素及大部分表单元素,使用 display: contents 的作用类似于 display: none。,也就是说对于一些常见的可替换元素、表单元素:,作用了 display: contents 相当于使用了 display: none ,元素的整个框和内容都没有绘制在页面上。,与其他表单元素不一样,正常而言,添加了 display: contents 相当于被隐藏,不会被渲染。但是实际运用过程中发现,<button></button> 如果包裹了内容,其一些可继承样式还是会被子内容继承。这个实际使用的过程中需要注意一下。,在一些外文文档中有一些讨论是关于 display: contents 的使用会影响到页面的可访问性。例如作用了 display: contents 的容器及列表,会对页面的可访问性带来一些意外结果。,这个我看暂时没有明确的结论,如果你的页面对可访问性的要求很高,具体使用的此属性的话也是需要注意一下这一点。,CSS 本身其实也在一直在努力,增加了各种属性去让我们在布局上有更多的空间与控制权。总而言之给我的感受是让 CSS 更加的像是一个完整的工程而不仅仅只是展现样式。,类似的一些有意思的属性:,看看兼容性[8](2022-05-31)。,display: contents 兼容性,到今天,兼容性已经不算太惨淡,如果不考虑 IE 系列,可以用起来了。当然,如果求稳,保守起见,可以考虑用在一些渐进增强的场景当中。,好了,本文到此结束,希望对你有帮助 :),[1]W3C: https://developer.mozilla.org/zh-CN/docs/Web/CSS/display。,[2]Codepen Demo -- display: contents | display: flex 的穿透影响: https://codepen.io/Chokcoco/pen/wvKLBVV。,[3]CodePen Demo -- Button with display: contents: https://codepen.io/Chokcoco/pen/oNjRePd。,[4]WAI-ARIA 标准: https://www.w3.org/TR/wai-aria-1.1/。,[5]前端优秀实践不完全指南: https://github.com/chokcoco/cnblogsArticle/issues/26。,[6][css-a11y][css-display] display: contents; strips semantic role from elements: https://github.com/w3c/csswg-drafts/issues/3040。,[7]CSS新特性contain,控制页面的重绘与重排 : https://github.com/chokcoco/iCSS/issues/23。,[8]兼容性: https://caniuse.com/#search=display%3A%20contents。,[9]How display: contents; Works: https://bitsofco.de/how-display-contents-works/。,[10]CSS的display:contents: https://www.w3cplus.com/css/display-contents-is-coming.html。,[11]Display: Contents Is Not a CSS Reset: https://adrianroselli.com/2018/05/display-contents-is-not-a-css-reset.html。
© 版权声明
文章版权归作者所有,未经允许请勿转载。