Css规范整理:3.2、常规流布局:块格式化上下文

简介: 块级盒(block level box):参与块格式化上下文的盒,即outer display type 为 block。 块容器盒(block container box):可以建立块格式化上下文 的容器。 块盒(block box):作为块容器的块级盒。

常规流布局

块格式化上下文

其中关键概念有:

  • 块级盒(block level box):参与块格式化上下文的盒,即outer display type 为 block。
  • 块容器盒(block container box):可以建立块格式化上下文 的容器。
  • 块盒(block box):作为块容器的块级盒。

何时建立新的块级格式化上下文:

  • 浮动盒
  • 绝对定位元素
  • 非块盒的块容器(flow-root):inline-blocks、table-cells、table-captions
  • overflow不为visible

布局方式:

竖直方向:

在一个块格式化上下文中,盒在竖直方向上,从包含块顶部一个接一个放置。两个兄弟盒之间的竖直距离由margin决定。同一个块格式化上下文中的相邻块级盒之间的竖直margin会合并。

在一个块格式化上下文中,盒在垂直方向一个接一个地放置,从包含块的顶部开始。两个兄弟盒之间的垂直距离由margin属性决定。同一个块格式化上下文中的相邻块级盒之间的垂直外边距会合并。(margin 合并相关知识在布局介绍完之后再介绍)


  <style>
        .main {
            width: 500px;
            height:500px;
            background: #008000;
            border:1px solid red;
        }
        .main > section {
            background: red;
            height: 100px;
            margin-top:10px;
            margin-bottom:10px;
        }
        .main > div {
            background: yellow;
            height:200px;
            margin-top:20px;
        }
    </style>
    <div class="main">
        <section>块级盒1</section>
        <div>块级盒2</div>
    </div>

垂直方向上的 margin 控制块级盒垂直方向上的距离。

水平方向:

在一个块格式化上下文中,每个盒的左外边界(left outer edge)挨着包含块的左外边界(对于从右向左的格式化,右外边界挨着),即使存在浮动(尽管一个盒的行框可能会因为浮动而收缩 译注:环绕浮动元素放置的行框比正常的行短一些),这也成立。

除非该盒建立了一个新的块格式化上下文(这种情况下,该盒自身可能会因为浮动变窄)


<style>
    body{
        direction:rtl
    }
    .fl{
        float: right;
        height:120px;
        width:100px;
        border: yellow 5px solid;
        color: blue
    }
    .main{
        height:500px;
        background: #008000;
    }
    .content{
        border: red 10px solid;
          height:100px;
    }
    .content2{
        border: purple 10px solid;
          height:100px;
    }
</style>
<div>
    <div class="main">
        <span class="fl">浮动盒内容</span>
        <div class="content">content块级盒内容
             <span class="fl" style="border-color:orange">内部浮动盒内容</span>
        </div>

        <span class="fl">浮动盒内容</span>
        <div class="content2" style="overflow:hidden">
          	content2块级盒内容 
             <span class="fl" style="border-color:orange">内部浮动盒内容</span>
        </div>
    </div>
</div>

  1. 以上代码,改变了格式化方向(direction:rtl),所以块级盒右边界对齐,左边界允许溢出。
  2. 上述代码的块级盒 content,在流内(即 inner display type = flow)块级盒右边界对齐,内部行盒宽度因浮动收缩,但块级盒本身宽度不变
  3. 上述代码的块级盒 content2,因为设置了overflow不为visible ,所以建立了新的格式化上下文,因此该盒因浮动变窄,外部浮动盒不能影响该块级盒的行盒,内部浮动盒溢出部分被隐藏(隐藏是overflow:hidden的作用)

Margin 合并:

同一个块格式化上下文中的相邻块级盒之间的垂直外边距会合并。

以下是规范的内容(可忽略):

CSS中,两个或多个盒(可能但不一定是兄弟)的相邻的margin会被结合成一个margin。外边距按这种方式结合叫做合并(collapse),产生的结合的外边距叫做折叠外边距(collapsed margin 译注:这里译作折叠表示结果,与合并的动作区分开)

相邻的垂直外边距会合并,除了:

水平margin不会合并

两个margin是相邻的,当且仅当:

  • 都属于流内(in-flow)块级盒,处于同一个块格式化上下文
  • 没有行框(line box),空隙,内边距和边框把它们隔开(注意,因此某些0高度行框(见9.4.2)会被忽略)
  • 都属于垂直相邻框边界(vertically-adjacent box edges),即形成下列某一对:
  • 盒的上边距与其第一个流内(in-flow)孩子的上边距
  • 盒的下边距与其下一个流内紧挨着的兄弟的上边距
  • 最后一个流内孩子的下边距与其height计算值为'auto'的父元素的下边距
  • 盒的上边距和下边距,要求该盒没有建立新的块格式化上下文,并且'min-height'计算值为0,'height'计算值为0或'auto',还没有流内孩子

折叠外边距也能与另一个外边距相邻,只要其外边距的任意一部分与那个外边距相邻就算

注意 相邻外边距也可以由不具兄弟或祖先关系的元素生成

注意 上面的规则表明:

  • 浮动的盒与任何其它盒之间的margin不会合并(甚至一个浮动盒与它的流内子级之间也不会)
  • 建立了新的块格式化上下文的元素(例如,浮动盒与'overflow'不为'visible'的元素)的margin不会与它们的流内孩子合并
  • 绝对定位的盒的margin不会合并(甚至与它们的流内子级也不会)
  • inline-block盒的margin不会合并(甚至与它们的流内子级也不会)
  • 流内块级元素的bottom margin总会与它的下一个流内块级兄弟的top margin合并,除非该兄弟(元素)具有间隙
  • 流内块级元素的top margin会与它的第一个流内块级子级的top margin合并,条件是该元素没有上边框和上内边距,并且其孩子不具有间隙
  • 一个'height'为'auto'并且'min-height'为0的流内块级盒的bottom margin会与它的最后一个流内块级子级的bottom margin合并,条件是该盒没有下内边距和下边框,并且其孩子的下外边距没有与具有间隙的上外边距合并
  • 盒自身的外边距也会合并,条件是'min-height'属性为0,既没有上下边框,也没有上下内边距,'height'为0或'auto',且不含行框的话,那么其所有流内孩子的外边距(如果存在的话)都会合并

当两个或者更多的margin合并时,产生的margin宽度为被合并的外边距宽度中的最大值。至于负margin,就从正相邻margin的最大值中减去负相邻margin的绝对值的最大值。如果没有正margin,就用0减去相邻margin的绝对值的最大值

如果盒的上下外边距相邻,那么外边距合并时可能会穿过它(it is possible for margins to collapse through it)。这种情况下,该元素的位置取决于它与其它外边距被合并了的元素的关系

  • 如果该元素的外边距与其父元素的上外边距合并了,盒的上边框边界被定义为与其父元素的相同
  • 否则,要么该元素的父元素没参与外边距合并,要么只涉及其父元素的下外边距。该元素上边框边界的位置与元素下边框非0时的位置相同

注意,被折叠外边距穿过的元素的位置不影响其它外边距正要被合并的元素的位置,其上边框边界的位置仅用于布局这些元素的后代元素

⭐要点

  • 同一个块格式化上下文:因此建立了 新的块格式化上下文的该盒 不与任何盒合并
    • 根元素的margin 不合并(<html></html>)
    • 浮动的盒与任何其它盒之间的margin不会合并(一个浮动盒与它的流内子级之间也不会)
    • 绝对定位的盒的margin不会合并(与它们的流内子级也不会)
    • 非块盒的块容器(flow-root):inline-block、table-cells、table-captions
      • inline-block盒的margin不会合并(与它们的流内子级也不会)
    • overflow不为visible
  • 相邻:margin 之间有间隔 就不可以进行合并。相邻一词没有考虑元素之间的关系,考虑的是margin 的位置关系
    • 没有行框(line box),空隙,内边距和边框把它们隔开。
  • 块级盒:行内级不可以。
  • 垂直:margin left 和 margin right 不受影响。

例子:(不完全展示上述的可能性,)


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        html {
            margin: 8px 0;
            /* 根元素上的margin 不合并*/
        }

        body {
            margin: 8px;
            /** 
             * 设置这个的原因是因为希望块级有内容的时候不是由字体撑起来内容的高度,
             * 是以行高撑起内容的高度,
             * 目的以方便计算margin的高度
             **/
            font-size: 12px;
            /**确定字体的大小**/
            line-height: 20px;
            /** 保证行高大于字体的大小**/
        }

        .div {
            margin: 10px 0;
        }
    </style>
</head>
<!-- margin-top:8px 不合并 -->
<body>
    <!-- margin-top:10px -->
    <div class="div" style="overflow:auto;"><!-- 建立新的格式化上下文 -->
        <!-- margin-top:10px 不合并 -->
        <div class="div">
            div内容<!-- line-height:20px -->
        </div>
        <!-- margin-bottom:10px 不合并 -->
    </div>
    <!-- margin-bottom:10px -->
    body内容<!-- line-height:20px -->

    <div class="div"></div>
</body><!-- margin top 与 bottom:10px 与 body margin-bottom:8px 合并 = margin-bottom:10px -->

</html>

规范是错误的:空隙(clearance)并不能阻止margin 合并。

<style>
    body {
        direction: rtl
    }

    .fl {
        float: right;
        height: 120px;
        width: 100px;
        border: yellow 5px solid;
        color: blue
    }

    .main {
        height: 500px;
        background: yellowgreen;
        position: relative;
    }

    .content {
        border: red 10px solid;
        height: 100px;
        margin-bottom:100px;
    }

    .content2 {
        clear: both;
        border: purple 10px solid;
        height: 100px;
        margin-top:120px;
    }
</style>
<div>
    <div class="main">
        <span class="fl">浮动盒内容</span>
        <div class="content">content块级盒内容
            <span class="fl" style="border-color:orange">内部浮动盒内容</span>
        </div>

        <div class="content2" style="overflow:auto">
            content2块级盒内容
            <span class="fl" style="border-color:orange">内部浮动盒内容</span>
        </div>
    </div>
</div>

原文发布时间为:2018年02月10日
原文作者:雕刻零碎 

本文来源:开源中国 如需转载请联系原作者

目录
相关文章
|
22天前
|
缓存 前端开发
前端代码整洁与规范之CSS篇
【4月更文挑战第2天】 前端代码整洁与规范之CSS篇
41 4
|
23天前
|
前端开发 开发者 容器
彻底学会CSS grid网格布局
【4月更文挑战第1天】 彻底学会CSS grid网格布局
16 0
|
3月前
|
前端开发 JavaScript
Vue中使用纯CSS实现全屏网格加渐变色背景布局
Vue中使用纯CSS实现全屏网格加渐变色背景布局
81 0
|
3月前
|
设计模式 前端开发 开发者
css 三栏布局的实现
css 三栏布局的实现
34 0
|
14天前
|
前端开发 开发者 容器
【掰开揉碎】详解 CSS3 Grid 布局
【掰开揉碎】详解 CSS3 Grid 布局
N..
|
1月前
|
前端开发 容器
DIV+CSS网页布局
DIV+CSS网页布局
N..
8 0
|
1月前
|
前端开发 UED 开发者
探索前端开发中的CSS布局技巧
本文将介绍一些在前端开发中常用的CSS布局技巧,包括盒模型、浮动布局、弹性布局和栅格系统等。通过学习这些技巧,开发者可以更加灵活地控制页面的布局,提升用户体验和界面的美观性。
|
1月前
|
前端开发 JavaScript 开发者
编程笔记 html5&css&js 014 网页布局框架
编程笔记 html5&css&js 014 网页布局框架
|
1月前
|
前端开发 开发者
编程笔记 html5&css&js 013 HTML布局
编程笔记 html5&css&js 013 HTML布局
|
2月前
|
容器
请解释一下 CSS3 的 Flexbox(弹性盒布局模型), 以及适用场景?
请解释一下 CSS3 的 Flexbox(弹性盒布局模型), 以及适用场景?