布局
文章中codepen demo无法实时预览,可以在这里获得更好的阅读体验。
当你构建一个组件或者页面时,有多种布局方式可供选择,本节内容是各种布局的一个概览。
假设你是一个开发者,此时一个设计专业的同事递给你一份新的网站设计稿让你开发。这份设计稿有很多有趣的布局和组件,有二维布局,也有非常灵活可流动的布局。你怎么去选择最好的css布局方式呢?
CSS为我们提供了多种布局方式,有水平轴布局,垂直轴布局或者水平和竖直混合布局。选择一个正确的布局方式往往很困难,通常你需要多个布局方式去解决问题。为了解决这些,在接下来的几个模块,你将会学习css的布局机制。
二.display属性
display
属性做了两件事。第一件事是他决定一个盒子是否表现为inline或者block。
.my-element {
display: inline
}
inline元素被称为行内元素,行内元素就像一段语句中的一个单词。它们在行内方向上紧挨着彼此。像<span>
和<strong>
元素就是典型的行内元素,它们在<p>
(段落,<p>
是一个block元素,后面将会介绍block元素)中都是紧挨着彼此的。它们同样拥有周围的空间,即padding
、border
和margin
属性都是有效的。
你无法设置行内元素的width
和height
属性。block层级的margin和padding将会被周围的元素忽略(这句话的英文原文是Any block level margin and padding will be ignored by the surrounding elements,我不清楚这样翻译是否合适)。
block元素,即块元素,它们并不是紧挨着其他元素的。它们在页面中会自动生成新的一行。块元素在行内方向上会扩展尺寸,因此它们会占据水平方向100%宽度。块元素任意方向的边距将不会被忽略。
.my-element {
display: block;
}
display
属性还可以决定元素的子元素的行为。例如设置display: flex
,使元素盒子成为一个block层级的盒子(块元素),并且将子元素变成flex项目(item)。这会启用flex属性,flex属性可以用来控制子元素的布局方式(对其、排序、流动)。
二.flex和Grid
flex(弹性布局)和grid(格子布局)是为多个元素创建布局规则的两种主要布局机制。它们有很多共同点,但是却是被设计出来去解决不同的布局问题的。
在后面的章节内容,我将会更详细的介绍弹性布局和格子布局的内容。但是目前我们仅大致看下这两种布局方式,了解它们的功能。
首先明确两个概念:
- flex/grid盒子(简称盒子):
display
属性设置为flex
或者grid
的元素被称为盒子。 - flex/grid项目(简称项目):flex/grid盒子元素的直接子元素,不包含孙子元素。
弹性布局
.my-element {
display: flex;
}
弹性布局主要用于一维布局。布局方向是单轴的,可以是水平方向或者竖直方向。默认情况下,弹性布局会在内联方向上(水平方向)排列元素,flex项目会紧挨着彼此,并且会在块方向上(竖直方向)被拉伸,所以项目与盒子高度相同。
See the Pen 008 Layout_1 by Pengfei Wang ( @AhCola) on CodePen.flex项目会保持同轴排列,在超过flex盒子范围时,并不会换行,而是被自动压缩宽度排列。可以通过align-items
、 justify-content
和flex-wrap
改变这一默认行为。
你也可以通过flex
属性设置flex项目如何压缩、拉伸尺寸。
.my-element {
flex: 1 0 auto;
}
flex
属性是flex-grow
、flex-shrink
、flex-basis
三个属性的混合写法。你可以将上面的例子改写为:
.my-element {
flex-grow: 1;
flex-shrink: 0;
flex-basis: auto;
}
开发人员提供这些低级规则,以提示浏览器当视口尺寸发生变化时如何布局元素。这使得弹性布局非常适合设计响应式网页。
格子布局
.my-element {
display: grid;
}
格子布局(Grid)与弹性布局(flex)非常相似,但是格子布局是为多轴布局而设计的。
格子布局引入了一些新的布局基础规则,例如repeat()
和minmax()
函数。还有一个fr
单位,用来描述分配剩余空间的弹性系数。你可以创建一个12列,每列之间有一个空白间距的布局。
.my-element {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1rem;
}
See the Pen
008 Layout_2 by Pengfei Wang (
@AhCola) on
CodePen.
你还可以通过格子布局设置二维布局。我们可以设置第一个grid项目占据两行三列的空间。
.my-element :first-child {
grid-row: 1/3;
grid-column: 1/4;
}
通过grid-row
和grid-column
属性设置盒子中第一个元素水平占据空间从第一列到第四列,竖直占据空间从第一行到第三行。
flow布局
如果不使用弹性布局和格子布局,你的元素将会显示为正常文档流。还有一些布局方式可以在正常文档流中改变元素的行为和位置。
inline-block
前面提到过,内联元素的块方向上的边距(margin和padding)将会被周围的元素忽略。通过设置inline-block
,可以使内联元素的块方向上的边距不会被忽略。
p span {
display: inline-block;
}
使用inline-block
可以让一个盒子拥有块元素的一些特性,但是仍然在处于内联文档流中,与其他元素紧挨着。
p span {
margin-top: 0.5rem;
}
Floats
如果一个段落中有一张图片,但是你想让文字环绕在图片周围,就像杂志一样。你可以使用floats特征去完成这种效果:
img {
float: left;
margin-right: 1em;
}
float
属性指示元素朝着指定方向流动。例子中的图片被指示朝着左侧流动,并且允许它的姐妹元素环绕着它。你可以设置float
属性为left
、right
、inherit
等值。
注意:当你使用float
属性,你要记住所有在float元素后的元素的布局都会被调整。为了防止这种情况,你可以清除float效果,可以通过设置float元素后面的元素clear: both
属性值,也可以通过为float元素的父元素添加display: flow-root
属性值。
多列布局
如果有一个很长的列表,你可以通过column-count
设置列表的列数,通过column-gap
设置列表的列间距。
.countries {
column-count: 2;
column-gap: 1em;
}
See the Pen
008 Layout_5 by Pengfei Wang (
@AhCola) on
CodePen.
上面的例子,会自动将列表分成两列,并且在列之间添加一个空白间距。
也可以通过设置column-width
,然后通过列表宽度,自动划分列数。
.countries {
width: 100%;
column-width: 260px;
column-gap: 1em;
}
See the Pen
008 Layout_6 by Pengfei Wang (
@AhCola) on
CodePen.
position
position
属性会改变元素在正常文档流中的表现和它与其他元素之间的关系。可用的属性值由static
、relative
、absolute
、fixed
和sticky
。默认值为static
。
-
static:该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。
-
relative: 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative对table-row, table-column, table-cell, table-caption 元素无效。
-
absolute:元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对于最近的非 static定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。
-
fixed:元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed属性会创建新的层叠上下文。当元素祖先的transform,perspective或filter属性非 none 时,容器由视口改为该祖先。
-
sticky:元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和containing block(最近块级祖先nearest block-level ancestor),包括table-related元素,基于top、right、bottom和left的值进行偏移。偏移值不会影响任何其他元素的位置。
可以在这里获得更详细的内容。
附:参考资料
(完)