Skip to content

HTML&CSS

注意

本文档仅能覆盖基本框架,详细内容在MDN中搜索

HTML

超文本标记语言(HyperText Markup Language)。是构建网页内容的标准标记语言,定义了网页的结构,如文本、图像、链接、表格等。

语义化

HTML的语义化是指在编写HTML代码时,使用具有明确含义的标签来描述内容的结构和意义,而不仅仅关注其呈现效果。

这种方法强调内容的语义,使网页在结构上更加清晰,有助于搜索引擎的索引和抓取,也有利于在不同设备上保持一致的显示效果。

元素

HTML 元素的基本结构如下:

HTML 元素是网页的构建块,每个元素通常由标签、内容和可选的属性组成。HTML 元素定义了网页的结构和内容。HTML 元素的基本结构如下:

html
<元素名 属性1="值1" 属性2="值2">内容</元素名>

常见 HTML 元素介绍

  1. <html>:定义整个 HTML 文档的根元素。

    • 示例:
      html
      <html lang="en">
      </html>
  2. <head>:包含页面的元数据,如字符集、网页标题、外部样式表和脚本。

    • 示例:
      html
      <head>
          <meta charset="UTF-8">
          <title>网页标题</title>
          <link rel="stylesheet" href="styles.css">
      </head>
  3. <body>:包含网页的可视内容,如文本、图像、按钮等。

    • 示例:
      html
      <body>
          <h1>欢迎来到我的网站</h1>
          <p>这是网页的内容。</p>
      </body>
  4. <h1> ~ <h6>:表示标题,<h1> 为最高级别的标题,<h6> 为最低级别的标题。

    • 示例:
      html
      <h1>这是一级标题</h1>
      <h2>这是二级标题</h2>
  5. <p>:定义段落,用于包裹文本内容。

    • 示例:
      html
      <p>这是一个段落。</p>
  6. <a>:定义超链接,用于在网页之间进行跳转。常用的属性是 href,指定链接的目标地址。

    • 示例:
      html
      <a href="https://www.example.com">点击访问示例网站</a>
  7. <img>:定义图像,使用 src 属性指定图像的路径,alt 属性提供替代文本。

    • 示例:
      html
      <img src="image.jpg" alt="描述性文本" />
  8. <ul>:定义无序列表,通常与 <li> 元素一起使用,每个 <li> 表示列表项。

    • 示例:
      html
      <ul>
          <li>苹果</li>
          <li>香蕉</li>
      </ul>
  9. <ol>:定义有序列表,也与 <li> 一起使用,但列表项会按顺序编号。

    • 示例:
      html
      <ol>
          <li>第一项</li>
          <li>第二项</li>
      </ol>
  10. <li>:定义列表项,通常用于 <ul><ol> 中。

    • 示例:
      html
      <ul>
          <li>苹果</li>
      </ul>
  11. <div>:定义一个区块元素,用于布局和分隔内容。它本身不提供任何视觉效果,但常用于组织页面结构。

    • 示例:
      html
      <div>
          <p>这是一个块级元素。</p>
      </div>
  12. <span>:定义一个内联元素,通常用于文档中对部分文本或元素进行样式修改。

    • 示例:
      html
      <span style="color: red;">这是红色的文本。</span>
  13. <form>:定义表单,用于收集用户输入。通常包含 <input><select><textarea> 等表单控件。

    • 示例:
      html
      <form action="/submit" method="post">
          <label for="name">姓名:</label>
          <input type="text" id="name" name="name">
          <input type="submit" value="提交">
      </form>
  14. <input>:定义一个输入控件,允许用户输入数据。常用的类型包括 textpasswordemail 等。

    • 示例:
      html
      <input type="text" placeholder="请输入用户名">
  15. <button>:定义一个按钮,通常用于触发操作或提交表单。

    • 示例:
      html
      <button>点击我</button>
  16. <table>:定义表格,用于组织数据。通常与 <tr>(行)、<td>(单元格)和 <th>(表头)一起使用。

    • 示例:
      html
      <table>
          <tr>
              <th>姓名</th>
              <th>年龄</th>
          </tr>
          <tr>
              <td>张三</td>
              <td>25</td>
          </tr>
      </table>
  17. <tr>:定义表格行,通常位于 <table> 中。

    • 示例:
      html
      <tr>
          <td>张三</td>
          <td>25</td>
      </tr>
  18. <td>:定义表格单元格,用于存放数据,通常位于 <tr> 中。

    • 示例:
      html
      <td>张三</td>
  19. <th>:定义表格的表头单元格,通常用于列标题。

    • 示例:
      html
      <th>姓名</th>
  20. <iframe>:定义一个内联框架,允许在网页中嵌入其他网页或媒体。

    • 示例:
      html
      <iframe src="https://www.example.com" width="600" height="400"></iframe>

CSS

CSS(Cascading Style Sheets,层叠样式表)是一种用于描述 HTML 或 XML(包括 XHTML)文档外观和格式的样式表语言。

CSS 负责定义网页的布局、颜色、字体等,使网页具有良好的视觉效果和用户体验。

CSS 规则由 选择器 和 声明块 组成,声明块中包含 属性 和 属性值。

css
选择器 {
    属性: 属性值;
}

示例:

css
p {
    color: red; /* 文字颜色为红色 */
    font-size: 16px; /* 字体大小16px */
}

引入方式

行内样式(Inline CSS)

直接在 HTML 元素的 style 属性中定义 CSS 样式,适用于简单的样式调整,但不推荐大规模使用。

html
<p style="color: blue; font-size: 18px;">这是一个带有行内样式的段落。</p>

内部样式表(Internal CSS)

在 HTML 文档的 <style> 标签内定义样式,适用于单个 HTML 文件的样

html
<head>
    <style>
        p {
            color: green;
            font-size: 20px;
        }
    </style>
</head>

外部样式表(External CSS)

CSS 代码写在独立的 .css 文件中,并在 HTML 中通过 <link> 标签引入,是推荐的方式。

html
<head>
    <link rel="stylesheet" href="styles.css">
</head>
css
p {
    color: black;
    font-size: 22px;
}

选择器

CSS 选择器用于选择 HTML 元素,并应用相应的样式。

选择器分为 基本选择器组合选择器伪类选择器伪元素选择器属性选择器

基本选择器(Basic Selectors)

通配选择器(*
  • 选择页面中的所有元素。
  • 示例:
    css
    * {
        margin: 0;
        padding: 0;
    }

    作用:通常用于清除默认的 margin 和 padding。

元素选择器(标签选择器)
  • 直接选取 HTML 标签,如 ph1div 等。
  • 示例:
    css
    p {
        color: red;
    }

    作用:所有 <p> 标签的文本颜色变为红色。

类选择器(.class
  • 选取具有特定 class 的所有元素。
  • 示例:
    css
    .highlight {
        background-color: yellow;
    }
    html
    <p class="highlight">高亮文本</p>
ID 选择器(#id
  • 选取具有特定 id 的唯一元素。
  • 示例:
    css
    #main {
        width: 80%;
    }
    html
    <div id="main">主要内容</div>

    注意id 选择器用于唯一元素,不推荐多次使用相同 id


组合选择器(Combinators)

后代选择器(A B
  • 选择 A 元素内的所有 B 元素(不限层级)。
  • 示例:
    css
    div p {
        color: blue;
    }
    html
    <div>
        <p>我是蓝色的文本</p>
    </div>
子元素选择器(A > B
  • 仅选择 A 的直接子元素 B(不包括嵌套更深的 B)。
  • 示例:
    css
    div > p {
        color: green;
    }
    html
    <div>
        <p>直接子元素</p>
        <span><p>非直接子元素</p></span>
    </div>

    结果:只有直接子元素<p> 变为绿色。

相邻兄弟选择器(A + B
  • 选取紧跟在 A 之后的 B 兄弟元素。
  • 示例:
    css
    h1 + p {
        color: orange;
    }
    html
    <h1>标题</h1>
    <p>这个段落会变成橙色</p>
    <p>这个段落不受影响</p>
通用兄弟选择器(A ~ B
  • 选取所有在 A 之后的 B 兄弟元素(不限距离)。
  • 示例:
    css
    h1 ~ p {
        color: purple;
    }
    html
    <h1>标题</h1>
    <p>第一个段落</p>
    <p>第二个段落</p>

    结果h1 后的所有 <p> 变成紫色。


伪类选择器(Pseudo-Classes)

伪类用于选取特定状态的元素,如鼠标悬停、选中、首个子元素等。

动作伪类(交互状态)

图片

  • :link:超链接未访问
  • :visited:超链接已访问
  • :hover:鼠标悬停时
  • :focus:获得焦点时
  • :active:鼠标点击时
css
a:hover {
    color: red;
}
input:focus {
    border: 2px solid blue;
}
button:active {
    background-color: gray;
}

书写顺序

这几个伪类选择器在 CSS 书写时,推荐遵循“LVHA(LoVe HAte)”顺序,即:

📌 顺序::link → :visited → :hover → :focus → :active ⚠️ :hover 必须放在 :visited 之后,:active 必须放在 :hover 之后!

为什么要按这个顺序?

  • :link(未访问):超链接的默认状态,应该先定义。
  • :visited(已访问):防止已访问链接样式被后面的 :link 覆盖。
  • :hover(悬停):用于交互效果,但必须放在 :link 和 :visited 之后,否则 :hover 可能不会生效。
  • :focus(焦点):让键盘导航也能获得样式变化,通常和 :hover 一起使用。
  • :active(点击):如果 :hover 放在 :active 之后,:active 可能无法生效。
结构伪类(位置选择)
  • :first-child:选取父元素的第一个子元素。
  • :last-child:选取父元素的最后一个子元素。
  • :nth-child(n):选取第 n 个子元素(n 可为数字、公式)。
  • :nth-of-type(n):选取相同类型的第 n 个元素。
css
p:first-child {
    font-weight: bold;
}
li:nth-child(odd) {
    background-color: lightgray; /* 选择奇数行 */
}
li:nth-child(2n) {
    background-color: lightblue; /* 选择偶数行 */
}

伪元素选择器(Pseudo-Elements)

伪元素用于选取元素的某个部分

::before::after
  • 在元素内容插入内容。
  • 示例:
    css
    p::before {
        content: "🔥 ";
        color: red;
    }
    p::after {
        content: " ✅";
        color: green;
    }
    html
    <p>CSS 选择器</p>

    结果:显示 "🔥 CSS 选择器 ✅"

::first-letter::first-line
  • ::first-letter:选取第一字母
  • ::first-line:选取第一行
css
p::first-letter {
    font-size: 24px;
    font-weight: bold;
}
p::first-line {
    color: blue;
}

属性选择器(Attribute Selectors)

[attr] 选择器
  • 选取含有该属性的元素:
    css
    [disabled] {
        background-color: gray;
    }
[attr="value"] 精确匹配
  • 选取属性值等于 "value" 的元素:
    css
    input[type="text"] {
        border: 1px solid blue;
    }
[attr~="value"] 词匹配
  • 选取属性值包含 value(独立单词) 的元素:
    css
    [title~="tooltip"] {
        color: green;
    }
[attr^="value"] 开头匹配
  • 选取属性值以 value 开头的元素:
    css
    a[href^="https://"] {
        color: blue;
    }
[attr$="value"] 结尾匹配
  • 选取属性值以 value 结尾的元素:
    css
    img[src$=".jpg"] {
        border-radius: 10px;
    }
[attr*="value"] 包含匹配
  • 选取属性值包含 value(任意位置) 的元素:
    css
    a[href*="example"] {
        color: red;
    }

层叠(Cascade)

在 CSS(层叠样式表)中,层叠(Cascade)指的是当多个规则作用于同一个元素时,浏览器会根据一系列规则来决定哪个样式生效。主要依据以下几个原则:


1. 重要性(Importance)

优先级最高的是 !important 规则:

css
p {
    color: red !important;
}
p {
    color: blue;
}

🔹 最终生效:红色(red),因为 !important 最高优先级

📌 优先级顺序(从高到低):

  1. 开发者定义的 !important 规则
  2. 开发者定义的普通样式
  3. 浏览器默认样式

2. 特异性(Specificity)

当多个规则冲突时,选择器的特异性(Specificity) 决定哪个生效。

特异性计算规则

选择器类型计算值
内联样式(style=""1000
ID 选择器(#id100
类、伪类、属性选择器(.class:hover[attr]10
元素、伪元素选择器(divp::before1
通配符、继承(*inherit0

示例

css
p { color: blue; }          /* specificity = 1 */
.class { color: red; }      /* specificity = 10 */
#id { color: green; }       /* specificity = 100 */

🔹 最终生效:绿色(#id),因为 ID 选择器的特异性最高(100 > 10 > 1)

总体规则

  • 比较特异性时,总是数值大的优先!
  • 选择器选择的越窄越优先

3. 位置与顺序(Source Order)

当两个选择器特异性相同时,后定义的规则覆盖前面的规则

css
p {
    color: red;
}
p {
    color: blue;
}

最终生效:蓝色(blue),因为它写在后面


4. 继承(Inheritance)

继承(Inheritance) 是 CSS 重要的特性之一,它允许某些属性从父元素传递给子元素,从而减少重复代码并提高可维护性。


哪些属性会被继承?

📌 文本相关属性 会自动继承:

继承的属性说明
color文字颜色
font复合字体属性
font-family字体系列
font-size字体大小
font-style字体样式(斜体等)
font-variant字体变体
font-weight字重(加粗等)
letter-spacing字母间距
line-height行高
visibility可见性
word-spacing单词间距
direction文本方向

示例

css
body {
    color: blue;
}
p {
    /* 继承 body 的 color */
}

📌 由于 color 是可继承的,<p> 里的文字颜色会自动变成 蓝色


哪些属性不会被继承?

📌 布局、盒模型、边框、背景等不会继承

非继承属性说明
margin外边距
padding内边距
border边框
width / height宽度、高度
background背景样式
display显示模式
position定位方式
z-index层级
box-shadow盒子阴影

示例

css
body {
    background: red;
}
p {
    /* 不继承背景 */
}

📌 <p> 不会继承 background: red;,仍然是默认背景。


如何控制继承?

CSS 提供了 3 种关键字来控制继承行为:

inherit(强制继承)

即使某个属性默认不会继承,也可以用 inherit 让它继承父级值:

css
p {
    background: inherit; /* 继承父元素的背景 */
}
initial(恢复默认值)

让元素回归 CSS 规范定义的默认值:

css
p {
    color: initial; /* 变回浏览器默认颜色(通常是黑色) */
}
unset(恢复继承或默认值)
  • 如果属性默认可继承unset 等于 inherit
  • 如果属性默认不可继承unset 等于 initial
css
p {
    color: unset; /* 继承父级 color */
    background: unset; /* 变回默认背景 */
}

继承的实际应用

案例:用继承统一颜色

css
body {
    color: darkblue;
    font-family: Arial, sans-serif;
}

📌 这样所有子元素的文本都会继承 colorfont-family,减少重复代码。

案例:用 inherit 让边框颜色继承

css
.container {
    border: 2px solid red;
}
.child {
    border-color: inherit;
}

📌 .child 会继承 .containerborder-color: red;


层叠规则优先级总结

优先级最高 → 最低

  1. !important
  2. 特异性(内联 > ID > 类 > 元素)
  3. 代码顺序(后定义的覆盖前面的)
  4. 继承(部分属性可继承)

"重要性 > 特异性 > 代码顺序 > 继承"
!important > Specificity > Source Order > Inheritance)

📌属性计算过程总结

浏览器会根据dom树先序遍历,依次解析并渲染节点。

其中每个节点的所有css属性会被渲染。

渲染过程如下:

<a>元素为什么不能继承

因为浏览器默认样式表中为<a>元素定义了特定的颜色值。

‌要让a元素继承父元素的颜色,可以使用CSS的inherit关键字。‌

比如:

css
a {
  color: inherit;
}

重置样式表(CSS Reset)

重置样式表(CSS Reset) 主要用于清除不同浏览器的默认样式,确保页面在各个浏览器中表现一致。


为什么需要重置样式表

不同浏览器对 HTML 元素有不同的默认样式,比如:

  • <h1> 在某些浏览器默认有 margin,而在另一些没有。
  • <button> 在不同浏览器的 paddingborder 可能不同。
  • <ul><ol> 默认有 paddinglist-style,但可能不同。

重置样式表的作用:

消除默认样式差异
提供统一的起点
增强可控性


常见的重置样式表
方法 1:Eric Meyer’s Reset.css

这是最早且最广泛使用的 CSS Reset 之一,由 CSS 专家 Eric Meyer 提供:

css
/* Eric Meyer’s Reset v2.0 (2011) */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend, table, caption,
tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote::before, blockquote::after,
q::before, q::after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}

📌 特点:

  • 全面清除 marginpaddingborder 等默认样式。
  • 去除 list-style,使 ulol 无默认列表符号。
  • table 变得紧凑,清除 border-spacing

方法 2:Normalize.css

Normalize.css 不是完全去除样式,而是让不同浏览器的默认样式更统一

🔗 官方 GitHub 地址
https://github.com/necolas/normalize.css

📌 特点:

  • 保留合理的默认样式(比如 buttoninput 的默认外观)。
  • 修正浏览器 bug(如 subsup 的对齐)。
  • 适用于现代浏览器,不像 Reset.css 那样极端清除所有样式。

适用于大多数现代项目,推荐使用!


方法 3:Minimal Reset(简化版重置)

如果不想使用 Reset.cssNormalize.css,可以使用简化版

css
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body {
    font-family: Arial, sans-serif;
    line-height: 1.6;
}

📌 特点:

  • 清除 marginpadding
  • 统一 box-sizing: border-box,防止 padding 影响尺寸计算。
  • 设定 line-height,让文本更易读。

重置方案总结
方案适用场景适合的项目
Reset.css彻底清除所有默认样式需要完全控制样式的大型项目
Normalize.css统一默认样式,不彻底清除现代网页、框架(如 Vue、React)
Minimal Reset只清除基础样式轻量级项目、快速开发

盒子(Box)

在CSS中,几乎每个元素都会生成一个“盒子”,这个盒子被称为盒模型(Box Model)。

盒类型(Box Type)

根据不同的显示需求和元素的性质,盒子模型会有所不同。常见的盒子类型有:

块盒(Block Box)

块盒(Block Box) 是指具有块级行为的元素。

特点

  • display属性是block

块级元素的默认display属性是block,即display: block;。如果没有显式设置display,则这些元素会按块级元素的方式显示。

  • 独占一行

块级元素会默认占据整行的宽度,并且在其前后会创建换行。换句话说,块级元素的默认行为就是“块状”的,占用完整的一行。例如,<div><p>等元素会自动换行。

  • 可以设置宽度和高度

块级元素的宽度默认填满其父容器的宽度,但你可以通过width属性设置其具体宽度。同时,块级元素也支持设置高度(height)。

常见的块级元素(容器元素、H1-H6、P )

  • <div>
  • <p>
  • <h1>, <h2>, <h3>, <h4>, <h5>, <h6>
  • <ul>, <ol>, <li>
  • <section>
  • <article>
  • <header>, <footer>, <main>
行盒(Inline Box)

行内盒子(Inline Box) 是指具有行内行为的元素。

特点

  • display属性是inline

行内元素的默认display属性是inline,即display: inline;。如果没有显式设置display,则这些元素会按行内元素的方式显示。

  • 不占据整行

行内元素不会独占一行,它们与其他行内元素在同一行内排列,直到空间用尽。例如,<span><a>等元素通常是在同一行内显示的,直到行宽填满为止。

  • 宽度和高度不能直接设置

行内元素的宽度和高度通常不能设置(即width和height属性对其不起作用),它们的大小由内容决定。行内元素的大小依赖于其包含的文本或其他内联元素的大小。

例如,<span>元素的宽度和高度由其中的文本内容或其他内联元素的尺寸决定。

常见的行内元素(内容)

  • <span>
  • <a>
  • <strong>
  • <em>
  • <img>
  • <b>
  • <i>
  • <br>
  • <code>
行块盒(Inline-Block Box)

行内块级盒子(Inline-Block Box) 是指具有行内元素排列方式和块级元素特性的元素。

可以简单理解为能设置宽高的行盒

行内块级元素常用于需要既有行内排列,又需要设置尺寸(如宽高)的场景。

例如,图片、按钮、链接等可以用inline-block进行布局,使得它们能够在一行内显示,并同时能够自定义大小。

Flexbox 盒子(Flexbox Box)

使用CSS的display: flex;,可以创建灵活的盒子布局。它允许在容器中按比例分配空间,元素的排列和对齐更加灵活。

参考 布局 > Flex

Grid 盒子(Grid Box)

使用CSS的display: grid;,可以创建网格布局。它允许根据行和列来控制元素的位置和大小,非常适合复杂的布局。

参考 布局 > Grid

盒模型(Box Model)

尺寸
css
width: 300px; /* 宽度 */
height: 200px; /* 高度 */
max-width: 100%; /* 最大宽度 */
min-height: 100px; /* 最小高度 */
内外边距
css
margin: 20px; /* 外边距 */
margin: 10px auto; /* 居中(左右 auto) */
padding: 15px; /* 内边距 */
边框
css
border: 2px solid black; /* 边框(宽度, 样式, 颜色) */
border-radius: 10px; /* 圆角 */
盒子阴影
css
box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.5); /* 阴影 */

📌应用

行盒的盒模型

  1. 行盒不能设置宽高,可以设置行高和padding-left、padding-right改变宽高。设置宽高最好使用行块盒。

例如,图片、按钮、链接等可以用inline-block进行布局

  1. 行盒的盒模型沿着内容延伸

  2. 行盒的padding、margin、border在水平方向有效,垂直方向无效。

设置宽高

  1. 设置宽高时,默认为 内容盒宽高,可以使用 box-sizeing: border-box; 使宽高为盒子的整体宽高。
css
* {
  box-sizing: border-box;
}
  1. 利用 aspect-ratio 保持宽高比。
css
.box {
  aspect-ratio: 16 / 9;
  width: 100%;
}
  1. 避免使用 height: 100%:​除非父元素有明确的高度,否则子元素设置 height: 100% 可能无效。
  2. marginpadding 设置百分比值是相对于包含块(containing block)的宽度计算的,而不是高度。

改变背景覆盖范围

默认情况下,背景(颜色与图片)覆盖边框,可以使用 background-clip: border-box; 使背景仅覆盖内容。

背景设置:

css
background-color: lightgray; /* 背景颜色 */
background-image: url('image.jpg'); /* 背景图片 */
background-size: cover; /* 图片尺寸(cover, contain, auto, 像素) */
background-position: center center; /* 图片位置 */
background-repeat: no-repeat; /* 是否重复 */
background-clip: border-box;

溢出处理(overflow)

  • visible - 溢流未被截断。内容在元素框外呈现
  • hidden - 溢出部分将被剪切,其余内容将不可见
  • scroll - 溢出部分被截断,并添加一个滚动条以查看其余内容
  • auto - 类似于scroll,但它只在必要时添加滚动条

除此之外,在使用浮动布局时,父元素可能无法自动包裹其内部的浮动子元素,导致高度塌陷。

可以对父元素设置 overflow 属性(如 auto 或 hidden),这将触发父元素建立新的块格式化上下文(Block Formatting Context,BFC),从而包含其浮动的子元素。

断词规则

  • word-break:​控制单词内部的断行方式,适用于需要在任意字符间断行的情况。
  • overflow-wrap(word-wrap):​处理不可分割字符串的断行,防止内容溢出容器。​

空白处理(white-space)

  • normal:这是默认值。它合并连续的空白字符为一个空格,并忽略文本开头的和结尾的空白字符。换行符会被视为一个空格处理。
  • nowrap:它同样合并连续的空白字符为一个空格,并忽略文本开头的和结尾的空白字符。但是,它不会将换行符视为一个空格,而是保留它们,这会导致文本不会换行,除非遇到<br>标签。
  • pre:此值会保留文本中的所有空白字符,包括换行符、制表符和空格。它常用于展示预格式化的文本,如代码。
  • pre-line:合并连续的空白字符为一个空格,保留换行符。文本会正常换行,就像在带有自动换行的<pre>元素中一样。
  • pre-wrap:与’pre-line’相似,但保留了文本开头的和结尾的空白字符。

单行文本溢出显示省略号

css
.single-line {
  width: 200px;          /* 设置容器宽度 */
  overflow: hidden;      /* 隐藏超出部分 */
  text-overflow: ellipsis; /* 溢出时显示省略号 */
  white-space: nowrap;   /* 禁止换行 */
}

布局(视觉格式化模型)

相关概念

包含块(Containing Block)

包含块是一个矩形区域,元素的尺寸和位置通常相对于其包含块进行计算。

大多数情况下包含块是元素最近的块级祖先元素的内容区域。​包含块的确定主要取决于元素的 position 属性。

确定规则:

  • position: static 或 relative:包含块是最近的块级祖先元素的内容区域。
  • position: absolute: 包含块是最近的 position 属性不为 static 的祖先元素的内边距区域。
  • position: fixed: 包含块是视口(viewport)。
  • position: sticky: 包含块是最近的滚动祖先元素的内容区域。

BFC (Block Formatting Context)

BFC(Block Formatting Context,块级格式化上下文)是一个独立的渲染区域,具有一套特定的布局规则。

BFC 是页面中的一块独立渲染区域,其内部的块级盒子按照特定规则进行布局。

​在 BFC 中,子元素的布局不会影响到外部元素,反之亦然。​可以将 BFC 理解为一个“结界”,内部的布局变化不会波及外部。

创建新的 BFC

  • 根元素(<html>)​
  • 设置了 float(非 none)的元素​
  • 绝对定位元素(position: absolute 或 fixed)​
  • display 为 inline-block、table-cell、table-caption、flow-root 的元素​
  • overflow 属性不为 visible 或 clip 的块级元素(如 hidden、auto、scroll)

布局规则

  • BFC 内部的块级盒子在垂直方向上一个接一个地放置。​
  • 同一个 BFC 中相邻的块级盒子的垂直外边距(margin)会发生重叠。​
  • BFC 的区域不会与浮动元素的区域重叠。​
  • 计算 BFC 的高度时,浮动子元素也会被包含在内。

常规流

总体规则:

  1. 所有元素默认属于常规流
  2. 块盒独占一行,行盒水平方向依次排列

其他详细规则参考盒子类型

宽度吸收

  1. 块盒的 content宽度 + border宽度 + padding宽度 + margin宽度 = 包含块的宽度
  2. 当设置某个盒子属性宽度为 auto时,宽度会被吸收

以上述为基础可以:

  • 块盒在块盒中垂直居中:

html

html
<div class="container">
  <div class="box">居中的盒子</div>
</div>

css

css
.container {
  width: 500px;
  background-color: lightgray;
  height: 200px;
}

.box {
  width: 200px;
  background-color: steelblue;
  margin: 0 auto;
  color: white;
  text-align: center;
  padding: 10px;
}
  • 可变宽度

html

html
<div class="container">
  <div class="box">悬浮盒子</div>
</div>

css

css
  .container {
    padding: 10px 0;
    margin: 100px;
    width: 500px;
    background-color: lightgray;
    height: 200px;
  }

  .box {
    width: auto;
    background-color: steelblue;
    margin: 0 -10px;
    color: white;
    text-align: center;
    padding: 10px;
  }

高度设置

  1. height: auto,适应内容
  2. margin: auto, 0

盒子属性百分比

  1. ​除非父元素有明确的高度,否则子元素设置 height: 100% 无效。
  2. content、border、padding、margin百分比(包括高度的百分比)均相对于包含块的宽度!

margin合并

  • 仅垂直方向合并:​只有垂直方向的外边距(即 margin-top 和 margin-bottom)会发生合并,水平方向的外边距不会合并。​
  • 相邻块级元素之间的合并:​当两个块级元素在文档流中相邻时,如果第一个元素的 margin-bottom 与第二个元素的 margin-top 接触,它们会合并为一个外边距,其大小为两者中的较大值。
  • 父元素与子元素之间的合并:​如果父元素与其第一个或最后一个子元素之间没有边框、内边距、行内内容或清除(clearance),那么它们的外边距也会合并。
  • 空块级元素的合并:​如果一个块级元素没有内容、边框或内边距,其上下外边距也会合并。


float(浮动)

float(浮动)布局是一种经典的布局方式,最初用于实现文本环绕图像的效果,后来被广泛应用于多列布局和响应式设计中。

现代布局技术(如 Flexbox 和 Grid)已逐渐取代 float

使用浮动

  • float: left:​元素向其包含块的左侧浮动。
  • float: right:​元素向其包含块的右侧浮动。
  • float: none:​默认值,元素不浮动,保持在文档流中

脱离文档流

设置了 float 的元素会脱离标准文档流,但仍保留在文本流中。

这意味着它不会占据原本在文档流中的位置,但后续的文本和行内元素会围绕它排列。

排列行为

多个浮动元素会在同一行内尽可能排列,直到空间不足时换行。

​浮动元素会尽量向其指定的方向移动,直到碰到包含块的边界或其他浮动元素。

尺寸特性

​浮动元素会自动变为块级元素,可以设置宽度和高度。

​如果未设置宽度,元素的宽度由内容决定,且不会超过其包含块的宽度。

高度坍塌

由于浮动元素脱离了文档流,后续的块级元素会忽略它的存在,导致高度坍塌:

解决方法:

  1. 使用伪元素和clear属性清除浮动(也可以直接添加一个元素)
css
.clearfix::after {
  content: "";
  display: block;
  clear: both;
}
  1. 设置 overflow 属性,触发 BFC
css
.container {
  overflow: hidden;
}


position

position 属性用于指定元素的定位方式,控制其在页面中的位置。

static(静态定位)

  • 默认值,元素按照正常文档流排列。
  • 不受 top、right、bottom、left 属性影响。
  • 元素位置由文档流决定,不可通过定位属性调整。

relative(相对定位)

  • ​元素相对于其在文档流中的原始位置进行偏移。
  • 使用 position: relative; 时,元素仍保留在文档流中,其他元素的布局不会因为其偏移而改变。
  • 相对定位常用于微调元素位置,或作为绝对定位子元素的参考点
  • 相对定位元素可以作为绝对定位子元素的包含块,便于控制子元素的位置。
css
.container {
  width: 300px;
  height: 200px;
  background-color: #f0f0f0;
  position: relative;
}

.box {
  width: 100px;
  height: 100px;
  background-color: #4CAF50;
  /* position: relative;
  top: 20px;
  left: 30px; */
}

css
.container {
  width: 300px;
  height: 200px;
  background-color: #f0f0f0;
  position: relative;
}

.box {
  width: 100px;
  height: 100px;
  background-color: #4CAF50;
  position: relative;
  top: 20px;
  left: 30px;
}

absolute(绝对定位)

  • 脱离文档流:​绝对定位的元素脱离了正常的文档流,不会占据空间,其他元素会忽略它的存在。​
  • 定位参考:​绝对定位元素的位置是相对于最近的非 static 定位祖先元素(如relative)进行计算的。如果没有这样的祖先元素,则相对于文档的初始包含块进行定位。​
  • 常见用途:​绝对定位常用于创建弹出层模态框工具提示等需要精确定位的界面元素。
css
.container {
    position: relative;
    width: 400px;
    height: 300px;
    background-color: #f0f0f0;
    border: 1px solid #ccc;
}

.absolute-box {
    /* position: absolute;
    top: 20px;
    right: 20px; */
    width: 150px;
    height: 100px;
    background-color: #4CAF50;
    color: white;
    padding: 10px;
    box-sizing: border-box;
  }

css
.container {
    position: relative;
    width: 400px;
    height: 300px;
    background-color: #f0f0f0;
    border: 1px solid #ccc;
}

.absolute-box {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 150px;
    height: 100px;
    background-color: #4CAF50;
    color: white;
    padding: 10px;
    box-sizing: border-box;
}

fixed(固定定位)

  • 脱离文档流: ​使用 position: fixed; 的元素脱离了正常的文档流,不会占据空间,其他元素的布局不会受到其影响。​
  • 定位参考: ​固定定位的元素是相对于浏览器的视口进行定位的,而不是相对于其父元素。​
  • 堆叠上下文: ​固定定位的元素会创建一个新的堆叠上下文,可以通过 z-index 属性控制其在页面中的堆叠顺序。​
  • 兼容性问题: ​在某些情况下,如果固定定位的元素的祖先元素设置了 transformfilterperspective 等属性,可能会导致固定定位失效,元素会相对于该祖先元素进行定位,而不是视口。

常见应用场景

  • 固定导航栏(Sticky Header): 将导航栏固定在页面顶部,确保用户在滚动页面时始终可以访问导航菜单。​

  • 固定底部工具栏(Sticky Footer): 在页面底部固定显示工具栏、版权信息或其他重要链接,提升用户体验。​

  • 浮动按钮(Floating Action Button): 在页面的角落固定显示操作按钮,如“返回顶部”或“联系客服”,方便用户操作。​

  • 通知条和提示框(Notification Bars): 在页面顶部或底部固定显示通知信息,确保用户在浏览页面时不会错过重要提示。​

  • 侧边栏(Sidebar): 将侧边栏固定在页面的一侧,常用于显示社交媒体链接、广告或其他辅助信息。

  • 后台管理系统

css
.fixed-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  background-color: #4CAF50;
  color: white;
  padding: 15px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  z-index: 1000;
  /* 设置透明度便于展示 */
  /* opacity: 0.8; */
}

.content {
  margin-top: 70px;
  /* 留出导航栏的空间 */
  padding: 20px;
}

sticky(粘性定位)

position: sticky 结合了 relativefixed 定位的特性。

当元素在页面滚动到达指定位置时,它会固定在视口的位置,直到其容器元素的边界被触及。

css
.content {
  height: 2000px;
}

.sticky-header {
  position: -webkit-sticky;
  /* Safari支持 */
  position: sticky;
  top: 0;
  /* 滚动到页面顶部时开始固定 */
  background-color: #4CAF50;
  color: white;
  padding: 10px;
  text-align: center;
  font-size: 20px;
  z-index: 1000;
  /* 保证导航栏显示在其他内容上方 */
}


flexbox 布局

CSS 的 flexbox 布局是一种用于在容器中分布空间和对齐元素的布局模式,尤其适用于一维(行或列)布局。

基础概念

  • 容器(Flex Container)display: flexdisplay: inline-flex 使元素成为 flex 容器。它的直接子元素会自动成为 flex 项目。
    • display: flex: 创建一个块级的 flex 容器。
    • display: inline-flex: 创建一个内联的 flex 容器。
  • 项(Flex Items):容器中的子元素称为 flex 项目。默认情况下,flex 项目会在容器中水平排列。

对容器的控制

  • flex-direction:定义主轴的方向(即项目的排列方式)。

    • row:水平排列(默认)。
    • column:垂直排列。
    • row-reverse:水平反向排列。
    • column-reverse:垂直反向排列。
  • flex-wrap:决定项目是否换行。

    • nowrap:不换行(默认)。
    • wrap:换行。
    • wrap-reverse:反向换行。
  • justify-content:沿主轴(水平轴或垂直轴)对齐项目。

    • flex-start:靠起始位置对齐。
    • flex-end:靠结束位置对齐。
    • center:居中对齐。
    • space-between:项目之间的间隔相等,第一个和最后一个项目贴着容器边缘。
    • space-around:项目之间的间隔相等,但容器边缘也有间隔。
  • align-items:沿交叉轴(与主轴垂直的方向)对齐项目。

    • flex-start:交叉轴的起始位置对齐。
    • flex-end:交叉轴的结束位置对齐。
    • center:交叉轴的中间对齐。
    • baseline:项目的基线对齐。
    • stretch:默认,项目拉伸以填充容器。
  • align-content:当有多行项目时,用来控制多行之间的对齐。

    • flex-startflex-endcenterspace-betweenspace-aroundstretch

对项的控制

  • flex-grow:指定项目的扩展因子,决定项目如何分配剩余空间。默认值为 0,即不扩展。

    • 1 表示项目会占据多余空间的份额。
  • flex-shrink:指定项目的收缩因子,决定在空间不足时如何收缩。默认值为 1,即允许收缩。

    • 0 表示项目不会收缩。
  • flex-basis:设置项目在主轴方向上的初始大小。它可以是任何有效的 CSS 长度单位,或者是 auto(根据项目的内容大小来确定)。

  • flex:是 flex-grow, flex-shrink, 和 flex-basis 的简写。比如,flex: 1 等同于 flex-grow: 1; flex-shrink: 1; flex-basis: 0%

  • align-self:允许单个项目覆盖 align-items 设置来指定该项目在交叉轴上的对齐方式。

    • auto:继承父容器的对齐方式。
    • flex-startflex-endcenterbaselinestretch

示例:

css
/* Flex 容器样式 */
.container {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

/* 页头样式 */
header {
  background-color: #4CAF50;
  color: white;
  padding: 10px;
  text-align: center;
}

/* 主体区域样式 */
main {
  display: flex;
  flex: 1;
  flex-direction: row;
  padding: 10px;
  gap: 10px;
}

/* 侧边栏样式 */
aside {
  background-color: #f4f4f4;
  width: 200px;
  padding: 10px;
}

/* 内容区域样式 */
section {
  flex: 1;
  background-color: #f9f9f9;
  padding: 10px;
}

/* 页脚样式 */
footer {
  background-color: #333;
  color: white;
  text-align: center;
  padding: 10px;
}

/* 响应式设计:当屏幕宽度小于 768px 时,调整布局 */
@media (max-width: 768px) {
  main {
    flex-direction: column;
  }

  aside {
    width: 100%;
  }
}

与 float的区别

特性FloatFlex
布局方式一维布局,适合简单的文本环绕布局一维布局,适合灵活的行或列布局
脱离文档流浮动元素脱离文档流,需要清除浮动保持在文档流中,自动调整对齐和间距
对齐控制需要额外的对齐方法,如 text-align支持强大的对齐方法,如 justify-content 和 align-items
响应式不太灵活,需要手动调整非常灵活,支持响应式设计
支持换行需要额外技巧或清除浮动内建支持换行功能 (flex-wrap)

grid 布局

Grid 是一个二维的布局系统,可以同时处理行和列的布局,使得复杂的网页布局更容易实现。

Grid 布局非常适合用来构建响应式设计、复杂的网格系统和页面结构。

基础概念

  • 容器(Grid Container): 通过设置 display: griddisplay: inline-grid 来创建一个 Grid 容器。容器中的所有直接子元素都会成为 Grid 项目(Grid Items)。
  • 网格线(Grid Lines): Grid 布局的主要特性之一,网格的行和列通过网格线(即 grid lines)来定义。每一行和每一列都有编号,可以通过这些编号来控制元素的位置。

基础属性

  • display: grid:将元素指定为 Grid 容器。
  • grid-template-columns:定义列的宽度,可以是一个或多个值,用空格分开。也可以使用 fr 单位来设置灵活的列宽。
  • grid-template-rows:定义行的高度,可以是一个或多个值,用空格分开。
  • grid-template-areas:通过命名区域来为网格项分配位置,使得布局更具可读性。
  • grid-column:控制一个元素跨越的列数(从第几列开始,到第几列结束)。
  • grid-row:控制一个元素跨越的行数(从第几行开始,到第几行结束)。
  • gap(或 grid-gap):定义网格项目之间的间隔。
  • justify-itemsalign-items:控制网格项目在其单元格内的对齐方式。

示例

html
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Grid 布局示例</title>
  <style>
    /* 设置全局样式 */
    body {
      margin: 0;
      font-family: Arial, sans-serif;
    }

    /* Grid 容器 */
    .container {
      display: grid;
      /* 两列布局,第一列占 1/4 宽度,第二列占 3/4 */
      grid-template-columns: 1fr 3fr;
      /* 三行布局,第一行为导航栏,自适应;第二行为主内容;第三行为页脚 */
      grid-template-rows: 1fr 3fr 1fr;

      grid-template-areas:
        /* 页头横跨两列 */
        "header header"
        /* 侧边栏在左,内容区在右 */
        "sidebar content"
        /* 页脚横跨两列 */
        "footer footer";
      /* 设置网格项之间的间隙 */
      gap: 10px;

    }

    /* 页头样式 */
    header {
      background-color: #4CAF50;
      color: white;
      padding: 20px;
      grid-area: header;
      text-align: center;
    }

    /* 侧边栏样式 */
    aside {
      background-color: #f4f4f4;
      padding: 20px;
      grid-area: sidebar;
    }

    /* 主内容样式 */
    article {
      background-color: #fafafa;
      padding: 20px;
      grid-area: content;
    }

    /* 页脚样式 */
    footer {
      background-color: #333;
      color: white;
      text-align: center;
      padding: 10px;
      grid-area: footer;
    }

    /* 响应式设计:小屏幕时,侧边栏和内容区竖排 */
    @media (max-width: 768px) {
      .container {
        grid-template-columns: 1fr;
        /* 切换为单列布局 */
        grid-template-areas:
          "header"
          "content"
          "sidebar"
          "footer";
        /* 各区域从上到下排列 */
      }
    }
  </style>
</head>

<body>

  <div class="container">
    <!-- 页头 -->
    <header>
      <h1>css grid 示例</h1>
    </header>

    <!-- 侧边栏 -->
    <aside>
      Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ullam, rem inventore neque et minus culpa, sequi hic at
      facere in iusto. Quas quis consequatur modi sapiente, perferendis deserunt facere? Illo!
    </aside>

    <!-- 主内容区 -->
    <article>
      Lorem ipsum dolor sit amet consectetur, adipisicing elit. Id beatae ad in consequuntur quis voluptate quisquam
      suscipit? Unde tempore sit facilis temporibus illo provident culpa odio odit maxime. Vitae, quo.
    </article>

    <!-- 页脚 -->
    <footer>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore similique recusandae eveniet corrupti quod
        pariatur itaque perferendis veritatis natus beatae ratione tempore, voluptates culpa repellendus eum quaerat
        odit perspiciatis doloremque!</p>
    </footer>
  </div>

</body>

</html>


📌应用

后台管理系统布局

html
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>后台管理系统布局</title>
  <style>
    /* 全局样式 */
    body {
      margin: 0;
      font-family: Arial, sans-serif;
      box-sizing: border-box;
    }

    /* Flex 容器 */
    .container {
      display: flex;
      /* 纵向排列 */
      flex-direction: column;
      /* 视口高度 */
      height: 100vh;
      /* 也可以使用fixed布局实现填充视口高度 */
      /* position: fixed;
      height: 100%; */
    }

    /* 页头 */
    header {
      background-color: #4CAF50;
      color: white;
      padding: 10px;
      text-align: center;
    }

    /* 主体部分 */
    .main {
      display: flex;
      /* 吸收剩余空间 */
      flex: 1;
      /* 防止溢出 */
      overflow: hidden;
    }

    /* 侧边栏 */
    .sidebar {
      background-color: #f4f4f4;
      width: 250px;
      padding: 20px;
      /* 侧边栏内容溢出时显示滚动条 */
      overflow-y: auto;
      /* 侧边栏充满主区域的高度 */
      /* 父元素有高度 */
      height: 100%;

    }

    /* 主内容 */
    .content {
      /* 吸收剩余空间 */
      flex: 1;
      padding: 20px;
      overflow-y: auto;
      /* 主内容区域溢出时显示滚动条 */
      background-color: #fafafa;
    }

    /* 页脚 */
    footer {
      background-color: #333;
      color: white;
      text-align: center;
      padding: 10px;
    }

    /* 响应式设计 */
    @media (max-width: 768px) {
      .main {
        /* 屏幕较小,侧边栏和主内容垂直排列 */
        flex-direction: column;
      }

      .sidebar {
        width: 100%;
        height: auto;
      }
    }
  </style>
</head>

<body>

  <div class="container">
    <!-- 页头 -->
    <header>
      <h1>后台管理系统</h1>
    </header>

    <!-- 主体区域 -->
    <div class="main">
      <!-- 侧边栏 -->
      <aside class="sidebar">
        <h2>导航</h2>
        <ul>
          <li>首页</li>
          <li>用户管理</li>
          <li>设置</li>
          <li>报告</li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
        </ul>
      </aside>

      <!-- 主内容区域 -->
      <div class="content">
        <h2>欢迎来到后台管理系统</h2>
        <p>这里是内容区,可以放置表格、图表等内容。</p>

        <p>这里是一些内容,假设内容很长,所以会导致滚动条出现...</p>
        <div style="height: 1500px;">Lorem*1000</div>
      </div>
    </div>

    <!-- 页脚 -->
    <footer>
      <p>© 2025 我的后台系统</p>
    </footer>
  </div>

</body>

</html>

📌其他常见 CSS 样式表总结

文本样式(Typography)

字体
css
font-family: Arial, sans-serif; /* 设置字体 */
font-size: 16px; /* 字体大小 */
font-weight: bold; /* 字体粗细(normal, bold, lighter, 100-900) */
font-style: italic; /* 斜体(normal, italic, oblique) */
line-height: 1.5; /* 行高 */
letter-spacing: 2px; /* 字母间距 */
word-spacing: 5px; /* 单词间距 */
文本颜色与对齐
css
color: #333; /* 文字颜色 */
text-align: center; /* 对齐方式(left, center, right, justify) */
text-decoration: underline; /* 文本修饰(none, underline, line-through) */
text-transform: uppercase; /* 文字大小写(uppercase, lowercase, capitalize) */
文本阴影
css
text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5); /* 文字阴影(水平, 垂直, 模糊度, 颜色) */

过渡与动画(Transitions & Animations)

过渡
css
transition: all 0.3s ease-in-out;
动画
css
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}
.element {
    animation: fadeIn 1s ease-in-out;
}

媒体查询(响应式设计)

css
@media (max-width: 600px) {
    body {
        background-color: lightblue;
    }
}

水平居中

  1. 行内元素(如 <span>
css
父元素 {
  text-align: center;
}
  1. 块级元素(如 <div>)固定宽度
css
元素 {
  margin: 0 auto;
  width: 200px;
}
  1. 使用 Flex 布局
css
父元素 {
  display: flex;
  justify-content: center;
}

垂直居中

  1. 行内元素或表格单元格(需要设置 line-height
css
元素 {
  line-height: 与父元素高度一致;
}
  1. 使用 vertical-align(需配合 display: table-cell
css
父元素 {
  display: table-cell;
  vertical-align: middle;
}
  1. 使用 Flex 布局
css
父元素 {
  display: flex;
  align-items: center;
}
  1. 使用绝对定位 + transform
css
元素 {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

水平 + 垂直 居中

  1. 使用 Flex 布局(推荐现代方法)
css
父元素 {
  display: flex;
  justify-content: center;
  align-items: center;
}
  1. 使用 Grid 布局(更简单)
css
父元素 {
  display: grid;
  place-items: center;
}
  1. 使用绝对定位 + transform
css
元素 {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

其他方式居中(绝对定位元素)

  1. 使用 margin: auto 自动居中(适合固定尺寸)
css
元素 {
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 0;
  margin: auto;
  width: 固定宽度;
  height: 固定高度;
}

Document Base on VitePress.