深挖显示属性:显示的两个值
已发表: 2022-03-10display
属性的值,是一个没有引起太多关注的属性的主力。 雷切尔安德鲁在一个短系列中得到了更好的表现。 flex 或 grid 布局从您声明display: flex
或display: grid
开始。 这些布局方法是 CSS display
属性的值。 我们倾向于不单独谈论这个属性,而是专注于flex
或grid
的值,但是,有一些有趣的事情需要了解display
以及它是如何定义的,这将使您在使用时更轻松用于布局的 CSS。
在这篇文章中,这是一个简短系列的第一篇,我将看一下在 3 级规范中定义display
值的方式。 这是我们在早期版本的 CSS 中定义display
的方式的改变。 虽然对于我们这些从事 CSS 多年的人来说,起初这可能看起来很不寻常,但我认为这些更改确实有助于解释当我们更改元素上的display
值时发生了什么。
块和内联元素
我们教给刚接触 CSS 的人的第一件事就是块元素和内联元素的概念。 我们将解释页面上的某些元素是display: block
,因此它们具有某些功能。 它们沿内联方向延伸,占用了它们可用的尽可能多的空间。 他们打破了一条新路线; 我们可以给它们设置宽度、高度、边距以及内边距,这些属性会将页面上的其他元素推离它们。
我们也知道有些元素是display: inline
。 内联元素就像句子中的单词; 它们不会换行,而是在它们之间保留一个空白字符。 如果您添加边距和填充,这将显示但不会推开其他元素。
块和内联元素的行为是 CSS 的基础,正确标记的 HTML 文档默认是可读的。 这种布局被称为“块和内联布局”或“正常流”,因为如果我们不对元素做任何其他事情,这就是元素自己布局的方式。
display
的内在价值和外在价值
我们了解块元素和内联元素,但是如果我们让项目display: grid
会发生什么? 这是完全不同的东西吗? 如果我们查看指定了display: grid
的组件,就布局中的父元素而言,它的行为类似于block level
元素。 元素将伸展并在内联维度中占用尽可能多的空间,它将从新行开始。 就其与布局其余部分的行为方式而言,它的行为就像一个block
元素。 我们还没有说display: block
虽然,还是我们说的?
事实证明,我们有。 在 Display 规范的 Level 3 中, display
的值被定义为两个关键字。 这些关键字定义了 display 的外部值,它将是inline
或block
,因此定义了元素在布局中与其他元素一起的行为方式。 它们还定义了元素的内部值——或者该元素的直接子元素的行为方式。
这意味着当你说display: grid
时,你真正说的是display: block grid
。 您要求的是块级网格容器。 一个拥有所有块属性的元素——你可以给它高度和宽度、边距和内边距,它会拉伸以填充容器。 但是,该容器的子项已被赋予grid
的内部值,因此它们成为网格项。 这些网格项的行为在 CSS 网格规范中定义: display
规范为我们提供了一种方法来告诉浏览器这是我们想要使用的布局方法。
我认为这种对display
的思考方式非常有用。 它直接解释了我们使用各种布局方法所做的事情。 如果您要指定display: inline flex
,您会期望什么? 希望是一个充当内联元素的盒子,其子元素是弹性项目。
通过以这种新方式思考display
,还有一些其他的事情得到了很好的解释,我将在本文的其余部分介绍其中的一些内容。
我们总是回到正常流程
在考虑这些内部和外部显示属性时,考虑一下如果我们根本不处理 display 的值会发生什么会很有帮助。 如果你编写一些 HTML 并在浏览器中查看它,你得到的是块和内联布局,或正常流。 元素显示为block
或inline
元素。
下面的示例包含一些标记,我通过使div
display: flex
(两个直接子项)现在变成了 flex 项,因此图像现在与内容排成一行。 但是,如果您在内容中看到,则会再次以正常流程显示标题和段落。 媒体对象的直接子对象变成了弹性项目; 除非我们更改 flex 项目上的 display 值,否则他们的孩子会恢复正常流程。 flex 容器本身是一个块框,正如您从边框延伸到其父级边缘的事实所看到的那样。
如果您使用此过程,那么页面上的元素将使用这种可读的正常流布局来布置自己,而不是与它对抗并尝试放置所有东西,CSS 会容易得多。 您也不太可能陷入可访问性问题,因为您正在处理文档顺序,这正是屏幕阅读器或浏览文档的人正在做的事情。
解释flow-root
和inline-block
inline-block
的价值对于我们很多从事 CSS 一段时间的人来说可能也很熟悉。 此值是一种获取inline
元素上的某些块行为的方法。 例如, inline-block
元素可以具有宽度和高度。 带有display: inline-block
的元素也以一种有趣的方式表现,因为它创建了一个B锁定格式内容( BFC )。
BFC 在布局方面做了一些有用的事情,例如,它包含浮动。 要更详细地了解块格式化上下文,请参阅我之前的文章“理解 CSS 布局和块格式化上下文”。 因此说display: inline-block
给你一个内联框,它也建立了一个 BFC。
正如您将发现的(如果您阅读了上面提到的关于块格式化上下文的文章),还有一个更新的 display 值,它也显式地创建了一个 BFC。 这是flow-root
的值。 此值在块上创建 BFC,而不是内联元素。
-
display: inline-block
为您提供了一个在线框上的 BFC。 -
display: flow-root
给你一个块框上的 BFC。
您现在可能认为这有点令人困惑:为什么我们在这里有两个完全不同的关键字,以及我们之前讨论的双值语法发生了什么? 这巧妙地引出了我需要解释的关于display
的下一件事,即 CSS 有我们需要根据display
属性处理的历史这一事实。
显示的传统价值
CSS2 规范详细说明了display
属性的以下值:
-
inline
-
block
-
inline-block
-
list-item
-
none
-
table
-
inline-table
还定义了各种表格内部属性,例如本文未涉及的table-cell
。
然后我们在这些值中添加了一些用于显示的值,以支持 flex 和 grid 布局:
-
grid
-
inline-grid
-
flex
-
inline-flex
注意:该规范还定义了ruby
和inline-ruby
以支持 Ruby 文本,您可以在 Ruby 规范中阅读。
这些都是display
属性的单个值,在规范更新之前定义,以这种方式解释 CSS 布局。 CSS 非常重要的一点是我们不会到处破坏网络。 我们不能简单地改变事情。 我们不能突然决定每个人都应该使用这种新的双值语法,因此每个使用单值语法构建的网站都会崩溃,除非开发人员回去修复它!
在考虑这个问题时,您可能会喜欢这个 CSS 设计中的错误列表,这些错误在许多情况下更少,因为设计时没有水晶球可以预见未来! 然而,事实是我们不能破坏网络,这就是为什么我们会出现这种情况,现在浏览器支持一组单一的显示值,并且规范正在转向两个显示值。
我们解决这个问题的方法是指定显示的旧值和短值,其中包括所有这些单个值。 这意味着可以在单个值和新的两个关键字值之间定义映射。 这为我们提供了下表的值:
单值 | 两个关键字值 | 描述 |
---|---|---|
block | block flow | 带正常流动内部的块箱 |
flow-root | block flow-root | 定义 BFC 的块框 |
inline | inline flow | 内嵌正常流量的内联盒 |
inline-block | inline flow-root | 定义 BFC 的内联框 |
list-item | block flow list-item | 带有正常流量内部和附加标记框的块框 |
flex | block flex | 具有内部 flex 布局的块框 |
inline-flex | inline flex | 具有内部 flex 布局的内联框 |
grid | block grid | 具有内部网格布局的块框 |
inline-grid | inline grid | 具有内部网格布局的内联框 |
table | block table | 具有内表布局的块框 |
inline-table | inline table | 具有内表布局的内联框 |
为了解释这是如何工作的,我们可以考虑一个网格容器。 在二值世界中,我们将创建一个块级网格容器,其中包含:
.container { display: block grid; }
但是, legacy 关键字意味着以下内容执行相同的操作:
.container { display: grid; }
相反,如果我们想要一个内联网格容器,在二值世界中,我们将使用:
.container { display: inline grid; }
如果使用旧值:
.container { display: inline-grid; }
我们现在可以回到对话开始的地方并查看display: inline-block
。 查看表格,您可以看到这在二值世界中被定义为display: inline flow-root
。 它现在匹配display: flow-root
在双值世界中将是display: block flow-root
。 稍微整理和澄清这些东西是如何定义的。 如果您愿意,可以对 CSS 进行重构。
浏览器对二值语法的支持
到目前为止,浏览器还不支持display
属性的二值语法。 可以在此处找到 Firefox 的实现错误。 实现——当它发生时——本质上将涉及将遗留值别名为双值版本。 因此,在您可以在代码中实际使用这些双值版本之前,可能还需要一段时间。 然而,这真的不是本文的重点。 相反,我认为根据二值模型查看 display 的值有助于解释发生的大部分情况。
当你在 CSS 中定义一个盒子的布局时,你是在定义这个盒子会发生什么,即它相对于布局中所有其他盒子的行为方式。 您还定义了该框的子项的行为方式。 在将值显式声明为两个独立的事物之前,您可以以这种方式思考,因为遗留关键字映射到这些值,它将帮助您了解更改display
的值时会发生什么。