前言

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

问题

测试代码如下:

<!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. alter table导致的mysql事务回滚失败

    今天做数据迁移, 发现事务有时候可以回滚, 有时候不可以回滚, 最后一点点调试发现中间有段修改表结构的语句, 最终导致回滚失败. 1.MySQL最常用的两个表类型: InnoDB和MyISAM.MyI ...

  2. IntelliJ IDEA 2017版 导入maven项目需要的包

    1.选中项目,鼠标右键--->maven---->Reimport

  3. HDU 3157 Crazy Circuits (有源汇上下界最小流)

    题意:一个电路板,上面有N个接线柱(标号1~N)   还有两个电源接线柱  +  - 然后是 给出M个部件正负极的接线柱和最小电流,求一个可以让所有部件正常工作的总电流. 析:这是一个有源汇有上下界的 ...

  4. web.xml配置中的log4jRefreshInterval讲解

    采用spring框架的项目如何使用log4j在spring中使用log4j,有些方便的地方, 1.动态的改变记录级别和策略,即修改log4j.properties,不需要重启web应用,这需要在web ...

  5. Xcode6制作动态及静态Framework[repost]

    有没有写SDK或者要将一些常用的工具类做成Framework的经历? 你或许自己写脚本完成了这项工作,相信也有很多的人使用 iOS-Universal-Framework ,随着xCode6的发布,相 ...

  6. spring注解@Value取不到值【转】

    spring注解@Value取不到值 今天在一个项目中发现一个情况,在Service中取不到name值,直接输出了{name}字符串,找了好久,最后在一篇文章中找到解决方案. 解决这个问题的一篇文章( ...

  7. UVA 11235 Frequent values 线段树/RMQ

    vjudge 上题目链接:UVA 11235 *******************************************************大白书上解释**************** ...

  8. cordova/webapp/html5 app 用corsswalk替换内核,优化安卓webview

    Crosswalk与WebView的不同 为什么要用corsswalk?由于cordova应用在安卓上运行的时候,都是调用的手机webview,而在不同的安卓机.不同版本的系统上,webview的性能 ...

  9. 微服务中的健康监测以及其在ASP.NET Core服务中实现运行状况检查

    1 .什么是健康检查? 健康检查几乎就是名称暗示的.它是一种检查您的应用程序是否健康的方法.随着越来越多的应用程序转向微服务式架构,健康检查变得尤其重要(Health Check).虽然微服务架构有很 ...

  10. Jenkins RestAPI调用出现Error 403 No valid crumb was included in the request

    方法一(不推荐): 在jenkins 的Configure Global Security下 , 取消“防止跨站点请求伪造(Prevent Cross Site Request Forgery exp ...