主题
浮动与行内元素或行内块元素在布局中的特点(Day8 2/2)
本页对应 Day08_CSS,共 6 段视频,约 1 小时 34 分。
学习目标
- 能使用浮动与版心布局完成包含头部、导航、主体内容、侧边栏和页脚的 PC 页面,并正确使用清除浮动避免父元素高度塌陷及后续元素错位。
- 能根据页面标注计算栏目宽高与间距,使用左浮动、右浮动和多列浮动完成复杂嵌套布局,并处理最后一个浮动元素的外边距溢出问题。
- 能针对块级、行内、行内块和浮动元素分别选择水平/纵向居中方案,并说明
margin: 0 auto、text-align、line-height与vertical-align的适用条件和限制。 - 能定位行内块元素之间空白由代码换行被解析为空格导致,并使用父元素
font-size: 0后为子元素恢复字号,或消除源码换行进行修复。 - 能解释行内块元素底部“幽灵空白”由基线与底线间距导致,并使用
vertical-align非baseline、父元素font-size: 0或图片display: block消除空白。 - 能诊断多个行内块元素因内容行数不同而呈阶梯状无法对齐的原因,并通过设置非
baseline的vertical-align使元素按指定参考线整齐对齐。
知识点
从表格布局到浮动布局
为什么需要:最早页面布局常用表格,因为表格天然能“一行多单元格”。但页面复杂后,单元格里还要套表格,一层结构就要写 table、tbody、tr、td 等标签,层次越来越深,缩进和可读性都很差。
怎么想:既然用表格主要是为了让元素排到一行,而浮动也能让块元素横向排列,就可以用“div + CSS 浮动”替代表格。思路仍是先把页面想成无形的表格:先分行,再分列。
怎么做:整个页面按行拆成头部、导航、主体、页脚;每一行内部再用左浮动、右浮动分列。常见经验是“一行两个元素一左一右;三个元素可两左一右;四个及以上可统一左浮动”。
易错点:浮动不是“随便漂”,父元素要处理浮动影响;结构要先分行再分列,不能一上来就堆样式。
先写全局样式和浮动工具类
为什么需要:浏览器给元素自带默认内外边距,页面尺寸容易算不准;浮动、清除浮动又会反复使用,提前写成工具类更省事。
怎么想:把“通用设置”和“具体页面样式”分开。通用设置放前面,具体模块再单独写。
怎么做:转写稿中的写法是先写全局样式,再去掉默认内外边距,并准备浮动类与清除浮动类:
css
* {
margin: 0;
padding: 0;
}
.left { float: left; }
.right { float: right; }
.clearfix::after {
content: "";
display: block;
clear: both;
}易错点:清除浮动类要加在“浮动元素的父元素”上,不是加在浮动元素自己身上;类名拼错也会导致“以为清除了,其实没清除”。
版心与页面头部
为什么需要:页面总宽常固定为 960px,但屏幕可能更宽,内容需要居中,两侧留白。这个有内容的居中区域就是“版心”。
怎么想:先做一个大容器 .container,宽度固定且水平居中;里面的模块不用反复算总宽,直接继承或使用版心宽度。
怎么做:
css
.container {
width: 960px;
margin: 0 auto;
}页面头部再分 logo、banner1、banner2。按“两左一右”:logo 和 banner1 左浮动,banner2 右浮动;父元素加 clearfix。logo 宽 200、高 80,banner1 宽 540、高 80,banner2 宽 200、高 80,背景可用 #ccc。banner1 加左外边距 10px,banner2 靠右后就不必再补右侧间距。
易错点:margin: 0 auto 只适合块级元素水平居中;浮动元素左右 auto 不能居中。头部父元素忘记清除浮动,后面的导航会受影响。
主体分栏与栏目尺寸
为什么需要:主体要分成左侧内容区和右侧侧边栏,左侧还要再分上下两行、A/B/C 型栏目,必须一层层分下去。
怎么想:先整体左右分:.content 宽 750px 左浮动,.sidebar 宽 200px 右浮动,中间留约 10px。左侧再分 .row,上行放 A 型栏目,下行放 B 型栏目;侧边栏放 C 型栏目。
怎么做:A 型总宽高 370×200,写内容宽高 368×198 再加 1px 边框;B 型总宽 180×200,写 178×198 加边框,并给前三个加右外边距 10px,最后一个加 last 类把右外边距归零;C 型总宽高 200×130,写 198×128 加边框。行与行之间用 margin-top:10px。
易错点:给 B 型四个都加右外边距,第四个会放不下而掉行;应只给前三个加,或用 .last { margin-right:0; } 覆盖。子元素浮动时,父元素仍要清除浮动,“父元素已经浮动”不能代替子元素父级的清除。
清除浮动的调试现场
为什么需要:浮动元素会脱离文档流,影响后面元素。转写稿中故意不清除头部浮动,导航条上去了,文字却被挤下来,页面看起来“乱套”。
怎么想:出现“元素上去了、字出来了”的怪现象,先怀疑清除浮动。不是所有怪异现象都要改结构,先检查父元素有没有 clearfix。
怎么做:每个包含浮动子元素的父级都加清除浮动类;导航、主体、页脚按顺序写,并用上外边距制造间距。
易错点:一看现象就重写结构,不如先查类名是否拼错、清除浮动加没加对位置。转写稿反复提醒:忘了清除浮动和单词拼错都非常常见。
行内块只能作补充
为什么需要:行内块不脱离文档流,设置宽高后可横向排列,某些“多个元素一起居中”的场景比浮动方便。
怎么想:但行内块在父元素眼里仍像“字”,会带来元素间空白、底部幽灵空白、基线对齐导致高低不齐等问题。
怎么做:元素间空白可给父元素 font-size:0,再给子元素恢复字号;底部空白可给行内块设 vertical-align:bottom 等非 baseline 值,图片也常直接 display:block;无法对齐时同样用 vertical-align 解决。
易错点:行内块问题比浮动多,不能替代浮动布局,只适合做补充;用 font-size:0 后别忘了给有文字的子元素恢复字号。
先理解:父元素把行内、行内块当成“字”
行内块元素(inline-block)的特点是:既能像行内元素一样水平排列,又能设置宽高,而且不像浮动那样脱离文档流。转写里提到,早年有人以为它能替代浮动布局,实际用下来发现“毛病更多”。核心原因只有一个:在父元素眼里,行内元素和行内块元素都像一个字。因此父元素上的文本属性,例如 text-align、line-height、font-size,会作用到它们身上。
为什么需要先建立这个认识?因为后面所有现象——水平居中、纵向居中、元素间空白、底部幽灵空白、不同文字行数对不齐——都来自“它被当成字”。怎么想?不要先背方案,先问:父元素是不是把它当字?它有没有继承父元素的行高、字体大小?怎么做?用 display:inline-block 把盒子变成行内块,再观察父元素文本属性对它的影响。易错点:行内元素不能设置宽高;行内块可以设置宽高,但仍受父元素文本属性影响。
css
.wrapper {
width: 600px;
height: 400px;
background: #ccc;
text-align: center;
}
.box {
display: inline-block;
width: 200px;
height: 100px;
padding: 10px;
background: #900;
color: #fff;
}水平居中:父元素 text-align:center
为什么需要?如果让行内块在父元素中水平居中,最直接的办法不是给行内块自己设 margin:0 auto,而是利用“父元素把它当字”的特点。怎么想?字可以用 text-align:center 居中,行内块也能。怎么做?给父元素设 text-align:center,行内块保持 inline-block。易错点:块级元素自身水平居中才常用 margin:0 auto;行内块用父元素 text-align 更顺。转写中演示过:行内块设了 text-align:center 后,水平方向确实能居中。
纵向居中:父行高 + 行内块 vertical-align:middle
为什么需要?只靠父元素 text-align 只能水平居中。纵向居中要利用父元素行高,但只设行高不够。怎么想?父元素把行内块当字,父元素设 line-height:400px 后,文字会居中,但行内块默认按基线对齐,可能出现“字居中了,元素没动”。怎么做?父元素设与高度一致的行高,再给行内块设 vertical-align:middle,让它中线与外部文字中线对齐。
css
.wrapper {
height: 400px;
line-height: 400px;
text-align: center;
}
.box {
display: inline-block;
width: 200px;
height: 100px;
vertical-align: middle;
}易错点:行内块会继承父元素行高,如果行内块里有文字,文字可能被父行高影响而跑到下方。转写中调试时给行内块单独设置 line-height,例如与自身高度一致,文字才在盒内居中。另一个易错点是只给父元素设 vertical-align 没用,必须设给行内块本身。
和块级、浮动居中对比:行内块更适合做补充
块级元素水平居中用 margin:0 auto 有效;纵向居中却要计算 margin-top,转写中算过 (400-120)/2=140,还遇到外边距塌陷,需要额外处理,不推荐。浮动元素左右 margin:auto 不生效,水平居中也要算,例如 (600-220)/2=190,比行内块麻烦。所以行内块在“居中”这种场景下可作为浮动布局的补充;但整体布局仍以浮动为主。易错点:不要把行内块的居中方案硬套到块级和浮动元素上。
问题一:行内块之间的空白
为什么会有空白?代码中多个行内块之间的换行符被浏览器解析成空格,父元素又把它们当字,于是出现间隙。怎么想?找到“换行被当空格”这个原因。怎么做?推荐给父元素设 font-size:0,再给需要文字的行内块单独恢复字体大小。转写中还提到“代码不换行”能解决,但可读性差,不推荐。
css
.wrapper { font-size: 0; }
.box { font-size: 16px; }易错点:只给父元素设 font-size:0 会让子元素文字也继承为 0,所以有文字的子元素要单独设置字体大小;图片本身没文字,可不恢复。
问题二:底部“幽灵空白”
为什么叫幽灵空白?行内块或图片底部会莫名多出一点空隙,很多人不知道原因。转写中通过旁边写字演示:行内块默认基线对齐,底部空白其实是基线与底线之间的距离。怎么做?推荐给行内块或图片设 vertical-align:bottom,从原因上解决;也可给父元素 font-size:0,让基线与底线距离消失;图片还常用 display:block。易错点:vertical-align 要设给行内块或图片本身,设给父元素无效;display:block 会让图片不再受行内块基线问题影响。
css
img {
display: block;
}
/* 或 */
.box {
vertical-align: bottom;
}问题三:文字行数不同导致无法对齐
为什么对不齐?多个行内块水平排列时,如果里面文字行数不同,对齐位置会不同:无文字时底部与基线对齐;一行文字时文字与外部基线对齐;多行文字时最后一行文字与外部基线对齐。怎么做?给行内块设 vertical-align 为 middle、top、bottom 等非默认 baseline 的值,让元素本身对齐,不再受内部文字行数影响。易错点:以为宽度没设好;其实通常是基线对齐在作怪。
调试提醒
转写中忘了清除浮动时,导航条上去了,文字却被挤出来;类名拼错也会造成“以为清除了其实没清除”。行内块问题多,但知道“父元素当字”这个总原因,再按水平居中、纵向居中、空白、对齐逐项排查,就能把现象解释清楚。
课堂画面






代码示例
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>浮动布局页面案例</title>
<style>
/* 全局样式:去掉所有元素自带的内外边距 */
* { margin: 0; padding: 0; }
/* 预置浮动类名:谁想浮动就加类名 */
.left { float: left; }
.right { float: right; }
/* 清除浮动:加在“浮动元素的父元素”上 */
.clearfix::after {
content: "";
display: block;
clear: both;
}
/* 文字居中:子元素可继承 */
body { text-align: center; }
/* 版心:宽度固定 + 水平居中 */
.container {
width: 960px;
margin: 0 auto;
}
/* ===== 页面头部:一行三列,两左一右 ===== */
.logo { width: 200px; height: 80px; background: #ccc; }
.banner1 { width: 540px; height: 80px; background: #ccc; margin-left: 10px; }
.banner2 { width: 200px; height: 80px; background: #ccc; }
/* ===== 页面导航 ===== */
.page-nav {
height: 30px;
background: #ccc;
margin-top: 10px;
}
/* ===== 页面主体:左内容 + 右侧边栏 ===== */
.page-main { margin-top: 10px; }
.page-content { width: 750px; }
.page-sidebar { width: 200px; }
.row { margin-top: 10px; }
/* A 型栏目:总宽高 370×200,减去 1px 边框 */
.cl-a {
width: 368px;
height: 198px;
border: 1px solid #ccc;
background: #eee;
}
/* B 型栏目:总宽高 180×200,减去 1px 边框 */
.cl-b {
float: left;
width: 178px;
height: 198px;
border: 1px solid #ccc;
background: #eee;
margin-right: 10px;
}
.cl-b.last { margin-right: 0; } /* 最后一个不要右外边距 */
/* C 型栏目:侧边栏里不用浮动,块级天然换行 */
.cl-c {
width: 198px;
height: 128px;
border: 1px solid #ccc;
background: #eee;
margin-top: 10px;
}
/* ===== 页脚 ===== */
.page-footer {
height: 60px;
background: #ccc;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<!-- 页面头部 -->
<div class="page-header clearfix">
<div class="logo left">logo</div>
<div class="banner1 left">banner1</div>
<div class="banner2 right">banner2</div>
</div>
<!-- 页面导航 -->
<div class="page-nav">导航</div>
<!-- 页面主体 -->
<div class="page-main clearfix">
<!-- 左边:先分上下两行 -->
<div class="page-content left">
<div class="row clearfix">
<div class="cl-a left">栏目1</div>
<div class="cl-a right">栏目2</div>
</div>
<div class="row clearfix">
<div class="cl-b">栏目3</div>
<div class="cl-b">栏目4</div>
<div class="cl-b">栏目5</div>
<div class="cl-b last">栏目6</div>
</div>
</div>
<!-- 右边:侧边栏 -->
<div class="page-sidebar right">
<div class="cl-c">栏目7</div>
<div class="cl-c">栏目8</div>
<div class="cl-c">栏目9</div>
</div>
</div>
<!-- 页脚 -->
<div class="page-footer">页脚</div>
</div>
</body>
</html>要点:
.clearfix只能加在“浮动元素的父元素”上,并且只管一层;如果父元素自己也是浮动的,就不用再清除。- 宽高要按“总宽高减边框”来写(368×198、178×198、198×128),否则加上 1px 边框后整行放不下,元素会掉到下一行。
- 一行里有两个元素时,常用“一左一右”;有三个元素时,用“两左一右”可以少设一个外边距。
- 栏目6 一定要用
.last把margin-right覆盖成 0,否则第 4 个会被挤出这一行。 - 一旦忘了清除浮动,最典型的现象就是后面的元素升上去,而文字被挤出来;还有一种常见情况是类名拼错,其实等于没有清除浮动。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>行内块元素:居中与元素间空白</title>
<style>
* { margin: 0; padding: 0; }
.wrapper {
width: 600px;
height: 400px;
background: #ccc;
text-align: center; /* 水平居中:行内块被当成“字” */
line-height: 400px; /* 纵向:行高 = 父元素高度 */
font-size: 0; /* 干掉标签换行产生的空白 */
}
.box {
display: inline-block;
width: 200px;
height: 100px;
padding: 10px;
background: #900;
color: #fff;
line-height: 100px; /* 覆盖从父元素继承来的 400px 行高 */
font-size: 16px; /* 覆盖父元素的 0 */
vertical-align: middle; /* 中线对齐,纵向居中的关键 */
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
</body>
</html>要点:
- 在父元素眼里,行内元素、行内块元素就是“一个字”,所以父元素设
text-align、line-height就能控制它们,这是它们居中特别方便的原因。 line-height会被继承;行内块里如果有文字,必须单独设回行高(这里 100px),否则文字会跟着 400px 的行高跑到下面。- 元素之间的空白来自代码里标签之间的换行,换行被解析成一个空格(也是“字”)。用
font-size: 0去掉后,如果行内块里还有文字,要再单独把font-size设回 16px。 - 只把代码写在一行也能去掉空白,但代码可读性就没了,不推荐。
- 默认是基线对齐,纵向居中一定要补
vertical-align: middle,否则元素会被外部文字的位置带着走。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>行内块元素:底部空白与无法对齐</title>
<style>
* { margin: 0; padding: 0; }
.wrapper {
width: 600px;
height: 400px;
background: #ccc;
margin-top: 20px;
text-align: center;
font-size: 0; /* 同时消掉元素间空白 */
}
.box {
display: inline-block;
width: 200px;
height: 100px;
background: #900;
color: #fff;
font-size: 16px;
vertical-align: bottom; /* 底部与底线对齐,消掉“幽灵空白” */
}
.img {
width: 200px;
vertical-align: bottom; /* 图片要单独设 */
}
/* 流传最广的经典方案:图片转块级 */
.img-block {
display: block;
width: 200px;
margin: 20px auto 0;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
<img class="img"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='120'%3E%3Crect width='200' height='120' fill='%23009'/%3E%3C/svg%3E"
alt="demo">
<img class="img-block"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='120'%3E%3Crect width='200' height='120' fill='%23009'/%3E%3C/svg%3E"
alt="demo">
</body>
</html>要点:
- 底部那块空白就是“基线与底线之间的距离”,并不是神秘现象;行内块默认基线对齐,所以底部会留一点。
- 最推荐从原因入手:给行内块本身(包括图片)设
vertical-align: bottom,只要不是默认的baseline都能消除,middle也行。 - 给父元素设
font-size: 0也能消除(四条线重合),但里面的文字会一起消失,需要单独设回。 - 把图片转成
display: block是流传很广的经典方案,但只对图片这类行内块有效,本质是绕开基线对齐,并不是真正的原因。 - 文字个数不同的行内块排不齐,也是基线对齐造成的:没有文字时底部对齐,有一行文字时文字对齐,多行时最后一行文字对齐;统一设一个非
baseline的vertical-align就能对齐。
常见错误
后续元素上移、文字被挤乱 → 浮动子元素后未给父元素清除浮动,或清除浮动类名拼写错误 → 给浮动元素的父元素加清除浮动类,并检查类名拼写与实际样式选择器一致。
浮动元素设置
margin: 0 auto不居中 → 左右auto对浮动元素不生效 → 改用计算左右外边距,或改用行内块方案;需要整组居中时优先考虑行内块布局。四个栏目统一加右外边距后最后一个掉行 → 行宽不足,最后一个元素仍带右外边距 → 给最后一个元素加
last类并将右外边距覆盖为0,或只给前几个元素加右外边距。行内块元素之间出现无法解释的空白 → HTML 元素之间的换行被解析为空格 → 父元素设
font-size: 0,再给行内块内部文字单独恢复字体大小;不推荐把代码挤到一行。行内块或图片底部出现“幽灵空白” → 行内块默认基线对齐,底部与基线对齐后留下基线与底线间距 → 给行内块设置
vertical-align: bottom(非默认值通常即可);图片也可用display: block作为经典修法。多个行内块内容行数不同时呈阶梯状错位 → 默认按基线对齐,内部有文字时取最后一行文字基线,无文字时取自身底部 → 给行内块设置
vertical-align为非baseline的值,如middle、bottom。行内块在父容器中只设
line-height后文字居中、元素没居中 → 只处理了父级行高,未改变行内块自身对齐方式 → 父元素设行高,行内块再设vertical-align: middle;内部有文字时再单独调整行高。块级元素想纵向居中,写上下
margin: auto无效甚至塌陷 → 上下auto不生效,且父元素可能发生外边距塌陷 → 用精确计算上外边距,或加overflow: hidden/边框等解决塌陷;更优先评估是否改用行内块方案。
练习
- 完成页面头部:
logo、banner1、banner2三列,采用“两左一右”浮动,父元素清除浮动,并只补一个中间间距。 - 完成主体左右分栏:左侧 750px、右侧 200px,中间留 10px;左侧再分上下两行,上行两个 A 型栏目,下行四个 B 型栏目,处理 B 型最后一个元素的右外边距。
- 用行内块实现 4 个导航项横向排列并整体水平居中,要求解决元素间空白,同时保证导航项内文字正常显示。
- 给出一个图片底部存在空白的页面,分别用
vertical-align和display: block两种方式修复,并说明两种修法的适用场景。 - 让一个行内块元素在 600×400 的父容器中水平、垂直居中;要求父元素和行内块各自承担正确的样式,并处理行内块内部文字的垂直位置。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 浮动页面案例01 | 19:46 |
| 2 | 浮动页面案例02 | 16:39 |
| 3 | 元素居中 | 31:40 |
| 4 | 行内块元素之间的空白 | 07:21 |
| 5 | 行内块元素底部的空白 | 12:44 |
| 6 | 行内块元素无法对齐的问题 | 05:50 |
小结
- 浮动布局要先分行、再分列,结构分层越清楚,后续样式越不容易乱。
- 只要用了浮动,就要条件反射检查父元素是否清除浮动,且要检查类名是否写对。
- 两左一右常用于三列布局,可少处理一个中间间距;四列及以上统一同向浮动更省事。
- 行内块适合做“补充布局”,尤其是需要整体居中的横向排列场景,但不能替代浮动布局。
- 行内块的三类高频问题集中在:元素间空白、底部空白、基线对齐错位。
- 行内块居中要分清横向和纵向:横向多由父级文本对齐控制,纵向需同时关注父级行高和自身
vertical-align。 - 看到“元素上去了、文字掉下来”“图片底部多一条缝”“内容行数不同就错位”,优先排查清除浮动、基线对齐和换行空白。