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; /* 网格容器的内边距 */
}

结语:

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

相关推荐
程序员buddha27 分钟前
ThinkPHP8.0+MySQL8.0搭建简单实用电子证书查询系统
javascript·css·mysql·php·layui·jquery·html5
高志小鹏鹏2 小时前
Tailwind CSS都更新到4.0了,你还在抵触吗?
前端·css·postcss
Mswanga4 小时前
探秘 CSS 盒子模型:构建网页布局的基石
前端·css
I will.8744 小时前
如何使用 CSS 实现黑色遮罩效果
前端·javascript·css
前端Hardy6 小时前
HTML&CSS :用 CSS 遮罩,让产品展示图 “高级感爆棚”
css·html
前端Hardy6 小时前
HTML&CSS :1 分钟学会,飞虫变色特效卡片
css·html
前端Hardy6 小时前
HTML&CSS&JS:必学!用动态导航栏,让网页颜值飙升 10 倍
css·html
王哈哈嘻嘻噜噜7 小时前
CSS简介以及导入形式
前端·css
祈澈菇凉7 小时前
如何在 React 中使用 CSS-in-JS?
javascript·css·react.js
Mswanga7 小时前
css中的浮动
前端·css