Skip to content

浮动与行内元素或行内块元素在布局中的特点(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 的值,让元素本身对齐,不再受内部文字行数影响。易错点:以为宽度没设好;其实通常是基线对齐在作怪。

调试提醒 ​

转写中忘了清除浮动时,导航条上去了,文字却被挤出来;类名拼错也会造成“以为清除了其实没清除”。行内块问题多,但知道“父元素当字”这个总原因,再按水平居中、纵向居中、空白、对齐逐项排查,就能把现象解释清楚。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

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 就能对齐。

常见错误 ​

  1. 后续元素上移、文字被挤乱 → 浮动子元素后未给父元素清除浮动,或清除浮动类名拼写错误 → 给浮动元素的父元素加清除浮动类,并检查类名拼写与实际样式选择器一致。

  2. 浮动元素设置 margin: 0 auto 不居中 → 左右 auto 对浮动元素不生效 → 改用计算左右外边距,或改用行内块方案;需要整组居中时优先考虑行内块布局。

  3. 四个栏目统一加右外边距后最后一个掉行 → 行宽不足,最后一个元素仍带右外边距 → 给最后一个元素加 last 类并将右外边距覆盖为 0,或只给前几个元素加右外边距。

  4. 行内块元素之间出现无法解释的空白 → HTML 元素之间的换行被解析为空格 → 父元素设 font-size: 0,再给行内块内部文字单独恢复字体大小;不推荐把代码挤到一行。

  5. 行内块或图片底部出现“幽灵空白” → 行内块默认基线对齐,底部与基线对齐后留下基线与底线间距 → 给行内块设置 vertical-align: bottom(非默认值通常即可);图片也可用 display: block 作为经典修法。

  6. 多个行内块内容行数不同时呈阶梯状错位 → 默认按基线对齐,内部有文字时取最后一行文字基线,无文字时取自身底部 → 给行内块设置 vertical-align 为非 baseline 的值,如 middle、bottom。

  7. 行内块在父容器中只设 line-height 后文字居中、元素没居中 → 只处理了父级行高,未改变行内块自身对齐方式 → 父元素设行高,行内块再设 vertical-align: middle;内部有文字时再单独调整行高。

  8. 块级元素想纵向居中,写上下 margin: auto 无效甚至塌陷 → 上下 auto 不生效,且父元素可能发生外边距塌陷 → 用精确计算上外边距,或加 overflow: hidden/边框等解决塌陷;更优先评估是否改用行内块方案。

练习 ​

  1. 完成页面头部:logo、banner1、banner2 三列,采用“两左一右”浮动,父元素清除浮动,并只补一个中间间距。
  2. 完成主体左右分栏:左侧 750px、右侧 200px,中间留 10px;左侧再分上下两行,上行两个 A 型栏目,下行四个 B 型栏目,处理 B 型最后一个元素的右外边距。
  3. 用行内块实现 4 个导航项横向排列并整体水平居中,要求解决元素间空白,同时保证导航项内文字正常显示。
  4. 给出一个图片底部存在空白的页面,分别用 vertical-align 和 display: block 两种方式修复,并说明两种修法的适用场景。
  5. 让一个行内块元素在 600×400 的父容器中水平、垂直居中;要求父元素和行内块各自承担正确的样式,并处理行内块内部文字的垂直位置。

原视频对照 ​

#视频时长
1浮动页面案例0119:46
2浮动页面案例0216:39
3元素居中31:40
4行内块元素之间的空白07:21
5行内块元素底部的空白12:44
6行内块元素无法对齐的问题05:50

小结 ​

  1. 浮动布局要先分行、再分列,结构分层越清楚,后续样式越不容易乱。
  2. 只要用了浮动,就要条件反射检查父元素是否清除浮动,且要检查类名是否写对。
  3. 两左一右常用于三列布局,可少处理一个中间间距;四列及以上统一同向浮动更省事。
  4. 行内块适合做“补充布局”,尤其是需要整体居中的横向排列场景,但不能替代浮动布局。
  5. 行内块的三类高频问题集中在:元素间空白、底部空白、基线对齐错位。
  6. 行内块居中要分清横向和纵向:横向多由父级文本对齐控制,纵向需同时关注父级行高和自身 vertical-align。
  7. 看到“元素上去了、文字掉下来”“图片底部多一条缝”“内容行数不同就错位”,优先排查清除浮动、基线对齐和换行空白。