CSS框盒模型>外边距重叠/BFC

CSS框盒模型>外边距重叠(Mastering margin collapsing)

写京东倒计时模块时碰到此问题, 文字title作为子盒子一移动会牵制父盒子背景一起移动.

原因是外边距重叠(Mastering margin collapsing).

更多详细知识请参考:

MDN 边距重叠(Mastering margin collapsing)

深入理解BFC和Margin Collapse

CSS外边距(margin)重叠及防止方法

块的上外边距(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的时候。
通用解决方式: 浮动/子盒子绝对定位能避免

实操注意:

  1. 注意有设定floatposition=absolute的元素不会产生外边距重叠行为。以上这些内容都是发生在Block-Level的元素,设定floating和absolutely positioned的元素完全不用担心边界重叠的问题。

  2. 设置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>

猜你喜欢

转载自blog.csdn.net/Fky_mie/article/details/114836800