Skip to content

Flex 布局(一) ​

本页对应 Flex 布局,共 7 段视频,约 1 小时 29 分。

学习目标 ​

  • 能够解释外边距塌陷的成因,并分别用父元素加 padding-top、overflow: hidden、透明上边框三种方式解决。
  • 能够实现版心居中:为有宽度的块级元素设置 margin: 0 auto,并说明其生效条件。
  • 能够独立复现“网页新闻列表”作业模块,正确使用高度剩余法、li 下边框、链接去下划线及 :hover 效果。
  • 能够独立复现“课程卡片”作业模块,正确设置图片 width: 100%、标题与段落的 margin 对齐、局部文字变色。
  • 能够完成小米登录案例的 logo、标题、两个输入框和登录按钮,正确使用背景图、placeholder、padding-left、margin-bottom 及按钮悬停样式。
  • 能够搭建爱宠案例大盒子,设置固定宽高、水平居中、边框、背景图片,并说明标准流默认排列及浮动仅作了解。

知识点 ​

标准流:标签默认的排布规则 ​

为什么需要:一个页面里往往同时存在 div、h2、p、ul、li、a、span、input 这些标签。如果不知道它们默认怎么排,写 CSS 就只能靠试——挪一下看看,不行再挪一下,效率极低。转写稿里反复追问“块的元素需要给宽吗”,就是在确认大家对默认规则的掌握程度。

怎么想:浏览器在完全没有 CSS 的情况下,也有一套自己的排布规则,这套规则叫标准流,也叫文档流。它不需要我们写任何代码,只要不给标签加浮动、定位、flex,它就一直在起作用。所以我们写布局,本质上是“先接受标准流,再按需要打破它”。

怎么做:在页面里写两个 div、两个 span,不写任何样式,打开浏览器观察它们的落位。

标准流排布规则示例

块元素独占一行,行内元素可以一行显示多个——这是标准流最直观的两条结论。

易错点:标准流不是一条 CSS 属性,不存在“开启标准流”的写法。它是默认状态,你只能通过浮动、定位、flex 去改变它。

块级元素:独占一行,宽度默认撑满父元素 ​

为什么需要:转写稿讲作业时,直接说:“块的元素是不是默认的宽度和父亲一样宽呀,所以我们只需要给个高给个下边框。”这句话决定了 CSS 到底写几行。不知道这一点,就会习惯性给每个 div 补一句 width: 100%。

怎么想:块级元素(div、h1~h6、p、ul、li 等)有两个默认行为:一是独占一行,后面的元素只能换行;二是宽度自动填满父元素。所以父盒子有确定宽度时,子块不写 width 就是满宽。

怎么做:给新闻列表的 li 只写高度和下边框就够了:

css
.box ul li {
  height: 50px;
  line-height: 50px;
  border-bottom: 1px dashed #ccc;
}

不用写 width,li 默认就和 ul 一样宽。

易错点:块元素即使写了 width,也仍然独占一行,右边不会自动补上别的块。想让两个块并排,必须等后面学浮动或 flex。另外“撑满父元素”的前提是父元素有宽度,父元素没宽度时,块元素的宽度由它的包含块决定。

行内元素:一行显示多个,盒子大小由内容决定 ​

为什么需要:新闻列表里“体验 JavaScript 的魅力”是 a 标签,转写稿里特意强调:“你没有必要非得给 A 这么大,我们这是网页新闻,你没有见过鼠标放到这儿去就可以点击。”这说明行内元素的盒子范围就是文字本身。

怎么想:行内元素(a、span 等)不独占一行,能在一行里连续排。它的宽高由内容撑开,所以给它设 width、height 是没有意义的。

怎么做:想让文字往里缩,从 li 的角度给 padding-left,而不是给 a 设宽度:

css
.box ul li {
  padding-left: 30px;
}
.box ul li a {
  color: #333;
  text-decoration: none;
}

转写稿里也提到“给 A 来一个 margin-left: 30px 也行”,两种都能挤过去,暂时没区别。但要注意原则:想改谁就选谁,改文字颜色必须选到 a,选 li 是不生效的。

易错点:给行内元素设宽高无效;给行内元素设上下 margin 往往不生效,只有左右 margin 可靠。

行内块元素:input 的默认宽度不是父元素的宽度 ​

为什么需要:小米登录案例里,两个 input 和按钮都要撑满 339px。转写稿里的原话是:“因为 input 它属于行内块元素,默认的大小呀,它不会和父亲一样宽,所以这个 input 必须要给宽高。”

怎么想:input 既不完全是块,也不完全是行内——它一行能放多个,但又能设宽高,所以归为行内块。正因为“不会和父亲一样宽”,就必须手动量出来给它。

怎么做:

css
.mi input {
  width: 339px;
  height: 50px;
  border: 1px solid #ccc;
  padding-left: 12px;
}

易错点:这里的 padding-left: 12px 只能用 padding,不能用 margin——margin 会把整个盒子推走,而我们要的是“盒子不动、文字往里缩”。同理,text-indent 是段落首行缩进用的,布局时不要拿它调距离。

标准流下的版心居中 ​

为什么需要:转写稿里说“所有的块级元素默认是不是都是左对齐”,而网站主要内容必须居中。小米版心 1226px、淘宝版心 1190px,宽度不同但居中的写法一样。

怎么想:块元素默认左对齐,说明它右侧有多余空间。把左右外边距都设成 auto,浏览器会把剩余空间平分到两边,盒子就居中了。

怎么做:

css
.w {
  width: 1226px;
  height: 500px;
  background-color: pink;
  margin: 0 auto;
}

易错点:第一,必须给宽度,没宽度的块本来就满宽,看不出居中效果;第二,行内元素不能用这招;第三,margin: 0 auto 只解决水平居中,上下写 auto 不会让盒子垂直居中。

小结 ​

标准流是所有布局的地基:块独占一行且默认满宽,行内能并排但盒子随内容,行内块能设宽高但不随父元素。记住这三条,写 CSS 时就知道哪些属性该写、哪些纯属多余。

本节定位:浮动“了解即可” ​

转写稿里明确说:浮动“作为一个弱化的了,简单了解了”,重点讲 flex 布局。所以本节不把浮动当主力布局,只掌握三件事:float 怎么用、浮动盒子有什么现象、父级没高度时怎么清除浮动。转写稿里常把 margin 说成“麻疹/马真”、padding 说成“排定/排令”,这里统一写 margin、padding,避免记错单词。

基本使用 ​

为什么需要:块元素默认独占一行,想让两个块元素水平排列,早期常用 float。
怎么想:给盒子加 float: left 或 float: right,让盒子向左/向右靠。
怎么做:

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>浮动</title>
  <style>
    .left,
    .right {
      /* width: 200px; */
      height: 200px;
      background-color: pink;
    }

    .left {
      /* 左浮动 */
      float: left;
      margin-left: 20px;
    }

    .right {
      /* 右侧浮动 */
      float: left;
      height: 300px;
      background-color: purple;
    }

    .bottom {
      height: 50px;
      background-color: black;
    }
  </style>
</head>

<body>
  <div class="left">左侧123</div>
  <div class="right">右侧123</div>
  <div class="bottom"></div>
</body>

</html>

特点:

  • 浮动后的盒子顶对齐
  • 浮动后的盒子具备行内块特点
  • 浮动后的盒子脱标,不占用标准流的位置

浮动后的盒子顶对齐与脱标效果

易错点:浮动后盒子“脱标”,后面的标准流盒子会往上占位;不要以为它还会像普通块元素一样撑开父级。

产品区域布局:左右分栏 ​

为什么需要:产品区常见“左固定栏 + 右内容区”。
怎么想:外层定宽居中,左盒子 float: left,右盒子 float: right。
怎么做:

html
  <div class="mi">
    <div class="left">左侧</div>
    <div class="right">右侧</div>
  </div>
html
 <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    li {
      list-style: none;
    }

    .mi {
      width: 1226px;
      height: 614px;
      /* background-color: pink; */
      margin: 100px auto;
    }

    .left {
      float: left;
      width: 234px;
      height: 614px;
      background-color: skyblue;
    }

    .right {
      float: right;
      width: 978px;
      height: 614px;
      background-color: purple;
    }
</style>

效果:

产品区左右分栏效果

易错点:左右宽度和间距要算准;父级最好给高度或后续清除浮动,否则可能影响下面布局。

产品区域布局:小 li 排列 ​

为什么需要:右侧商品列表要一行多个排列。
怎么想:让 li 左浮动,用 margin-right、margin-bottom 做间距,每行最后一个去掉右间距。
怎么做:

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    li {
      list-style: none;
    }

    .mi {
      width: 1226px;
      height: 614px;
      /* background-color: pink; */
      margin: 100px auto;
    }

    .left {
      float: left;
      width: 234px;
      height: 614px;
      background-color: skyblue;
    }

    .right {
      float: right;
      width: 978px;
      height: 614px;
      /* background-color: purple; */
    }

    .right li {
      float: left;
      width: 234px;
      height: 300px;
      background-color: pink;
      margin-bottom: 14px;
      margin-right: 14px;
    }

    /* 让第4,8 个li 去掉外边距 */
    .right li:nth-child(4n) {
      margin-right: 0;
    }
  </style>
</head>

<body>
  <div class="mi">
    <div class="left">左侧</div>
    <div class="right">
      <ul>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
      </ul>
    </div>
  </div>
</body>

</html>

小 li 浮动排列效果

易错点:nth-child(4n) 是去第 4、8 个的右间距;宽度、间距、父级宽度要能对上,否则会掉行。

清除浮动:为什么需要 ​

为什么需要:浮动元素脱标,父级没高度时,子级撑不开父级高度,下面盒子会跑上来。
怎么想:清除浮动不是“删除浮动”,而是清除浮动对后面布局的影响。
怎么做:先看问题场景:

父级高度塌陷导致下方盒子错位

html
<style>
  .top {
    margin: 10px auto;
    width: 1200px;
    /* height: 300px; */
    background-color: pink;
  }

  .left {
    float: left;
    width: 200px;
    height: 300px;
    background-color: skyblue;
  }

  .right {
    float: right;
    width: 950px;
    height: 300px;
    background-color: orange;
  }

  .bottom {
    height: 100px;
    background-color: brown;
  }

</style>

<div class="top">
  <div class="left"></div>
  <div class="right"></div>
</div>
<div class="bottom"></div>

易错点:父级“没高度”是常见诱因;不要只盯子级,先看父级是否被撑开。

清除浮动的四种写法 ​

额外标签法:在父元素内容最后加块级元素,设置 clear: both。

html
<style>
.clearfix {
  clear: both;
}
</style>

<div class="father">
  <div class="left"></div>
  <div class="right"></div>
  <div class="clearfix"></div>
</div>

单伪元素法:给父级加 clearfix 类。

css
.clearfix::after {
  content: "";
  display: block;
  clear: both;
}
html
<div class="father clearfix"></div>

双伪元素法:before 解决外边距塌陷,after 清除浮动。

css
/* before 解决外边距塌陷问题 */
/* 双伪元素法 */
.clearfix::before,
.clearfix::after {
  content: "";
  display: table;
}

/* after 清除浮动 */
.clearfix::after {
  clear: both;
}
html
<div class="father clearfix"></div>

overflow 法:给父级加 overflow: hidden。

css
.father {
  margin: 10px auto;
  width: 1200px;
  /* height: 300px; */
  background-color: pink;

  overflow: hidden;
}

易错点:额外标签法会多一个空标签;伪元素法要记得给父级加类;overflow: hidden 可能裁剪溢出内容。实际开发中优先按项目规范选,不要混用后忘记原因。

本节图示 ​

02-浮动(了解即可,不用复习) 图示 1

代码示例 ​

代码示例一:浮动基本使用 ​

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>浮动</title>
  <style>
    .left,
    .right {
      /* width: 200px; */
      height: 200px;
      background-color: pink;
    }

    .left {
      /* 左浮动 */
      float: left;
      margin-left: 20px;
    }

    .right {
      /* 右侧浮动 */
      float: left;
      height: 300px;
      background-color: purple;
    }

    .bottom {
      height: 50px;
      background-color: black;
    }
  </style>
</head>

<body>
  <div class="left">左侧123</div>
  <div class="right">右侧123</div>
  <div class="bottom"></div>
</body>

</html>

关键行与易错点:

  • float: left 让块元素水平排列,两个盒子顶对齐。
  • 浮动后的盒子脱标,不占标准流位置,所以 .bottom 会钻到浮动盒子的下面(被遮住),这是最典型的“看不出效果”的原因。
  • 浮动后的盒子具备行内块特点:不给宽度时宽度由内容撑开(.left 的 width 被注释掉就是这个演示点)。
  • .right 只改了 height: 300px,与 .left 高度不同,用来验证顶对齐而不是底部对齐。

代码示例二:小米产品区域布局(左右布局 + 小 li 布局) ​

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    li {
      list-style: none;
    }

    .mi {
      width: 1226px;
      height: 614px;
      /* background-color: pink; */
      margin: 100px auto;
    }

    .left {
      float: left;
      width: 234px;
      height: 614px;
      background-color: skyblue;
    }

    .right {
      float: right;
      width: 978px;
      height: 614px;
      /* background-color: purple; */
    }

    .right li {
      float: left;
      width: 234px;
      height: 300px;
      background-color: pink;
      margin-bottom: 14px;
      margin-right: 14px;
    }

    /* 让第4,8 个li 去掉外边距 */
    .right li:nth-child(4n) {
      margin-right: 0;
    }
  </style>
</head>

<body>
  <div class="mi">
    <div class="left">左侧</div>
    <div class="right">
      <ul>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
      </ul>
    </div>
  </div>
</body>

</html>

关键行与易错点:

  • margin: 100px auto 是版心居中:有宽度的块级元素,左右外边距设为 auto 才能水平居中。
  • .left 用 float: left、.right 用 float: right,一个靠左一个靠右,实现左右布局。
  • 每个 li 都 float: left 才能一行排 4 个;宽度计算依赖 box-sizing: border-box(内减模式)。
  • 易错点:一排 4 个时,第 4 个 li 的 margin-right 会把 4 个挤到下一行,必须用 :nth-child(4n) 去掉每行最后一个的右外边距。
  • 易错点:* { margin: 0; padding: 0 } 和 li { list-style: none } 是清除默认样式的固定前置写法,漏写会出现小圆点和莫名间距。

代码示例三:清除浮动(父级没有高度,子级浮动脱标) ​

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>清除浮动</title>
  <style>
    .top {
      margin: 10px auto;
      width: 1200px;
      /* height: 300px; */
      background-color: pink;
    }

    .left {
      float: left;
      width: 200px;
      height: 300px;
      background-color: skyblue;
    }

    .right {
      float: right;
      width: 950px;
      height: 300px;
      background-color: orange;
    }

    .bottom {
      height: 100px;
      background-color: brown;
    }

    /* 单伪元素法:父级加上 clearfix 类即可 */
    .clearfix::after {
      content: "";
      display: block;
      clear: both;
    }
  </style>
</head>

<body>
  <div class="top clearfix">
    <div class="left"></div>
    <div class="right"></div>
  </div>
  <div class="bottom"></div>
</body>

</html>

关键行与易错点:

  • 场景:.top 的 height 被注释掉(父级没有高度),里面两个子盒子都浮动脱标,子级撑不开父级高度,父级高度塌成 0,.bottom 就顶上去造成布局错乱。
  • 单伪元素法三件套必须齐全:content: ""、display: block、clear: both,少任何一个都清不掉浮动。
  • 注意 .clearfix 要加在父级(.top)上,不是加在子级上。
  • 笔记中的其他三种写法(任选其一即可):
css
/* 双伪元素法:before 解决外边距塌陷,after 清除浮动 */
.clearfix::before,
.clearfix::after {
  content: "";
  display: table;
}

.clearfix::after {
  clear: both;
}

/* overflow 法:直接加给父级 */
.father {
  overflow: hidden;
}
  • 额外标签法:在父元素内容的最后加一个块级元素,设置 clear: both(行内元素无效,这是易错点)。
  • 易错点:clear: both 是加在“清除浮动影响”的元素上(伪元素/额外标签/父级 overflow),不是加在浮动盒子自己身上。

常见错误 ​

  1. 父级没有高度,子级浮动后底部盒子顶上来
    现象:父盒子背景/边框包不住浮动子元素,后面的 .bottom 与浮动区域重叠。
    原因:浮动元素脱标,父级未形成 BFC,也未清除浮动。
    修法:给父级加 .clearfix(伪元素清除)或 overflow: hidden,不要只在浮动子元素上写 clear: both。

  2. 清除浮动写成给浮动子元素加 clear: both
    现象:父级高度仍然塌陷,页面布局没恢复。
    原因:clear 要作用在浮动元素之后的块级元素/伪元素上,不是随便加在浮动元素自身。
    修法:在父元素内容最后加块级清除元素,或用 .clearfix::after { content:""; display:block; clear:both; }。

  3. 版心居中写成 text-align: center 或只写 margin-left: auto
    现象:盒子没有整体水平居中,或只有左侧自动外边距导致偏右/无效。
    原因:text-align 控制行内内容,不是块级盒子居中;块级盒子需左右外边距都为 auto。
    修法:有宽度的块级盒子写 margin: 0 auto; 或 margin: 100px auto;。

  4. 父子嵌套时直接给子元素 margin-top,父盒子一起下移
    现象:想让子盒子往下走,结果父盒子整体被带下来。
    原因:父子外边距塌陷。
    修法:优先给父级加 padding-top;或父级 overflow: hidden;或加透明上边框;或按需求改用父级 padding 控制内容位置。

  5. input 不给宽高,直接指望它撑满父级
    现象:输入框很短,和设计稿宽度不一致。
    原因:input 是行内块元素,不会像块元素一样默认占满父级宽度。
    修法:显式给 width、height、border,需要文字内缩时用 padding-left。

  6. 背景图被前面的 background-color 或简写覆盖
    现象:写了 background: url(...) 后背景色没了,或背景图不显示。
    原因:background 是复合属性,后写会覆盖前面同名部分;层叠顺序写反。
    修法:按“先大后小”写,先写 background 简写,再补 background-color;或分开写 background-image、background-color。

  7. 多列小 li 给每个都加右外边距,最后一列被挤换行
    现象:一行 4 个变成一行 3 个或布局错位。
    原因:第 4、8 个 li 仍保留 margin-right,总宽度超过父级。
    修法:用 :nth-child(4n) { margin-right: 0; } 去掉每行最后一个的右外边距,并确认盒模型为 border-box。

练习 ​

  1. 找错并修复:浮动父级塌陷
    给出 .top 内两个浮动子元素、下方 .bottom 的结构,要求让 .top 正确包住子元素且 .bottom 不被覆盖。
    检查点:父级是否使用清除浮动;是否没有给浮动子元素乱加 clear。

  2. 实现一个版心居中的两栏区域
    要求:外层宽 1226px 居中,左栏 234px 左浮动,右栏 978px 右浮动,并保证下方模块不重叠。
    检查点:margin: 0 auto、浮动方向、父级高度/清除浮动处理。

  3. 实现 4 列小卡片布局
    要求:右栏内 8 个 li 左浮动,每行 4 个,卡片宽 234px、右间距 14px、下间距 14px。
    检查点:第 4、8 个 li 的右外边距是否为 0;总宽度是否超出容器。

  4. 复现小米登录框局部
    要求:完成 logo、标题、两个 input、登录按钮。logo 用 h1 + 背景图;输入框给宽高、边框和左内边距;按钮去掉默认边框并设置背景色。
    检查点:input 是否显式设宽高;文字是否用 padding-left 内缩;按钮边框是否清除。

  5. 复现爱宠卡片局部
    要求:大盒子宽高约 262×342,水平居中,带边框和背景图;内部标题、列表项按设计稿调整间距。
    检查点:背景图是否平铺;父级是否居中;列表项间距是否用外边距/内边距合理控制。

原视频对照 ​

#视频时长
1反馈和复习19:56
2作业118:52
3作业212:47
4小米登录案例-logo制作13:41
5小米标题和input10:17
6小米input和button07:26
7爱宠案例-大盒子搭建06:02

小结 ​

  1. 浮动适合让块元素水平排列,但必须处理脱标带来的父级高度塌陷问题。
  2. 清除浮动的核心是让父级重新包住浮动子元素,常用伪元素法或 overflow: hidden。
  3. 版心居中的关键是“有宽度的块级盒子 + 左右 margin: auto”,不是 text-align。
  4. 父子嵌套优先用父级 padding 控制内容整体内缩,能减少外边距塌陷和重复写子元素外边距。
  5. 盒子和盒子之间的距离优先考虑 margin;盒子内部文字/内容的内缩优先考虑 padding。
  6. input、按钮等行内块/表单元素通常需要显式宽高,不能默认依赖父级宽度。
  7. 背景图、背景色、边框和盒模型要一起检查,尤其注意 background 简写的层叠覆盖。
  8. 多列布局要计算总宽度,并用 :nth-child 去掉每行最后一个元素的多余外边距。