列表、表格、表单 — 三类部件的默认样式与重置
列表、表格、表单 — 三类部件的默认样式与重置
原书拆成第 19、20、21 三章,合并讲——三章是同一件事的三个实例: HTML 这三类部件都带浏览器默认样式,长得不受你控制; CSS 要做自定义,第一步永远是「先重置,再重建」。 每章各配几个即取即用的标准模式(横向导航、斑马纹表格、自定义复选框)。
1. 这一章在全书链条里的位置
前面所有章节的属性都是「原料」,这一章是「成品车间」:导航条、数据表格、登录表单—— 网页上最常见的三类界面,各自怎么从默认长相加工成定制外观。 它们也是「用户代理样式」(user agent styles)这个概念的主战场: 浏览器给每个元素垫的默认样式,平时看不见,一自定义就撞上来1。
2. 顶层全景:重置 → 重建
三类部件的通用工序:
浏览器默认长相 ──▶ ① 重置(剥掉默认) ──▶ ② 重建(用自己的样式) ──▶ ③ 标准模式(导航/斑马纹/…)
图说:每章都走这条流水线。「重置不干净」是三类部件共同的头号毛病。3. 列表(原书第 19 章)
默认的 <ul>(无序列表)有两个自带件:圆点(marker)和左边约 40px 的缩进。
第一章工具:list-style-type 换记号形状——disc(默认圆点)、circle、square,
有序列表的 decimal(数字)、lower-roman(罗马数字)等;none 则彻底去掉2。
重置的两个动作都要做:list-style: none 去圆点,padding: 0 去缩进——
只去圆点不去缩进,列表会留下一块推不掉的左边距,这是书里点名的初学者陷阱
(那 40px 在 padding 里,不在 margin 里)3。
主线例子:从列表到横向导航
输入:一个普通的纵向链接列表,输出:顶部导航条。
nav ul {
list-style: none; /* ① 去圆点 */
padding: 0; /* ② 去缩进(margin: 0 顺手) */
margin: 0;
display: flex; /* ③ 横排(第 06 章) */
gap: 20px;
}四行,网页上出现率最高的 CSS 片段之一:重置两行 + Flex 两行4。 「列表拿来当导航」正是「语义标签 + 视觉重建」的标准操作——HTML 说它是列表, CSS 说它是横排按钮。
::marker:只给圆点/编号染色,不碰文字:
li::marker { color: red; font-weight: bold; font-size: 1.5em; }效果:记号又大又红又粗,列表文字原样5。书里注明了它的能力边界:
marker 只接受颜色、字体、content 等少数属性,不能做边距和复杂定位6。
想要完整的自定义记号(emoji、对勾),改用 ::marker { content: "✅ " } 或
list-style: none + li::before 的路子——后者更可控,也是本书给的备选7。
4. 表格(原书第 20 章)
默认表格有两个毛病:相邻单元格各画各的边框(双线网格,挤)、 列宽由内容决定(一个长 URL 把整表撑变形)。三个工具:
border-collapse:双线并单线
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid black; }collapse 让相邻边框合并成一条,清清爽爽;默认的 separate 是各自为战8。
配套的 border-spacing 只在 separate 模式下有效(调两条线间距),日常很少用9。
table-layout:自动 vs 固定
auto(默认):列宽跟着内容走,内容长列就宽,不可预测。fixed:列宽只看表格总宽和第一行,内容再长也保持列宽——更快、更稳10。
宽表一律 fixed;第一行是表头,正好用它把列宽定死。
主线例子:一张好用的数据表
table { border-collapse: collapse; width: 100%; table-layout: fixed; }
th, td { padding: 10px; text-align: left; }
tbody tr:nth-child(even) { background-color: #f2f2f2; } /* 斑马纹 */
tbody tr:hover { background-color: #ddd; } /* 悬停高亮 */
th { position: sticky; top: 0; background: white; } /* 表头钉住 */走一遍:双线并单线;列宽定死不再被长内容撑开;padding 给单元格留白——
注意 padding 只能写在 td/th 上,写在 tr 上无效,书里的「padding 陷阱」11;
nth-child(even) 隔行染色,长表扫读不累(斑马纹是本章模式的第一个)12;
长表格滚动时表头用 sticky 钉在视口顶(top: 0 + 底色必给,否则透出下面的行)13。
移动端最后一招:整表裹一层 overflow-x: auto 的 div,小屏横向滑表格而不是撑破版面14。
两个底线:表格只为数据服务,排版布局用 Flex/Grid,别用 table15;
表头用 <th>、分区用 <thead>/<tbody>,屏幕阅读器靠它们报读表格16。
5. 表单(原书第 21 章)
表单控件(输入框、按钮、下拉框)是自定义最难的一类——它们不是普通盒子, 而是系统原生控件(浏览器调用操作系统的件),各家长得都不一样(Chrome 的聚焦蓝圈、 iOS 的圆角按钮),这就是用户代理样式在这章的主场17。
基础定制两件套
input[type="text"], textarea {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box; /* 必给:否则 padding 把 100% 宽顶破(第 04 章) */
font-size: 1rem;
}输入框的第一课:box-sizing: border-box,书里标为 essential18。
状态伪类:表单的主战场
input:focus { border-color: blue; box-shadow: 0 0 5px rgba(0,0,255,0.5); }
input:disabled { background: #eee; color: #888; cursor: not-allowed; }
input:invalid { border-color: red; }
input:required { border-left: 5px solid orange; }
input::placeholder { color: #999; font-style: italic; }五个状态各管一景:聚焦(focus)、禁用(disabled)、内容不合法(invalid)、
必填(required)、占位提示文字(::placeholder)。
focus 样式有一条 Accessibility 红线:可以换样式,不能没样式——
书里严禁「outline: none 之后不给任何替代」:键盘用户靠聚焦环确认自己在哪,
你把它抹了,等于对键盘用户关灯。正确姿势是 outline: none 的同时给一个
box-shadow 或 border 的替代聚焦样式19。顺带:iOS 上输入框字号小于 16px,
用户一点击浏览器就自动放大页面——正文输入框字号设 16px 是移动端纪律20。
appearance: none——总重置开关
select {
appearance: none; /* 剥掉系统皮肤(箭头、圆角) */
background: url('arrow.svg') no-repeat right center;
padding-right: 30px; /* 给自制箭头让位 */
}appearance: none 是表单重置的总开关:下拉框的箭头、iOS 按钮的圆角,
全靠它剥掉再自己画21。自定义复选框是这套思路的完整版,也是主线例子的第三段。
主线例子第三段:自定义复选框
输入:系统复选框丑得没法品牌化,要求「换成 18px 方框,勾选时变黑底白勾」。
input[type="checkbox"] { display: none; } /* ① 藏真身 */
input[type="checkbox"] + label::before { /* ② 伪元素画假框 */
content: ""; display: inline-block;
width: 18px; height: 18px;
border: 2px solid #333; vertical-align: middle;
}
input[type="checkbox"]:checked + label::before { /* ③ 勾选态换肤 */
background: #333; content: "✓"; color: white; text-align: center;
}走一遍三步:真复选框藏起来(不是删——它的选中状态还在,第 ②③ 步全挂钩在 :checked 上);
+(相邻兄弟选择器,第 02 章)选中紧跟其后的 label,用 ::before 画一个 18px 假框;
勾选时假框变黑底、content 换成白勾。点击 label 等于点击复选框(HTML 的 label for 关联),
所以真身藏起来也不影响用——这也是书里提醒的:这类结构依赖正确的 label 关联22。
配套的按钮三态(默认/悬停/按下)是同一套伪类:
.btn:active { transform: translateY(1px); } /* 按下去沉 1px */:active 是「正在被按住」的瞬间,配一个微小的下沉,按钮就有了手感23。
6. 作者的判断与证据
- 「list-style: none 是 UI 布局的起点」——用法定位,附「记得连 padding 一起清」的实操提醒3。
- 「表格只为数据,别做布局」——行业铁律断言,附屏幕阅读器的理由1516。
- 「outline: none 必须配替代样式」——可访问性硬约束,给了具体理由(键盘导航)19。
- 「iOS 小于 16px 会缩放」——平台行为事实,可作为可核验断言20。
- 证据类型同全书:经验断言 + 最小例子,表单章的断言最接近「可核验事实」。
7. 边界与局限
- 表单一章没讲
:focus-visible(只在键盘聚焦时给样式,鼠标点击不打扰)—— 当代可访问性的推荐做法,本书未收;也没讲:focus-within(聚焦在子元素上时给父级样式)。 - 自定义复选框模式没提可访问性细节(真身
display: none会让部分屏幕阅读器跳过该控件, 更稳妥的藏法是 visually-hidden 技巧)——本书的模式能用,但非最优。 - 表格章没讲响应式表格的「数据转卡片」方案,只给了横向滚动一种。
- ::marker 的能力边界给了,但没说清楚哪些属性可用(实际规范只放行一小撮)。
判断(我们的,不是书里的): 「重置 → 重建」作为三章的统一骨架,是本章合并后最清晰的部分—— 原书三章各自重复这个节奏,合并讲一次反而把共性显出来了。三份重置清单 (list-style+padding / border-collapse / appearance)可以抄成一页 cheatsheet。 如果错,会错在: 现代组件库大多自带样式重置(Normalize、Tailwind preflight), 手写重置的需求在下降;但对「想知道默认值从哪来」的学习者,手Reset 仍是必经之路。
8. 可带走的
- 列表重置两动作:
list-style: none+padding: 0(缩进在 padding 里)3。 - 横向导航 = 重置 +
display: flex; gap: 20px;4。 ::marker只染记号不染字,能力有限,复杂记号用::before56。- 表格三件套:collapse、table-layout: fixed、斑马纹
nth-child(even)81012。 - padding 不能写在 tr 上,只能写在 td/th11。
- 输入框必带
box-sizing: border-box18。 - 抹 outline 必须给替代聚焦样式;iOS 输入框字号 ≥ 16px1920。
- 自定义复选框三步:藏真身、伪元素画框、
:checked换肤——靠的是 label 关联和相邻兄弟选择器22。
9. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 列表容器/项/记号 | Chapter 19: List Styling | text/20-ch01-1-chapter-overview.txt:19(搜「Marker」) |
| list-style-type 取值 | 同上 | text/20-ch01-1-chapter-overview.txt:29(搜「list-style-type」) |
| 40px 缩进陷阱 | 同上 | text/20-ch01-1-chapter-overview.txt:134(搜「40px」) |
| 横向导航模式 | 同上 | text/20-ch01-1-chapter-overview.txt:110(搜「Horizontal Navigation」) |
| ::marker 示例与边界 | 同上 | text/20-ch01-1-chapter-overview.txt:94(搜「::marker」);:138 搜「limited set」 |
| 边框两种模式 | Chapter 20: Table Styling | text/21-ch01-1-chapter-overview.txt:21(搜「Border Models」) |
| border-collapse | 同上 | text/21-ch01-1-chapter-overview.txt:29(搜「border-collapse」) |
| table-layout auto/fixed | 同上 | text/21-ch01-1-chapter-overview.txt:62(搜「table-layout」);:81 搜「renders faster」 |
| 斑马纹 | 同上 | text/21-ch01-1-chapter-overview.txt:113(搜「Zebra Striping」) |
| 粘性表头 | 同上 | text/21-ch01-1-chapter-overview.txt:124(搜「Sticky Table Header」) |
| 移动端横滚外套 | 同上 | text/21-ch01-1-chapter-overview.txt:134(搜「Responsive Table Wrapper」) |
| padding 陷阱与表格布局禁令 | 同上 | text/21-ch01-1-chapter-overview.txt:151(搜「Padding Trap」);:149 搜「Never use」 |
| 用户代理样式 | Chapter 21: Forms & UI States | text/22-ch01-1-chapter-overview.txt:21(搜「User Agent Styles」) |
| 输入框基础样式 | 同上 | text/22-ch01-1-chapter-overview.txt:31(搜「textarea」) |
| focus 与 outline 红线 | 同上 | text/22-ch01-1-chapter-overview.txt:59(搜「:focus」);:166 搜「outline: none」 |
| appearance: none | 同上 | text/22-ch01-1-chapter-overview.txt:101(搜「appearance」) |
| 自定义复选框 | 同上 | text/22-ch01-1-chapter-overview.txt:138(搜「Custom Checkbox」) |
| iOS 16px 缩放 | 同上 | text/22-ch01-1-chapter-overview.txt:168(搜「zoom」) |
| 按钮三态 | 同上 | text/22-ch01-1-chapter-overview.txt:117(搜「Modern Button States」) |
Footnotes
-
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:21,搜「User Agent Styles」)。原文:「The default look browsers give to inputs (e.g., the blue glow in Chrome).」 ↩ -
出处:「Chapter 19: List Styling」(
text/20-ch01-1-chapter-overview.txt:29,搜「list-style-type」)。原文常用值:disc、circle、square、decimal、lower-alpha、lower-roman、none。 ↩ -
出处:「Chapter 19: List Styling」(
text/20-ch01-1-chapter-overview.txt:134,搜「40px」)。原文:「bullets are usually held inside a 40px padding-left on the <ul> element. If you set list-style: none, remember to also set padding: 0.」 ↩ ↩2 ↩3 -
出处:「Chapter 19: List Styling」(
text/20-ch01-1-chapter-overview.txt:110,搜「Horizontal Navigation」)。原文模式:nav ul { list-style: none; padding: 0; margin: 0; display: flex; gap: 20px; }。 ↩ ↩2 -
出处:「Chapter 19: List Styling」(
text/20-ch01-1-chapter-overview.txt:94,搜「::marker」;:106搜「large, red, and bold」)。原文:「The bullet or number will be large, red, and bold, while the text of the list item remains unchanged.」 ↩ ↩2 -
出处:「Chapter 19: List Styling」(
text/20-ch01-1-chapter-overview.txt:138,搜「limited set」)。原文:「::marker only allows a limited set of properties (color, font, content). You cannot use it for margins or complex positioning.」 ↩ ↩2 -
出处:「Chapter 19: List Styling」(
text/20-ch01-1-chapter-overview.txt:124,搜「Emoji」)。原文:「Using the content property on the ::marker to use emojis or custom symbols.」;自定义图像的建议(背景图 + padding-left 或 ::before)见第 136 段。 ↩ -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:29,搜「border-collapse」;:47搜「merge」)。原文:「With collapse, the borders between cells merge into single lines. This is the most common setting for modern web tables.」 ↩ ↩2 -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:49,搜「border-spacing」)。原文:「Sets the distance between the borders of adjacent cells (only works if border-collapse is set to separate).」 ↩ -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:62,搜「table-layout」;:81搜「renders faster」)。原文:fixed「Column width is determined by the width of the table and the width of the first row of cells」,「Fixed layout renders faster and prevents long URLs or text from stretching the table unexpectedly.」 ↩ ↩2 -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:151,搜「Padding Trap」)。原文:「You cannot apply padding to the <tr> (row) element. Padding must be applied directly to <td> or <th> elements.」 ↩ ↩2 -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:113,搜「Zebra Striping」)。原文:「Adding a background color to every other row to improve readability of large datasets.」,tbody tr:nth-child(even) { background-color: #f2f2f2; }。 ↩ ↩2 -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:124,搜「Sticky Table Header」)。原文:「Keeping the header visible while scrolling through a long table.」,示例th { position: sticky; top: 0; background-color: white; z-index: 10; }。 ↩ -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:134,搜「Responsive Table Wrapper」)。原文:「Wrapping the table in a container with overflow is the standard fix.」 ↩ -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:149,搜「Never use」)。原文:「Never use <table> for page layouts (columns, sidebars). Use Flexbox or Grid instead. Tables should only be used for data.」 ↩ ↩2 -
出处:「Chapter 20: Table Styling」(
text/21-ch01-1-chapter-overview.txt:155,搜「<thead>」)。原文:「Always use <th> for header cells and include a <thead> and <tbody>. This helps screen readers interpret the data correctly.」 ↩ ↩2 -
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:7,搜「most difficult」)。原文:「Form elements… are among the most difficult parts of a webpage to style consistently across different browsers.」 ↩ -
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:176,搜「mandatory」;:42搜「Essential」)。原文:「Inputs should always use box-sizing: border-box」,示例注释「Essential for inputs」。 ↩ ↩2 -
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:166,搜「outline: none」)。原文:「Never use outline: none without providing a visible box-shadow or border for the :focus state. This breaks navigation for keyboard users.」 ↩ ↩2 ↩3 -
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:168,搜「zoom」)。原文:「On iOS, if your input font size is smaller than 16px, the browser will automatically zoom in when the user taps the input. Set font-size: 16px to prevent this.」 ↩ ↩2 ↩3 -
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:101,搜「appearance」)。原文:「Allows you to remove the default browser styling of an element (like the arrow on a select menu or the roundness of a button on iOS).」 ↩ -
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:138,搜「Custom Checkbox」)。原文:「Since checkboxes are hard to style, we hide the original and style a pseudo-element.」;label 关联见第 170 段:「Always use <label for="id">… CSS styles like :focus-within or sibling selectors rely on correct structure.」 ↩ ↩2 -
出处:「Chapter 21: Forms & UI States」(
text/22-ch01-1-chapter-overview.txt:135,搜「push」)。原文:「.btn:active { transform: translateY(1px); /* Slight "push" effect */ }」 ↩