CSS 从 Twitter 网页布局入门媒体查询

274 阅读5分钟

前言

本文先以 BFE.dev 上的一道 CSS 问题 Twitter 网页布局为引,介绍了媒体查询的基本用法,之后讲解了如何使用 flex 布局和媒体查询实现本题的响应式布局。

题目

Twitter 网页布局是 BFE.dev 上的一题:8. Twitter 网页布局(建议点击链接查看原题,原题有示意图,比较清晰)。

假设我们有如下 HTML 结构。

<div class="container">
  <div class="left">left</div>
  <div class="middle">middle</div>
  <div class="right">right</div>
</div>

现在请完成CSS以满足以下要求:

  • 当视口宽度不够时,将左列设置为 40px 宽,将中间列设置为拉伸。
  • 中间列的最大宽度为 240px。
  • 当有足够的空间时,显示宽度为 120px 的右列。
  • 如果有更多空间,请将左列设置为 80px。
  • 当右列可见时,将最小 10px 空间水平设置为视口边框。

本体是响应式布局的经典案例,下面将先介绍媒体查询实现响应式布局的基本用法。

媒体查询

通过媒体查询(Media queries),您可以根据各种设备特征和参数的值或者是否存在来调整您的网站或应用。它们是响应式设计的关键组成部分。CSS 媒体查询为你提供了一种应用 CSS 的方法,仅在浏览器和设备的环境与你指定的规则相匹配的时候 CSS 才会真的被应用,例如“视口宽于 480 像素”的时候。(摘自MDN

媒体查询由以下部分组成:

  • 一个媒体类型,告诉浏览器这段代码是用在什么类型的媒体上的(例如印刷品或者屏幕);
  • 一个媒体表达式,是一个被包含的 CSS 生效所需的规则或者测试;
  • 一组 CSS 规则,会在测试通过且媒体类型正确的时候应用。

最简单的媒体查询语法看起来是像这样的:

@media media-type and (media-feature-rule) {
  /* CSS rules go here */
}

媒体类型

媒体类型描述设备的一般类别,可以是:

  • all:适用于所有设备。
  • print:适用于在打印预览模式下在屏幕上查看的分页材料和文档。
  • screen:主要用于屏幕。

媒体特性(媒体特征规则)

媒体特性可以是最简单的宽和高,使用 min-widthmax-widthwidth ,在视口宽度大于或者小于某个大小,或者是恰好处于某个大小的时候应用 CSS,具体使用可以参考 MDN 文档,或者下文的题解也会介绍具体的使用方法。

媒体特性也可以是朝向、悬浮等等,可以查询 MDN 文档查看详细介绍,本文只做简单入门。

逻辑操作符

我们可以使用逻辑操作符构造复杂的媒体查询。

  • and 类似“与”逻辑,当每个查询规则都为真时则该条媒体查询为 true,它还用于将媒体功能与媒体类型结合在一起。
  • ,or 类似“或”逻辑,用于将多个媒体查询合并为一个规则,如果列表中的任何查询为 true,则整个媒体查询语句返回 true
  • not 类似“非”逻辑,用于否定媒体查询,如果不满足这个条件则返回 true,否则返回 false。 如果出现在以逗号分隔的查询列表中,它将仅否定应用了该查询的特定查询。 如果使用 not 运算符,则还必须指定媒体类型。
  • only 仅在整个查询匹配时才用于应用样式,并且对于防止较早的浏览器应用所选样式很有用。 当不使用 only 时,旧版本的浏览器会将 screen and (max-width: 500px) 简单地解释为 screen,忽略查询的其余部分,并将其样式应用于所有屏幕。 如果使用only运算符,则还必须指定媒体类型。

一定要用媒体查询?

弹性盒、网格和多栏布局已经给了我们建立可伸缩的甚至是响应式组件的方式,有些布局完全可以使用以上几种方式实现,并不是一定要用媒体查询。

题解

下面将使用 flex 布局和媒体查询实现本题的响应式布局。

这题有个隐藏条件是盒子里的元素是水平垂直居中对齐的,所以题解中的冗余代码不少。 题解通过 flex 实现水平垂直居中对齐。

display: flex;
justify-content: center;
align-items: center;

规则实现:

  • 当视口宽度不够时,将左列设置为 40px 宽,将中间列设置为拉伸。 默认设置左列 min-width: 40px;,使用 flex: 1; 实现中间拉伸。
  • 中间列的最大宽度为 240px。 设置 max-width: 240px;
  • 当有足够的空间时,显示宽度为 120px 的右列。 使用媒体查询,因为规则 5 ,实际视口宽度足够的大小为 40px + 240px + 120px + 10px * 2 = 420px。 媒体类型和表达式为 @media screen and (min-width: 420px)
  • 如果有更多空间,请将左列设置为 80px。 使用媒体查询,视口大小大于 460px 时应用样式。
  • 当右列可见时,将最小 10px 空间水平设置为视口边框。

代码实现如下:

.container {
  display: flex;
  justify-content: center;
  height: 150px;
}

.left {
  display: flex;
  justify-content: center;
  align-items: center;
  min-width: 40px;
  background-color: #eee;
}

.middle {
  display: flex;
  justify-content: center;
  align-items: center;
  flex: 1;
  max-width: 240px;
  background-color: #ddd;
}
.right {
  display: none;
  background-color: #eee;
}

@media screen and (min-width: 420px) {
  .container {
    margin: 0 10px;
  }

  .right {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 120px;
  }
}

@media screen and (min-width: 460px) {
  .left {
    width: 80px;
  }
}

参考资料

8. Twitter 网页布局 | BFE.dev - 前端刷题,准备前端面试拿到心仪的Offer。
媒体查询入门指南 - 学习 Web 开发 | MDN
媒体查询 - CSS(层叠样式表) | MDN
@media - CSS(层叠样式表) | MDN