主题
CSS 课堂案例(Day8 1/2)
本页对应 Day08_CSS,共 6 段视频,约 1 小时 55 分。
学习目标
- 能准确复述盒子模型的组成,并说明内边距、外边距、外边距塌陷与合并、样式继承及自带样式的关键规则。
- 能独立完成导航条案例,包括设置高度、边框、背景、链接水平垂直居中、取消下划线、实现 hover 变色及背景图下拉图标,并能解释选择器权重相同时的覆盖问题及修正方法。
- 能使用
float让图片或指定元素左/右浮动,实现文字环绕效果,并能说明浮动最初用于文字环绕的设计目的。 - 能判断元素浮动后的显示特点,包括脱离文档流、多个浮动元素水平排列、一行放不下自动换行、不被父元素当作文本处理,以及左右浮动后的排列与重叠现象。
- 能分析浮动元素对后面兄弟元素的影响,使用
clear: both消除影响,并遵循“兄弟元素要浮动都浮动”的布局原则。 - 能识别浮动导致父元素高度塌陷及后续元素受影响的连锁问题,列举并实现固定高度、父元素浮动、
overflow、清除元素、伪元素清除浮动等方案,重点掌握伪元素清除浮动的标准写法及content、display: block、clear: both的必要性。
知识点
一、先回顾盒子模型,再进入案例
为什么需要:导航条、文字环绕、浮动布局都绕不开盒子模型。内容、内边距、边框、外边距算不清,后面调高度和间距就会靠猜。
怎么想:先判断元素默认宽度:块级元素基于父元素内容宽计算,行内/行内块多由内容撑开;最大最小宽高只用于限制默认计算值,不要和固定宽高混用。
怎么做:复习内边距百分比参照父元素内容宽、外边距可为负、行内元素上下内/外边距效果不完美;块级元素左右 margin:auto 可居中。
易错点:把“外边距塌陷”和“浮动造成父元素高度塌陷”混为一谈;二者只是共用“塌陷”一词。行内元素不要硬设上下外边距。
二、导航条:先搭骨架,再调交互
为什么需要:课堂用导航条把高度、边框、背景、行高、伪类、背景图串起来。
怎么想:先去掉 body 默认外边距,再给 .nav 定高、边框和背景;文字横向居中用 text-align:center,纵向居中用 line-height 等于高度。
怎么做:
css
body { margin: 0; }
.nav {
height: 40px;
background: #fcfcfc;
border-top: 4px solid #1483ef;
border-bottom: 1px solid #eaecec;
text-align: center;
line-height: 40px;
}
.nav a {
color: #333;
text-decoration: none;
padding: 0 20px;
display: inline-block;
line-height: 40px;
}
.nav a:hover {
background-color: #edeef0;
color: #1483ef;
}
.nav a.dropdown {
background: url("down.png") no-repeat 55px center;
}易错点:a 默认是行内元素,不能直接设高度;改成 inline-block 后既有宽高又能横向排列。调试时发现鼠标移入背景不变:检查元素可见 .nav a.dropdown 与 .nav a:hover 权重相同,后写覆盖前写;若把 :hover 提前,复合属性 background 又会把背景图覆盖掉。最终把 :hover 放后,并写 background-color,问题解决。
三、浮动实现文字环绕
为什么需要:浮动最初就是为文字环绕图片而生,理解这一点才能理解后面“文字为什么会被挤出来”。
怎么想:图片默认参与行内排列,文字不会自动绕图;让图片 float:left/right,文字就会环绕浮动元素。
怎么做:
css
.book { width: 600px; padding: 20px; background: #ddd; }
.book img { width: 250px; float: left; margin-right: 16px; margin-bottom: 16px; }
.big { float: right; font-size: 8em; font-weight: 800; }易错点:检查元素时会看到段落盒子与图片重叠,但文字被挤出环绕,这是浮动的设计初衷,不是错位。浮动的元素仍会影响后续布局。
四、浮动元素的特点
为什么需要:用浮动布局必须知道它脱离文档流后怎么排队。
怎么想:把文档流想成排队;元素一浮动就“飞起来”,后面的非浮动元素会占它原来的位置。多个浮动元素横向排列,一行放不下自动换行。
怎么做:左浮动靠父元素内容区左边,右浮动靠右边;浮动后行内元素也可设宽高、内外边距;多个浮动元素按顺序横向排列。
易错点:浮动元素不会像块级元素那样左右 margin:auto 居中,也不存在外边距塌陷和合并;它不会被父元素当作文本,所以父元素 text-align:center 不会让浮动元素本身居中,只会通过继承影响其内部文字。高度参差不齐时,自动换行可能被较高的浮动元素“卡住”。
五、对兄弟/父元素的影响与清除浮动
为什么需要:浮动元素会让后面兄弟占位、父元素高度撑不开,页面会“乱套”。
怎么想:对后面兄弟,非浮动元素会占据浮动元素原位置,可能重叠;对父元素,子元素浮动后不能撑开父元素高度,造成高度塌陷,后面的段落文字还会被浮动元素挤出。
怎么做:布局原则是“兄弟要浮动都浮动,不浮动就别和浮动元素当兄弟”;父元素清除浮动推荐伪元素:
css
.clearfix::after {
content: "";
display: block;
clear: both;
}给父元素加 .clearfix 即可。content 必须写,display:block 必须写,clear:both 必须写。
易错点:clear:both 不是把浮动元素变不浮动,而是让当前元素不占前面浮动元素的位置;只有块级元素才能可靠设置 clear。固定父高、父元素也浮动、overflow 非 visible 也能解决,但各有副作用,课堂最推荐伪元素方案。
盒子模型回顾:先建立“分层”思维
为什么需要:盒子模型是后面布局、浮动、定位的共同底座。元素在页面上占多大、内容从哪里开始、边框和外边距算在哪,都绕不开它。
怎么想:把元素想成四层:内容 content、内边距 padding、边框 border、外边距 margin。设置宽高时先问:我设的是内容宽高,还是盒子整体?最大最小宽高是不是和固定宽高冲突?
怎么做:本节笔记先保留整体结构:
1. 盒子模型
1.1 内容 content
1.2 内边距 padding
1.3 边框 border
1.4 外边距 margin
塌陷 合并
1.5 内容溢出
1.6 隐藏元素 display visibility
2. 继承的样式和自带的样式
继承的样式
自带的样式
直接设置的样式、自带的样式、继承的样式内容部分要会设置宽高,也要理解最大最小宽高是对“默认计算出来的宽高”做限制。转写稿特别提醒:不要一边设固定宽高,一边又指望最大最小宽高发挥主要作用,否则固定宽高的意义会被削弱。块级元素的默认宽度不是随便来的,它基于父元素内容宽计算,还要减去自身左右外边距;行内元素、行内块元素更多是被内容撑开。
易错点:把“内容宽”和“盒子总宽”混为一谈;给行内元素设置上下内边距或上下外边距,效果不完整,容易和相邻元素重叠,所以行内元素上下方向要谨慎,左右方向通常没问题。
padding 与 border:规则要能“倒背如流”
为什么需要:padding 决定内容与边框之间的呼吸空间,border 决定盒子边界。它们直接影响盒子尺寸和视觉层次。
怎么想:padding 有上下左右四个方向,也可用复合属性一次写。百分比 padding 不论上下左右,都参照父元素内容宽;padding 不能为负。border 属性虽多,但本质是 style、width、color 的组合,可以四个边框一起设,也可以单独设某一边。
怎么做:先记复合属性规则:一个值、两个值、三个值、四个值分别对应哪些方向;边框先写“几像素、什么线型、什么颜色”,再按需拆边。
易错点:复合属性顺序记混;百分比参照对象误以为是父元素高度;行内元素上下 padding 看似有效但不完美,布局中不要依赖它撑开上下间距。
margin:塌陷与合并要分清
为什么需要:margin 控制盒子与盒子之间的距离,但父子之间、兄弟之间会出现特殊规则,不了解就会“明明写了却没效果”。
怎么想:margin 的取值规则跟 padding 类似,百分比也参照父元素内容宽,但 margin 可以是负值;块级元素左右 margin 为 auto 可以居中。父子之间可能发生外边距塌陷:最上面子元素的上外边距、最下面子元素的下外边距会塌陷到父元素上,看起来像父元素的外边距。兄弟之间是合并:上兄弟的下外边距与下兄弟的上外边距合成一个,间距取较大者。
怎么做:塌陷不是所有情况都出现,父元素有边框、有内边距,或设置 overflow 非 visible 时,通常就能避免;如果背景色不明显、不影响效果,不必强行处理。合并一般不用“解决”,布局时避开即可。
易错点:把“塌陷”和“合并”混为一谈;以为行内元素、行内块元素也会发生同样的上下塌陷——转写稿强调,这类问题主要发生在块级元素的上下外边距上;给行内元素设置上下 margin 往往不好使。
内容溢出与隐藏元素:display 与 visibility 的区别
为什么需要:内容可能超出盒子,元素也可能需要隐藏。不同隐藏方式对页面占位的影响不同。
怎么想:溢出先看 overflow,默认是 visible,内容会显示出来;需要时再隐藏或滚动。隐藏元素有两个常见属性:display 和 visibility。display:none 更彻底,不但看不见,页面中也不占位置;visibility 隐藏后仍占位置。
怎么做:先判断“要不要保留位置”,再选属性。日常更常用 display:none,因为它的隐藏更彻底。
易错点:把“看不见”等同于“不占位”;overflow 的值和 margin 的 auto 混淆——这类只是名字相似,不是同一概念。
继承样式、自带样式与直接设置样式:权重顺序要清楚
为什么需要:元素最终样式可能来自多个来源,不知道优先级就会反复“为什么我写了不生效”。
怎么想:样式来源至少有三类:直接设置(用选择器选中元素)、元素自带样式、从祖先继承的样式。继承主要发生在文字、文本、颜色相关属性上,比如一组 font 属性、文本样式和 color;但宽高、尺寸、边框等通常继承不了。文本样式中还要注意有些属性并不继承,转写稿提到像 white-space 这类要排除。自带样式最典型的是标题:自带 font-size、font-weight、上下 margin;常规字号常见是 16px,但标题会更大。
怎么做:遇到样式不生效,先查“是不是被自带样式或更高优先级覆盖”,再查“是不是根本继承不过来”。权重上:直接设置的样式最高;自带样式高于继承样式;继承样式权重最低,甚至不如自带样式。
易错点:以为继承一定优先;想靠祖先元素让链接颜色、下划线生效——转写稿明确说,a 的颜色、下划线要直接给它设置,继承不如自带。还有标题的上下 margin、字号、加粗,都是自带样式,容易被自己设置的样式覆盖,但排查时不能忽略它们。
课堂画面






代码示例
示例一:导航条(inline-block + 权重覆盖)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>导航条</title>
<style>
/* body 自带外边距,先清掉 */
body { margin: 0; }
.nav {
height: 40px;
background-color: #FCFCFC;
border-top: 4px solid #1483EF;
border-bottom: 2px solid #EAECF0;
/* 行高 = 高度,让行内文字纵向居中 */
line-height: 40px;
}
.nav a {
/* 行内元素设高度无效,必须改成行内块 */
display: inline-block;
/* 左右内边距撑开间距,行内元素左右 padding 完全有效 */
padding: 0 20px;
/* a 的下划线和颜色是自带样式,必须直接选中 a 设置,继承不生效 */
text-decoration: none;
color: #333;
}
/* 下拉图标:写在 hover 之前 */
.nav .dropdown {
background: url(./down.png) no-repeat 55px center;
}
.nav a:hover {
/* 用 background-color 而不是 background 复合属性 */
background-color: #EDEEF0;
color: #1483EF;
}
</style>
</head>
<body>
<div class="nav">
<a href="#">博客</a>
<a href="#">首页</a>
<a href="#">关于</a>
<a href="#" class="dropdown">微博</a>
</div>
</body>
</html>关键行与易错点
body { margin: 0 }:body 自带外边距,不清掉导航条贴不满边。.nav上height: 40px+line-height: 40px:高度管盒子,行高管文字纵向居中,两者要配对写;只写 height 文字会贴顶。a是行内元素,直接设 height 无效,必须display: inline-block才能让 a 撑满 40px;改成block则每个 a 独占一行、宽度铺满父元素,也不对。text-decoration、color是 a 的自带样式,继承权重最低,干不过自带样式,所以必须.nav a { ... }直接选中 a,指望祖先继承过来一定失败。.nav .dropdown与.nav a:hover权重相同(都是两个选择器),权重相同时后写的覆盖先写的。所以.dropdown放前面、hover 放后面;如果顺序反过来,鼠标移上去背景图就没了。- hover 里写
background-color而不是background:background是复合属性,会把background-image一并重置成 none,图标就消失了。 - 图标 X 轴
55px= 左右内边距 20 + 文字宽 16 + 少量间距,是视觉微调的结果,不必追求“精确测量”,浏览器渲染本来就不保证像素级一致。
示例二:浮动实现文字环绕
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>文字环绕</title>
<style>
.book {
width: 600px;
padding: 20px;
background-color: #DDD;
}
.book img {
width: 250px;
/* 图片左浮动,后面的文字就会环绕它 */
float: left;
/* 文字贴着图片太挤,留出一个字的间距 */
margin-right: 1em;
margin-bottom: 1em;
}
/* 让文字环绕一个“大字” */
.big {
float: right;
font-size: 8em;
font-weight: 800;
}
</style>
</head>
<body>
<div class="book">
<img src="./images/pic.jpg" alt="">
<p>这是一段用来演示文字环绕效果的段落文字,文字文字文字文字文字文字文字文字。</p>
<p>这是第二段文字,文字文字文字文字文字文字文字文字文字文字文字文字文字。</p>
<span class="big">乐</span>
<span>小字小字小字小字小字小字小字小字小字小字小字小字小字小字小字。</span>
</div>
</body>
</html>关键行与易错点
- 不浮动时,图片是行内块,只和第一行文字在同一行,后面的文字不会绕过去;加上
float: left后才出现环绕,这是浮动最初的设计目的。 - 浮动元素只能在父元素的内容区里活动,不会跑到父元素的
padding上;向右浮动也只到内容区右边界。 margin-right/margin-bottom用1em是给文字留出一个字的距离,不加会紧贴图片;左右外边距对行内元素本来就有意义,但浮动后上下外边距也完全生效。- 浮动元素不区分原来的显示模式:
span这种行内元素浮动后,宽高、内外边距全都正常起作用。 - 用检查元素看时会发现
<p>的盒子和图片重叠、文字却在外侧——这不是 bug,正是浮动的本意;它也会成为后面浮动布局的麻烦来源。 - 浮动元素设置
margin: 0 auto不会居中,只有块级元素才有左右 auto 居中的本事。
示例三:清除浮动(::after 伪元素方案)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>清除浮动</title>
<style>
.wrapper {
width: 800px;
border: 2px solid #999;
}
/* 给父元素动态添加一个子元素来清除浮动 */
.wrapper::after {
content: ""; /* 必须写,空着也要写 */
display: block; /* 必须写,只有块级元素才能设 clear */
clear: both; /* 别纠结 left/right,一律 both */
}
.box {
float: left;
width: 200px;
height: 120px;
background-color: pink;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box">元素A</div>
<div class="box">元素B</div>
<div class="box">元素C</div>
</div>
<p>后面的段落,浮动不处理就会顶上来,文字还会被挤到浮动元素旁边。</p>
</body>
</html>关键行与易错点
- 子元素浮动后脱离文档流,父元素高度撑不起来(高度塌陷),后面的
<p>会顶上来、文字被挤到浮动元素边上——这是初学者最容易搞出“页面乱套”的原因。 ::after是给父元素(不是浮动元素)动态加一个子元素,HTML 结构里看不到它,只存在于浏览器解析后的结构中。content必须写,哪怕content: "";不写整个伪元素不生成,清除浮动也就无效。display: block必须写:只有块级元素才能设置clear,所以方案四里直接写<div>可以,写<span>不行。clear: both别去分 left/right,前面无论左浮右浮,一律不上前占位。- 单冒号
:after是旧写法(老浏览器不认双冒号),现在写双冒号即可,属于向下兼容的历史问题。 - 这套写法是“固定三件套”:
content+display: block+clear: both,外面套父元素选择器;不要被网上写成display: table/flex的版本带偏,本质仍是块级。 - 布局原则:兄弟元素要浮动就全浮动,出现“一浮一不浮”时别让它们当兄弟(外面包一层),从源头上避免问题。
常见错误
- 现象:导航条顶部出现白边。→ 原因:
body默认外边距未处理。→ 修法:先重置body { margin: 0; }。 - 现象:给导航链接
a设height不生效。→ 原因:a默认是行内元素,宽高不可靠。→ 修法:改为display: inline-block后再设宽高、内边距。 - 现象:鼠标悬停时文字变色但背景色不变。→ 原因:
.nav a与.nav a:hover权重相同,后写规则或复合属性覆盖了背景。→ 修法:调整规则顺序,悬停态用background-color单独覆盖,必要时提高选择器权重。 - 现象:想通过祖先元素改链接颜色和下划线,结果无效。→ 原因:
a自带样式优先于继承样式。→ 修法:直接选中a设置color、text-decoration。 - 现象:子元素浮动后父容器高度变成 0,后面段落文字钻进浮动区域。→ 原因:浮动元素脱离文档流,不再撑开父元素高度,且文字会环绕浮动元素。→ 修法:给父元素清除浮动,推荐
父元素::after { content: ""; display: block; clear: both; }。 - 现象:前面的兄弟浮动、后面的兄弟不浮动,出现位置重叠。→ 原因:浮动元素脱离文档流,后续兄弟占据其原位置。→ 修法:紧邻的后续兄弟设
clear: both;更稳妥的是遵循“兄弟要浮都浮,不浮动的别和浮动的当兄弟”,必要时调整 HTML 结构。 - 现象:伪元素清除浮动写了却没效果。→ 原因:漏写
content、display: block或clear: both,或选择器选错对象。→ 修法:确认选中父元素,并补齐三件套:content: ""; display: block; clear: both;。 - 现象:多个浮动元素自动换行时被前面较高元素“卡住”。→ 原因:浮动换行受前方高度参差不齐影响。→ 修法:布局中尽量统一浮动项尺寸;刻意错落时先接受并验证换行基准。
练习
- 复刻课堂导航条:完成
body重置、高度 40px、上下边框、链接行内块化、左右内边距、悬停背景与文字颜色变化,并加入下拉背景图标。 - 实现图文环绕:图片分别左浮动、右浮动各做一版,给图片补右/下外边距;再用一个放大的
span浮动,让周围小字环绕它。 - 做“浮动兄弟影响”实验:A 左浮动、B 右浮动、C 不浮动,观察重叠;分别用
clear: both和调整 HTML 结构解决,并说明哪种更稳。 - 做“父元素高度塌陷”实验:父元素不设固定高,内部四个子元素全部浮动,后面接一个段落;分别用固定高、
overflow: hidden、真实清除元素、::after伪元素清除,比较副作用并写出推荐方案。 - 排错题:给出导航条悬停样式和伪元素清除浮动代码各一段,其中包含顺序错误、复合属性覆盖、漏写
content/display/clear等问题,要求定位并修复。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 回顾 | 09:11 |
| 2 | 导航条案例 | 15:14 |
| 3 | 浮动实现文字环绕 | 09:10 |
| 4 | 元素浮动之后的特点 | 43:43 |
| 5 | 浮动元素对后面兄弟元素的影响 | 10:30 |
| 6 | 浮动元素对父元素的影响 | 28:09 |
小结
- 页面起步先处理默认样式,尤其是
body外边距,否则后续定位和高度判断容易偏。 - 行内元素不要硬设宽高和上下内外边距;导航项这类需要尺寸和点击区域的元素优先行内块化。
- 链接的颜色、下划线、悬停态要直接选中
a或其状态选择器处理,不能依赖继承。 - 悬停样式失效先查权重和书写顺序,再查复合属性是否把目标属性整体覆盖。
- 浮动布局要同时看三件事:自身特点、对后续兄弟的影响、对父元素高度的影响。
- 兄弟元素布局尽量遵守“要浮都浮”;浮动与不浮动混作兄弟时,必须主动清除或改结构。
- 写浮动就条件反射清除浮动;推荐父元素伪元素方案,结构干净、副作用小。
- 布局微调以整体视觉为准,不必追求像素绝对精确;但要保证结构原则和清除浮动逻辑不出错。