第19章 display属性与文档流

第十九章:display 属性与文档流

CSS 布局的核心是"文档流"——浏览器默认排列元素的方式。而 display 属性则是控制元素如何参与文档流的关键。理解这两个概念,就等于掌握了 CSS 布局的第一把钥匙。想象一下,文档流就像河流,元素就像河里的船只,display 属性决定了你是一艘货船(块级)还是一艘快艇(行内)。

19.1 文档流

19.1.1 浏览器默认布局方式——块级元素垂直排列,行内元素水平排列

文档流(Document Flow)是浏览器默认的布局方式。简单来说,就是浏览器按照 HTML 文档中的顺序,依次排列页面上元素的方式。

什么是文档流?

想象一下排队买东西:有些人"占地方"很大,一个人就要占一整排(块级元素);有些人很小,可以好几个人挤在一排(行内元素)。文档流就是这个"排队规则"——浏览器按照这个规则把元素排列在页面上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!-- 文档流的简单示例 -->

<!-- 块级元素:每个占一整行 -->
<div>我是块级元素1,占一整行</div>
<div>我是块级元素2,占一整行</div>
<div>我是块级元素3,占一整行</div>

<!-- 行内元素:多个可以在一行 -->
<span>行内1</span>
<span>行内2</span>
<span>行内3</span>

<!-- 混合 -->
<div>这是块级div</div>
<p>这也是块级p</p>
<span>这是行内span,</span>
<strong>这也是行内strong,</strong>
<em>还有行内em</em>

文档流的排列规则:

文档流排列示意:

块级元素排列(垂直):
┌────────────────────────┐
│      块级元素 1         │ ← 独占一行
├────────────────────────┤
│      块级元素 2         │ ← 独占一行
├────────────────────────┤
│      块级元素 3         │ ← 独占一行
└────────────────────────┘

行内元素排列(水平):
┌────────────────────────────────────┐
│ [行内1] [行内2] [行内3] → →
└────────────────────────────────────┘

19.1.2 块级元素——div、p、h1、ul、li、section、article 等,默认宽度 100%,独占一行

块级元素(Block-level Elements)是文档流中的"大块头"。它们的特点是:独占一行,可以设置宽高,宽度默认是父元素的 100%。

常见的块级元素:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- 常见块级元素 -->
<div>通用块级容器</div>
<p>段落,段落之间有上下间距</p>
<h1>一级标题,字号最大</h1>
<h2>二级标题</h2>
<h3>三级标题</h3>
<h4>四级标题</h4>
<h5>五级标题</h5>
<h6>六级标题,字号最小</h6>
<ul>无序列表
  <li>列表项1</li>
  <li>列表项2</li>
</ul>
<ol>有序列表
  <li>列表项1</li>
  <li>列表项2</li>
</ol>
<li>列表项(块级)</li>
<section>语义化区块</section>
<article>文章内容</article>
<aside>侧边栏</aside>
<nav>导航栏</nav>
<header>头部区域</header>
<footer>底部区域</footer>
<main>主要内容</main>
<form>表单</form>
<table>表格</table>
<address>地址信息</address>

块级元素的特点:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* 块级元素的默认特点 */

.block-element {
  /* 1. 独占一行 */
  display: block;  /* 默认值 */

  /* 2. 宽度默认是父元素的100% */
  width: 100%;  /* 默认值,不需要写 */

  /* 3. 高度由内容决定(除非设置明确高度)*/
  height: auto;  /* 默认值 */

  /* 4. 可以设置宽高 */
  width: 300px;
  height: 200px;

  /* 5. 可以设置外边距和内边距 */
  margin: 20px;
  padding: 20px;

  /* 6. 上下外边距会折叠 */
  margin-top: 10px;
  margin-bottom: 20px;
  /* 实际间距可能只有20px(取较大值)*/
}

19.1.3 行内元素——span、a、strong、em 等,默认宽度由内容决定,不独占一行

行内元素(Inline Elements)是文档流中的"小个子"。它们的特点是:不独占一行,多个行内元素可以排在一行,宽度由内容决定。

常见的行内元素:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!-- 常见行内元素 -->
<span>通用行内容器</span>
<a href="#">链接,蓝色带下划线</a>
<strong>强调文本,加粗</strong>
<em>斜体文本,强调</em>
<b>加粗文本</b>
<i>斜体文本</i>
<u>带下划线文本</u>
<s>带删除线文本</s>
<mark>高亮文本</mark>
<small>小号文本</small>
<sub>下标</sub>
<sup>上标</sup>
<img src="photo.jpg" alt="图片(虽然是替换元素,但行为类似行内)">
<button>按钮(块级元素,但可以和其他元素在一行)</button>
<input type="text"> <!-- 输入框(替换元素),是自闭合空元素 -->
<label>标签</label>
<br>换行(空元素)

行内元素的特点:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* 行内元素的默认特点 */

.inline-element {
  /* 1. 不独占一行 */
  display: inline;  /* 默认值 */

  /* 2. 宽度由内容决定 */
  width: auto;  /* 默认值,无法设置固定宽度 */

  /* 3. 高度由内容决定 */
  height: auto;

  /* 4. 水平方向的外边距和内边距有效 */
  margin-left: 10px;
  margin-right: 10px;
  padding-left: 10px;
  padding-right: 10px;

  /* 5. ⚠️ 垂直方向的外边距和内边距不占据布局空间 */
  margin-top: 50px;   /* ⚠️ 不生效,行内元素垂直外边距不参与块级布局计算 */
  margin-bottom: 50px;  /* ⚠️ 不生效,同上 */
  padding-top: 50px;     /* ⚠️ 不占据块级布局空间,可能被裁剪 */
  padding-bottom: 50px;  /* ⚠️ 不占据块级布局空间,可能被裁剪 */
  /* 注意:行内元素的垂直 margin 不会像块级元素那样折叠,而是直接应用于元素本身 */

  /* 6. ⚠️ 不能设置固定宽高 */
  width: 200px;   /* ⚠️ 不生效 */
  height: 100px;  /* ⚠️ 不生效 */
}

块级元素 vs 行内元素对比:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 对比示例 */

.block-box {
  display: block;
  width: 300px;  /* ✅ 有效 */
  height: 100px;  /* ✅ 有效 */
  margin: 20px;  /* ✅ 有效 */
  padding: 20px;  /* ✅ 有效 */
  background-color: #3498db;
  color: white;
  text-align: center;
}

.inline-box {
  display: inline;
  width: 300px;  /* ⚠️ 无效! */
  height: 100px;  /* ⚠️ 无效! */
  margin: 20px;  /* ✅ 左右有效,上下无效 */
  padding: 20px;  /* ✅ 左右有效,上下可能显示但占空间 */
  background-color: #2ecc71;
  color: white;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<div class="block-box">
  块级元素:独占一行,可以设置宽高
</div>

<span class="inline-box">
  行内元素:不独占一行,多个可以并排
</span>
<span class="inline-box">
  另一个行内元素
</span>

行内元素如何"变块级":

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/* 使用 display 属性改变元素类型 */

.inline-as-block {
  display: block;  /* 变成块级元素 */
  width: 200px;   /* 现在有效了 */
  margin: 10px auto;  /* 可以居中了 */
}

.block-as-inline {
  display: inline;  /* 变成行内元素 */
  /* width 和 height 失效了 */
  /* 但可以和别的元素排在一行 */
}

💡 小技巧:理解文档流是 CSS 布局的基础。记住:块级元素独占一行,行内元素可以并排。如果想让块级元素并排,使用 display: inline-blockfloatflex

19.2 display 属性值

19.2.1 display: block——块级,独占一行,可设宽高

display: block 将元素设置为块级元素。这是 CSS 中最常用的显示方式之一。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* display: block 的特点 */

/* 1. 独占一行 */
.block-element {
  display: block;
}

/* 2. 可以设置宽高 */
.block-element {
  display: block;
  width: 300px;
  height: 200px;
}

/* 3. 宽度默认100% */
.full-width {
  display: block;
  /* width: 100% 是默认值 */
}

/* 实际应用 */
.card {
  display: block;
  width: 100%;
  max-width: 400px;
  padding: 20px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
1
2
3
4
5
6
7
8
9
<!-- display: block 的元素会独占一行 -->
<div class="block-element">
  我是一个块级元素
</div>

<!-- 可以设置宽高 -->
<div class="card">
  我是一个卡片,可以设置宽高
</div>

19.2.2 display: inline——行内,不独占一行,宽高由内容决定

display: inline 将元素设置为行内元素。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* display: inline 的特点 */

/* 1. 不独占一行 */
.inline-element {
  display: inline;
}

/* 2. 宽高由内容决定,无法设置固定宽高 */
.inline-element {
  display: inline;
  width: 300px;   /* ⚠️ 无效 */
  height: 200px;  /* ⚠️ 无效 */
}

/* 3. 只能设置水平方向的 margin 和 padding */
.inline-element {
  display: inline;
  margin-left: 10px;   /* ✅ 有效 */
  margin-right: 10px;
  padding-left: 10px;  /* ✅ 有效 */
  padding-right: 10px;
  margin-top: 20px;    /* ⚠️ 垂直方向不占据空间 */
  padding-top: 20px;   /* ⚠️ 可能显示但不占空间 */
}
1
2
3
4
<!-- 多个 inline 元素可以在一行 -->
<span class="inline-element">行内1</span>
<span class="inline-element">行内2</span>
<span class="inline-element">行内3</span>

19.2.3 display: inline-block——对外像行内(不独占一行),对内像块级(可设宽高)

display: inline-blockinlineblock 的"混血儿"。对外它像行内元素(不独占一行),对内它像块级元素(可以设置宽高)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* display: inline-block 的特点 */

/* 1. 不独占一行(对外像行内)*/
.inline-block-element {
  display: inline-block;
}

/* 2. 可以设置宽高(对内像块级)*/
.inline-block-element {
  display: inline-block;
  width: 200px;    /* ✅ 有效 */
  height: 100px;   /* ✅ 有效 */
}

/* 3. 多个 inline-block 可以在一行 */
.nav-item {
  display: inline-block;
  width: 100px;
  height: 40px;
  background-color: #3498db;
  color: white;
  text-align: center;
  line-height: 40px;
}
1
2
3
4
5
6
7
<!-- 多个 inline-block 可以并排 -->
<nav>
  <span class="nav-item">首页</span>
  <span class="nav-item">产品</span>
  <span class="nav-item">关于</span>
  <span class="nav-item">联系</span>
</nav>

inline-block vs block vs inline 对比:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* display 属性值对比 */

/* block:独占一行,可以设置宽高 */
.demo-block {
  display: block;
  width: 200px;
  height: 100px;
  margin: 10px;
  background-color: #3498db;
}

/* inline:不独占一行,不能设置宽高 */
.demo-inline {
  display: inline;
  margin: 10px;
  padding: 10px;
  background-color: #2ecc71;
}

/* inline-block:混合体,不独占一行但可以设置宽高 */
.demo-inline-block {
  display: inline-block;
  width: 200px;
  height: 100px;
  margin: 10px;
  padding: 10px;
  background-color: #e74c3c;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!-- 对比效果 -->

<div class="demo-block">block1</div>
<div class="demo-block">block2</div>
<!-- 两个block各占一行 -->

<span class="demo-inline">inline1</span>
<span class="demo-inline">inline2</span>
<span class="demo-inline">inline3</span>
<!-- 三个inline在一行,但宽高设置无效 -->

<span class="demo-inline-block">inline-block1</span>
<span class="demo-inline-block">inline-block2</span>
<!-- 两个inline-block在一行,且可以设置宽高 -->

19.2.4 display: none——不显示,不占据空间(不同于 visibility:hidden)

display: none 会让元素完全消失,不仅不可见,而且不占据任何空间。这与 visibility: hidden 不同。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* display: none 的特点 */

/* 1. 完全不显示 */
.hidden-element {
  display: none;
  /* 元素从页面布局中完全消失 */
}

/* 2. 不占据空间 */
.no-space {
  display: none;
  /* 下面的元素会"顶上来"填补空位 */
}

/* 实际应用:响应式显示/隐藏 */
.desktop-only {
  display: none;
}

@media (min-width: 768px) {
  .desktop-only {
    display: block;  /* 大屏幕显示 */
  }

  .mobile-only {
    display: none;  /* 大屏幕隐藏 */
  }
}
1
2
3
4
5
<!-- display: none 的元素完全不存在于布局中 -->
<div class="hidden-element">
  看不到我,也占不了我的空间
</div>
<div>我会顶上去填补空位</div>

display: none vs visibility: hidden 对比:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/* 两种隐藏方式的对比 */

/* display: none */
.display-none {
  display: none;  /* 完全消失,不占空间 */
}

/* visibility: hidden */
.visibility-hidden {
  visibility: hidden;  /* 不可见,但占空间 */
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!-- visibility: hidden:元素不可见,但空间还在 -->
<div style="visibility: hidden;">
  我不可见,但我占的位置还在
</div>
<div>我会紧贴在我下面的元素,不会填补上面的空位</div>

<!-- display: none:元素完全消失,空间也被回收 -->
<div style="display: none;">
  我完全消失,空间也被回收了
</div>
<div>我会顶上去填补空位</div>

19.2.5 display: contents——让容器本身消失,只影响子元素的布局,常用于消除父容器对布局的影响

display: contents 是一个比较"奇怪"的值。它会让元素的盒子完全消失,但保留子元素的渲染。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/* display: contents 的特点 */

/* 1. 元素的盒子消失 */
.contents-element {
  display: contents;
  /* 这个元素本身不产生任何盒子 */
  /* 但它的子元素仍然正常渲染 */
}

/* 2. 常用于消除不必要的包装容器 */
.card-wrapper {
  display: contents;
  /* 容器消失,但里面的内容还在 */
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!-- 原始结构 -->
<article class="card-wrapper">
  <h2>标题</h2>
  <p>内容段落</p>
  <img src="image.jpg" alt="图片">
</article>

<!-- display: contents 后,相当于变成 -->
<!-- <h2>标题</h2>
     <p>内容段落</p>
     <img src="image.jpg" alt="图片"> -->

display: contents 的实用场景:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 1. 消除布局影响的父容器 */
.grid-wrapper {
  /* 这个wrapper本来会影响布局 */
  display: contents;
  /* 现在它消失了,但子元素正常渲染 */
}

/* 2. Semantic wrapper without layout impact */
.article-header {
  /* 你可能需要一个语义化的header包裹 */
  display: contents;
  /* 但不想它影响布局 */
}

/* 3. 配合CSS Grid使用 */
.grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

.grid-item-wrapper {
  display: contents;
  /* 子元素直接成为grid项目 */
}

19.2.6 display: flow-root——创建新的 BFC,最简单的清除浮动方案

display: flow-root 是一个专门用来创建 BFC(Block Formatting Context)的值。它就像是一个"结界",让元素内部的布局与外部隔离。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/* display: flow-root 的特点 */

/* 1. 创建新的 BFC */
.flow-root-element {
  display: flow-root;
  /* 这个元素内部形成独立的格式化上下文 */
}

/* 2. 清除浮动(最简单的方案)*/
.clearfix {
  display: flow-root;
  /* 子元素的浮动不会溢出 */
}

overflow: hidden vs display: flow-root 清除浮动对比:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 方案1:overflow: hidden(传统方案)*/
.clearfix-overflow {
  overflow: hidden;  /* 副作用:可能裁剪内容 */
  /* 会创建 BFC */
}

/* 方案2:display: flow-root(现代方案,推荐)*/
.clearfix-flow-root {
  display: flow-root;  /* 更语义化,没有副作用 */
  /* 会创建 BFC */
}

/* 方案3:clearfix 伪元素(经典方案)*/
.clearfix::after {
  content: "";
  display: block;
  clear: both;
}

/* 方案4:display: flow-root(最简洁)*/
.flow-root-wrapper {
  display: flow-root;
  /* 直接使用,无需伪元素 */
}

19.2.7 visibility: hidden——不显示,但占据空间

visibility: hiddendisplay: none 都会让元素不可见,但有一个关键区别:visibility: hidden 会保留元素占据的空间

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/* visibility: hidden 的特点 */

/* 1. 不可见 */
.hidden {
  visibility: hidden;
}

/* 2. 占据空间 */
.space-reserved {
  visibility: hidden;
  /* 下面的元素不会填补空位 */
}

/* 3. 子元素可以被 visibility: visible 恢复 */
.parent-hidden {
  visibility: hidden;
}

.child-visible {
  visibility: visible;  /* 子元素可以恢复显示 */
}
1
2
3
4
5
6
7
<!-- visibility: hidden:不可见但空间保留 -->
<div class="hidden" style="height: 100px; background: red;">
  我不可见,但我的100px高度还在
</div>
<div style="background: blue;">
  我会紧贴在红色块的下方,不会填补空位
</div>

19.2.8 visibility: collapse——用于表格行/列隐藏,不占据空间

visibility: collapse 主要用于表格,与 display: none 类似,但它只用于表格元素。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
/* visibility: collapse 的特点 */

/* 用于表格行或列时 */
tr.collapse {
  visibility: collapse;  /* 行隐藏且不占空间 */
}

colgroup.collapse {
  visibility: collapse;  /* 列隐藏且不占空间 */
}

/* 用于其他元素时,等同于 hidden */
div.collapse {
  visibility: collapse;  /* 等同于 visibility: hidden */
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<table>
  <tr>
    <td>第1行</td>
    <td>数据</td>
  </tr>
  <tr class="collapse">
    <td>第2行(被隐藏)</td>
    <td>数据</td>
    <!-- 这行会完全消失,不占空间 -->
  </tr>
  <tr>
    <td>第3行</td>
    <td>数据</td>
  </tr>
</table>

💡 小技巧display: flow-root 是目前最简洁的清除浮动方案,比传统的 clearfix 伪元素方案更现代、更易读。

19.3 inline-block 间隙问题

19.3.1 间隙产生原因——HTML 中的换行符被浏览器解析为空格

使用 display: inline-block 时,你可能会发现元素之间莫名其妙地出现了一个小间隙。这个间隙是由于 HTML 中的换行符(回车)被浏览器解析为空格导致的。

什么是 inline-block 间隙?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/* 间隙问题演示 */

.inline-block-wrapper {
  font-size: 0;  /* 解决方案:把父元素字体设为0,消除换行产生的空格 */
}

.inline-block-item {
  display: inline-block;
  width: 100px;
  height: 100px;
  background-color: #3498db;
  font-size: 16px;  /* 子元素要恢复字体大小 */
}

19.3.2 解决方法——父元素设置 font-size: 0; 或用注释拼接元素、或用 flex 替代

解决方案1:设置父元素 font-size: 0

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/* font-size: 0 解决方案 */

.no-gap-wrapper {
  font-size: 0;  /* 把父元素的字体设为0 */
}

.no-gap-item {
  display: inline-block;
  width: 100px;
  height: 100px;
  font-size: 16px;  /* 子元素必须恢复字体大小 */
  margin: 0;         /* 可以配合 margin 消除间距 */
}

解决方案2:使用注释消除换行符

1
2
3
4
<!-- 使用注释消除换行符 -->
<div class="inline-block-item">1</div><!--
--><div class="inline-block-item">2</div><!--
--><div class="inline-block-item">3</div>

解决方案3:使用 Flexbox 替代

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/* Flexbox 替代方案 */

.flex-wrapper {
  display: flex;  /* 使用 Flexbox 代替 inline-block */
  gap: 10px;     /* 使用 gap 控制间距 */
}

.flex-item {
  width: 100px;
  height: 100px;
  background-color: #3498db;
}

/* 这是最推荐的现代方案 */

完整示例对比:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* 有间隙的 inline-block */
.with-gap {
  display: inline-block;
  width: 100px;
  height: 100px;
  background-color: #3498db;
  color: white;
  text-align: center;
  line-height: 100px;
}

/* 解决方案1:font-size: 0 */
.font-size-zero-wrapper {
  font-size: 0;  /* 消除换行符产生的空格 */
}

.font-size-zero-wrapper .with-gap {
  font-size: 16px;  /* 子元素恢复字体 */
}

/* 解决方案2:使用 flexbox */
.flex-wrapper {
  display: flex;
  gap: 0;  /* 无间隙,无需额外设置子元素 */
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!-- 有间隙的布局 -->
<div class="with-gap">1</div>
<div class="with-gap">2</div>
<div class="with-gap">3</div>
<!-- 元素之间会有几像素的间隙 -->

<!-- 无间隙的布局 -->
<div class="flex-wrapper">
  <div class="with-gap">1</div>
  <div class="with-gap">2</div>
  <div class="with-gap">3</div>
</div>
<!-- 使用 flexbox,没有间隙问题 -->

19.4 appearance

19.4.1 appearance: none——去除浏览器默认样式,如去除按钮原生样式、去除 select 下拉箭头

appearance 属性用于去除浏览器的原生外观,让元素可以完全通过 CSS 自定义样式(注意:各浏览器前缀是必须的)。

什么是 appearance

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* appearance: none 重置默认样式 */

/* 去除按钮原生样式 */
.reset-button {
  appearance: none;
  -webkit-appearance: none;  /* Safari/Chrome */
  -moz-appearance: none;    /* Firefox */
  background: none;
  border: none;
  cursor: pointer;
}

/* 去除 select 下拉箭头 */
.reset-select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("arrow.png");  /* 自定义箭头 */
  background-position: right center;
  background-repeat: no-repeat;
  padding-right: 30px;
}

appearance 的实用场景:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* 1. 自定义复选框 */
.checkbox-wrapper {
  display: flex;
  align-items: center;
  cursor: pointer;
}

.custom-checkbox {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 20px;
  height: 20px;
  border: 2px solid #ddd;
  border-radius: 4px;
  margin-right: 10px;
  cursor: pointer;
  position: relative;
}

.custom-checkbox:checked {
  background-color: #3498db;
  border-color: #3498db;
}

.custom-checkbox:checked::after {
  content: "✓";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: white;
  font-size: 14px;
}

/* 2. 自定义单选框 */
.radio-wrapper {
  display: flex;
  align-items: center;
  cursor: pointer;
  margin-bottom: 10px;
}

.custom-radio {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 20px;
  height: 20px;
  border: 2px solid #ddd;
  border-radius: 50%;
  margin-right: 10px;
  cursor: pointer;
  position: relative;
}

.custom-radio:checked {
  border-color: #3498db;
}

.custom-radio:checked::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 10px;
  height: 10px;
  background-color: #3498db;
  border-radius: 50%;
}

/* 3. 自定义下拉框 */
.custom-select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 100%;
  padding: 12px 40px 12px 16px;
  border: 2px solid #ddd;
  border-radius: 8px;
  background-color: white;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23333' stroke-width='2'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px;
  cursor: pointer;
}

.custom-select:focus {
  outline: none;
  border-color: #3498db;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 自定义复选框 -->
<label class="checkbox-wrapper">
  <input type="checkbox" class="custom-checkbox">
  <span>我同意用户协议</span>
</label>

<!-- 自定义单选框 -->
<label class="radio-wrapper">
  <input type="radio" name="gender" class="custom-radio">
  <span></span>
</label>
<label class="radio-wrapper">
  <input type="radio" name="gender" class="custom-radio">
  <span></span>
</label>

<!-- 自定义下拉框 -->
<select class="custom-select">
  <option>选项1</option>
  <option>选项2</option>
  <option>选项3</option>
</select>

本章小结

恭喜你完成了第十九章的学习!让我们来回顾一下这章的精华:

核心知识点

属性说明
display: block块级元素,独占一行,可设宽高
display: inline行内元素,不独占一行,不可设宽高
display: inline-block行内块级,混合体
display: none完全消失,不占空间
display: contents元素盒子消失,子元素保留
display: flow-root创建新 BFC,清除浮动
visibility: hidden不可见,但占空间
appearance: none重置浏览器默认样式

display 属性值对比

graph TD
    A["display 属性"] --> B["block"]
    A --> C["inline"]
    A --> D["inline-block"]
    A --> E["none"]
    A --> F["contents"]
    A --> G["flow-root"]

    B --> B1["独占一行 ✅"]
    B1 --> B2["可设宽高 ✅"]
    C --> C1["不独占一行 ✅"]
    C1 --> C2["不可设宽高 ❌"]
    D --> D1["不独占一行 ✅"]
    D1 --> D2["可设宽高 ✅"]
    E --> E1["不显示 ✅"]
    E1 --> E2["不占空间 ✅"]
    F --> F1["盒子消失 ✅"]
    F1 --> F2["子元素保留 ✅"]
    G --> G1["创建BFC ✅"]
    G1 --> G2["清除浮动 ✅"]

实战建议

  1. inline-block 间隙:使用 Flexbox 替代是最现代的解决方案
  2. 清除浮动display: flow-root 是最简洁的方案
  3. 自定义表单元素:使用 appearance: none 配合自定义样式

下章预告

下一章我们将学习格式化上下文(Formatting Context),理解 BFC 和 IFC 是掌握高级布局的关键!