开发者社区> 问答> 正文

重提CSS中外边距折叠问题

避免父子元素边距折叠问题的方式分两类:

为父元素创建块级格式化上下文(BFC)(有一些元素是默认创建了 BFC 的,比如 body 元素),让它的子元素的 margin 值不影响父元素的 margin 值计算
将父元素与它的第一子元素「隔离开」,比如给父元素加 padding 或 border
但是当这个父元素是 body 元素的时候,奇怪的现象发生了,HTML 代码如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <title>testBodyMargin</title>
</head>
<body>
    <div class="father">
        <div class="son"></div>
    </div>
</body>
</html>
CSS 代码如下

html,
body,
div {
    margin: 0;
    padding: 0;
}
html, 
body {
    width: 100%;
    height: 100%;
}
html {
    background: #fff;
}
body {
    background: #a0cbed;
}

.father {
    overflow: hidden;
    width: 200px;
    height: 200px;
    margin: 50px;
    background: #008800;
}

.son {
    width: 50px;
    height: 50px;
    margin: 20px;
    background: #cc0000;
}

现象如图:
screenshot

展开
收起
a123456678 2016-05-26 18:01:30 2041 0
1 条回答
写回答
取消 提交回答
  • 2# body在什么时候能够创建BFC?
    测试一下常规的BFC创建方式:

    给body加上overflow:hidden
    http://jsfiddle.net/0yjxurfv/4/点击预览
    结果:无法触发BFC的创建。

    给body和html同时加上overflow:hidden
    http://jsfiddle.net/0yjxurfv/5/点击预览
    结果:可以触发BFC的创建。

    给body加上display:table、display:inline-block、position:absolute
    http://jsfiddle.net/0yjxurfv/6/点击预览
    结果:可以触发BFC的创建。

    为何呢?W3C CSS2.1中,BFC是这样被定义的:

    Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
    overflow:visible以外的块级元素将创建BFC,除非该值已经扩散到了视口。
    (大部分中文资料都没有译出这个except,直到这个问题被提出,我也没有意识到这个except适用于哪个场景)

    再寻找overflow:hidden的标准:

    UAs must apply the 'overflow' property set on the root element to the viewport.
    When the root element is an HTML "HTML" element or an XHTML "html" element, and that element has an HTML "BODY" element or an XHTML "body" element as a child, user agents must instead apply the 'overflow' property from the first such child element to the viewport, if the value on the root element is 'visible'.
    The 'visible' value when used for the viewport must be interpreted as 'auto'.
    The element from which the value is propagated must have a used value for 'overflow' of 'visible'.
    按语序提取一下(这段颠三倒四颠鸾倒凤的话的)要点:

    UA需要将root元素上的overflow属性置于视口之上;
    overflow扩散行为:当root元素是html元素且overflow为visible,而且html元素有body作为其子元素,UA则需要将第一个body之上的overflow属性应用于视口;
    用于视口的overflow: visible将被解析为overflow: auto
    overflow扩散行为将导致body的使用值为overflow: visible
    我们可以解释本节的三个用例里发生的事情了:

    给body加上overflow:hidden,无法触发BFC创建。
    解释:本用例中body {overflow:hidden} html {overflow: visible}(html为默认overflow),body的overflow:hidden被应用于视口,body的最终使用值为overflow:visible,因此body没有创建BFC。
    给body和html同时加上overflow:hidden,成功触发BFC创建。
    解释:本用例中body, html{overflow:hidden},html的overflow:hidden被用于视口,body的overflow计算值是hidden,因此创建了BFC。
    给body加上display:table、display:inline-block、position:absolute,成功触发BFC创建。
    解释:这些属性都导致body正常创建了BFC。
    LZ的用例2的body没有创建BFC因此没有避免margin折叠,用例3的body成功创建了BFC因此避免了margin折叠。

    2019-07-17 19:16:44
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
零基础CSS入门教程 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载