深入理解 css中margin

简介

在平常开发过程中经常用到margin属性,但是也会遇到很多的问题,比如说margin重叠(BFC)负margin等等问题,下面就一个一个来记录问什么会这样。

标准盒模型

css margin

要了解margin就要先了解css中的盒子模型(Box Model)标准盒模型可以分为:外边距(margin)、边框(border)、内边距(padding)、内容区域(content)。在标准盒模型中平常所说道的高度只是content的高度,不包含border的高度,而在ie盒模型中是把border算在内的。

margin属性

margin有四个属性margin-topmargin-leftmargin-bottommargin-right,它们的值可以为百分比数值(左右可为负数)em、rem、vh、vwauto等等。

margin与容器尺寸

元素尺寸:①可视尺寸 clientWidth(标准);②占据尺寸

css margin

margin与可视尺寸:①适用于没有设定width/height的普通block元素;②只适用于水平方向尺寸
margin与占据尺寸:①block/inline-block水平元素均适用;②与有没有设定width/height无关;

③适用于水平方向和垂直方向。可用于页面的上下留白(padding兼容性不好)。

margin与可视尺寸

特性:

  • 适用于没有设定width/height的普通block元素
  • 只适用于水平方向尺寸

应用:一侧定宽自适应

1
2
<img width="150px" style="float:left">
<p style="margin-left:170px;">图片左浮动....</p>

css margin

margin与占据尺寸

特性:

  • block、inline-block水平元素均适应
  • 与有没有设定width、height值无关
  • 适应于水平方向和垂直方向

margin与百分比单位

  • 普通元素的百分比:相对于容器宽度计算
  • 绝对定位元素的百分比:相对于第一个定位的祖先容器的宽度计算的

margin中的重叠

margin重叠通常特性

  1. block水平元素(不包括floatabsolute元素)
  2. 不考虑writing-mode,只发生垂直方向(margin-top/margin-bottom

margin重叠的3种情景

  1. 相邻的兄弟元素
  2. 父级和第一个/最后一个子元素
  3. 空的block元素

父子margin重叠其他条件

margin-top重叠

margin-top重叠 解决
父元素非块状格式化上下文元素 设置父元素overflowhidden
父元素没有border-top设值 设置父元素border
父元素没有padding-top 设置父元素padding-top
父元素和第一个子元素之间没有inline元素分隔 插入一个内联元素如空格&bsp;

margin-bottom重叠

  1. 父元素非块状格式化上下文元素
  2. 父元素没有border-bottom设置
  3. 父元素没有padding-bottom
  4. 父元素和最后一个子元素之间没有inline元素分隔
  5. 父元素没有height相关声明

空block元素margin重叠

条件限制:

  1. 元素没有border设置
  2. 元素没有padding
  3. 里面没有inline元素
  4. 没有height、或者min-height

重叠的计算规则

  • 正正取大值
  • 正负值相加
  • 负负最负值

理解CSS中的margin:auto

margin:auto的作用机制:自动分配剩余空间

垂直居中方法(margin实现)

writing-mode

更改流为垂直方向,但是水平居中失效

1
2
.father { height:200px; width:100%; writing-mode:vertical-lr; }
.son { height:100px; width:500px; margin:auto; }

css margin

绝对定位元素的margin:auto居中

1
2
.father { height:200px; position:relative; }
.son { position:absolute; top:0; right:0; left:0; bottom:0; height:100px; width:500px; margin:auto; }

css margin

margin负值

为了方便理解负值margin,我们引入参考线的定义,参考线就是就是margin移动的基准点,而margin的值就是移动的数值。
margin的参考线有两类,一类是top、left,它们以外元素作为参考线;
另一类是right、bottom,它们以自身作为参考线。
简单点说就是:

  • top负值就是以包含块(Containing block) 内容区域的上边或者上方相连元素 margin 的下边线为参考线;
  • left负值就是以包含块(Containing block) 内容区域的左边或者左方相连元素 margin 的右边为参考线;
  • right负值就是以元素本身border的右边为参考线;
  • bottom负值就是以元素本身border的下边为参考线;

另外关于包含块的定义具体请参考KB008包含块(Containing block)

css margin

公用代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
.box {
width:200px;
height: 200px;
margin: auto;
border: 1px black solid;
}
.box div {
width:100px;
height: 100px;
}
.one {
background:orange;
}
.two {
background:green;
}
</style>
<div class="box">
<div class="one">one</div>
<div class="two">two</div>
</div>

margin-top和margin-left负值

margin-top

修改css代码如下:

1
2
3
.two {
margin-top: -50px;
}

效果图如下:

css margin

当设置.twodivmargin-top: -50px的时候,它的参考线是div.one的下边,整个div.two向上移动-50px使得div.two覆盖div.one

margin-left

修改css代码如下:

1
2
3
4
5
6
.box div {
float: left;
}
.two {
margin-left: -50px;
}

效果图如下:

css margin

当设置.twodivmargin-left: -50px的时候,它的参考线是div.one的右边线,整个div.two向左移动-50px使的div.two覆盖div.one

margin-right和margin-bottom负值

margin-right

修改css代码如下:

1
2
3
.one {
margin-right: -50px;
}

效果图如下:

css margin

当设置.onedivmargin-right: -50px的时候,它的参考线是div.one的右边线,整个div.one向左收缩-50px使的div.two覆盖div.one

margin-bottom

修改css代码如下:

1
2
3
4
5
6
.box div {
float: static;
}
.one {
margin-bottom: -50px;
}

效果图如下:

css margin

当设置.onedivmargin-bottom: -50px的时候,它的参考线是div.one的下边线,整个div.one向上收缩-50px使的div.two覆盖div.one

实际应用

margin负值下的两端对齐:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 1200px;
margin: auto;
background: orange;
}
.ul {
list-style: none;
overflow: hidden;
margin-right: -20px;
}
.li {
width: 386.66px;
height: 300px;
margin-right: 20px;
background: green;
float: left;
}
</style>
<div class="box">
<ul class="ul">
<li class="li">列表1</li>
<li class="li">列表2</li>
<li class="li">列表3</li>
</ul>
</div>

css margin

margin负值下的等高布局:

css margin

margin负值下的两栏自适应布局:

css margin

margin无效情形解析

  1. inline水平元素的垂直margin无效前提:

    • 非替换元素,例如不是<img>元素;
    • 正常书写模式。
  2. margin重叠

  3. display:table-cellmargin:display:table-cell/display:table-row等声明的margin无效。
  4. position:absolutemargin:绝对定位元素未设置定位方向的margin值”无效“。例如,img{top:10%}margin-top有效其他均无效。
  5. 内联特性导致的margin无效:

了解margin-start/margin-end属

-webkit-margin-start、-webkit-margin-end

  • 正常的流向,margin-start等同于margin-left,两者重叠不累加
  • 如果水平流是从右往左,margin-start等同于margin-right
  • 在垂直流下(writing-mode:vertical-*;),margin-start等同于margin-top

margin-collaps

1
-webkit-margin-collaps: <collaps> | <discard> | <separate>
  • collaps,默认,重叠
  • discard,取消重叠,使margin无效
  • separate,取消重叠,不合并

总结

在本篇文章中介绍主要的margin百分比margin重叠条件margin在盒模型中的区域,但是本文总结的margin负值并不是全部情况,比如说div.two设置为margin-right: -50px为什么不会收缩自己的宽度等等。希望大家多多做补充。

参考

CSS深入理解之relative
CSS深入理解之margin
CSS深入理解学习笔记之margin
浅谈margin负值