前端快速上手保姆级教程day4: 半小时彻底搞懂Position

在Web前端开发中,CSS定位(Positioning) 是构建复杂页面布局的核心基石。无论是实现悬浮的导航栏、精美的商品角标,还是便捷的“回到顶部”按钮,都离不开对 position 属性的精准掌控。许多初学者在面对 relative、absolute、fixed 和 sticky 时常常感到困惑,尤其是当元素出现“跑偏”或层级覆盖异常时,往往难以快速定位问题根源。本文旨在通过通俗易懂的原理解析与实战案例,帮助开发者彻底厘清文档流、视口与定位参照系之间的关系。我们将深入探讨每种定位模式的底层逻辑,分析其在不同场景下的最佳实践,并揭示常见的陷阱与解决方案。掌握这些知识,不仅能提升页面还原的准确度,更能显著优化代码的可维护性与性能,为构建响应式、交互丰富的现代Web应用打下坚实基础。

深入理解文档流与视口概念

要精通CSS定位,首先必须建立两个核心概念的认知:文档流(Normal Flow)视口(Viewport)。这两个概念构成了浏览器渲染页面的基础坐标系,理解了它们,才能明白元素是如何“默认”排列的,以及定位属性是如何打破这种默认规则的。

文档流 是指网页中的元素按照其在HTML结构中出现的顺序,自上而下、自左向右进行自动排列的规则。在默认情况下,块级元素(如 <div>、<p>、<h1>)会独占一行,垂直堆叠,如同地铁车厢一节接一节;而行内元素(如 <span>、<a>)则会在同一行内水平排列,直到空间不足时自动换行,类似于排队买票的人群。这种自然的排列方式被称为“标准流”。绝大多数CSS布局操作,本质上都是在干预或脱离这个标准流。

视口 则是用户查看网页内容的可视区域。在桌面端,视口通常指浏览器窗口中除去工具栏、地址栏后的内容显示区。而在移动端,情况稍显复杂。早期移动设备为了兼容为桌面设计的宽屏网页,默认使用一个较宽的虚拟视口(通常为980px),这导致页面在手机上显示时会整体缩小,文字难以辨认。为了解决这一问题,开发者需要在HTML头部引入 <meta name="viewport"> 标签,指定 width=device-width 和 initial-scale=1.0。这一设置告诉浏览器以设备的实际物理宽度作为视口宽度,且不进行初始缩放,从而确保CSS像素与屏幕物理像素的正确映射,使页面布局符合预期。

文档流与视口的关系可以比喻为“积木”与“盒子”。文档流是积木的排列规则,而视口是容纳这些积木的盒子大小。如果盒子(视口)宽度固定,积木(元素)就会根据盒子的宽度决定是并排还是换行。在移动端开发中,正确设置视口是确保定位元素(特别是固定定位和粘性定位)行为符合预期的前提条件。

Position属性的四种核心模式解析

CSS的 position 属性定义了元素在文档中的定位方式。除了默认值 static 外,最常用的四种值分别是 relative、absolute、fixed 和 sticky。每种模式都有其独特的行为特征和适用场景,理解它们的差异是解决布局问题的关键。

Relative:相对定位与参照系建立

position: relative 表示相对定位。启用该属性后,元素仍然保留在正常的文档流中,占据原有的空间位置,不会导致后续元素发生位移变化。然而,开发者可以通过 top、right、bottom、left 属性相对于元素原本的位置进行偏移。

相对定位最核心的价值往往不在于移动元素本身,而在于为子元素创建定位上下文。当一个父元素设置为 relative 时,它就成为了其内部所有绝对定位(absolute)或固定定位(fixed,在某些特定条件下)子元素的定位参照物。如果没有这个参照物,子元素可能会一直向上查找,直到以浏览器视口为基准进行定位,这通常会导致布局失控。因此,在需要精确定位子元素时,“父相对,子绝对”是一种经典且安全的组合模式。

Absolute:绝对定位与脱离文档流

position: absolute 表示绝对定位。启用该属性的元素会完全脱离文档流,不再占据原来的空间,周围的元素会忽略它的存在并填补其空缺。绝对定位元素的位置是相对于其最近的、已定位(即 position 值不为 static)的祖先元素确定的。

如果找不到这样的祖先元素,绝对定位元素将相对于初始包含块(通常等同于视口)进行定位。这种行为特性使得 absolute 非常适合用于创建浮层、角标、关闭按钮等需要覆盖在其他内容之上的组件。例如,在一个卡片组件中,通过将卡片容器设为 relative,内部的角标设为 absolute 并指定 top: 0; right: 0,即可轻松实现角标固定在卡片右上角的效果,且不受外部布局变化的影响。

需要注意的是,如果祖先元素设置了 transform、perspective 或 filter 等CSS属性,即使没有显式设置 position,它们也可能成为绝对定位元素的参照物。这一特性在现代CSS框架中常被利用,但也可能引发意想不到的布局偏差,调试时需格外留意。

Fixed:固定定位与视口绑定

position: fixed 表示固定定位。与绝对定位类似,固定定位的元素也会脱离文档流。不同的是,它的参照物始终是浏览器视口(Viewport),而非某个祖先元素。这意味着,无论页面如何滚动,固定定位的元素都会保持在屏幕上的相同位置,仿佛被“钉”在了屏幕上。

这种特性使得 fixed 成为实现全局悬浮元素的理想选择,如“回到顶部”按钮、悬浮客服入口或全局提示条。由于它脱离了文档流,可能会遮挡下方的正常内容。因此,在实际应用中,通常需要为页面主体内容预留足够的内边距(padding)或外边距(margin),或者通过调整 z-index 层级来管理视觉堆叠顺序,确保用户体验的流畅性。

Sticky:粘性定位的动态切换

position: sticky 是一种混合了相对定位和固定定位特性的新型定位模式。在正常情况下,粘性定位元素表现为相对定位,跟随文档流正常滚动。然而,当页面滚动达到指定的阈值(由 top、right、bottom 或 left 定义)时,它会“粘”在视口的相应位置,表现出类似固定定位的行为。

粘性定位常用于实现吸顶导航栏、表格表头固定或侧边目录跟随等功能。例如,设置 position: sticky; top: 0; 后,导航栏会在滚动到页面顶部时吸附在顶端,方便用户随时访问菜单。使用 sticky 时需注意,其父容器不能具有 overflow: hidden、overflow: auto 或 overflow: scroll 属性,否则粘性效果可能会失效。此外,为了确保吸附后内容不被遮挡,通常建议配合较高的 z-index 值和背景色使用。

常见定位场景实战代码示例

理论的理解需要结合具体的代码实践才能转化为技能。以下通过三个典型的前端交互场景,展示如何组合使用不同的定位属性来实现预期效果。

场景一:吸顶导航栏

吸顶导航是现代Web应用中常见的交互模式,要求导航栏在页面滚动至顶部时保持可见。使用 sticky 属性可以以最少的代码实现这一功能。

/* 导航栏样式 */
.navbar {
  position: sticky; /* 启用粘性定位 */
  top: 0;           /* 吸附阈值为视口顶部 */
  z-index: 1000;    /* 确保层级高于其他内容 */
  background-color: #ffffff; /* 设置背景色防止内容透视 */
  box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* 添加阴影增强视觉分离感 */
}

在上述代码中,position: sticky 让导航栏在未达到顶部前随页面正常滚动。一旦滚动距离使得导航栏顶部触及视口顶部(top: 0),它便固定在该位置。z-index 确保了导航栏始终位于内容之上,而背景色则避免了下方滚动内容透过导航栏显示造成的视觉混乱。

场景二:卡片角标设计

在电商或内容展示场景中,经常需要在卡片右上角显示“新品”、“热销”等角标。这需要结合父元素的相对定位和子元素的绝对定位来实现。

/* 卡片容器 */
.card-container {
  position: relative; /* 建立定位上下文 */
  width: 300px;
  height: 200px;
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden; /* 防止角标溢出圆角边界 */
}

/* 角标元素 */
.badge {
  position: absolute; /* 脱离文档流,相对于父容器定位 */
  top: -10px;         /* 向上微调,使其部分超出卡片边界 */
  right: -10px;       /* 向右微调 */
  background-color: #ff4d4f;
  color: white;
  padding: 4px 8px;
  font-size: 12px;
  transform: rotate(45deg); /* 可选:旋转角标增加动感 */
  transform-origin: center;
}

这里的关键在于 .card-container 设置了 position: relative。这使得 .badge 的 top 和 right 值是相对于卡片容器的边角计算的,而不是相对于整个页面。如果移除父容器的相对定位,角标将会飞到页面的右上角,导致布局错误。

场景三:回到顶部按钮

“回到顶部”按钮需要在用户浏览长页面时始终可见,且不影响正文内容的排版。fixed 定位是此类需求的标准解决方案。

/* 回到顶部按钮 */
.back-to-top-btn {
  position: fixed;    /* 相对于视口固定 */
  bottom: 20px;       /* 距离视口底部20像素 */
  right: 20px;        /* 距离视口右侧20像素 */
  width: 40px;
  height: 40px;
  background-color: #007bff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  cursor: pointer;
  z-index: 999;       /* 确保不被其他固定元素遮挡 */
  opacity: 0.8;
  transition: opacity 0.3s;
}

.back-to-top-btn:hover {
  opacity: 1;
}

通过 position: fixed 以及 bottom 和 right 属性,按钮被牢牢固定在屏幕右下角。无论用户滚动到页面的任何位置,按钮始终处于可点击状态。z-index 的设置保证了它在多层叠加界面中的可见性。

定位开发中的常见陷阱与调试技巧

尽管CSS定位功能强大,但在实际开发中,开发者经常会遇到一些令人头疼的问题。识别并解决这些常见陷阱,能显著提升开发效率。

1. 绝对定位元素“跑飞” 这是新手最常遇到的问题。当子元素设置 position: absolute 后,发现它没有相对于预期的父元素定位,而是跑到了页面角落。

  • 原因:父元素未设置非 static 的 position 值(如 relative、absolute 等)。
  • 解决:检查父级链条,确保最近的期望参照父元素设置了 position: relative。可以使用浏览器开发者工具的“计算样式”面板查看元素的 offsetParent 属性,确认其实际的定位参照物。

2. 粘性定位(Sticky)失效 设置了 position: sticky 但元素没有任何吸附效果。

  • 原因
    • 未指定 top、bottom 等阈值属性。
    • 父容器设置了 overflow: hidden、auto 或 scroll。
    • 父容器的高度小于或等于粘性元素的高度,导致没有滚动空间。
  • 解决:确保添加了至少一个方向的位置属性(如 top: 0)。检查父容器的 overflow 属性,必要时将其改为 visible。确保父容器有足够的高度供元素滚动。

3. 层级覆盖异常(Z-index问题) 定位元素被其他元素遮挡,或者无法点击。

  • 原因:z-index 仅在定位元素(非 static)上生效。此外,z-index 的比较是在同一个堆叠上下文(Stacking Context)中进行的。如果父元素创建了新的堆叠上下文,子元素的 z-index 只能在该父元素内部比较,无法跨越父元素去覆盖外部的兄弟元素。
  • 解决:确保元素具有定位属性。合理规划 z-index 值,避免过大或过小的随意赋值。理解堆叠上下文的形成条件(如 opacity < 1、transform 等也会创建新上下文),必要时调整DOM结构或CSS属性以提升层级。

4. 固定定位遮挡内容 使用 fixed 元素(如底部导航或顶部横幅)时,页面底部或顶部的内容被遮挡,导致用户无法查看完整信息。

  • 解决:为页面主体内容(如 <body> 或主容器)添加相应的 padding-bottom 或 padding-top,其值应等于固定元素的高度加上适当的间距。这是一种简单有效的布局补偿策略。

总结与实践建议

CSS的 position 属性是前端布局中不可或缺的工具。通过本文的解析,我们明确了 relative 用于建立参照系和微调,absolute 用于脱离文档流的精确覆盖,fixed 用于视口级别的固定展示,而 sticky 则提供了动态的滚动吸附体验。

在实际开发中,建议遵循以下最佳实践:

  1. 最小化原则:尽量使用标准文档流和Flexbox/Grid布局,仅在必要时使用定位属性。过度使用定位会增加布局的复杂度和维护成本。
  2. 明确参照系:使用 absolute 时,务必显式为父元素设置 position: relative,以避免不可预测的定位行为。
  3. 注意兼容性:虽然 sticky 在现代浏览器中支持良好,但在旧版浏览器中可能需要降级处理或使用JavaScript polyfill。
  4. 层级管理:建立统一的 z-index 管理规范,避免魔术数字,推荐使用CSS变量或预处理器变量来定义层级常量。

掌握这些原则并结合不断的实战练习,开发者将能够从容应对各种复杂的页面布局需求,构建出既美观又健壮的Web界面。

CSS 优先级与链式选择器:精准控制样式的核心逻辑

在复杂的页面布局中,样式冲突是开发者最常遇到的问题之一。理解 CSS 优先级(Specificity)链式选择器 的运作机制,不仅能帮助你快速排查样式失效的原因,还能让你写出更健壮、易维护的代码。这部分内容虽然属于进阶知识,但在实际工程实践中极具价值,是区分初级与中级前端开发者的关键分水岭。

深入理解链式选择器

链式选择器(Chained Selectors)是一种通过紧密连接多个类名来缩小匹配范围的技术。其核心语法特征是两个类名之间没有任何空格,例如 .card.badge-card。这种写法意味着目标元素必须同时拥有 card 和 badge-card 这两个类名,浏览器才会应用该规则。这与后代选择器 .card .badge-card(中间有空格)有着本质区别,后者匹配的是 .card 内部任意层级的 .badge-card 子元素。

/* 链式选择器:元素必须同时具备两个类名 */
.card.badge-card {
  border: 2px solid #3b82f6; /* 仅当元素同时有 card 和 badge-card 时生效 */
}

/* 对比:后代选择器(注意中间的空格) */
.card .badge-card {
  color: red; /* 匹配 .card 内部的所有 .badge-card 元素 */
}

使用链式选择器的主要优势在于提高选择器的特异性而不增加 HTML 结构的复杂度。它允许我们在不修改 DOM 结构的前提下,为特定组合状态的元素定义专属样式。例如,在一个通用的卡片组件系统中,我们可以为基础卡片定义默认样式,然后通过链式选择器为“选中状态”或“高亮状态”的卡片添加额外的视觉反馈,从而实现样式的模块化复用与精准覆盖。

CSS 优先级计算规则详解

当多个 CSS 规则针对同一元素的同一属性产生冲突时,浏览器并非随机选择,而是依据一套严格的 优先级算法 来决定最终生效的样式。这套算法通常被称为“特异性权重”,其基本层级从低到高依次为:标签选择器 < 类选择器/伪类/属性选择器 < ID 选择器 < 行内样式。理解这一层级关系,有助于我们预测样式的应用结果,避免陷入“为什么我的样式不生效”的调试困境。

/* 优先级较低:标签选择器 (权重 0,0,1) */
div {
  color: gray;
}

/* 优先级中等:类选择器 (权重 0,1,0) */
.content {
  color: blue;
}

/* 优先级较高:ID 选择器 (权重 1,0,0) */
#main-content {
  color: green;
}

/* 优先级最高:行内样式 (权重 1,0,0,0 - 近似理解) */
/* <div id="main-content" class="content" style="color: red;">Text</div> */

需要注意的是,!important 声明可以强制提升某条规则的优先级,使其凌驾于上述常规计算之上。然而,滥用 !important 会破坏样式的可预测性,导致后期维护困难,因此被视为一种“最后手段”。在实际开发中,应优先通过优化选择器结构和利用层叠顺序来解决冲突,而非依赖 !important。此外,当优先级完全相同时,浏览器会遵循 “后来居上” 原则,即代码中后定义的规则会覆盖先定义的规则。

常见陷阱与调试技巧

新手开发者常误以为“写在后面的样式一定生效”,这忽略了优先级权重的影响。如果一个低优先级的选择器写在后面,而一个高优先级的选择器写在前面,最终生效的依然是高优先级的规则。另一个常见的错误是混淆链式选择器与后代选择器的空格含义,导致样式无法命中预期元素。掌握这些细节,能显著减少因语法误解导致的布局偏差。

/* 陷阱示例:看似后写,但因优先级低而被覆盖 */
.button {
  background-color: blue; /* 权重 0,1,0 */
}

#submit-btn {
  background-color: red; /* 权重 1,0,0,即使写在前面也会生效 */
}

当遇到样式不符合预期的情况时,最高效的方法是浏览器的 开发者工具(DevTools)。在 Elements 面板中选中目标元素,查看 Styles 侧边栏。浏览器会清晰地列出所有匹配的规则,并将被覆盖的规则显示为删除线,同时在旁边标注出覆盖原因(如“Overridden by...”)。通过观察 Computed 面板,你可以直接看到最终生效的属性值,从而逆向推导出是哪条规则起了作用,这是定位 CSS 问题的终极利器。

border-radius: 999px 的视觉魔法与应用场景

在现代 UI 设计中,圆角元素无处不在,从按钮到标签,再到头像框。其中,border-radius: 999px 成为一种流行的“黑客技巧”,用于创建完美的胶囊形或圆形效果。这并非真正的魔法,而是利用了浏览器对圆角半径渲染的限制机制。理解这一属性的行为差异,能帮助你在不同尺寸和比例的元素上实现一致的视觉圆润感。

为什么超大数值能实现完美圆角?

border-radius 属性定义了元素角落的弯曲程度。当你设置一个极大的固定值(如 999px 或 9999px)时,浏览器并不会强行绘制一个半径为 999 像素的圆弧,因为这在几何上往往超出了元素的边界。相反,浏览器会自动将圆角半径裁剪至该元素当前维度允许的最大值。这意味着,无论元素的宽度或高度如何变化,角落都会尽可能变得圆润,直到形成半圆或完整的四分之一圆。

.pill-button {
  /* 无论按钮多宽,两端都会变成半圆形 */
  border-radius: 999px; 
  padding: 10px 24px;
  background-color: #3b82f6;
  color: white;
}

这种机制的优势在于自适应性强。对于宽度动态变化的内容(如不同长度的文本标签),使用固定大数值可以确保两端始终保持完美的半圆形状,而无需计算具体的百分比或像素值。相比之下,如果使用较小的固定像素值,当元素变窄时,圆角可能会显得过大甚至重叠;当元素变宽时,圆角又可能显得不够明显。999px 提供了一种“尽力而为”的圆润策略,简化了响应式设计的复杂度。

999px 与 50% 的核心区别

虽然 border-radius: 50% 也能创建圆形效果,但它与 999px 的应用场景截然不同。50% 是基于元素自身尺寸的百分比计算,只有当元素的宽度和高度相等(即正方形)时,才能形成完美的正圆。如果元素是长方形,50% 会导致边缘形成椭圆弧形,甚至在极端比例下出现视觉畸变。因此,50% 专用于正方形容器,如用户头像或图标背景。

特性border-radius: 999pxborder-radius: 50%
计算基准固定像素值(自动裁剪)元素宽高的百分比
最佳场景长方形按钮、标签、胶囊导航正方形头像、圆形图标容器
非正方形表现两端呈半圆,中间直线(胶囊形)呈椭圆形,可能变形
响应式稳定性高,随宽度变化保持端部圆润低,依赖宽高比维持形状

在实际项目中,回到顶部按钮、悬浮操作按钮(FAB)以及各类 Tag 标签通常采用 999px 方案,因为它们的宽度往往由内容决定,且不一定是正方形。而用户头像组件则严格使用 50%,并配合 aspect-ratio: 1/1 或固定的宽高样式,以确保在任何屏幕尺寸下都呈现标准的圆形。正确区分这两者的使用语境,是提升界面精致度的重要细节。

实战总结:完整代码回顾与最佳实践

通过前面的解析,我们已经构建了一个包含固定定位、粘性导航、绝对定位角标以及圆角按钮的综合页面。以下代码整合了所有讨论过的技术点,展示了如何在真实场景中协同使用这些 CSS 属性。请注意代码中的注释,它们解释了关键样式的设计意图,帮助你将理论知识转化为实际的编码能力。

<!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>
    /* 全局重置:确保盒模型一致,避免边距塌陷问题 */
    *, *::before, *::after {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      font-family: system-ui, -apple-system, sans-serif;
      line-height: 1.5;
      color: #333;
    }

    /* 固定定位演示:始终位于视口右上角,不受滚动影响 */
    .fixed-notification {
      position: fixed;
      top: 0;
      right: 20px;
      z-index: 100; /* 确保高于其他内容 */
      background: #fef3c7;
      padding: 12px 16px;
      border-bottom-left-radius: 8px;
      border-bottom-right-radius: 8px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }

    /* 占位区域:用于演示滚动行为 */
    .hero-section {
      height: 300px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: linear-gradient(135deg, #e0f2fe 0%, #f0f9ff 100%);
      border-bottom: 1px solid #bae6fd;
    }

    /* 粘性定位:滚动到顶部时吸附,未到时随文档流移动 */
    .sticky-nav {
      position: sticky;
      top: 0;
      z-index: 10;
      background: rgba(255, 255, 255, 0.95); /* 轻微透明背景 */
      backdrop-filter: blur(8px); /* 毛玻璃效果 */
      border-bottom: 1px solid #e5e7eb;
    }

    .nav-container {
      max-width: 960px;
      margin: 0 auto;
      padding: 12px 16px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .nav-link {
      text-decoration: none;
      color: #2563eb;
      margin-left: 16px;
      font-weight: 500;
    }

    /* 回到顶部按钮:固定定位 + 胶囊圆角 */
    .back-to-top {
      position: fixed;
      right: 24px;
      bottom: 24px;
      background: #2563eb;
      color: white;
      text-decoration: none;
      padding: 12px 20px;
      border-radius: 999px; /* 胶囊形状关键 */
      box-shadow: 0 4px 6px rgba(37, 99, 235, 0.2);
      transition: background 0.2s;
    }

    .back-to-top:hover {
      background: #1d4ed8;
    }

    /* 主容器:限制最大宽度并居中 */
    .main-content {
      max-width: 960px;
      margin: 0 auto;
      padding: 24px 16px 80px;
    }

    /* 基础卡片样式 */
    .card {
      background: #fff;
      border: 1px solid #e5e7eb;
      border-radius: 12px;
      padding: 20px;
      margin-bottom: 20px;
      box-shadow: 0 1px 3px rgba(0,0,0,0.05);
    }

    /* 相对定位父元素:为绝对定位子元素提供参照系 */
    .card-with-badge {
      position: relative;
    }

    /* 绝对定位角标:脱离文档流,相对于父元素定位 */
    .badge {
      position: absolute;
      top: -12px;
      right: -12px;
      background: #ef4444;
      color: white;
      font-size: 12px;
      font-weight: bold;
      padding: 4px 10px;
      border-radius: 999px; /* 小标签也使用胶囊圆角 */
      box-shadow: 0 2px 4px rgba(239, 68, 68, 0.3);
    }

    /* 链式选择器应用:仅当卡片同时拥有 highlight 类时生效 */
    .card.highlight {
      border-color: #3b82f6;
      background-color: #eff6ff;
    }

    /* 填充内容以产生滚动条 */
    .spacer {
      min-height: 1200px;
      background: repeating-linear-gradient(
        45deg,
        #f9fafb,
        #f9fafb 10px,
        #f3f4f6 10px,
        #f3f4f6 20px
      );
    }
  </style>
</head>
<body>

  <!-- 固定通知栏 -->
  <div class="fixed-notification">
    📢 系统公告:CSS 定位实战演示
  </div>

  <!-- 顶部英雄区域 -->
  <section class="hero-section">

<p>向下滚动以观察导航栏的粘性效果</p>
  </section>

  <!-- 粘性导航栏 -->
  <header class="sticky-nav">
    <div class="nav-container">
      <strong>Position 实战指南</strong>

<nav>
        <a href="#intro" class="nav-link">简介</a>
        <a href="#badge-demo" class="nav-link">角标</a>
        <a href="#layout" class="nav-link">布局</a>
      </nav>
    </div>
  </header>

  <main class="main-content">
    <section class="card" id="intro">

<h2>课程简介</h2>

<p>本页面演示了 relative, absolute, fixed, sticky 四种定位模式的最佳实践。</p>
    </section>

    <!-- 使用链式选择器和高亮类 -->
    <section class="card card-with-badge highlight" id="badge-demo">
      <span class="badge">HOT</span>

<h3>绝对定位角标示例</h3>

<p>父元素设置 <code>position: relative,角标设置 position: absolute

此类卡片还应用了 .card.highlight 链式选择器样式。

布局说明

右下角的蓝色按钮使用了 position: fixedborder-radius: 999px

无论页面如何滚动,它始终保持在视口右下角。