前言

之前在前端开发的过程中,都没有遇到外边距合并的问题(其实是因为大多时候都直接用前端样式库(〃'▽'〃)),这一次需要动手排一个页面,也挺简单,但是遇到了一个奇怪的问题,所以学习记录一下。

问题

测试代码如下:

<!doctype html>
<html class="no-js" lang=""> <head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>test</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<style>
* {
margin: 0;
padding: 0;
} body {
max-width: 750px;
margin: 0 auto;
} .div1 {
background: yellow;
height: 200px;
} .div2 {
background: blue;
height: 200px;
} .div2Child {
background: red;
height: 100px;
}
</style> <body>
<div class="div1">我是吃瓜群众</div>
<div class="div2">
<div class="div2Child" style="margin-top: 50px">我是子div</div>
<p style="color: white">我是父div</p>
</div>
</body> </html>



子div设置了margin-top之后,父div也跟着一起margin-top了。

原因如下:

Margin Collapsing 外边距合并

块的顶部外边距和底部外边距有时被组合(折叠)为单个外边距,其大小是组合到其中的最大外边距,这种行为称为外边距塌陷(margin collapsing),或外边距合并。

外边距合并的3中基本原因:

1、相邻的元素

毗邻的两个兄弟元素之间的外边距会合并

2、块级父元素与其第一个/最后一个子元素

  • 如果块级父元素中,不存在border, padding, inline part, block formatting context created, or clearance 来隔离第一个子元素的上边距,就会发送外边距合并现象。
  • 如果块级父元素,不存在border, padding, inline content, height, min-height, max-height来隔离下边距,则会和最后一个子元素合并。

3、空块元素

如果存在一个空的块级元素,不存在 border、padding、inline content、height、min-height来隔离上下外边距,那么它的上下外边距将会合并。

  • 当都为正数时,取两者中较大者。
  • 当都为负数时,取绝对值较大者。
  • 当一正一负时,取相加之和。
  • 外边距设为0时,这些规则也仍旧生效。

BFC(Block Formatting Context 块格式化上下文)与元素外边距合并 :

  • 当两个元素属于不同的BFC时,这两个元素的外边距不会合并
  • 但在同一个BFC内,两个相邻元素的外边距仍会合并。

Block Formatting Context 块格式化上下文

一个块格式化上下文(block formatting context) 是Web页面的可视化CSS渲染出的一部分。它是块级盒模型出现的区域,也是浮动元素与其他元素进行交互的区域。

一个块格式化上下文由以下之一创建:

  • 根元素或一些包含它的元素
  • 浮动元素 (元素的 float 不是 none)
  • 绝对定位元素 (元素的 position 为 absolute 或 fixed)
  • 内联块 (元素具有 display: inline-block)
  • 表格单元格 (元素具有 display: table-cell,HTML表格单元格默认属性)
  • 表格标题 (元素具有 display: table-caption, HTML表格标题默认属性)
  • display隐式创建的匿名表格列,包括table, table-row, table-row-group, table-header-group, table-footer-group (这些都是html的默认样式), or inline-table
  • 具有overflow 且值不是 visible 的块元素,
  • display: flow-root
  • flex 项目
  • grid 项目
  • 多列容器(column-count 和 column-width 不是 auto, 包括 column-count: 1的元素)
  • column-span: all 应当总是会创建一个新的格式化上下文,即便具有 column-span: all 的元素并不被包裹在一个多列容器中。

解决方案

知道了问题原因所在,以及了解了相关原理,就很好办了。

1、给div2设置border

为了不改变div2的大小,还需将设置 box-sizing为border-box将padding和border包含在定义的width和height之内

.div2 {
background: blue;
height: 200px;
border-top: 1px solid transparent;
box-sizing: border-box;
}

2、去掉div2Child的margin,改为设置div2的padding

.div2 {
background: blue;
height: 200px;
padding-top:50px;
box-sizing: border-box;
}

3、div2设置为内联元素

.div2 {
background: blue;
height: 200px;
display: inline-block;
width: 100%;
}

4、清除浮动

所有浮动元素包含在div2内,增加样式clearfix

.clearfix::before, .clearfix::after{
overflow: hidden;
display: table;
visibility: hidden;
content: '';
clear: both;
}

或者创建一个新的BFC,使其在不同的上下文中,不合并外边距。

5、给div2设置Position

.div2 {
background: blue;
height: 200px;
position: absolute;
width: 100%;
max-width: 750px;
}

6、给div2设置float,注意后面的元素需要clear浮动

.div2 {
background: blue;
height: 200px;
float: left;
width: 100%;
}

7、给div2设置display

.div2 {
background: blue;
height: 200px;
display: inline-block;
/*display: table;*/
width: 100%;
}

8、给div2设置flex

.div2 {
background: blue;
height: 200px;
display: flex;
flex-direction: column;
}

9、给div2设置overflow

.div2 {
background: blue;
height: 200px;
overflow: hidden;
}

万变不离其宗

参考

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing

https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context

CSS外边距合并&块格式上下文的更多相关文章

  1. CSS外边距合并的几种情况

    CSS外边距合并的几种情况 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距.合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. 外边距在CSS1中就有 The width ...

  2. css外边距合并和z-index的问题

    参考这篇文章, 将外边距的 折叠 参考这篇文章, 将bfc的生成, bfc的应用 参考这篇文章 position: absolute的元素, 仍然具有内填充padding和border边框属性样式, ...

  3. CSS外边距合并(塌陷/margin越界)

    原文 简书原文:https://www.jianshu.com/p/5f18f12cd162 大纲 1.什么是外边距合并?(折叠外边距) 2.外边距带来的影响 3.折叠的结果 4.产生折叠的原因 5. ...

  4. CSS 外边距合并

    外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. 外边距合并 外边距合并(叠加)是一个相当简单的概念.但是,在实践中对网 ...

  5. CSS外边距合并问题

    今天无意中碰到了外边距合并的问题,于是便研究了一下.这里做个笔记. 所谓外边距合并,指的是当两个垂直外边距相遇时,它们将形成一个外边距.合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. ...

  6. CSS 外边距合并。

    <div id = "parent"> <div id = "child"> demo </div> </div> ...

  7. CSS框模型(框模型概述、内边距、边框、外边距、外边距合并)

    CSS 框模型概述 CSS 框模型 (Box Model) 规定了元素框处理元素内容.内边距.边框 和 外边距 的方式. 元素框的最内部分是实际的内容,直接包围内容的是内边距.内边距呈现了元素的背景. ...

  8. CSS min-height不能解决垂直外边距合并问题

    垂直外边距合并有一种情况是嵌套元素的垂直外边距合并,当父级元素没有设定外边距时,在顶部或者底部边缘的子元素的垂直外边距就会和父级的合并,导致父级也有了“隐形”的垂直外边距. 当父级元素的min-hei ...

  9. 关于CSS inline-block、BFC以及外边距合并的几个小问题

    CSS inline-block和BCF对于初学者来说,总是弄不太明白,下面记录下我在学习这块知识的过程中遇到的几个问题,供大家参考,有不足的地方,欢迎大家批评指正. 一.在什么场景下会出现外边距合并 ...

随机推荐

  1. XtrasReport 标签打印

    var lblList = new List<product_LblPrt_tmp>(); using (JL_MFGEntities ctx = new JL_MFGEntities() ...

  2. OpenGl中的Nurbs B样条曲面绘制

    NURBS 贝塞尔曲线的缺点是当我们增加很多控制点的时候,曲线变得不可控,其连续性会变差差.如果控制点很多(高阶曲线),当我们调整一个控制点的位置,对 整个曲线的影响是很大的.要获得更高级的控制,可以 ...

  3. Java反射API研究(3)——java.lang.Class<T>

    对于反射来说,Class是核心,任何反射的对象都需要通过Class来获得. Class 类的实例表示正在运行的 Java 应用程序中的类和接口.枚举是一种类,注释是一种接口.每个数组属于被映射为 Cl ...

  4. Python 爬虫入门实例(爬取小米应用商店的top应用apk)

    一,爬虫是什么? 爬虫就是获取网络上各种资源,数据的一种工具.具体的可以自行百度. 二,如何写简单爬虫 1,获取网页内容 可以通过 Python(3.x) 自带的 urllib,来实现网页内容的下载. ...

  5. mysql 删表引出的问题

    背景 将测试环境的表同步到另外一个数据库服务器中,但有些表里面数据巨大,(其实不同步该表的数据就行,当时没想太多),几千万的数据!! 步骤 1. 既然已经把数据同步过来的话,那就直接delete掉就行 ...

  6. 3:C#异步WaitAll的使用

    编写界面如图: private async void button1_Click(object sender, EventArgs e) { #region 单个执行的异步,效率慢 HttpClien ...

  7. 使用WebService调用第三方服务

    场景 某个系统服务由第三方提供,我方要使用到这个这个服务,就可以使用WebService的方式. 什么是WebService 关于什么WebService,官方是这么解释的: Web service是 ...

  8. 「BZOJ1426」收集邮票

    题目链接 戳我 \(Solution\) 我们首先转换一下问题: 假设我们进行了k轮得到了所有种类的邮票 则所花费用为: \[(1+2+5+...+k)=\frac{(1+k)*k}{2}=\frac ...

  9. python 杂谈

    python 当前文件导入自定义模块的时候,会默认执行一遍 python使用的变量必须是已经定义或者声明过的.

  10. Spark Streaming初步使用以及工作原理详解

    在大数据的各种框架中,hadoop无疑是大数据的主流,但是随着电商企业的发展,hadoop只适用于一些离线数据的处理,无法应对一些实时数据的处理分析,我们需要一些实时计算框架来分析数据.因此出现了很多 ...