Skip to content

margin

margin 与容器

容器

在 CSS 标准盒模型中

CSS标准盒模型

其中我们要注意一下元素的可视空间和占据空间两个概念。

可视空间: 可以看到元素信息的空间,如 border + padding + content
占据空间: 元素使用了那么大的空间,但是它可能占据了更大的地方,只是没有使用而已。 如 margin + border + padding + content

margin 如何修改可视尺寸

  1. 适用于没有设定 width/height 的普通 block 水平元素(float 元素,absolute/fixed 元素,inline 元素...都不行)

  2. 只适合水平方向的尺寸

html
<div class="box">
	<div class="row1" style="background-color: red;height: 20px;"></div>
	<!-- 红色背景宽度变窄了 -->
	<div class="row2" style="background-color: red;height: 20px;margin: 0 30px;"></div>
</div>

效果如下:

修改可视尺寸

row2 红色背景的宽度确实变窄了,这就是 margin 可以修改<font class="j-font-red j-font-blod">没有设置宽度</font>的 block 元素的可视宽度,且只能在水平方向。

为什么可以修改可视宽度

这就涉及到 block 元素的特性,其会沾满整个水平方向的空间,哪怕他设置了宽度,那么他也会使用了此宽度的空间,但是还是占着这个水平空间(利用这个原理 margin:auto 所以会 水平居中), 那么这时候如果没有固定 block 的宽度,设置了 margin:0 xxpx;那么就会挤挤宽度。

而为什么其他的如 inline inline-block 设置了 margin,只是修改元素的可视空间,而不是修改占用空间,就是因为 width 根据盒模型的原理只有 border、padding、content 受影响,而 margin 不会影响 width,那么这时候设置了 margin 就只能左移移右移移了。

修改可视尺寸

margin 修改占据尺寸

  1. block/inline-block 水平元素均使用

  2. 与有没有设定 width/height 值无关

  3. 适用于水平方向和垂直方向

作用
  1. 滚动容器内上下留白(不要使用 padding,原因是只有 chrome 上下留白,其他下部不会留白)

margin 的百分之单位

对于百分比单位我们主要分为这几个方向:

  • 水平方向百分比和垂直方向百分比

  • 普通元素的百分比/绝对定位元素的百分比

计算规则

我们先了解一下概念

  • 普通元素的百分比是相对于其本身容器的

  • 绝对定位元素的百分比是相对于第一个定位祖先元素进行计算的

栗子

html
<div class="box" style="background-color: #eee;height: 1000px; width: 1000px; color: #fff;">
	<div class="box" style="background-color: red;height: 700px; width: 700px; margin: 100px;padding: 100px;">
		<div style="background-color: green;height: 50px; width: 50px;">block</div>
		<div style="background-color: green;height: 50px; width: 50px;margin: 10% 0 0 10%;">block-m</div>
		<div style="background-color: green;height: 50px; width: 50px;display: inline; ">inline</div>
		<div style="background-color: green;height: 50px; width: 50px;display: inline; margin: 10% 0 0 10%;">inline-m</div>
		<div style="background-color: green;height: 50px; width: 50px; display: inline-block;margin: 10% 0 0 10%;">
			inline-block
		</div>
		<div style="background-color: green;height: 50px; width: 50px; float: left;">float</div>
		<div style="background-color: green;height: 50px; width: 50px; float: left;margin: 10% 0 0 10%;">float-margin</div>
		<div style="background-color: green;height: 50px; width: 50px; position: relative;">position</div>
		<div style="background-color: green;height: 50px; width: 50px; position: relative;margin: 10% 0 0 10%;">
			position-margin
		</div>
	</div>
</div>

效果如下:

普通元素的百分比是相对于其本身容器的

我们从效果图上可以看出对于普通元素(block 、inline 、 inline-block、float、position:relative 等)其百分比单位都是 <font class="j-font-red j-font-blod">相对于父容器的内容宽度(content)</font>

这时候我们没有看绝对定位元素

html
<div class="pp-container" style="position:relative;background-color: #eee;height: 1000px; width: 1000px; color: #fff;">
	<div
		class="p-container"
		style="position:relative;background-color: red;height: 500px; width: 500px; color: #fff; padding : 100px;margin: 100px"
	>
		<div style="display: inline-block;background-color: blue;height: 200px; width: 200px; color: #fff;">
			<div
				class="box"
				style="position:absolute;background-color: green;height: 50px; width: 50px; color: #fff;margin: 10%;"
			>
				position
			</div>
		</div>
		xxxx
	</div>
</div>

效果如下:

普通元素的百分比是相对于其本身容器的

可以看出对于我们绝对定位元素 box 来说,其没有跟普通元素一样百分比相对于其相对于父容器的宽度(200px _ 0.1 = 20px),而是相对于第一个定位祖先元素(.p-container)进行计算的(500px * 0.1 = 50)。

注意:

1. 其不管是普通元素相对于父容器,还是绝对定位元素相对于第一个祖先定位元素,其都是基于容器的宽高(不受 box-sizing 的影响,也就是可视空间)

margin 重叠

什么是 margin 重叠

我们有些时候会发现 两个元素都设置了 margin 上面的 margin-bottom:20px 下面的元素 margin-top:20px;那么这时候两个元素的间隔应该是 20 + 20 = 40px,但是实际上其间隔仍然是 20px,这就是所谓的 margin 重叠

例子

html
<div class="box">
	<div style="height: 20px;background-color: red;margin-bottom: 20px;"></div>
	<div style="height: 20px;background-color: red;margin-top: 20px;"></div>
</div>

效果如下:

margin重叠

产生规则

1. 特定的元素

  • block 水平元素(不包括 float,absolute 元素)

2. 方向

  • 不考虑 writing-mode,只发生在垂直方向 margin-top/margin-bottom

3. 特定的位置

3.1. 相邻的兄弟元素

3.2. 父级和第一个、最后一个子元素(传说中的 margin 穿透)

父元素的条件:

  • 父元素非块状格式化上下文

  • 父元素没有 border-top

  • 父元素没有 padding-top

  • 父元素和第一个子元素之间没有 inline 元素分隔

  • 父元素没有设置 height|min-height|max-height (这是对于 margin-bottom)

3.3. 自己和自己(空元素)

  • 没有 border

  • 没有 padding

  • 没有 inline 元素

  • 没有设置 height 等

例子

  1. 相邻的兄弟元素 margin 重叠

这个想想都应该知道是上面元素的 margin-bottom 和下面元素的 margin-top 产生重叠

html
<div class="bfc-box">
	<div style="height: 20px;background-color: red;margin: 20px 0;"></div>
	<div style="height: 20px;background-color: red;margin: 20px 0;"></div>
	<div style="display: inline-block;width:100px;height: 20px;background-color: red;margin: 20px 0;">inline-block</div>
	<div style="display: inline;width:100px;height: 20px;background-color: red;margin: 20px 0;">inline</div>
	<div style="float: left;width:100px;height: 20px;background-color: red;margin: 20px 0;">float</div>
</div>

效果如下

margin重叠

可以看出确实只有两个都是 block 的普通元素才能产生 margin 的重叠。

  1. 父级和第一个、最后一个子元素(传说中的 margin 穿透)

父元素与定一个元素只有 margin-top 的穿透,对于父元素与最后一个元素那应该是 margin-bottom 的穿透

同时根据 CSS 的盒模型,子元素是存放在父元素的 content 内的,那么父元素还有 padding、border 两个属性,所以父元素没有 padding-top 没有 border-top 这个条件是应该的。 对于第一个条件:父元素非块状格式化上下文,这个也可以想象

html
<div class="box1" style="background-color: #eee;margin: 20px 0;">
	<div style="height: 20px;background-color: red;margin: 20px 0;">box1</div>
</div>
<div class="box2" style="background-color: #eee;margin: 20px 0;overflow: auto;">
	<div style="height: 20px;background-color: red;margin: 20px 0;">box2</div>
</div>
<div class="box3" style="background-color: #eee;margin: 20px 0;border-top: 1px solid green;">
	<div style="height: 20px;background-color: red;margin: 20px 0;">box3</div>
</div>
<div class="box4" style="background-color: #eee;margin: 20px 0;height: 30px;">
	<div style="height: 20px;background-color: red;margin: 20px 0;">box4</div>
</div>
<div class="box5" style="background-color: #eee;margin: 20px 0;height: 30px;">
	<div style="height: 20px;background-color: red;margin: 20px 0;">box5</div>
</div>

效果如下

margin重叠

解析

在 box1 中 box1 盒子没有设置 padding-top border-top,也没有形成 BFC,所以 box1 的 margin:20px 0 与子元素的 margin:20px 0 形成 margin 重叠,导致 margin-top 只有 20px 而不是 20 + 20 = 40px

在 box2 中我们将 box2 设置成了 overflow:auto;形成 BFC,所以父元素与子元素的 margin 重叠不会形成,看到 box2 有上下的 20px 的灰色背景,即 20 + 20 = 40px。

同样在 box3 中我们将 box3 添加了 border-top,所以父元素与子元素的 margin 重叠不会形成,看到 box3 有上的 20px 的灰色背景,即 20 + 20 = 40px。

同样在 box4 中我们将 box4 添加了 height,所以父元素与子元素的 margin 重叠不会形成,看到 box3 有上的 20px 的灰色背景,即 20 + 20 = 40px。

margin:auto 原理

因为元素没有设置宽度或者高度的时候元素会撑满水平或者垂直方向,那么这时候我们强制设置宽高的时候,其还是占用那一部分空间,所以我们的 margin:auto 就可以平分这部分空间

html
<!-- box1中 -->
<div class="box1" style="background-color: #333;">
	<!-- 我们看到margin1是一个block元素,那么他会占据整个水平方向的空间,但是我们这时候设置了width;所以对于block元素来说,他使用了50px的空间,但是庚哥水平空间都是占着,所以这时候我们在设置margin: 0 auto;就会在水平方向水平居中 -->
	<div class="margin1" style="height: 20px;background-color: red;width: 50px; margin: 0 auto;"></div>
	<!-- 对比margin1元素 ,inlineblock元素 将元素设置成了行内块元素,所以他不会占用整个水平空间,所以margin:0 auto谈何而起,他都没有多余的空间去分配的 -->
	<div
		class="inlineblock"
		style="height: 20px;background-color: red;width: 50px; margin: 0 auto; display: inline-block;"
	></div>
	<!-- 对比margin1和inlineblock元素 ,inline元素也不会占用整个水平空间,所以margin:0 auto谈何而起,他都没有多余的空间去分配的 -->
	<div class="inline" style="height: 20px;background-color: red;width: 50px; margin: 0 auto; display: inline;"></div>
	<div class="float" style="height: 20px;background-color: red;width: 50px; margin: 0 auto; float: left;"></div>
</div>
<!-- 这是我们水平垂直居中方法中的一个 -->
<div class="box2" style="display: inline-block;background-color: #333; width: 100px; height: 100px;position: relative;">
	<div
		class="center"
		style="position:absolute;top: 0;left: 0;right: 0;bottom: 0;background-color: red;height: 20px;width: 20px;margin: auto;"
	></div>
</div>
<div class="box3" style="display: inline-block;background-color: #333; width: 100px; height: 100px;position: relative;">
	<div
		class="center"
		style="position:absolute;top: 0;left: 0;right: 0;bottom: 0;background-color: red;width: 20px; margin: auto;"
	></div>
</div>

效果如下

margin:auto 原理

我们在这边着重讲解一下 box2 中元素使用 margin:auto 使水平垂直居中的方法,我们可以看到这段代码重点在这三个方面

  • position:absolute;top: 0;left: 0;right: 0;bottom: 0; 使得子元素 center 占据父元素的所用空间(将 center 伪装成 block 元素)

  • height: 20px;width: 20px; 使得子元素 center 只使用 20px 的宽高空间

  • margin : auto; 这时候设置 margin:auto;就可以使用元素在占据比可视空间多的情况下能够左右平分剩余的空间

margin:auto 原理

所以我们在 box3 中将 center 元素设置成 height: 20px; 的时候,会将元素的高度占据空间变成根可视空间一样大,那么就谈何 margin 平分

margin 负值定位

margin 无效情形解析

  1. inline 水平元素的垂直 margin 无效
  • 非替换元素

  • 正常的书写模式

  1. margin 重叠

  2. display: table-cell 与 margin

  3. position:absolute 与 margin

  • 绝对定位元素在非定位方向的 margin 值无效

解析

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

html
<span style="background-color: #333;margin: 20px;color: #fff;">11111111111</span>
<div style="display: inline;background-color: #333;margin: 20px;color: #fff;">11111111111</div>

效果如下

inline水平元素的垂直margin无效

可以看出对于元素设置成 display:inline ,那么其在垂直方向上的 margin 就会失效。

但是对于一些其他的替换元素 如 img,其在表现上跟 inline 很像,但是其在垂直方向上的 margin 有效。

html
<span style="background-color: #333;margin: 20px;color: #fff;">11111111111</span>
<div style="display: inline;background-color: #333;margin: 20px;color: #fff;">11111111111</div>

效果如下

替换元素水平元素的垂直margin有效

4. position:absolute 的 margin

html
<div class="bfc-box box1" style="background-color: #333;height: 100px;width: 100px;display: inline-block;">
	<div style="position:absolute;top: 20px;left:20px;background-color: red;margin-left:-10px;margin-bottom: -10px;">
		11
	</div>
</div>
<div class="bfc-box box2" style="background-color: #333;height: 100px;width: 100px;display: inline-block;">
	<div style="position:absolute;top: 20px;left:20px;background-color: red;margin-left:-10px;margin-bottom: 100px;">
		11
	</div>
</div>

效果如下

position:absolute 的 margin

我们可以看出对于绝对定位元素,我们设置了top: 20px;left:20px;,所以其margin-left:-10px;有效,而margin-bottom: -10px;是无效的。

但是在实际上其还是有效的,他只是没有改变元素的位置,但是改变了元素的占据空间大小

参考文章