本节深入研究如何更好的调整元素之间的间距(margin和padding)。
first,假设有三个box,从上往下堆叠在一起。现在你想在它们之前添加一个间距,你有几种方式处理这个问题呢?
margin
属性也许正好能满足你现在的要求,但是它可能会添加了额外的边距,超出了你的预期。例如,你如何调整边距正好处在这些元素的之间?可能gap
属性更适合这种情况。调整元素的间距有很多方式,每种方式都有它们的优点和使用场景。
HTML本身提供了一些元素可以用来创建间距(空间)。<br>
和<hr>
元素可以在block流方向上创建一个空白间距。
<br>
元素的作用是换行,类似于你在文本编辑器上敲了一个回车键。
<hr>
元素的作用是创建一个水平线,并且水平线两侧都附有外边距(margin)。
HTML还提供了一些HTML实体(HTML entities),它们是保留的字符串,在浏览器中渲染会被替换成指定的字符实体。例如©
和
,©
会被渲染成©,
会创建一个内联空格。
只有当可以增加页面的阅读性,理解性时,才使用HTML元素来创建间距。而不要为了增加间距去使用HTML元素。例如
<hr>
元素不仅仅是为了增加间距,更重要的是将页面内容分块。
如果你想在元素box外侧添加一个边距,可以使用margin
属性。margin
属性是margin-top
、margin-right
、margin-bottom
和margin-left
的简写。
以下两种方式等价:
// margin属性简写方式
margin: 1px 2px 3px 4px;
// 另一种等价写法
margin-top: 1px;
margin-right: 2px;
margin-bottom: 3px;
margin-left: 4px;
margin
属性可以接受一个值、两个值、三个值或者四个值。
margin: 1px;
:元素四侧外边距都是1px。margin: 1px 2px;
:上下外边距为1px,左右外边距为2px。margin: 1px 2px 3px;
:上外边距为1px,左右外边距为2px,下外边距为3px。margin: 1px 2px 3px 4px;
:上右下左外边距分别为1px、2px、3px、4px。margin
可以被定义为一个指定长度、百分比或者auto
值,例如1em
和20%
。使用百分比,最终的外边距是基于该元素的包含元素的width
进行计算的。
这意味着,如果元素的包含元素的宽度为250px
,元素的外边距为20%
:那么该元素任意一侧的外边距等于50px
。
你还可以给外边距赋予auto
值,如果一个拥有固定大小的block元素,给它的某一侧margin
设置为auto
,那么这一侧的margin会尽可能的填充剩余空间。下例中,第三个item左边距设置为auto
,它的外边距会自动将填充左侧的空间,从而与其他item分开。
还可以利用auto
值,将block元素居中。
margin
还可以设置为负值。设置一个负值,可以用来减少两个元素间的间距,可以用来创建两个折叠的元素。
外边距重叠是一个很少见的概念,但是这个现象在绘制页面工作中是非常常见的。假设有两个段落,第一个段落的margin-bottom
为2em
,第二个段落的margin-top
为3em,那么你认为两个段落之间的间距是多少?5em
吗?
当然不是5em
,因为垂直外边距会重叠,所以结果是3em
。
你可以打开浏览器开发者工具,查看两个box之间的间距。
可以看到两个相邻上下元素的垂直外边距是可以重叠的,元素的间距取得是两个元素外边距的最大值。还需要知道,仅垂直外边距会出现外边距重叠的现象,水平相邻元素的水平外边距不会重叠。
如果两个元素是弹性布局的项目,那么它们的外边距不会重叠。
第一个<div>
的下外边距为10px
,第二个<div>
的上外边距为10px
,因为它们是弹性布局盒子的项目,所以它们之间垂直外边距不会重叠,所以间距为20px。
padding
与margin
相似,但是它是在盒子内部创建一个边距,称之为内边距。
如果元素设置了padding
,那么在不同box-sizing
属性值时,元素的尺寸也不同。
上例中,两个block的width
和height
都设置成100px
,并设置padding: 10px;
,但是因为两个元素的box-sizing
值不同,所以导致最终尺寸不一样。box-sizing在这里讲解过,它有两种取值方式:border-box
和content-box
。
border-box
:你想要设置的边框和内边距的值是包含在width内的。也就是说,如果你将一个元素的width设为100px,那么这100px会包含它的border和padding,内容区的实际宽度是width减去(border + padding)的值。大多数情况下,这使得我们更容易地设定一个元素的宽高。content-box
:box-sizing
属性的默认值,如果你设置一个元素的宽为100px,那么这个元素的内容区会有100px 宽,并且任何边框和内边距的宽度都会被增加到最后绘制出来的元素宽度中。因为第二个block的box-sizing
为content-box
,所以最后看到的高度是加上内边距后的高度120px
,而第一个block的box-sizing
为border-box
,所以高度就是设置的height
属性高度110px
。
与margin
类似,padding
属性是padding-top
、padding-right
、padding-bottom
和padding-left
属性的结合简写方式。
padding: 1px;
:元素四侧内边距都是1px。padding: 1px 2px;
:上下内边距为1px,左右内边距为2px。padding: 1px 2px 3px;
:上内边距为1px,左右内边距为2px,下内边距为3px。padding: 1px 2px 3px 4px;
:上右下左内边距分别为1px、2px、3px、4px。在布局章节中讲解过position
属性,当你为position
设置了非static
值,那么你可以使用top
、right
、bottom
和left
属性设置元素的位置。
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
的值进行偏移。偏移值不会影响任何其他元素的位置。
下面看一个position:sticky;
的例子。
在Grid和Flex中,可以使用gap
属性,在元素中间添加一个间距。
无论你采用哪种方式调整元素的间距。最好的是保持整个页面同种类型布局的间距统一性。例如你将所有段落的间距都设置为20px,最好的方式是利用css变量(css自定义属性)。
:root {
--gutter: 20px;
--spacing: 1em;
}
h1 {
margin-left: var(--gutter);
margin-top: var(--spacing);
}
css变量通过--varname
(两个短横线)定义,然后在其他位置使用var()
函数获取变量的值。上面定义了--guuter
和--spacing
两个变量。
(完)