CSS 核心布局指南:盒模型、Flex 布局与 Position 定位

0 阅读12分钟

CSS 核心布局指南:盒模型、Flex 布局与 Position 定位(从入门到 React 实战)

学习目标:理解 CSS 布局的三个核心机制,能够看懂 React 项目中常见的页面布局代码,独立实现导航栏、筛选表单、任务列表、固定按钮等业务页面。

一、CSS 布局的核心思路

在前端开发中,HTML 负责描述页面结构,而 CSS 负责控制页面的样式和布局。

理解 CSS 布局,首先要回答三个问题:

核心问题CSS 知识点作用
一个元素占多大空间?Box Model控制宽高、内外边距、边框
多个元素如何排列?Flex控制横向、纵向、居中、间距
元素如何放在指定位置?Position控制相对、绝对、固定、粘性定位

可以简单理解为:

盒模型管尺寸,Flex 管排列,Position 管定位。


第一部分:CSS 盒模型(Box Model)

1. 什么是盒模型?

浏览器会将大部分 HTML 元素按照矩形盒子的形式进行布局。

例如:

<div class="box">Hello CSS</div>
.box {
  width: 200px;
  height: 100px;
  padding: 20px;
  border: 5px solid blue;
  margin: 10px;
}

一个盒子由四部分组成:

  1. Content(内容区) :存放文字、图片等内容。
  2. Padding(内边距) :内容与边框之间的距离。
  3. Border(边框) :围绕内容和内边距的边框。
  4. Margin(外边距) :元素与其他元素之间的外部距离。

image.png 从内到外:

┌──────────────────────────────┐
│           Margin             │
│  ┌────────────────────────┐  │
│  │         Border         │  │
│  │  ┌──────────────────┐  │  │
│  │  │     Padding      │  │  │
│  │  │  ┌────────────┐  │  │  │
│  │  │  │  Content   │  │  │  │
│  │  │  └────────────┘  │  │  │
│  │  └──────────────────┘  │  │
│  └────────────────────────┘  │
└──────────────────────────────┘

四个属性的区别

.box {
  width: 200px;        /* 内容宽度 */
  padding: 20px;       /* 内边距 */
  border: 5px solid;   /* 边框 */
  margin: 10px;        /* 外边距 */
}

理解重点:

  • padding 是盒子内部的间距。
  • margin 是盒子外部的间距。
  • border 是盒子的边界。
  • width 默认设置内容区的宽度。

2. 盒模型的宽度如何计算?

这是盒模型最值得掌握的知识点。

2.1 默认盒模型:content-box

image.png

.box {
  box-sizing: content-box;

  width: 200px;
  padding: 20px;
  border: 5px solid;
}

实际盒子宽度:

内容宽度:200px
左右 padding:20px × 2
左右 border:5px × 2

实际宽度 = 200 + 40 + 10
         = 250px

公式:

实际边框盒宽度 = width + 左右 padding + 左右 border

如果还要计算外边距占用的空间,则需要再考虑左右 margin。

2.2 推荐盒模型:border-box

image.png

image.png 现代前端开发中,通常推荐:

* {
  box-sizing: border-box;
}

例如:

.box {
  box-sizing: border-box;

  width: 200px;
  padding: 20px;
  border: 5px solid;
}

此时实际边框盒宽度就是:

200px

因为 width 已经包含了 padding 和 border。

两种盒模型对比:

属性content-boxborder-box
width 包含内容是是
width 包含 padding否是
width 包含 border否是
推荐程度了解即可推荐使用

注意:border-box 也不包含 margin。

2.3 margin 与 padding 的区别

.card {
  margin: 20px;
  padding: 16px;
}
  • margin: 20px:卡片与外界保持距离。
  • padding: 16px:卡片内容与卡片边缘保持距离。

在 React 中后台系统中,几乎每个卡片、弹窗、表单都会使用这两个属性。

2.4 四个方向的简写

.box {
  margin: 10px;                /* 四个方向 */
  margin: 10px 20px;           /* 上下、左右 */
  margin: 10px 20px 30px;      /* 上、左右、下 */
  margin: 10px 20px 30px 40px; /* 上、右、下、左 */
}

记忆顺序:

上 → 右 → 下 → 左(顺时针)

另外,margin: 0 auto 经常用于让指定宽度的块级元素水平居中。

2.5 注意 margin 合并

普通文档流中,相邻块级元素的上下 margin 在特定条件下可能发生折叠。

例如:

.first {
  margin-bottom: 20px;
}

.second {
  margin-top: 30px;
}

两个元素之间的距离可能是 30px,而不是 50px。

这种现象叫 Margin Collapsing(外边距折叠)。

在 Flex 和 Grid 布局中,Flex/Grid 子项之间不会发生这种外边距折叠,因此现代布局可以优先使用 gap 控制间距。


第二部分:Flex 布局(重点)

**这部分有点绕,给个比较好学习的方式,就是下面的这个网页动画,实操一下就能快速理解了!!! **


<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Flex 布局交互演示</title>

  <style>
    * {
      box-sizing: border-box;
    }

    body {
      font-family: Arial, sans-serif;
      padding: 30px;
      background: #f5f6f8;
    }

    .panel {
      max-width: 650px;
      margin: 0 auto;
      padding: 24px;
      background: white;
      border-radius: 12px;
    }

    /* Flex 演示容器 */
    .container {
      display: flex;
      flex-direction: row;
      justify-content: flex-start;
      align-items: center;
      gap: 8px;

      height: 250px;
      padding: 12px;
      border: 2px dashed #aaa;
      border-radius: 8px;
    }

    /* 三个演示元素 */
    .item {
      padding: 12px 20px;
      background: #dceafe;
      border: 1px solid #81afe5;
      border-radius: 6px;
      color: #205e9a;
    }

    .control {
      margin-top: 20px;
    }

    label {
      display: block;
      margin-bottom: 8px;
      font-weight: bold;
    }

    select {
      width: 100%;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 6px;
    }

    pre {
      padding: 16px;
      background: #f1f3f5;
      border-radius: 8px;
      white-space: pre-wrap;
    }
  </style>
</head>

<body>
<div class="panel">
  <h2>Flex 布局交互演示</h2>

  <!-- 1. 演示区域 -->
  <div class="container" id="flexDemo">
    <div class="item">新增</div>
    <div class="item">编辑</div>
    <div class="item">删除</div>
  </div>

  <!-- 2. 控制排列方向 -->
  <div class="control">
    <label for="direction">flex-direction</label>
    <select id="direction">
      <option value="row">row(横向)</option>
      <option value="column">column(纵向)</option>
    </select>
  </div>

  <!-- 3. 控制主轴对齐 -->
  <div class="control">
    <label for="justify">justify-content</label>
    <select id="justify">
      <option value="flex-start">flex-start(起点)</option>
      <option value="center">center(居中)</option>
      <option value="space-between">
        space-between(两端对齐)
      </option>
    </select>
  </div>

  <!-- 4. 控制交叉轴对齐 -->
  <div class="control">
    <label for="align">align-items</label>
    <select id="align">
      <option value="flex-start">flex-start(起点)</option>
      <option value="center" selected>center(居中)</option>
      <option value="flex-end">flex-end(终点)</option>
    </select>
  </div>

  <h3>当前 CSS</h3>
  <pre id="cssCode"></pre>
</div>

<script>
  // 1. 获取 DOM 元素
  const container = document.getElementById("flexDemo");

  const direction = document.getElementById("direction");
  const justify = document.getElementById("justify");
  const align = document.getElementById("align");

  const cssCode = document.getElementById("cssCode");

  // 2. 根据选项更新 Flex 布局
  function updateFlex() {
    const directionValue = direction.value;
    const justifyValue = justify.value;
    const alignValue = align.value;

    // 修改 DOM 元素的 CSS 样式
    container.style.flexDirection = directionValue;
    container.style.justifyContent = justifyValue;
    container.style.alignItems = alignValue;

    // 显示当前 CSS
    cssCode.textContent = `
.container {
  display: flex;
  flex-direction: ${directionValue};
  justify-content: ${justifyValue};
  align-items: ${alignValue};
  gap: 8px;
}`;
  }

  // 3. 监听下拉框变化
  direction.addEventListener("change", updateFlex);
  justify.addEventListener("change", updateFlex);
  align.addEventListener("change", updateFlex);

  // 4. 初始化
  updateFlex();
</script>
</body>
</html>
属性row 横向排列时column 纵向排列时
justify-content控制左右控制上下
align-items控制上下控制左右

核心:justify 控制主轴,align 控制交叉轴。 主轴方向由 flex-direction 决定。

1. 什么是 Flex?

Flex,全称 Flexible Box,叫弹性盒布局。

它主要解决一个问题:

如何让多个元素方便地横向排列、纵向排列、对齐、居中以及分配剩余空间?

例如三个按钮:

<div class="container">
  <button>新增</button>
  <button>编辑</button>
  <button>删除</button>
</div>
.container {
  display: flex;
}

设置 display: flex 之后,三个按钮默认会沿水平方向排列。

这里需要理解两个角色:

  • Flex Container:设置了 display: flex 的父容器。
  • Flex Item:Flex 容器的直接子元素。

注意:Flex 控制的是直接子元素的布局,而不是任意层级的所有后代元素。


2. Flex 的两条轴

Flex 最重要的概念是:

  • 主轴(Main Axis)
  • 交叉轴(Cross Axis)

默认情况下:

.container {
  display: flex;
  flex-direction: row;
}

主轴是水平方向,交叉轴是垂直方向。

如果改成:

.container {
  display: flex;
  flex-direction: column;
}

主轴变成垂直方向,交叉轴变成水平方向。

这一点非常重要,因为后面的 justify-content 和 align-items 都依赖主轴、交叉轴。


3. flex-direction:排列方向

决定子元素沿什么方向排列。

.container {
  display: flex;
  flex-direction: row;
}

四个常见取值:

属性值含义
row水平排列,默认值
row-reverse水平反向排列
column垂直排列
column-reverse垂直反向排列

最常用的是:

flex-direction: row;
flex-direction: column;

4. justify-content:主轴对齐

控制元素在主轴方向的排列方式。

.container {
  display: flex;
  justify-content: center;
}

常见属性:

属性值作用
flex-start主轴起点对齐
flex-end主轴终点对齐
center主轴居中
space-between首尾贴边,中间均匀分配剩余空间
space-around每个元素两侧分配相等空间
space-evenly所有相邻间隔及两端间隔相等

例如:

.header {
  display: flex;
  justify-content: space-between;
}

适用于:

┌──────────────────────────────┐
│ Logo                用户头像 │
└──────────────────────────────┘

这在后台管理系统的导航栏中非常常见。


5. align-items:交叉轴对齐

控制子元素沿交叉轴的对齐方式。

例如:

.container {
  display: flex;
  align-items: center;
}

常见取值:

属性值含义
stretch默认值,符合条件的子项沿交叉轴拉伸
flex-start交叉轴起点对齐
flex-end交叉轴终点对齐
center交叉轴居中
baseline文本基线对齐

需要注意:

当 flex-direction: row 时:

  • justify-content 控制水平排列。
  • align-items 控制垂直对齐。

当 flex-direction: column 时:

  • justify-content 控制垂直排列。
  • align-items 控制水平对齐。

不要死记 justify 是水平、align 是垂直。要记主轴和交叉轴。


6. 实现水平垂直居中

这是非常经典的 CSS 布局场景。

<div class="container">
  <div class="box">Hello</div>
</div>
.container {
  display: flex;
  justify-content: center;
  align-items: center;

  height: 300px;
}

效果:

┌─────────────────────────────┐
│                             │
│                             │
│          ┌───────┐          │
│          │ Hello │          │
│          └───────┘          │
│                             │
│                             │
└─────────────────────────────┘

这三个属性值得直接记住:

display: flex;
justify-content: center;
align-items: center;

7. gap:控制元素之间的间距

例如:

.container {
  display: flex;
  gap: 16px;
}

三个元素之间会保持 16px 的间距。

相比给每个子元素设置 margin-right,使用 gap 通常更简单。

支持:

gap: 10px;

row-gap: 10px;

column-gap: 20px;

8. flex: 1:自动填充剩余空间

这是 React 开发中非常重要的属性。

例如:

<div class="container">
  <div class="sidebar">侧边栏</div>
  <div class="content">主内容</div>
</div>
.container {
  display: flex;
}

.sidebar {
  width: 200px;
  flex-shrink: 0;
}

.content {
  flex: 1;
  min-width: 0;
}

效果:

┌─────────────┬────────────────────────┐
│             │                        │
│   侧边栏    │       主内容区域       │
│   200px     │       剩余宽度         │
│             │                        │
└─────────────┴────────────────────────┘

flex: 1 是一个简写,通常相当于:

flex: 1 1 0%;

三个值分别对应:

  • flex-grow:有剩余空间时的扩展比例。
  • flex-shrink:空间不足时的收缩比例。
  • flex-basis:分配剩余空间之前的基础尺寸。

入门阶段可以先理解为:

flex: 1 让元素参与分配剩余空间,适合自适应布局。


9. flex-wrap:是否允许换行

默认情况下:

flex-wrap: nowrap;

Flex 元素会尽量保持在同一行,必要时可能收缩或者溢出。

如果希望元素换行:

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

常用于:

  • 标签列表
  • 筛选条件
  • 按钮组
  • 多个内容卡片

第三部分:CSS 定位(Position)

交互演示:切换 Position 看元素怎么移动


<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>CSS Position 定位交互演示</title>

  <style>
    * {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      padding: 30px;
      font-family: Arial, sans-serif;
      background: #f5f6f8;
    }

    .panel {
      max-width: 720px;
      margin: 0 auto;
      padding: 24px;
      background: white;
      border-radius: 12px;
    }

    h2 {
      margin-top: 0;
    }

    /* 模拟浏览器视口 */
    .viewport {
      position: relative;
      border: 2px solid #9da5b4;
      border-radius: 8px;
      overflow: hidden;
    }

    .viewport-header {
      padding: 10px;
      background: #e8ebf0;
      font-size: 13px;
    }

    /* 可滚动区域 */
    .scroll-area {
      position: relative;
      height: 280px;
      overflow-y: auto;
      overflow-x: hidden;
    }

    .normal-box {
      padding: 12px;
      height: 45px;
      margin-bottom: 10px;
      background: #dceee7;
      border-radius: 5px;
    }

    /* 定位父容器 */
    .parent {
      position: relative;
      margin: 12px;
      padding: 12px;
      min-height: 300px;
      border: 2px dashed #83a3d4;
      border-radius: 8px;
      background: #f8faff;
    }

    /* 被观察的目标元素 */
    .target {
      position: static;
      top: 20px;
      left: 20px;

      width: 150px;
      height: 60px;
      padding: 12px;
      margin-bottom: 10px;

      background: #fce1db;
      border: 2px solid #e78f7e;
      border-radius: 6px;
      color: #9d342d;
      font-weight: bold;
      z-index: 2;
    }

    /* fixed 使用模拟视口实现,避免遮挡页面 */
    .fixed-target {
      display: none;
      position: absolute;
      z-index: 5;

      width: 150px;
      height: 60px;
      padding: 12px;

      background: #fce1db;
      border: 2px solid #e78f7e;
      border-radius: 6px;
      color: #9d342d;
      font-weight: bold;
    }

    .bottom-content {
      height: 220px;
      padding: 20px;
      background: #f1f4f8;
    }

    .control {
      margin-top: 20px;
    }

    label {
      display: block;
      margin-bottom: 8px;
      font-weight: bold;
    }

    select {
      width: 100%;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 6px;
    }

    input[type="range"] {
      width: 100%;
    }

    .description {
      margin-top: 20px;
      padding: 14px;
      background: #f1f3f5;
      border-radius: 8px;
      line-height: 1.6;
    }

    pre {
      padding: 16px;
      background: #f1f3f5;
      border-radius: 8px;
      white-space: pre-wrap;
    }
  </style>
</head>

<body>
  <div class="panel">
    <h2>CSS Position 定位交互演示</h2>

    <p>
      切换定位类型,调整 top / left,
      并滚动演示区域观察变化。
    </p>

    <!-- 1. 演示区域 -->
    <div class="viewport">
      <div class="viewport-header">
        模拟浏览器视口(内部可滚动)
      </div>

      <div class="scroll-area" id="scrollArea">
        <div style="padding: 12px;">
          上方内容区域
        </div>

        <div class="parent">
          <p>父容器(position: relative)</p>

          <div class="normal-box">
            普通元素 A
          </div>

          <!-- 定位目标 -->
          <div class="target" id="target">
            目标元素 B
          </div>

          <div class="normal-box">
            普通元素 C
          </div>
        </div>

        <div class="bottom-content">
          下方内容区域,向下滚动观察变化
        </div>
      </div>

      <!-- fixed 模拟元素 -->
      <div class="fixed-target" id="fixedTarget">
        目标元素 B(fixed)
      </div>
    </div>

    <!-- 2. Position 选择 -->
    <div class="control">
      <label for="position">position 类型</label>

      <select id="position">
        <option value="static">static(默认定位)</option>
        <option value="relative">relative(相对定位)</option>
        <option value="absolute">absolute(绝对定位)</option>
        <option value="fixed">fixed(固定定位)</option>
        <option value="sticky">sticky(粘性定位)</option>
      </select>
    </div>

    <!-- 3. top 控制 -->
    <div class="control">
      <label for="top">
        top: <span id="topValue">20</span>px
      </label>

      <input
        type="range"
        id="top"
        min="0"
        max="80"
        step="10"
        value="20"
      />
    </div>

    <!-- 4. left 控制 -->
    <div class="control">
      <label for="left">
        left: <span id="leftValue">20</span>px
      </label>

      <input
        type="range"
        id="left"
        min="0"
        max="80"
        step="10"
        value="20"
      />
    </div>

    <!-- 5. 说明 -->
    <div class="description" id="description"></div>

    <h3>当前 CSS</h3>
    <pre id="cssCode"></pre>
  </div>

  <script>
    // 1. 获取 DOM 元素
    const target = document.getElementById("target");
    const fixedTarget = document.getElementById("fixedTarget");
    const scrollArea = document.getElementById("scrollArea");

    const position = document.getElementById("position");
    const topInput = document.getElementById("top");
    const leftInput = document.getElementById("left");

    const topValue = document.getElementById("topValue");
    const leftValue = document.getElementById("leftValue");

    const description = document.getElementById("description");
    const cssCode = document.getElementById("cssCode");

    // 2. 不同定位模式的说明
    const descriptions = {
      static:
        "static:默认定位,元素按正常文档流排列,top 和 left 不生效。",

      relative:
        "relative:相对自身原来的位置移动,但原位置仍被保留。",

      absolute:
        "absolute:脱离正常文档流,相对于定位父容器移动。其他元素会补上它原来的位置。",

      fixed:
        "fixed:通常相对于浏览器视口固定。这里通过模拟视口展示滚动时不移动的效果。",

      sticky:
        "sticky:滚动到指定位置后,在滚动容器内吸附。"
    };

    // 3. 更新定位方式
    function updatePosition() {
      const pos = position.value;
      const top = Number(topInput.value);
      const left = Number(leftInput.value);

      // 更新滑块数值
      topValue.textContent = top;
      leftValue.textContent = left;

      // fixed 模式使用模拟视口
      if (pos === "fixed") {
        target.style.display = "none";
        fixedTarget.style.display = "block";

        fixedTarget.style.top = (42 + top) + "px";
        fixedTarget.style.left = left + "px";
      } else {
        target.style.display = "block";
        fixedTarget.style.display = "none";

        // 直接修改 DOM 的 CSS
        target.style.position = pos;
        target.style.top = top + "px";
        target.style.left = left + "px";
      }

      // 显示当前模式说明
      description.textContent = descriptions[pos];

      // 显示对应 CSS
      cssCode.textContent = `
.target {
  position: ${pos};
  top: ${top}px;
  left: ${left}px;
}`;

      // sticky 切换时重置滚动位置
      if (pos === "sticky") {
        scrollArea.scrollTop = 0;
      }
    }

    // 4. 监听控件变化
    position.addEventListener("change", updatePosition);
    topInput.addEventListener("input", updatePosition);
    leftInput.addEventListener("input", updatePosition);

    // 5. 初始化
    updatePosition();
  </script>
</body>
</html>

1. 什么是 Position?

Flex 负责元素之间的排列,而 Position 负责元素在页面中的定位方式。

.box {
  position: relative;
}

CSS 中常见的五种定位方式:

属性含义是否脱离正常文档流
static默认定位否
relative相对定位否
absolute绝对定位是
fixed固定定位是
sticky粘性定位通常仍保留原有布局空间

2. static:默认定位

.box {
  position: static;
}

所有普通元素默认是 static。

元素按照正常文档流排列。

此时:

top: 20px;
left: 10px;

不会产生定位偏移效果。

日常开发一般不需要显式设置 position: static。


3. relative:相对定位

相对于元素自身原本的位置进行偏移。

.box {
  position: relative;
  top: 20px;
  left: 30px;
}

含义:

  • 向下移动 20px。
  • 向右移动 30px。

重要特点:

元素虽然发生了视觉位移,但它在原本布局中占据的空间仍然保留。

因此,周围元素不会因为它的位移而自动补上原来的位置。

另一个重要用途:为内部的绝对定位元素提供定位参考。


4. absolute:绝对定位

这是 Position 中的重点。

.child {
  position: absolute;
  top: 10px;
  right: 10px;
}

绝对定位元素会脱离正常文档流。

它通常相对于最近的、具有定位属性且建立定位参考的祖先元素进行定位;如果没有合适的祖先,则使用初始包含块。

最常见组合:父 relative,子 absolute

<div class="card">
  <span class="badge">NEW</span>
  <h3>任务卡片</h3>
</div>
.card {
  position: relative;

  width: 300px;
  height: 200px;

  border: 1px solid #ddd;
}

.badge {
  position: absolute;

  top: 10px;
  right: 10px;
}

效果:

┌──────────────────────────┐
│                     NEW  │
│                          │
│       任务卡片           │
│                          │
└──────────────────────────┘

最需要记住的组合:

.parent {
  position: relative;
}

.child {
  position: absolute;
  top: 0;
  right: 0;
}

在 React 开发中,这种写法非常常见,例如:

  • 卡片右上角的状态标签。
  • 输入框内部的搜索图标。
  • 图片右上角的关闭按钮。
  • 消息通知红点。

5. fixed:固定定位

fixed 通常相对于浏览器视口定位。

例如:

.back-to-top {
  position: fixed;

  right: 20px;
  bottom: 20px;
}

效果:

┌───────────────────────────────┐
│                               │
│          页面内容             │
│                               │
│                               │
│                        ┌────┐ │
│                        │ ↑  │ │
│                        └────┘ │
└───────────────────────────────┘

即使页面滚动,按钮通常也会停留在右下角。

常用于:

  • 返回顶部按钮。
  • 悬浮客服按钮。
  • 固定导航栏。
  • 全屏遮罩层。

注意:某些祖先元素具有 transform 等属性时,可能改变 fixed 元素的定位参考。


6. sticky:粘性定位

sticky 可以理解为一种结合正常布局与滚动约束的定位方式。

.header {
  position: sticky;
  top: 0;
}

元素正常情况下位于原有位置。

当页面滚动到指定位置时,会在其滚动容器的约束范围内保持粘性。

常用于:

  • 表格固定表头。
  • 页面顶部导航。
  • 滚动时吸顶的筛选栏。

注意:sticky 可能受到父容器高度、滚动容器以及 overflow 属性的影响。


7. z-index:元素层级

当多个元素重叠时,需要控制显示顺序。

.modal {
  position: fixed;
  z-index: 1000;
}

通常可以理解为:

在同一个层叠上下文中,z-index 较大的元素更容易显示在上层。

但 z-index 不完全是全局数值比较,不同层叠上下文之间存在层级限制。

例如:

.overlay {
  position: fixed;
  z-index: 100;
}

.modal {
  position: fixed;
  z-index: 101;
}

适用于弹窗遮罩与弹窗内容的层级控制。


第四部分:React 业务实战

下面通过一个任务管理页面,将三个核心知识点串联起来。

1. 实现需求

页面包括:

  1. 顶部固定导航栏。
  2. 左侧固定宽度的侧边栏。
  3. 右侧自适应的主内容区。
  4. 任务卡片右上角显示状态标签。
  5. 页面右下角显示悬浮按钮。

2. React JSX

import "./App.css";

function App() {
  return (
    <div className="app">
      {/* 顶部导航 */}
      <header className="header">
        <span>任务管理平台</span>
        <span>用户中心</span>
      </header>

      {/* 主体布局 */}
      <div className="layout">
        <aside className="sidebar">
          <div>任务列表</div>
          <div>任务配置</div>
        </aside>

        <main className="content">
          <h2>任务列表</h2>

          <div className="task-card">
            <span className="status">
              运行中
            </span>

            <h3>回查任务 A</h3>
            <p>执行中...</p>
          </div>
        </main>
      </div>

      {/* 悬浮按钮 */}
      <button className="floating-btn">
        +
      </button>
    </div>
  );
}

export default App;

3. CSS 样式

/* 全局盒模型 */
* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

/* 顶部导航 */
.header {
  position: sticky;
  top: 0;
  z-index: 10;

  height: 60px;
  padding: 0 24px;

  display: flex;
  justify-content: space-between;
  align-items: center;

  background: #1677ff;
  color: white;
}

/* 整体布局 */
.layout {
  display: flex;
  min-height: calc(100vh - 60px);
}

/* 侧边栏 */
.sidebar {
  width: 200px;
  flex-shrink: 0;
  padding: 20px;

  background: #f5f5f5;
}

/* 主内容 */
.content {
  flex: 1;
  min-width: 0;
  padding: 24px;
}

/* 任务卡片 */
.task-card {
  position: relative;

  width: 300px;
  max-width: 100%;
  padding: 20px;
  margin-top: 20px;

  border: 1px solid #ddd;
  border-radius: 8px;
}

/* 右上角状态 */
.status {
  position: absolute;
  top: 10px;
  right: 10px;

  color: green;
}

/* 悬浮按钮 */
.floating-btn {
  position: fixed;
  bottom: 20px;
  right: 20px;

  width: 48px;
  height: 48px;

  border: none;
  border-radius: 50%;

  background: #1677ff;
  color: white;
  cursor: pointer;
}

4. 核心知识点分析

代码对应知识
box-sizing: border-box盒模型
padding: 20px内边距
margin-top: 20px外边距
display: flexFlex 布局
justify-content: space-between主轴排列
align-items: center交叉轴对齐
flex: 1自适应剩余空间
position: relative相对定位
position: absolute绝对定位
position: fixed固定定位
position: sticky粘性定位
z-index: 10元素层级

通过这个案例,你已经接触到了 React 中后台业务开发中大部分常用的 CSS 布局属性。


第五部分:常见问题与面试考点

Q1:padding 和 margin 有什么区别?

  • padding:元素内部间距,位于内容与边框之间。
  • margin:元素外部间距,通常用于控制与其他元素的距离。

Q2:content-box 和 border-box 有什么区别?

content-box:width 不包含 padding、border。

border-box:width 包含 padding、border。

通常推荐全局设置:

* {
  box-sizing: border-box;
}

Q3:justify-content 和 align-items 的区别?

  • justify-content:控制主轴方向。
  • align-items:控制交叉轴方向。

具体是水平还是垂直,由 flex-direction 决定。

Q4:flex: 1 是什么意思?

通常相当于:

flex: 1 1 0%;

表示元素可以伸展和收缩,并以 0% 作为分配空间的基础尺寸。

实际开发中常用于分配父容器剩余空间。

Q5:relative 和 absolute 的区别?

对比relativeabsolute
是否脱离正常文档流否是
定位参考自身原位置定位包含块
原布局空间是否保留是否
常用场景定位参考、微调角标、图标、悬浮内容

Q6:fixed 和 sticky 的区别?

  • fixed:通常固定在视口指定位置,不随正常页面内容滚动。
  • sticky:在滚动容器内,根据滚动位置和约束进行粘性定位。

Q7:Flex 和 Position 应该怎么选择?

一般原则:

  • 多个元素排列:优先使用 Flex。
  • 二维网格布局:优先使用 Grid。
  • 元素内部角标:relative + absolute。
  • 悬浮固定按钮:fixed。
  • 滚动吸顶内容:sticky。

不要为了实现正常的页面排列而大量使用绝对定位。


六、知识点总结与学习优先级

知识点优先级掌握要求
width、heightP0熟练使用
padding、marginP0熟练使用
box-sizingP0理解两种盒模型
display: flexP0熟练使用
flex-directionP0熟练使用
justify-contentP0熟练使用
align-itemsP0熟练使用
gapP0熟练使用
flex: 1P0理解空间分配
position: relativeP0熟练使用
position: absoluteP0熟练使用
position: fixedP1掌握常用场景
position: stickyP1掌握吸顶场景
z-indexP1理解层叠上下文
margin 折叠P2理解现象即可

最后总结

CSS 布局最重要的三个模型:

  1. 盒模型(Box Model) :决定元素自身占据的尺寸和内外间距。
  2. Flex 布局:决定多个元素如何排列、对齐和分配空间。
  3. Position 定位:决定元素如何相对于参考位置进行布局和偏移。

对于 React 中后台开发,建议把主要精力投入 Flex 布局、盒模型和 relative + absolute 组合。

理解这些知识之后,再学习 CSS 选择器、响应式布局、Grid 和组件库样式覆盖,就能更高效地处理真实项目中的页面开发与样式问题。