前言

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

问题

测试代码如下:

<!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. 如何在centos环境下搭建java环境

    在CentOS上安装Java环境:[1]使用yum安装java 现阶段做企业级项目开发一般都采用Java语言.开发的项目需要放在服务器上运行测试,若以CentOS系统为服务器系统,首先要解决就是Cen ...

  2. HDU 5117 Fluorescent (数学+状压DP)

    题意:有 n 个灯,初始状态都是关闭,有m个开关,每个开关都控制若干个.问在m个开关按下与否的2^m的情况中,求每种情况下亮灯数量的立方和. 析:首先,如果直接做的话,时间复杂度无法接受,所以要对其进 ...

  3. C++ 数据封装和抽象

    C++ 数据抽象 数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节. 数据抽象是一种依赖于接口和实现分离的编程(设计)技术. 让我们举一个现实生活中的真实例子 ...

  4. 7.使用ZookeeperNet进行CDU操作参数详解

    一.创建,删除,更新 1. zkCli.sh 中使用命令执行. 2. 学会查看api文档 zookeeper C# driver 官方文档,文档是java代码的. http://zookeeper.a ...

  5. 利用ROW_NUMBER中的partition by 删除重复Key的数据

    With temp As ( Select ROW_NUMBER() over(partition by LogisticsPlan order by createon) rowID,ID from ...

  6. EJB3.0 EJB开发消息驱动bean

    (7)EJB3.0 EJB开发消息驱动bean JMS 一: Java消息服务(Java Message Service) 二:jms中的消息 消息传递系统的中心就是消息.一条 Message 由三个 ...

  7. 开源应用框架BitAdminCore:更新日志20180817

    索引 NET Core应用框架之BitAdminCore框架应用篇系列 框架演示:http://bit.bitdao.cn 框架源码:https://github.com/chenyinxin/coo ...

  8. Android 多线程基础

    需要注意几个概念:Runnable,Thread,Handler. 1. Runnable只是一个接口,里面包含run()函数.所以Runnable本身不会开启线程. 2. Thread实现Runna ...

  9. 【文文殿下】浅谈KMP算法next数组与循环节的关系

    KMP算法 KMP算法是一种字符串匹配算法,他可以在O(n+m)的时间内求出一个模式串在另一个模式串下出现的次数. KMP算法是利用next数组进行自匹配,然后来进行匹配的. Next数组 Next数 ...

  10. Myeclipse修改项目名称发布后web Context root名称无法修改

    选中项目,右键--->Properties--->在搜索框搜索:deployment as  然后点击显示出的搜索项.修改右侧视图的Web Context Root名称即可. 如图: