CSS框盒模型>外边距重叠(Mastering margin collapsing)
写京东倒计时模块时碰到此问题, 文字title作为子盒子一移动会牵制父盒子背景一起移动.
原因是外边距重叠(Mastering margin collapsing).
更多详细知识请参考:
块的上外边距(margin-top)和下外边距(margin-bottom)有时合并(折叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个),这种行为称为边距重叠(Mastering margin collapsing)。
文章目录
什么是BFC(Block formatting contexts)
简单来说,BFC 就是一种属性,这种属性会影响着元素的定位以及与其兄弟元素之间的相互作用。
从样式上看,具有 BFC 的元素与普通的容器没有什么区别,但是从功能上,具有 BFC 的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器没有的一些特性,例如可以包含浮动元素,上文中的第二类清除浮动的方法(如 overflow 方法)就是触发了浮动元素的父元素的 BFC ,使到它可以包含浮动元素,从而防止出现高度塌陷的问题。
如何触发BFC属性
w3c规范中的BFC定义:
浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建新的BFC(块级格式上下文)。
在BFC中,盒子从顶端开始垂直地一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin 值所决定的。在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠。
在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘)。
边距重叠的发生
当元素没有被触发BFC属性的时候, 就可能会发生边距重叠, 带来一些问题
边距重叠带来的常见问题有:
-
相邻盒子. 上一个设置margin-bottom, 下一个设置margin-top, 两者距离会挑选最大边界范围留下
-
父子盒子. 给子盒子设置margin-top, 会使得父盒子一起移动
边距重叠会发生的三种情形:
外边距合并发生情形 | 合并规则/合并条件 | 解决方式-专用/通用 |
---|---|---|
1. 垂直相邻(兄弟)盒子之间 | a.如果两个外边界值都为正,则两个盒子垂直方向的距离是两个外边距值中的最大的值。b. 如果一正一负,则是正边界值减去负边距值中的绝对值。 c. 如果都是负数,则用零减去绝对值最大的负边距(只有外边距才可以为负值,内边距不允许为负值) | a. 在设置margin-top/bottom值时统一设置上或下 |
2. 嵌套(父子)盒子之间 | 如果没有边框border ,内边距padding ,行内内容,也没有创建块级格式上下文或清除浮动来分开一个块级元素的上边界margin-top 与其内一个或多个后代块级元素的上边界margin-top ;或没有边框,内边距,行内内容,高度height ,最小高度min-height 或 最大高度max-height 来分开一个块级元素的下边界margin-bottom 与其内的一个或多个后代后代块元素的下边界margin-bottom ,则就会出现父块元素和其内后代块元素外边界重叠,重叠部分最终会溢出到父级块元素外面。 | a. 给父盒子设置透明border; b.用父盒子padding值隔开父子; c. 父盒子设置overflow: hidden; d.子盒子display: inline-block |
3. 空的块级元素 | 当一个块元素上边界margin-top 直接贴到元素下边界margin-bottom 时也会发生边界折叠。这种情况会发生在一个块元素完全没有设定边框border 、内边距paddng 、高度height 、最小高度min-height 、最大高度max-height 、内容设定为inline或是加上clear-fix的时候。 | |
通用解决方式: 浮动/子盒子绝对定位能避免 |
实操注意:
-
注意有设定float和position=absolute的元素不会产生外边距重叠行为。以上这些内容都是发生在Block-Level的元素,设定floating和absolutely positioned的元素完全不用担心边界重叠的问题。
-
设置padding值要同时改用CSS3盒子模型, 补上以下代码以免padding撑大盒子
如图, 圈主部分是被padding撑开的盒子
/* CSS3盒子模型 */
* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
}
测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>秒杀倒计时牌子</title>
<style>
/* 特殊样式补充: */
/* CSS3盒子模型 */
* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
}
* {
margin: 0px;
padding: 0px;
}
a {
color: #666;
text-decoration: none;
}
.topbox {
width: 300px;
height: 20px;
font-size: 14px;
text-align: center;
background-color: pink;
}
.seckill-countdown {
/* position: relative; */
/* float: left; */
display: block;
width: 190px;
height: 260px;
color: #fff;
background-color: #e83632;
background-image: url(images/jd_seckill.png);
background-size: contain;
background-repeat: no-repeat;
padding-top: 31px;
overflow: hidden;
border-top: 31px pink;
}
.countdown-title {
/* position: absolute;
top: 31px;
left: 0px; */
width: 100%;
font-size: 30px;
font-weight: 700;
text-align: center;
/* margin-top: 31px; */
}
</style>
</head>
<body>
<div class="topbox">
这里是顶端
</div>
<a href="https://miaosha.jd.com/" class="seckill-countdown" aria-label="京东秒杀">
<div class="countdown-title">
京东秒杀
</div>
<!-- <span class="hour">hour</span>
<span class="minute">minute</span>
<span class="second">second</span> -->
</a>
<!-- <script>
var h = document.querySelector('.hour');
var m = document.querySelector('.minute');
var s = document.querySelector('.second');
var date = new Date();
</script> -->
</body>
</html>