外边界 ( margin )
在网页元素容器主体的外面,还有一层使用 margin 控制样式的“外边界”,这篇教学会介绍网页元素的 margin,除了基本的单数值设定、多数值设定和长度单位,还会介绍 margin 重叠现象、可置换元素和不可置换元素使用 margin 时的细节差异。
请先阅读:容器盒子模型 ( box Model )
快速导览:
教学影片
搭配教学影片一起阅读,效果会更好!欢迎大家订阅 STEAM 教育学习网的 Youtube 频道。
margin 撰写语法
margin 是元素容器盒子模型里的“外边界”,也就是在网页元素容器主体外面延伸出去的空间,W3C 为了避免网页元素出现时太过紧密,许多元素都有外边界 margin 默认值,因此就算不做任何设定,元素之间也会按照默认值互相撑开。
由于各个元素默认值都太相同,详细参考“HTML 教学”,从左侧选单选择元素查看默认值。
如果要调整外边界,需要使用下列几种撰写语法修改数值,数值的位置对应不同方向的外边界 ( margin 没有继承特性 ):
| 语法 | 说明 |
|---|---|
margin: 上 右 下 左; |
空白分隔“四个”数值,分别设定四个方向的外边界。 |
margin: 上 (左右) 下; |
空白分隔“三个”数值,分别设定上、下和左右外边界,左右的数值相同。 |
margin: (上下) (左右); |
空白分隔“二个”数值,分别设定上下和左右外边界,上下的数值相同,左右的数值相同。 |
margin: (上下左右); |
一个数值,上下左右外边界数值相同。 |
下方的范例使用五个 div 呈现不同的 margin 的写法,div 里会放入另一个 em,并设定该 div 的外边界。
<!-- HTML 程式碼 -->
<div><div>預設值</div></div>
<div><div class="a">margin: 20px 15px 10px 5px;</div></div>
<div><div class="b">margin: 20px 10px 5px;</div></div>
<div><div class="c">margin: 20px 5px;</div></div>
<div><div class="d">margin: 20px;</div></div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
background: orange;
width: max-content; /* 讓內容撐開 */
margin: 10px;
}
div div {
display: block;
width: 240px;
height: 30px;
border: none;
background: yellow;
}
.a {margin: 20px 15px 10px 5px;}
.b {margin: 20px 10px 5px;}
.c {margin: 20px 5px;}
.d {margin: 20px;}
</style>
margin-* 单一外边界
除了一次设定四个方向的 margin 数值,也可以透过单一外边界的样式属性,单独设定上下左右数值。
| 单一外边界样式 | 说明 |
|---|---|
margin-top |
上方外边界 |
margin-right |
右侧外边界 |
margin-bottom |
下方外边界 |
margin-left |
左侧外边界 |
单一外边界的权重与 margin 相同,有时会运用“撰写顺序”来覆写特定方向的外边界,下方的范例先将 div 的 margin 统一设定为 10px,再运用单一外边界调整特定方向的宽度。
<!-- HTML 程式碼 -->
<div><div class="a">margin-top: 30px;</div></div>
<div><div class="b">margin-right: 30px;</div></div>
<div><div class="c">margin-bottom: 30px;</div></div>
<div><div class="d">margin-left: 30px;</div></div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
background: orange;
width: max-content;
margin: 10px;
}
div div {
display: block;
width: 240px;
height: 30px;
border: none;
background: yellow;
margin: 10px; /* 四個方向的外邊界都是 10px */
}
.a {margin-top: 30px;}
.b {margin-right: 30px;}
.c {margin-bottom: 30px;}
.d {margin-left: 30px;}
</style>
margin 使用的长度单位
margin 使用的数值需要具有“长度单位”,支援相对长度和绝对长度,数值“可以负值”,长度单位如下表所示:
延伸阅读:长度与角度单位
| 长度单位 | 性质 | 说明 |
|---|---|---|
| auto 或不设定 | - | 采用元素默认外边界值。 |
| px | 绝对长度 | 像素。 |
| % | 相对长度 | 父元素内容宽度的百分比。 |
| em | 相对长度 | 元素本身字体大小的几倍。 |
| rem | 相对长度 | 根元素字体大小的几倍。 |
| pt、cm、mm、in | 绝对长度 | 印刷单位。 |
下方的范例使用不同长度单位设定元素的外边界值,注意 margin 就算是设定上下的数值,使用百分比为单位时,仍然是采用“父元素内容宽度”进行计算。
<!-- HTML 程式碼 -->
<div><div class="a">margin: 10px;</div></div>
<div><div class="b">margin: 0.5em;</div></div>
<div><div class="c">margin: 3rem;</div></div>
<div><div class="d">margin: 10%;</div></div>
<!-- CSS 程式碼 -->
<style>
:root {font-size: 10px;} /* 根元素字型大小 10px */
div {
border: 1px solid #000;
background: orange;
width: 300px; /* 父元素寬度 300px */
margin: 10px;
}
div div {
font-size: 20px; /* 元素本身字型大小 20px */
display: block;
width: 240px;
height: 30px;
border: none;
background: yellow;
}
.a {margin: 10px;} /* 絕對長度 10px */
.b {margin: 0.5em;} /* 20px x 0.5 = 10px */
.c {margin: 3rem;} /* 10px x 3 = 30px */
.d {margin: 10%;} /* 300px x 10% = 30px */
</style>
除了使用单一种长度单位,margin 也支援多种长度单位混合使用,或使用 calc() 等 CSS 函数去计算长度,下方范例同时使用了四种不同长度单位呈现方式。
<!-- HTML 程式碼 -->
<div><div>margin: 10px 1em 1rem calc(10px * 5);</div></div>
<!-- CSS 程式碼 -->
<style>
:root {font-size: 50px;}
div {
border: 1px solid #000;
background: orange;
width: max-content;
margin: 10px;
}
div div {
font-size: 14px;
display: block;
width: 260px;
height: 30px;
border: none;
background: yellow;
margin: 5px 1em 1rem calc(10px * 5);
}
</style>
然而在这些单位中,如果使用“百分比 %”要特别小心,由于百分比单位是“父元素宽度”的百分比,若父元素使用 max-content 作为宽度时,不会考虑百分比单位所计算出的 margin 数值,会发生无法撑开父元素的状况,下方范例中会呈现使用像素 px 和使用百分比 % 的差异。
由于
max-content会根据内容文字多寡以及“像素值”计算最大宽度,因此如果子元素使用“百分比”,表示子元素要乘以父元素宽度,而父元素宽度又要根据子元素改变,最后就会无法计算出真正的数值,详细参考:使用 max-content
<!-- HTML 程式碼 -->
<div>
<h2 class="a">margin: 20px; 撐開父元素</h2>
</div>
<div>
<h2 class="b">margin: 10%; 父元素不變</h2>
</div>
<!-- CSS 程式碼 -->
<style>
div {
width: max-content;
border: 1px solid #000;
font-size: 10px;
background: red;
margin: 10px;
}
h2 {
width: 250px;
height: 100px;
font-size: 20px;
background: #fb0;
}
.a {margin: 20px;} /* 父元素寬度會計算像素單位數值 */
.b {margin: 10%;} /* 父元素寬度不會計算百分比單位數值 */
</style>
margin 设定负值
margin 可以设定“负值”,当数值为负值时,就会产生“内缩到元素里”的负向外边界,有时会透过负向外边界让元素内缩或与其他元素重叠在一起,实现网页排版的特殊效果,下方的范例会透过负值的 margin,将 div 重叠在一起 ( 每个 div 都把 margin-bottom 设为 0,避免向下边界的推开下方元素 )。
<!-- HTML 程式碼 -->
<div></div>
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
width: 100px;
height: 100px;
background: orange;
}
.a {
margin: -60px 30px 0;
background: #f003;
}
.b {
margin: -60px 60px 0;
background: #0f05;
}
.c {
margin: -60px 10px 0;
background: #00f5;
}
</style>
margin 边界重叠特性
margin 有一个很重要的特性,叫做“边距重叠 Collapsing margins”,意思是如果有两个或多个元素 垂直摆放,就会发生“上下外边界自动组合成单一个边界”的行为,这种方式组生成的外边界称为重叠边界,重叠边界会采用“最大的 margin 值”。
边界重叠特性是由区块容器排版格式所产生,详细参考:区块容器排版格式 ( BFC )
下方范例的画面中有三个 div 元素,虽然设定了 margin: 10px;,但可以看出因为重叠边界的缘故,两个 div 之间的间距还是保持 30px,而不是两两相加的 60px。
<!-- HTML 程式碼 -->
<div></div>
<div></div>
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
width: 200px;
height: 30px;
margin: 30px;
background: #f005;
}
</style>
这种边界重叠现象不只发生在“兄弟元素”,在“父子元素”的结构更为明显,下方的范例位于子元素的 div 不仅没有保持和父元素的外边界,甚至因为发生了外边界重叠,造成父元素与其他元素的边界值变成了子元素的 50px ( 因为子元素的 margin 值较大 )
<!-- HTML 程式碼 -->
<div>
<div></div>
</div>
<div>
<div></div>
</div>
<!-- CSS 程式碼 -->
<style>
div {
width: 200px;
height: 50px;
margin: 10px;
background: #f005;
}
div div {
margin: 50px;
background: #00f5;
}
</style>
不会发生边界重叠的状况
虽然元素会发生 margin 外边界重叠,但下列几种情况“不会发生外边界重叠”:
- 水平的外边界不会重叠。
- 父元素
- 父元素有设定
padding或border,“父子元素”不会重叠。- 父元素的
display属性是inline-*、flex、grid、table、table-*、flow-root。- 元素本身
- 元素的
display属性是inline-block、table-caption。- 元素的
position样式使用absolute或fixed。- 元素之间穿插了非区块容器元素,例如
inline、table...等。
下方范例展示父元素设定了 padding 和 border 后,margin 不会重叠的状况,从中也可以发现,垂直的外边界会重叠,但水平的外边界不会重叠。
<!-- HTML 程式碼 -->
<div>
<div>預設</div>
</div>
<div class="a">
<div>父元素有 border</div>
</div>
<div class="b">
<div>父元素有 padding</div>
</div>
<!-- CSS 程式碼 -->
<style>
div {
width: 200px;
height: 50px;
margin: 30px;
background: #f005;
}
div div {
margin: 20px;
background: #05f5;
border: none;
}
.a {border: 1px solid #000;}
.b {padding: 1px;}
</style>
下方范例更改父元素的 display,可以发现没有产生外边界重叠现象。
<!-- HTML 程式碼 -->
<div class="a">
<div>父元素 display: inline-block;</div>
</div>
<div class="b">
<div>父元素 display: table;</div>
</div>
<div class="c">
<div>父元素 display: grid;</div>
</div>
<div class="d">
<div>父元素 display: flex;</div>
</div>
<!-- CSS 程式碼 -->
<style>
div {
width: 240px;
height: 50px;
margin: 30px;
background: #f005;
}
div div {
margin: 20px;
background: #05f5;
}
.a {display: inline-block;}
.b {display: table;}
.c {display: grid;}
.d {display: flex;}
</style>
下方范例会在元素之间穿插 inline、table 显示类型元素,这也会让外边界不重叠,此外如果加入的是 block 区块容器元素,就会发生外边界重叠现象。
<!-- HTML 程式碼 -->
<div>
<span>我是行內容器 inline</span>
<div></div>
</div>
<table>
<tr>
<td>我是表格</td>
<td>我是oxxo</td>
</tr>
</table>
<div class="b">
<div>我是區塊容器 block</div>
<div></div>
</div>
<!-- CSS 程式碼 -->
<style>
div {
width: 240px;
height: 50px;
margin: 30px;
background: #f005;
}
div div {
margin: 20px;
background: #05f5;
}
td {
border: 1px solid #000;
}
</style>
不可置换行内容器的 margin
虽然不可置换行内容器无法调整宽高 ( 文字样式的显示类型大多都是 inline ),但却可以透过 margin 改变外边界,进而改变宽度,不过由于行内容器的高度由字号和行高所管控,就算设定了 margin 数值也不会影响整体高度。
不可置换行内容器表示不会透过 src 等属性改变元素内容。
下方的范例设定了 strong 和 em 这两个行内容器元素的 margin 数值,因为外边界的改变而把左右两侧的内容推开,上下的 margin 则没有作用,不影响容器的行高表现,也不会影响整体的高度与外部的元素,如果设定为“负值”,重叠的方式和元素流向相同,都是“右边在上层,左边在下层”。
<!-- HTML 程式碼 -->
<span>hello oxxo</span>
<div>
<span><strong>STEAM 教育學習網</strong>透過免費且高品質的<em>教學與範例</em>讓所有人都能輕鬆跨入 STEAM 的學習領域。</span>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
line-height: 30px;
}
strong {
margin: 80px;
background: orange;
}
em {
margin: -25px;
background: cyan;
}
</style>
如果 margin 为负值,会造成“第一行超出范围”的表现行为,但却不会影响其他行。
<!-- HTML 程式碼 -->
<div>
<span>STEAM 教育學習網透過免費且高品質的教學與範例讓所有人都能輕鬆跨入 STEAM 的學習領域。</span>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
line-height: 30px;
width: 200px;
margin: 100px;
}
span {margin: -80px;}
</style>
可置换行内容器的 margin
网页中的图片元素 img 或 svg 都属于“可置换”行内容器 ( 显示类型大多都是 inline-block ),这些元素原本就能设定宽高,而不是根据字型或行高决定容器大小,因此如果设定了 margin 数值,外边界就会发生作用,将旁边的元素推开*。
下方的范例在文字中插入两张图片,当设定了图片的 margin 数值,如果是正值就会将周围元素推开,如果是负值就会让周围元素内缩到元素里,或发生元素跑到边界外的状况。
<!-- HTML 程式碼 -->
<div>
<span>STEAM 教育學習網透過免費且高品質的教學與範例
<img src="https://steam.oxxostudio.tw/download/css/function-filter-demo.jpg">讓所有人都能輕鬆跨入 STEAM 的<img class="a" src="https://steam.oxxostudio.tw/download/css/function-filter-demo.jpg">學習領域。</span>
</div>
<span>hello oxxo!!!</span>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
line-height: 30px;
}
span {background: yellow;}
img {
width: 100px;
margin: 50px;
}
img.a {margin: -50px;}
</style>
小结
元素的外边界 margin 虽然在使用上跟 padding 大同小异,但对于其他元素或边界重叠的现象却大相径庭,不过只要透过这篇教学,就能熟悉相关做法,也能轻松应用在网页设计或网页排版啰!
微信扫码关注
抖音扫码关注