CSS进阶之 盒模型的高级属性 与 何为BFC?

盒模型的box-sizing属性:

在网页设计开发中,盒模型是掌握布局和格式化网页内容的最先需要了解的基本概念。

而每个HTML元素都可以被视为一个矩形的盒子(盒模型),一般由4个部分组成,即:内容区域(content)、内边距(padding)、边框(border)和外边距(margin)。这些部分共同决定了元素在页面上的尺寸和空间分布,并且每个盒子都有其单独的样式。

但是盒模型却有两种不同的box-sizing(计算方式):标准盒模型与IE盒模型(也称为怪异盒模型)。

举这两种模型最简单的例子:

创建三个简单的盒模型,并且设置其基本的宽高、背景颜色与边跨颜色。但是第一个盒子不指定其box-sizing属性(计算方式),而另外两个分别指定为标准盒模型 (content-box)与IE盒模型 (border-box),不妨来看看有何区别。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Box</title>
    <style>
        *{ /* 通用选择器(*) */
            margin: 0;
            padding: 0; 
        }
        .box1, .box2, .box3 {
            width: 100px;
            height: 100px;
            padding: 10px;
            border: 1px solid red;
            background-color: green;
        }
        .box2 {
            /* IE盒模型 */
            box-sizing: border-box;
        }
        .box3 {
            /* 标准盒模型 */
            box-sizing: content-box;
        }
    </style>
</head>
<body>
    <div class="box1"></div>
    <div class="box2"></div>
    <div class="box3"></div>
</body>
</html>

很明显,box1与box3的大小是一样的,而box2明显较小,这也就体现两种计算方式的差距。

  • 标准盒模型:在常态下是默认值,设置的widthheight仅应用于内容区域,也就是box1和box3的content100px(显示的总宽还需要包含额外设置的padding,border,margin)
  • IE盒模型: 设置的widthheight包含了padding,border,margin部分,所以图中box2的content100px (w/h) - 10px * 2 (padding) - 1px * 2 (border) = 78px

display属性:

默认状态下是由标签来决定元素的类型与其在页面上的布局,但是有没有一个属性能直接改变其标签类型呢?有的兄弟,有的!那就是display属性了。

举两个最简单的例子:

比较常用的两种元素类型就是块级元素 (block)与行内元素(inline)了。

  • 块级元素:默认占据父容器的整个宽度,每个块级元素从上到下独占一行,可以修改宽度、高度、内边距和边框等属性。
  • 行内元素:只占据内容所需的宽度,每个行内元素从左到右排列,不能直接设置宽高。
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        div {
            width: 100px;
            height: 100px;
            border: 1px solid red;
            padding: 10px 20px;
            /* 将其转换为行内元素 */
            display: inline; 
        }
        span {
            width: 100px;
            height: 100px;
            /* 将其转换为块级元素 */
            display: block;
            background-color: green;
        }
    </style>
</head>
<body>
    <div>123</div>
    <span>11</span><span>222</span>
</body>
</html>

由于元素类型的转换,也就导致了虽然为<div>容器设置了宽高,但是其只占据了其内容123所需大小。而由于文档流导致<span>容器紧跟在<div>容器后,但是<div>paddingborder仍然会对周围环境造成影响,所以产生了容器交集。

BFC(块级格式化上下文)详解:

什么是BFC?

BFC(Block Formatting Context,块级格式化上下文)是 CSS 中的一个独立渲染区域 ,其不受外界影响,同样也不影响外界,并且决定了如何布局块级盒子以及它们之间的相互作用。

HTML 和 Body 的 BFC

  • HTML 元素:HTML元素作为根元素,构成了整个页面的基础布局环境,所以其是页面的第一个也是最顶级的 BFC。而其他元素是镶嵌在根元素内,并且受到BFC影响(Body元素也包括在内)
  • Body 元素 :其在默认情况下是包含在HTML元素内的,但是通过一些特定的CSS属性(例如:overflowfloat)来创建自己的BFC,并且独立于HTML元素布局。

触发新的 BFC

这里举例以下几种情况会创建新的 BFC:

  • position 值为 absolutefixed
  • display 值为 inline-block, table-cell, table-caption, flex, inline-flex, grid, inline-grid
  • overflow 值不是 visible(如 hidden, auto, scroll)。

BFC 的特性

  • 在一个 BFC 内,块级元素会从上到下依次排列,并且默认宽度为 100%。
  • 同一个 BFC 中盒子的垂直方向的距离由 margin 决定,相邻盒子的margin会发生重叠(塌陷),较大的 margin 值生效。
  • 每个元素的 margin-left 与包含块的 border-left 相接触,即使存在浮动也是如此。
  • BFC 是一个独立的渲染区域,其内部布局不会受到外部元素的影响。
  • 当计算 BFC 的高度时,浮动元素的高度也会被考虑在内,并且阻止其他元素与浮动元素重叠。

BFC 特性有何用处

解决外边距重叠:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>BFC</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            width: 200px;
            height: 200px;
            background-color: lightblue;
            border: 1px solid #000;
        }
        .box1 {
            margin-bottom: 50px;
        }
        .box2 {
            margin-top: 30px;
        }
    </style>
</head>
<body>
    <div class="box box1">Box1</div>
    <div>
        <div class="box box2" >Box2</div>
    </div>
</body>
</html>

如果没有创建新的 BFC,.box1.box2 之间的实际间距将是 50px(较大的外边距值),而不是 80px(50px + 30px),如图:

修改:

但是对.box2外部的div进行设置就可以解决这个问题。

html 复制代码
<div style="overflow:hidden;">
    <div class="box box2" >Box2</div>
</div>

由于 .box2 被包裹在一个设置了 overflow: hidden; 的父元素中,这创建了一个新的 BFC,阻止了外边距重叠。

清除float而导致的高度坍缩:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Float Example</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        .container {
            border: 2px solid black;
            padding: 10px;
            width: 300px;
            /* overflow: hidden; */
        }
        .float-left {
            float: left;
            width: 100px;
            height: 100px;
            background-color: lightblue;
            margin: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="float-left">浮动元素</div>
    </div>
</body>
</html>

上述代码中设置了<float-left>转换为浮动元素,而浮动元素会脱离正常的文档流,从而导致了父元素高度坍缩。但是如果在<container>中添加了overflow: hidden(清除浮动),父元素计算高度就会包括浮动元素。如图:

解决浮动元素带来的布局问题:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
  .container {
    border: 2px solid black;
    padding: 10px;
  }

  .float-box {
      float: left;
      width: 150px;
      height: 100px;
      background-color: lightblue;
      margin: 10px;
  }

  .bfc-box {
      width: 300px;
      height: 100px;
      background-color: lightgreen;
      /* overflow: auto;  */
  }
  </style>
</head>
<body>
  <div class="container">
    <div class="float-box">这是一个左浮动的盒子</div>
    <div class="bfc-box">这是一个创建了 BFC 的盒子</div>
  </div>
</body>
</html>

由于浮动元素脱离了原本的文档流,所以会导致bfc-boxfloat-box,发生重叠,样式如图:

而为了使浮动元素不再影响父元素中的其他子元素,就可以为其他子元素添加overflow: auto等使其创建自身的 BFC,这样就使其形成一个独立的渲染区域,不会与浮动元素相互干扰。例如在上述代码中重新启用overflow: auto。如图:

注:如果bfc-box位于float-box下方也是正常的,因为当页面宽度不足以支撑这两个盒子水平放置时,由于float-box的浮动特性导致bfc-box会根据可用空间调节自身位置。

当然如果再在bfc-box中创建新的块级元素或行内元素都不会被float-box影响。

格式上下文(Formatting Context)

常见的格式上下文包括:

  • BFC(块级格式化上下文)
  • IFC(行内格式化上下文)
  • FFC(弹性格式化上下文)
  • GFC(网格格式化上下文)

弹性布局和网格布局

弹性布局(Flexbox)

弹性布局通过 display: flex;display: inline-flex; 创建了一个新的 BFC(准确地说是 FFC,即 Flex Formatting Context)。这意味着:

  • FFC(Flex Formatting Context) :在弹性容器中,子元素按照 flex-direction 的定义进行排列(默认是 row,即从左到右)。
  • 独立渲染区域:弹性容器中的布局完全独立于外部的 BFC,不会受到外界元素的影响。

举个例子:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            width: 100px;
            height: 100px;
            background-color: green;
        }
        .box:nth-child(odd) {
            background-color: red;
        }
    </style>
</head>
<body>
    <div class="flex">
        <div class="box">1</div>
        <div class="box">2</div>
        <div class="box">3</div>
    </div>
</body>
</html>

而当在<style>中添加对flex的编辑后

css 复制代码
.flex {
    display: flex;
}

.flex 容器就被设置为 Flex 容器,使它的直接子元素(.box 元素)成为 Flex 项目。而在默认情况下,Flex 项目的排列方向是由 flex-direction 属性决定的,默认值为 row,这意味着子元素会在水平方向上从左到右排列。即:

网格布局(Grid)

网格布局通过 display: grid;display: inline-grid; 创建了一个新的 GFC(Grid Formatting Context)。类似于弹性布局,网格布局也是一个独立的渲染区域。

css 复制代码
.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr); /* 三列等宽 */
    gap: 10px; /* 单元格之间的间隔 */
    padding: 10px; /* 网格容器的内边距 */
}

结语:

本文用于分享学习,如有错误或需要补充的麻烦在评论区补充,感谢。

相关推荐
微刻时光28 分钟前
影刀RPA开发-CSS选择器介绍
css·python·低代码·自动化·rpa·影刀rpa·影刀实战
码农黛兮_465 小时前
HTML、CSS 和 JavaScript 基础知识点
javascript·css·html
读心悦14 小时前
CSS结构性伪类、UI伪类与动态伪类全解析:从文档结构到交互状态的精准选择
css·ui·交互
码农黛兮_4617 小时前
CSS3 基础知识、原理及与CSS的区别
前端·css·css3
(((φ(◎ロ◎;)φ)))牵丝戏安18 小时前
根据输入的数据渲染柱形图
前端·css·css3·js
逍遥德19 小时前
CSS可以继承的样式汇总
前端·css·ui
读心悦19 小时前
CSS3 选择器完全指南:从基础到高级的元素定位技术
前端·css·css3
_龙衣20 小时前
将 swagger 接口导入 apifox 查看及调试
前端·javascript·css·vue.js·css3
为美好的生活献上中指1 天前
java每日精进 5.11【WebSocket】
java·javascript·css·网络·sql·websocket·网络协议
asqq81 天前
CSS 中的 ::before 和 ::after 伪元素
前端·css