掌控CSS布局:从盒模型到BFC,一探究竟 🧩💻

414 阅读7分钟

引言

文章有点长但看完一定会让你收获满满!

image.png

在开发网页时,CSS就像是一块多功能的魔法石✨。你可以通过它来控制网页的布局、样式,甚至是用户交互的方式。然而,CSS的魔法世界深不可测,特别是在涉及布局和渲染规则时,它更是有一堆复杂的术语和规则。今天,让我们通过一个轻松又风趣的探险,来解锁CSS的布局秘密——从盒模型到BFC,慢慢带你走向CSS布局的巅峰。

496.avif

一、盒模型——CSS世界的基石 🏗️

在了解CSS的布局之前,先要搞清楚盒模型。盒模型就像是CSS的骨架,它决定了每个元素如何在页面上展现出来。

1.1 盒模型基础 📦

OIP-C (4).jpg

盒模型分为两种——标准盒模型IE盒模型。标准盒模型是现代浏览器的标准,元素的总宽度和高度由内容、内边距(padding)、边框(border)和外边距(margin)决定。

标准盒模型

  • box-sizing: content-box;
  • 它的宽度和高度只计算内容区域,不包括内边距和边框。
  • 比如你设置width: 100px;,那100px就只代表内容区域的宽度,不包含内边距和边框。

IE盒模型

  • box-sizing: border-box;
  • 它的宽度和高度包括内容、内边距和边框的大小,换句话说,widthheight会控制整个盒子的尺寸,而不仅仅是内容区域的尺寸。

image.png

看看下面的HTML示例,你就能更直观地理解:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>一个盒子,自己的规则</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .box,
    .box2,
    .box3 {
      width: 100px;
      height: 100px;
      padding: 10px;
      border: 1px solid red;
      background-color: green;
    }
    .box2 {
      box-sizing: border-box;
    }
    .box3 {
      box-sizing: content-box;
    }
  </style>
</head>
<body>
  <div class="box"></div>
  <div class="box2"></div>
  <div class="box3"></div>
</body>
</html>

这里有三个盒子,它们的差异在于box-sizing属性。第一个盒子使用标准的content-box模型,第二个盒子使用border-box模型。它们的外观和尺寸会有所不同,具体请自行运行看看👀。

1.2 为什么盒模型这么重要? 🤔

你可能会问:“盒模型到底有多重要?”,答案是:超重要! 它是你布局的基础。如果不理解盒模型,你就无法精准控制元素的尺寸和布局,进而影响整个页面的设计📐。

二、布局基础:display——掌控元素的行为 📏

你可能已经发现,CSS有各种属性来决定元素的展示方式,其中最关键的一个就是display。它决定了元素是如何显示的,是块级元素、行内元素还是其他什么特殊的展示形式。

2.1 display属性——给元素定性 🏷️

  • block:块级元素,它会独占一行,宽度默认100%(如果不设置的话)。
  • inline:行内元素,它不会独占一行,而是与其他元素挤在同一行里,宽度由内容决定,不能设置宽度和高度。

例如,下面的HTML和CSS演示了display属性的作用:

<!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;
      background-color: green;
      display: block;
    }
  </style>
</head>
<body>
  <div>123</div>
  <span>11</span>
  <span>222</span>
</body>
</html>

image.png

在这个例子中,div被设置为行内元素,它不会占据一整行,而是根据内容宽度来决定自身宽度;而span是块级元素,会独占一行。并且我们可以看到绿色的部分往上挤了但是没有到文字部分就停止了,这是因为div被转化为了inline元素,所以行高就是由其内部的文字撑着,其他的元素只能感知到文字的行高,自然就向上挤压了,外面的红线是由于padding的存在。至于怎么解决就要看到文章下面的BFS了。

2.2 现代布局:Flexbox与Grid 🌍

在现代网页设计中,我们通常会用到FlexboxGrid布局,它们给CSS带来了灵活性和强大的布局能力。

2.2.1 Flex布局:顺从你的心 💨

Flexbox(弹性盒布局)是一个灵活的布局模型,可以让元素的大小和排列方式更适应父元素的尺寸。举个例子:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Flex布局</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .flex {
      display: flex;
    }

    .box {
      background-color: green;
      width: 100px;
      height: 100px;
    }

    .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>

image.png

在这个示例中,div元素被设置为Flex容器,它会让每个子元素按顺序排列,并且可以在行内水平方向上自动对齐。

2.2.2 Grid布局:高级排版大师 🎨

CSS Grid布局则是另一种强大的布局工具,特别适合于复杂的二维布局。它允许你同时控制行和列,进行更加精细的布局控制。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>网格布局</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .grid-container {
      display: grid;
      grid-template-columns: auto auto auto;
      gap: 10px;
      padding: 10px;
    }

    .grid-item {
      background-color: rgba(255, 255, 255, 0.8);
      border: 1px solid rgba(0, 0, 0, 0.8);
      padding: 20px;
      font-size: 30px;
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="grid-container">
    <div class="grid-item item1">1</div>
    <div class="grid-item item2">2</div>
    <div class="grid-item item3">3</div>
    <div class="grid-item item4">4</div>
    <div class="grid-item item5">5</div>
    <div class="grid-item item6">6</div>
    <div class="grid-item item7">7</div>
    <div class="grid-item item8">8</div>
    <div class="grid-item item9">9</div>
  </div>
</body>
</html>

image.png

在这个示例中,Grid容器设置了三列等宽,每个子项自动分配到网格中。

在这篇文章我们暂时不对FFSGFS作过多介绍。

image.png

三、BFC——布局中的隐形力量 🕵️‍♀️

BFC(块级格式化上下文)是CSS中一个非常重要的概念,它决定了元素如何在页面中布局和相互作用。简单来说,BFC是一个独立的渲染区域,它的内容不会被外部元素影响。

3.1 BFC的特点 🔍

  • 它是一个独立的渲染区域,不会被外部的浮动元素影响。
  • 它计算自己的高度时,浮动元素也会被考虑进来。

3.2 触发BFC的方法 📂

你可以通过overflowfloatposition等属性来触发BFC,下面是一个示例:

<!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;
      overflow: hidden; /* 触发BFC */
    }
  </style>
</head>
<body>

  <div class="box box1">Box1</div>

  <div class="box box2">Box2</div>

</body>
</html>

image.png

在这个例子中,box2触发了BFC,通过overflow: hidden;使它的布局独立于其他元素。但是它并没有解决问题,margin仍然是重叠的。

  • 这该怎么办呢?

  • 我们先来分析一下原因:

为什么 BFC 没有解决 margin 合并?

  • BFC 的作用是阻止 父子元素之间 的外边距合并,而不能阻止兄弟元素之间的外边距合并
  • 在你的例子中,box2 触发了 BFC,但是它和 box1 是兄弟关系,因此 BFC 的隔离特性并没有阻止它们的 margin 合并。

我们只需要稍微改一下就行了:

  <div class="box box1">Box1</div>
  <div style="overflow: hidden;">
    <div class="box box2">Box2</div>
  </div>

image.png

我们通过在box2外层加了一个div并且在这个盒子加了overflow: hidden;这个样式打破了box1box2的兄弟关系,为box2单独创立了一个BFC,它就不会受到外界(box1)的margin干扰了。

结语:CSS的奥秘由你掌控 🏆

从盒模型到BFC,从Flexbox到Grid,CSS的布局世界就像一张迷人的地图🗺️。每一个概念都是一片未知的领土,等待你去探索。当你掌握了这些布局技巧,网页就像是你的画布,设计和布局完全在你的掌控之中🎨。希望你能通过这篇文章,快速理解CSS布局的精髓,并且在开发中游刃有余地运用它们!

20200229174423_bzukt.jpg