主题
CSS 常用属性与CSS 选择器(Day6 3/4)
本页对应 Day06_CSS,共 5 段视频,约 55 分钟。
学习目标
- 能够使用
cursor属性设置default、pointer、move、none等鼠标光标样式,并使用url(...)加回退值实现自定义光标。 - 能够使用
list-style-type、list-style-position、list-style-image及list-style复合属性设置列表项标记,并判断样式对ul、ol、li及其他元素是否生效。 - 能够使用
table-layout、border-spacing、border-collapse、caption-side、empty-cells等表格专用属性完成列宽固定、单元格边框合并等表格样式设置。 - 能够编写后代元素选择器(空格),选中指定元素内部所有符合条件的后代元素,并准确判断匹配结果。
- 能够编写子元素选择器(
>),仅选中指定元素的直接子元素,并与后代选择器对比区分匹配范围;能够混合使用两种选择器并判断最终匹配结果。
知识点
说明:本节笔记未提供可嵌入的图片文件,转写稿中提到的光标图、列表项小火箭/火焰图均以代码中的图片路径说明保留。
鼠标光标样式:cursor
为什么需要:普通元素悬停时仍是箭头,但链接会变小手,文字会变文本光标。开发者需要用 cursor 主动告诉用户“这里可点”“这里可拖动”“这里别点”。
怎么想:先判断元素默认行为,再决定是否覆盖。常见值只需记 pointer(小手)和 move(移动图标);none 可隐藏光标,但属于特殊效果;自定义光标要用图片 URL,并补一个备用值。
怎么做:
css
.box {
width: 600px;
height: 250px;
background: #eee;
}
.box:hover {
cursor: pointer;
}
.custom {
/* 自定义图片后必须再跟一个常见值作为备用 */
cursor: url("./a23.png"), pointer;
}
a {
cursor: pointer;
}易错点:只写 cursor: url("./a23.png"); 可能无效。转写稿中调试时,检查元素发现属性值无效,原因是 URL 后缺少逗号备用值。写成 url(...), pointer 才生效。另外 none 会让光标“失踪”,商业项目少用。
列表样式:list-style 系列
为什么需要:ul/ol 自带小黑点或数字,但实际网页常要去掉默认图标,再用背景图、伪元素或自定义图片做更统一的列表标记。列表样式还决定标记在 li 里面还是外面。
怎么想:先明确选择器选到的是 ul/ol 还是 li。list-style-type 管图标类型,list-style-position 管位置,list-style-image 管自定义图片,list-style 是复合属性。实际开发第一步常写 list-style: none; 去掉默认标记。
怎么做:
css
.news {
list-style-type: none; /* 最常用:去掉默认图标 */
}
.news li {
list-style-type: square; /* disc/circle/square/decimal/lower-alpha/upper-roman 等 */
list-style-position: inside;/* 默认 outside,在 li 外面 */
}
.news li.custom {
list-style-image: url("./fire.png");
}
.news li {
list-style: url("./rocket.png") inside;
}易错点:列表样式只对 ul、ol、li 这类列表标签有效,给 p 设置 list-style-type: disc 不会出现小黑点。复合属性 list-style 会覆盖前面分开写的子属性;图片不能乱用大图,否则列表标记会撑得很大。inside 会让标记进入 li 内容区,outside 在外部。
表格样式:table 专用属性
为什么需要:旧表格常用 cellspacing、cellpadding 等 HTML 属性控制样式,学了 CSS 后应改用 CSS。表格列宽还会受内容影响,数据一长列就变宽,需要固定列宽。
怎么想:先给 table 设宽度,再给 td, th 设边框和内边距。列宽用 table-layout: fixed 固定;单元格间距用 border-spacing;相邻边框合并用 border-collapse: collapse;标题位置用 caption-side;空单元格显隐用 empty-cells。
怎么做:
css
table {
width: 800px;
table-layout: fixed; /* 列宽固定,平均分配 */
border-spacing: 10px; /* 单元格间距 */
border-collapse: collapse; /* 合并相邻单元格边框 */
caption-side: bottom; /* 标题在表格下方,默认 top */
empty-cells: hide; /* 隐藏无内容单元格,默认 show */
}
td, th {
border: 1px solid #999;
padding: 10px;
}
caption {
font-size: 24px;
font-weight: 800;
}易错点:table-layout、border-spacing、border-collapse、caption-side、empty-cells 这些表格专用属性只对 table 生效,设给 td/th 不好使。设了 border-collapse: collapse 后,border-spacing 无效,因为相邻单元格已共用一条边框。empty-cells: hide 在合并边框时也不容易看出效果,需先取消合并边框观察。
后代元素选择器
为什么需要:页面结构常有“列表套列表”,如果直接写 li 会选中所有层级的 li。后代选择器可以限定“某个祖先里面的所有后代”,让选择更精确。
怎么想:从左往右读,先找选择器一,再在它的后代中找选择器二。后代不限层级,子级、孙级都算。类名、标签名可组合,也可写多层。
怎么做:
css
.news li {
border: 1px solid red;
}
.news ol li {
border: 1px solid red;
}易错点:.news li 会选中 .news 里所有层级的 li,不只是直接子级。写多层时不要漏空格;空格表示“后代”,不是普通装饰。
子元素选择器
为什么需要:有时只想选直接子级,不想选孙级。比如 .news > li 只控制外层列表项,嵌套列表项不受影响。
怎么想:把后代选择器中的空格换成 >。> 两边常加空格只为可读,语法上不是必须。它只匹配直接子元素。
怎么做:
css
.news > li {
border: 1px solid red;
}
.news > li > ol {
border: 1px solid red;
}易错点:.news > li 选不到孙级 li;.news ol 能选到后代中的 ol,但 .news > ol 选不到,因为 ol 不是 .news 的直接子元素。后代选择器与子元素选择器可混搭,如 .news ul > li,但读的时候要逐层分析。
小结
本节核心是“专用属性要设对元素”:cursor 记 pointer、move,自定义光标加备用值;列表样式只对列表标签有效,常先用 list-style: none 清默认标记;表格五个专用属性只设给 table,合并边框后 border-spacing 失效;选择器里空格是后代,> 是直接子元素。
鼠标光标样式:cursor
为什么需要:鼠标悬停在元素上时,默认箭头、文字光标、超链接小手并不总够用;通过 cursor 可以提示“可点击”“可移动”“等待”等交互状态。
怎么想:先记住最常用的两个值:pointer 表示小手,move 表示移动图标;特殊效果如 none、wait、text 了解即可。自定义光标要用图片 URL,并给出回退值。
怎么做:
css
.book {
width: 600px;
height: 250px;
background: #eee;
cursor: pointer; /* 小手,最常用 */
}
.pic {
cursor: move; /* 移动图标,常见于商品放大镜 */
}
a {
cursor: url("./rocket.cur"), pointer;
}转写稿中调试自定义光标时,只写 cursor: url(...) 会被浏览器判为无效,需要写成 url(...), pointer,表示图片不可用时回退为小手。
易错点:cursor 不是 csor;只写 URL 容易无效;图片路径要正确;none 会让光标“失踪”,属于恶搞;商业项目通常只用 pointer、move 等常见值。
列表样式:list-style 系列
为什么需要:ul/ol/li 的语义是列表,但默认小黑点、数字不一定是设计需要的;CSS 可以在保留语义的同时改图标、改位置、换图片。
怎么想:实际开发常先 list-style: none; 去掉默认图标,再用背景图或伪元素自行装饰;需要保留系统符号时再用 list-style-type。
怎么做:
css
.news {
list-style: none; /* 最常用:去掉默认图标 */
}
.news li {
width: 560px;
padding: 20px;
margin-bottom: 10px;
background: #f5f5f5;
}
.music {
list-style: decimal inside;
}
.news {
list-style: url("./fire.png") inside;
}转写稿中用给 li 设宽度、内边距、背景的方式观察范围,从而看清 outside 在 li 外面、inside 在 li 里面。
易错点:列表样式只对 ul/ol/li 有效,给 p 设置无效;ul/ol 自带约 40px 左内边距,缩进结构来自它;list-style 复合属性会覆盖子属性;自定义图片不能过大,否则列表项会被撑坏;outside/inside 受 li 范围影响。
表格样式:用 CSS 替代表格旧属性
为什么需要:以前用 table 的 cellspacing 等 HTML 属性做样式,结构和表现混在一起;学 CSS 后应把样式交给 CSS。
怎么想:通用属性如宽高、内边距可给 table/td/th;表格专用属性如 table-layout、border-spacing、border-collapse、caption-side、empty-cells 只对 table 生效。
怎么做:
css
table {
width: 800px;
table-layout: fixed;
border-collapse: collapse; /* 合并相邻单元格边框 */
}
td, th {
border: 1px solid #999;
padding: 10px;
}
caption {
font-size: 24px;
font-weight: 800;
}转写稿调试:table-layout: fixed; 后列宽平均分配,长地址自动换行,避免列宽被内容撑得忽宽忽窄;border-spacing: 10px; 可设单元格间距,但设置 border-collapse: collapse; 后间距无效。
易错点:表格专用属性设置给 td/th 不好使,只能设给 table;border-collapse 合并的是单元格边框,不是合并单元格;合并边框后 border-spacing 无效;empty-cells: hide 在合并边框下不易看出效果;caption-side: bottom 虽可用但很少用。
后代元素选择器:空格
为什么需要:页面结构常有嵌套,只想选“某个容器里的所有某类元素”,需要比单个类名更精确。
怎么想:从左往右读:先找选择器一,再从它的所有后代中找选择器二;后代不限直接子级,层级可多层。
怎么做:
css
.news li {
border: 1px solid red;
}
.news ol .item {
border: 1px solid red;
}转写稿中 .news li 会选中 .news 里所有 li,包括嵌套列表中的 li;.news ol .item 可三层混搭。
易错点:空格不能省;选的是所有后代,不是只有子元素;ID 语法上可参与但一般少与组合选择器混用;全局选择器权重低,少参与复杂组合。
子元素选择器:>
为什么需要:只想选直接子级,避免把深层后代也选进来。
怎么想:A > B 表示先找 A,再只从 A 的直接子元素中找 B。
怎么做:
css
.news > li {
border: 1px solid red;
}
ul > li {
border: 1px solid red;
}
.news > li > ol {
border: 1px solid red;
}
.news ul > li {
border: 1px solid red; /* 可与后代选择器混搭 */
}转写稿对比:.news li 会选中所有后代 li;改成 .news > li 后,嵌套在 ol 里的 li 选不中,因为它不是 .news 的直接子元素。> 两边空格只为好看,不是后代选择器的空格含义。
易错点:> 只认直接子元素;.news > ol 选不到深层 ol;不要把它和后代选择器混为一谈;多层组合可以,但要从左到右逐层验证。
课堂画面





代码示例
示例一:鼠标光标样式(cursor)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>鼠标光标样式</title>
<style>
.book {
width: 600px;
height: 250px;
background: #eee;
cursor: pointer; /* 最常用:小手 */
}
.book p {
width: 560px; /* 560 + 左右内边距 20*2 = 600 */
margin: 20px;
padding: 0 20px;
background: #ccc;
}
/* 超链接默认就是 pointer,这里故意改成“移动”图标 */
.book a {
cursor: move; /* 第二个常用值:移动十字 */
}
.none { cursor: none; } /* 光标消失,恶搞用 */
.text { cursor: text; } /* 文本竖线光标 */
.custom {
/* 自定义光标:url(图片路径), 兜底关键字 —— 兜底值不能省 */
cursor: url(./images/a23.cur), pointer;
}
</style>
</head>
<body>
<div class="book">
<p>普通段落:鼠标放到文字上是文本光标,放到 p 的空白处还是箭头。</p>
<a href="#">超链接:这里被我改成了 move 图标</a>
</div>
<div class="book none">cursor: none,鼠标放上来就“失踪”了</div>
<div class="book text">cursor: text</div>
<div class="book custom">自定义光标(图片不存在时退回 pointer)</div>
</body>
</html>关键行与易错点
cursor是继承属性,写在.book上,整块区域(包括p)都变成小手;a单独覆盖成move才生效。- 默认
cursor: default就是“该什么样就什么样”,一般元素不用写。 - 自定义光标语法必须是
cursor: url(路径), 关键字;——只写url(...)浏览器会判定“属性值无效”,检查元素里能看到删除线。 - 兜底关键字写什么都行(
pointer、move等),意思是“图片加载不出来时用它”。 - 实战只记两个值:
pointer(小手)、move(移动),自定义光标属奇技淫巧。
示例二:列表样式(list-style)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>列表样式</title>
<style>
/* 1. 列表项图标类型 */
.news {
list-style-type: square; /* 实心圆 disc(默认) / 空心圆 circle / 方块 square / 数字 / 字母 / 罗马数字 */
}
/* 2. 列表项图标位置:默认 outside(在 li 外面),inside 在 li 里面 */
li {
width: 300px;
padding: 10px;
margin-bottom: 10px;
background: #f5f5f5;
list-style-position: inside;
}
/* 3. 复合属性:一句话搞定类型 + 位置 + 自定义图片 */
.music {
list-style: none; /* 最常用:先去掉自带图标 */
}
.music li {
list-style: url(./images/fire.png) outside; /* 自定义图片当列表图标 */
}
/* 4. 只给某几个 li 单独设置 */
.music .active {
list-style: url(./images/fire.png) inside;
}
</style>
</head>
<body>
<ul class="news">
<li>新闻一</li>
<li>新闻二</li>
<li>新闻三</li>
</ul>
<hr>
<ol class="music">
<li>音乐排行榜 1</li>
<li class="active">音乐排行榜 2</li>
<li>音乐排行榜 3</li>
</ol>
</body>
</html>关键行与易错点
- 用
ul还是ol取决于语义,不是看前面是小圆点还是数字——图标完全可以被 CSS 改掉(ul也能显示数字)。 list-style-type: none是最常用的值:实际项目里 99% 的列表都会先去掉自带图标,再自己用背景图等方式做“点”。list-style-position只有两个值:outside(默认,图标在 li 外面)、inside(图标进入 li 内部)。想看出区别,必须先给li设宽度、内边距、背景色,否则看不到 li 的范围。list-style复合属性一写,前面单独写的list-style-type等子属性全部失效;多个值用空格分隔,无顺序、无数量要求。list-style-image的图片尺寸不能乱选,图太大图标会撑爆;且它同样受list-style-position影响。- 列表样式只能设置给
ul/ol/li,给p、div设置一概无效。
示例三:表格样式 + 后代/子元素选择器
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>表格样式与选择器</title>
<style>
table {
width: 800px;
table-layout: fixed; /* 列宽固定,各列平均分,内容多就换行 */
border-collapse: collapse; /* 合并相邻单元格边框,真正 1px */
/* border-spacing: 10px; 与 collapse 冲突,写了也无效 */
}
td, th {
border: 1px solid #999;
padding: 10px;
}
caption {
font-size: 24px;
font-weight: 800;
caption-side: top; /* 默认值;改成 bottom 标题跑到表格下方 */
}
/* empty-cells: hide; 隐藏没有内容的单元格(需配合 border-collapse: separate 才看得出来) */
/* 后代选择器:空格。找 .news 里“所有后代”中的 li(含嵌套层) */
.news li {
border: 1px solid red;
}
/* 子元素选择器:> 。只找 .news 的“直接子元素” li */
/* .news > li { border: 1px solid red; } */
/* 混搭:先找 .news 的后代 ul,再找它的直接子元素 li */
/* .news ul > li { border: 1px solid blue; } */
</style>
</head>
<body>
<table>
<caption>用户信息表</caption>
<thead>
<tr><th>姓名</th><th>年龄</th><th>电话</th><th>地址</th></tr>
</thead>
<tbody>
<tr>
<td>张三</td><td>20</td><td>13800000000</td>
<td>新疆维吾尔自治区伊犁哈萨克自治州某某自治县</td>
</tr>
<tr><td>李四</td><td>22</td><td>13900000000</td><td>北京</td></tr>
<tr><td>王五</td><td>25</td><td>13700000000</td><td></td></tr>
</tbody>
</table>
<ul class="news">
<li>新闻 1</li>
<li>新闻 2
<ol>
<li>子新闻 2-1</li>
<li>子新闻 2-2</li>
</ol>
</li>
<li>新闻 3</li>
</ul>
</body>
</html>关键行与易错点
table-layout: fixed让列宽不再受内容影响(否则谁的地址长谁的列就宽),默认值是auto;实际项目数据是后端动态渲染的,固定列宽更稳。border-collapse: collapse才是“相邻单元格共用一条 1px 边框”;把border-spacing设为 0 只是“间距没了”,中间仍是两条边框叠成 2px,看起来更粗。- 设了
border-collapse: collapse后,border-spacing无论写在前面还是后面都失效——都合并共用边框了,哪还有间距。 - 边框不能只给
table设,否则只有最外圈一圈;要给td, th设(逗号是“并集选择器”,同时选中两类元素)。 table-layout、border-spacing、border-collapse、caption-side、empty-cells这 5 个属性只能设置在table上,给td/th设置无效;宽高、内外边距这些是通用属性,谁都行。- 后代选择器
.news li与子元素选择器.news > li的区别:前者连嵌套在ol里的li也会被选中(那些是后代但不是子元素);后者只选.news的直接子li。 >两边的空格只是排版好看,与后代选择器的“空格”含义完全不同,别混;>不加空格语法也合法。- 选择器可以多级串联(
.news ul > li三层、甚至更多),也可与后代选择器混搭,范围越写越精确。
常见错误
自定义光标写了不生效,DevTools 里
cursor值被划删除线并提示"属性值无效" 现象:cursor: url(./img/rocket.png);刷新后光标毫无变化。 原因:url()后面必须再跟一个关键字作为回退,单独写图片地址是非法值。 修法:cursor: url(./img/rocket.png), pointer;—— 逗号 + 常用关键字结尾。给
p、div设list-style-type: none或disc完全没反应 现象:想让段落前出现小圆点,怎么写都不出现。 原因:列表样式是"专用属性",只对ul/ol/li生效,其他元素一概无效。 修法:样式写到列表元素上;若确实要给普通元素加符号,用背景图或::before自造。给
table设了border,结果只有最外圈有框,单元格里空空如也 现象:表格像被"框"住,但格子之间没有线。 原因:table的边框只作用于表格自身外框,td/th是独立盒子。 修法:table { border-collapse: collapse; }+td, th { border: 1px solid #ccc; }。table-layout: fixed写了但列宽依旧被长内容撑开 现象:地址一列内容变长,整张表跟着变形。 原因:写到了td上,或table没有确定宽度。 修法:table { width: 800px; table-layout: fixed; },属性只认table标签。设了
border-collapse: collapse后border-spacing突然失效 现象:间距怎么调都是 0,以为属性写错了。 原因:相邻单元格共用一个边框后,本就不存在"单元格之间的距离"。 修法:二者取其一——要间距就别 collapse(或把间距写成 0 再 collapse);border-spacing本身也只写在table上。想只改一级菜单,结果嵌套的二级、三级
li全被染色 现象:.news li { border: 1px solid red; }把孙级项也套上了红框。 原因:空格是后代选择器,匹配所有层级的后代。 修法:改用子元素选择器.news > li;注意>两侧的空格只是排版好看,不表示后代关系。cursor: none用在整页或按钮上,用户找不到鼠标 现象:演示很酷,实际点不到东西。 原因:none是把光标彻底隐藏。 修法:正式页面只用pointer/move;确需隐藏须同时提供视觉反馈(高亮、放大镜框等)。
练习
购物车列表:
ul去掉自带符号,每一项前面用一张小火箭图片做图标(要求图标尺寸可控、且位于li内部使文字整体右移),鼠标悬停整行时变成小手。 考察点:list-style清空 + 自造图标 +cursor: pointer。数据表格:宽度 800px,列宽不随内容变化,单元格 1px 灰色边框且相邻共用一条线,单元格内容留 10px 内边距,标题加粗放大。 考察点:
table-layout、border-collapse、padding、caption样式。多级菜单对比实验:写出三层嵌套的
ul > li结构,先用后代选择器、再用子元素选择器给li加边框,截图对比两种写法的命中范围差异,并说明原因。混搭选择器:用"后代 + 子元素"混合写法,只给某个
ul内直接子级的ol里的li加样式,验证哪些元素被命中。改错题:下面三行各有问题,找出并修正——
p { list-style-type: disc; }td { table-layout: fixed; }a { cursor: url(./img/hand.png); }
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 鼠标光标样式 | 09:53 |
| 2 | 列表样式 | 15:18 |
| 3 | 表格样式 | 15:58 |
| 4 | 后代元素选择器 | 10:02 |
| 5 | 子元素选择器 | 04:40 |
小结
cursor日常只需记pointer(小手)和move(移动)两个值;自定义图标必须写成"图片地址 + 逗号 + 回退关键字"。- 列表图标一律"先清空、再自造":
list-style: none起手,图标交给背景图或伪元素,尺寸才可控。 - 列表样式与表格样式都是专用属性,只对各自的标签生效,写到别的元素上等于白写——这是与宽高、内外边距、背景等通用属性的根本区别。
- 表格五属性全部只认
table标签;其中border-collapse: collapse是做出"1px 细线表格"的关键,也是它与border-spacing: 0的本质差别。 table-layout: fixed用于抵御后端动态内容对列宽的干扰,必须写在table上并配合确定宽度。- 后代选择器(空格)匹配所有层级,子元素选择器(
>)只匹配直接子级;>两侧的空格纯属排版,与后代含义无关。 - 选择器可以多层、可混搭、可用类名或标签名自由组合,越具体命中越精确,但权重也随之上升,所以 ID 一般不参与组合。
- 写样式前先问一句"这个属性归谁管"——通用属性随便写,专用属性认准标签,能省掉大半调试时间。