在布局中, display
属性是最重要的CSS属性之一。其最常见的属性值有 block
, inline
, none
, table
以及 inline-block
。最近的新宠为 flex
,因为它是专门为布局创建的 display
属性。新出现的 grid
(最近仍比较活跃)是另外一个指定的布局属性,其很快就会广泛被使用。
这篇文章比我预期的要长很多,你可以选择性进行阅读,但是我更希望你可以静下心来阅读整篇文章。
通过创建各种响应式设计,对于 display
以及 position
属性我学习到了很多,关于他们的工作原理以及如何和媒体查询相结合实现所需的布局。我会简短的介绍每一个值,并且会提及之前创建的与之有很强依赖性的一些响应式组件。
如果不涉及 盒子树(box tree) 我们是没有办法谈及这些属性的。浏览器基本上是通过生成盒子树解析CSS并进行相关渲染呈现,这里盒子树是指呈现文档的格式结构。 display
属性定义了盒子的显示类型。
关于浏览器如何进行渲染在屏幕上显示这个话题,真的令人十分陶醉。这里我建议你阅读 Talia Garsiel 书写的 浏览器工作原理: 现代web浏览器的幕后 。另外一篇必读的文章是 Fantasai 书写的 CSS布局演变: 始于1990年终于未来 ,该作者目前在W3C CSS规范组工作。她曾有一个优秀的演讲: 用于企业会议的新兴技术 ,如果你对视频不感兴趣,还有一篇相关文章讲解。
有趣的事实: 我们所使用的 display
属性值实际上有很大的限制。如: block
在块流中有很大限制。请参考 规范 获取完整的列表。
所有的元素都有一个默认的 display
值,但是均可以被显式设置所重写。
将元素与其子元素从普通文档流中移除。这时文档的渲染就像元素从来没有存在过一样,也就是说它所占据的空间被折叠了。元素的内容也会被屏幕阅读所忽略。
该元素生成一个或多个行内框。就如名字般,行内级元素所占具的空间就是他的标签所定义的大小。可以被视为对块级元素的补充。
该元素生成块级框。除特殊声明外,所有的块级元素开始于新的一行,延展到其容器的宽度。
元素被渲染为列表项呈现的方式,确切说就像是一个块级元素,但是会生成一个可以被 list-style
属性进行样式修饰的标记框。只有 <li>
元素可以具有 list-style
的默认值。通常将 <li>
元素重置为默认行为。
该元素生成一个块级别框,但是整个框的行为就像是一个内联元素。尝试在 Codepen 书写此示例,改变窗口的大小,这样会更有意义。
我创建的组件之一是针对不同旅客使用的数字叠加器。我得到了一个用于移动布局与一个用于桌面布局的静态的photoshop文件。但是他们都具有一个中间宽度以防“打破”布局。
这主要是由于括号内的文字没有很好的折叠在一起。所以我需要使用媒体查询进行宽度调整。使相关元素以不同的宽度显示。在 Codepen 中查阅全尺寸效果并观察该组件在不同宽度窗口的显示。
这有一组 display
值允许你的元素表现类似于HTML表格。新加坡的开发人员 Colin Toh 写了一篇优秀的 有关于 display
为表格属性的文章 ,你应该认真看一下。
虽然我们大多数的人都不在使用基于表格的布局, display: table
在一定的情况下还是十分有用的。如: 如果你想要在更广泛的布局上使用表格,但是在在较小宽度上保持典型的块布局。这可以同时结合媒体查询与 display
(为了采取更好的措施,使用伪元素)进行实现,仅需要调整窗口的大小观看实现的效果。
table | 对应于HTML元素中的 <table> 。定义了一个块级框。 |
---|---|
table-header-group | 对应于HTML元素中的 <thead> |
table-row | 对应于HTML元素中的 <tr> |
table-cell | 对应于HTML元素中的 <td> |
table-row-group | 对应于HTML元素中的 <tbody> |
table-footer-group | 对应于HTML元素中的 <tfoot> |
table-column-group | 对应于HTML元素中的 <colgroup> |
table-column | 对应于HTML元素中的 <col> |
table-caption | 对应于HTML元素中的 <caption> |
inline-table | 这是唯一没有直接映射到HTML元素的值。这个元素的表现形式将为表格HTML元素,但是是一个内联块而不是块级元素。 |
@media screen and (min-width: 720px) { .table { display: table; width: 100%; border-collapse: collapse; } } .tr { margin-bottom: 1.6rem; } @media screen and (min-width: 720px) { .tr { display: table-row; } } @media screen and (min-width: 720px) { .td { display: table-cell; border: #f0f0f0 1px solid; padding: 0.4rem; } .td:first-child { width: 11em; } } .th { font-size: 1rem; line-height: 1.6rem; font-family: "Palo Alto"; } @media screen and (min-width: 720px) { .th { font-size: 1.294rem; line-height: 1.6rem; } } @media screen and (min-width: 720px) { .th { font-size: 0.8rem; line-height: 1.6rem; font-family: "Roboto Slab", Rockwell, serif; font-weight: 700; } } @media screen and (min-width: 720px) and (min-width: 720px) { .th { font-size: 1rem; line-height: 1.6rem; } } .th::before { content: 'display: '; } @media screen and (min-width: 720px) { .th::before { content: ''; } } .th::after { content: ';'; } @media screen and (min-width: 720px) { .th::after { content: ''; } }
Tab Atkins Jr. 是Flexbox以及网格规范的主要作者,关于新布局规范的显示模式提出了最突出的一点。
Flexbox是一维布局 -- 用于任何需要在一条直线上显示的布局(或者是中断线,如果他们迂回在一起则会表现为单一的直线)。 网格是二维布局,它可以用于低功能的flexbox的替代品(我们已经测试过单一的行/列的形式十分近似于flexbox),但是不可以用于完全替代。 - Tab Atkins Jr. to www-style
需要时刻牢记于心,在工作中使用这些新CSS布局,并在使用过程中对其充满了困惑。
引入flexbox布局模块或CSS弹性框,标志着我们第一次有了专门为浏览器内容进行布局的规范。自从HTML被引入之后,网页内容布局已经演变了很多。当设计者想要创建一些富有创意的设计时,使用的第一种方法就是嵌套的HTML表格,或者我们所说的基于表格的布局。
当CSS开始升温的时候,我们转向了基于浮动的布局,通过将内容嵌套在不同的 div
中进行浮动实现想要的效果。基于浮动的布局仍然十分常见,但是随着时间的推移,所有当代浏览器均支持flexbox布局。我相信不久的将来基于flexbox与网格的布局将会成为布局的普遍方式。
这里我要引用Scott Vandehey的文章 - 什么是Flexbox? 。这是其向Tab Atkins Jr.探索Flexbox历史时所书写的一篇文章。最早的草案规范日期为 2009年7月23日 ,但是讨论始于几年之前。
然而并没有什么正式的结构,各浏览器供应商也已经实现了flexbox,但是并没有真正的遵循规范。这也是为什么felxbox语法变得一团糟的原因(向后兼容一些老的浏览器时也是如此)。
flexbox模型是十分强大的,它可以实现很多功能,如果想要彻底搞明白flexbox的工作原理以及如何使用它,你需要多花点心思。flexbox以及网格布局需要长篇的文章进行深度覆盖,这里我列举了一些有关于flexbox的相关文章:
有关于Flexbox更多的教程,可以猛击这里阅读。
在一个元素上声明 dispaly: flex
,它就会变为flex容器,同时它的子元素就会变为flex项。这不会被继承即其子元素的下一代不会具有felx属性。flex容器和flex项都有各自的flex属性。
再次强调,我希望你认真查阅上述有关于flexbox的资源列表,这将会有助于你更好地理解并使用flexbox。
flex-direction | 定义了主轴以及flex项的方向。 flex-direction 值的完整列表 |
---|---|
flex-wrap | 指定flex项的调整,单行显示亦或允许多行显示。 flex-wrap 值的完整列表 |
flex-flow | flex-direction 以及 flex-wrap 属性的补充。 flex-flow 值的完整列表 |
justify-content | 定义flex项沿主轴分布时的间隙大小。 justify-content 值的完整列表 |
align-items | 定义flex项在垂直主轴分布时的间隙大小。 align-items 值的完整列表 |
align-content | 指定行flex项在flex容器内如何分布,如果flex项为单独一行则不适用。 align-content 值的完整列表 |
order | 指定flex项的布局顺序,按顺序值进行升序,若值相同根据源顺序进行布局。 order 值的完整列表 |
---|---|
flex-grow | 若有足够空间,定义元素是否可扩展,根据此值确定该元素扩展的空间比例(这有些小复杂)。 flex-grow 值的完整列表 |
flex-shink | 若没有足够空间,定义元素是否可缩小,该值决定了元素可缩小的比例。 flex-shink 值的完整列表 |
flex-basis | 制定了flex项在主轴方向上的输出大小。 flex-basis 值的完整列表 |
flex | flex-grow , flex-shrink , flex-basis 属性的补充。 felx 值的完整列表 |
align-self | 指定单个flex项的被重写的对齐方式。 align-self 值的完整列表 |
任何有关网格布局的,我都会去参考 Rachel Andrew - 我认为她是CSS网格大师。她一直在带头努力提高人们对这个新的 display
属性的认识,通过一些演讲,文章以及教程。
CSS网格使我们可以创建网格系统并且可以纯粹使用CSS控制网格项的定位,实现了与HTML的分离。当结合使用媒体查询时,CSS网格变成了一个有用的工具用于设计并创建一些灵活的布局。
当前的 CSS网格布局模块1 草案始于 2011年 。像flexbox,本规范的成熟需要一个用于布局的适当的方法,奠定网页内容而不损害HTML语义。
注意,虽然Microsoft Edge以及Internet Explorer可以使用 -ms-
实现旧版本浏览器的支持,CSS网格还没有在所有的浏览器中实现。这并不足以为奇,因为最原始的网格规范的编辑大部分来自于Microsoft。
在flexbox规范凌乱的实施之后,正在发展的CSS网格采取了不同的做法。浏览器供应商使用不同的供应商前缀将正在实验的功能添加到浏览器中以便于开发人员的测试。这十分有助于规范的制定,并且在正式规范形成之前找到所有的缺陷。
为了这样子实施,CSS网格发展了一个标记。它必须由开发人员手动启动。在Chrome和Opera中,分别导航到 chrome://flags
和 opera://flags
,并启动“网页实验平台功能”。对于 Firefox,导航到 about:config
并将 layout.css.grid.enabled
以及 layout.css.grid-template-subgrid-value.enabled
设置为true。
Grid Container | 相似于flex容器的概念,元素声明为 display: grid; 。其直接后代(子元素)为网格项 |
---|---|
Grid Item | 如果父元素为 display: grid; , 那么这个元素就被视为网格项。网格项的子元素不被视为网格项。 |
Grid Track | 可以为网格的行或列。 |
Grid Line | 定义网格结构的线,被视为网格轨道之间的界限。 |
Grid Cell | 单个的网格单元,由相邻的水平和垂直的网格线所包围的空间。 |
Grid Area | 最酷的一部分。由多个网格单元格组成的区域。 |
试图用简短的语言概述网格真的是一件十分具有挑战的事情。请参考一下资源,并尝试使用CSS网格进行实现。事实上,你可以现在进行 网格相关实验 并且查看Codepen有关于网格不同用例的相关链接的演示。
有关于Grid更多的教程,可以猛击这里阅读。
这是十分有趣的一个,我之前都不知道它的存在知道我阅读了 CSS display 规范 。并且我也阅读了2010文章, Chris Coyier 书写的 CSS Run-in Display值 。不幸的是,浏览器厂商不喜欢这种规范已被移除,这样你就可以认为这是一个备用的现实规范。
事实上,你将一个元素的 display
属性设置为 run-in
,就会渲染一个 run-in
框。用例就是使用本地方法创建一个run-in标题,这在平面设计中的说法是和正文位于同一行的标题。
你可以使用浮动实现相似效果,但是被视为一个hack方法。将标题的基线定位到正文基线上是具有挑战性的,你需要调整标题字体大小以及正文的行高使之相匹配。并有可能出现标题多余一行的情况。
如果你将标题的设置为 display: inline
,除非你将标题嵌套在段落元素内( p
为块元素),否则它不会工作的。但是这又会出现语义上的错误。就我个人而言我希望看到其可以实现,但是我想那时浏览器厂商会有更多的担忧。
介绍这一特定属性之前需要首先介绍一下 <ruby>
元素。简单地说,有一种元素用于在文本基线旁的注释,通常是帮助发音。这对于东南亚语言是十分常见的,如汉语或者日语。我所研究的大多数文章是2010年左右,所以我使用 <ruby>
书写了 2016的状态 。
display:ruby;
和 display:table;
有很大的相似之处,但是规范不鼓励将ruby值应用到非ruby元素上,如使用 span
显示ruby文本。相反,我们应该使用HTML ruby元素,所以屏幕阅读器和非CSS渲染器可以解析ruby结构的内容。
ruby | 对应于HTML元素中的 <ruby> ,它将生成一个ruby容器框,产生一个ruby格式上下文用于标记为内部ruby框的子元素。 |
---|---|
ruby-base | 对应于HTML元素中的 <rb> ,ruby格式上下文中的一个内部ruby框。 |
ruby-text | 对应于HTML元素的 <rt> ,ruby格式上下文中的内部ruby框。 |
ruby-base-container | 对应于HTML元素的 <rbc> ,ruby格式上下文中的一个内部ruby框。 |
ruby-text-container | 对应于HTML元素中的 <rtc> ,ruby格式上下文中的一个内部ruby框。 |
元素本身不会产生任何框,但是其子元素和伪元素可以正常生成框。为了框的生成和布局,需要将元素处理为好像和子元素或者伪元素一样处于文档树中。 - CSS Display Module Level 3
规范想表达的是,当你将一个元素设置为 display:contents
,它就会从DOM中消失,但是其子元素会保留并且占据空间。不幸的是,本规范现在仅仅得到了火狐的支持。在火狐浏览器下,调整全尺寸的 Codepen 来感受其效果。
我已经尝试概述迄今为止谈及该属性的两篇文章, Sam Rueby 书写的 火狐所支持的CSS属性 - dispaly:contents 以及 Rachel Andrew 书写的 display:contents与消失的的框 。Rachel Andrew还介绍了使用 flex-items
书写的有关于这个属性的一个神奇的用例。
这篇文章的长度超出了我的预期,如果你阅读到此,我要表示真挚的感谢。我很高兴不久的将来我们就可以在不使用hack的情况下使用这些布局。同时,希望这篇文章可以帮助你了解到更多有关于CSS布局相关的知识。
本文根据 @Hui Jing 的《 How well do you know CSS display? 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: https://www.chenhuijing.com/blog/how-well-do-you-know-display/ 。
在校学生,本科计算机专业。一个积极进取、爱笑的女生,热爱前端,喜欢与人交流分享。想要通过自己的努力做到心中的那个自己。微博:@静-如秋叶