【CSS in Depth 2 精译_046】7.1 CSS 响应式设计中的移动端优先设计原则(下)

当前内容所在位置(可进入专栏查看其他译好的章节内容)

  • 第一章 层叠、优先级与继承(已完结)
    • 1.1 层叠
    • 1.2 继承
    • 1.3 特殊值
    • 1.4 简写属性
    • 1.5 CSS 渐进式增强技术
    • 1.6 本章小结
  • 第二章 相对单位(已完结)
    • 2.1 相对单位的威力
    • 2.2 em 与 rem
    • 2.3 告别像素思维
    • 2.4 视口的相对单位
    • 2.5 无单位的数值与行高
    • 2.6 自定义属性
    • 2.7 本章小结
  • 第三章 文档流与盒模型(已完结)
    • 3.1 常规文档流
    • 3.2 盒模型
    • 3.3 元素的高度
    • 3.4 负的外边距
    • 3.5 外边距折叠
    • 3.6 容器内的元素间距问题
    • 3.7 本章小结
  • 第四章 Flexbox 布局(已完结)
    • 4.1 Flexbox 布局原理
    • 4.2 弹性子元素的大小
    • 4.3 弹性布局的方向
    • 4.4 对齐、间距等细节处
    • 4.5 本章小结
  • 第五章 网格布局(已完结)
    • 5.1 构建基础网格
    • 5.2 网格结构剖析 (上)
      • 5.2.1 网格线的编号(下)
      • 5.2.2 网格与 Flexbox 配合(下)
    • 5.3 两种替代语法
      • 5.3.1 命名网格线
      • 5.3.2 命名网格区域
    • 5.4 显式网格与隐式网格(上)
      • 5.4.1 添加变化 (中)
      • 5.4.2 让网格元素填满网格轨道(下)
    • 5.5 子网格(全新增补内容)
    • 5.6 对齐相关的属性
    • 5.7 本章小结
  • 第六章 定位与堆叠上下文(已完结)
    • 6.1 固定定位
      • 6.1.1 创建一个固定定位的模态对话框
      • 6.1.2 在模态对话框打开时防止屏幕滚动
      • 6.1.3 控制定位元素的大小
    • 6.2 绝对定位
      • 6.2.1 关闭按钮的绝对定位
      • 6.2.2 伪元素的定位问题
    • 6.3 相对定位
      • 6.3.1 创建下拉菜单(上)
      • 6.3.2 创建 CSS 三角形(下)
    • 6.4 堆叠上下文与 z-index
      • 6.4.1 理解渲染过程与堆叠顺序(上)
      • 6.4.2 用 z-index 控制堆叠顺序(上)
      • 6.4.3 深入理解堆叠上下文(下)
    • 6.5 粘性定位
    • 6.6 本章小结
  • 第七章 响应式设计(概述)
    • 7.1 移动端优先设计原则(上篇)
      • 7.1.1 创建移动端菜单(下篇) ✔️
      • 7.1.2 给视口添加 meta 标签(下篇) ✔️
    • 7.2 媒体查询(精译中 ⏳)

文章目录

      • [7.1.1 创建移动端菜单 Creating a mobile menu](#7.1.1 创建移动端菜单 Creating a mobile menu)
      • [7.1.2 给视口添加 meta 标签 Adding the viewport meta tag](#7.1.2 给视口添加 meta 标签 Adding the viewport meta tag)

《CSS in Depth》新版封面

译者按

何谓经典著作?大概就是在阅读过程中,可以深切感受到作者对所讲内容的如数家珍、倾囊相授;通过把每个细节掰开了揉碎了演示出来,手把手地教你怎么去理解某个知识点,生怕读者看不懂。就比如这本再版的《CSS in Depth》。

至此,页面中要实现的最复杂的部分就只剩菜单了。完成后的页面效果将如图 7.6 所示:

【图 7.6 在移动端设备打开的导航菜单效果图】

译注

由于翻译是分开发表的,不像原文可以在同一页面上下滚动来回看提到的 HTML 片段;即便用 PDF 格式的电子书进行阅读,定位某个内容也比看单独发表的博文容易得多,因此书里并没有给出汉堡按钮相关的 HTML 片段,后面的讨论只能全靠大家想象。这里特地补上一段,减轻大家的跳转负担:

html 复制代码
<header id="header" class="page-header">
  <div class="title">
    <h1>Wombat Coffee Roasters</h1>
    <div class="slogan">We love coffee</div>
  </div>
</header>

<nav class="menu" id="main-menu">
  <button class="menu-toggle" id="toggle-menu"> <!-- 定义移动端菜单的"汉堡"状按钮 -->
    toggle menu
  </button>
  <div class="menu-dropdown"> <!-- 在移动端设备上默认隐藏的主菜单 -->
    <ul class="nav-menu">
      <li><a href="/about.html">About</a></li>
      <li><a href="/shop.html">Shop</a></li>
      <li><a href="/menu.html">Menu</a></li>
      <li><a href="/brew.html">Brew</a></li>
    </ul>
  </div>
</nav>

不管用什么语言写代码都有个迭代过程,CSS 也不例外。在本页中,菜单的设计就经过了一番深思熟虑。<nav> 原本是放在 <header> 中的,因为希望汉堡图标出现在 <header> 元素内;后来写 CSS 的时候发觉不对,应该将这两个元素设计成并列的兄弟节点,这样才能在桌面端中呈自然的上下排列。HTML 里的某些内容有时候也需要像这样反复调试,才能达到最佳的预期效果。

从功能上看,该菜单很像上一章(代码清单 6.9)里的下拉菜单:先隐藏 menu-dropdown 元素,再用 JavaScript 添加一些交互功能;用户一点击(或轻触)menu-dropdown 元素,就会出现下拉菜单;再点一次,菜单就隐藏。

提示

读屏工具会将某些 HTML5 元素,比如 <form><main><nav> 以及 <aside> 视为 导航标识(landmarks ,以帮助视力欠佳的用户群体快速浏览网页。因此,最好将控制菜单切换的汉堡按钮设计在 <nav> 元素的里面,以便用户浏览到这里时能快速发现它;不然等浏览到 <nav> 时会误以为里面是空的(因为读屏工具会忽略掉样式为 display: none 的下拉菜单)。
汉堡菜单的弊端

汉堡菜单已成为近年来一种流行的移动端设计方案。它解决了在小尺寸屏幕下显示更多内容的问题,但也存在弊端。事实证明,隐藏页面关键元素(如主导航菜单)会降低用户与之交互的可能性。

这些因素需要您和您的团队或设计师综合考量:有时启用汉堡菜单会很合适,有时则未必。无论如何,掌握汉堡菜单的构建方法还是有必要的,也很重要。

根据代码清单 7.1 的 HTML 标记内容,<nav> 作为同级元素出现在了 <header> 之后,这意味着它将随文档流来到标题区的下方位置显示。为了达到既定的设计要求,只能采用一种不太常用的做法,将 menu-toggle 按钮元素绝对定位到上面的标题栏区域内。根据代码清单 7.3 更新菜单样式:

代码清单 7.3 移动端菜单样式代码

css 复制代码
.menu {
  position: relative; /* 给绝对定位的两个子元素创建包含块 */
}

.menu-toggle {
  position: absolute;
  top: -1.2em; /* 用负的 top 值将按钮拉到包含块的上方 */
  right: 0.1em;

  border: 0; /* 覆盖浏览器的默认按钮样式 */
  background-color: transparent;

  font-size: 3em;
  width: 1em;
  height: 1em;
  line-height: 0.4;
  text-indent: 5em; /* 隐藏按钮文字内容,字号设为 1em */
  white-space: nowrap;
  overflow: hidden;
}
.menu-toggle::after {
  position: absolute;
  top: 0.2em;
  left: 0.2em;
  display: block;
  content: "\2261"; /* 用一个代表汉堡图标的 Unicode 字符盖在按钮上面 */
  text-indent: 0;
}

.menu-dropdown {
  display: none;
  position: absolute;
  right: 0;
  left: 0;
  margin: 0;
}

.menu.is-open .menu-dropdown {
  display: block; /* 在菜单加上 is-open 类时显示下拉菜单 */
}

以上代码实现了很多效果,但大部分都是讲过的内容。相对定位的菜单容器为其内部的两个子元素(切换按钮与下拉菜单)建立了包含块;切换按钮通过负的 top 值往上走,right 属性则将其定位到屏幕右侧,最终位于页面标题区的右侧。

然后在按钮上设置一些文字替换的"小把戏"(replacement trick):限定宽度、加大 text-indent(文字缩进量)、并隐藏溢出部分,以实现按钮文字的隐藏;然后给按钮的 ::after 伪元素设置一个 Unicode 字符(\2261)作为内容。该字符是一个数学符号(译注:即恒等号、全等号 ),由三条横线组成。要是想进一步定制图标,还可以在伪元素上设置背景图片。

如果拿不准每个样式的作用是什么,可以先把它们注释掉,看看页面的实际效果。该页面在大尺寸屏幕下看着有点滑稽。把浏览器窗口调小些,看着就更像移动端里的效果了。

而样式类 is-open 则在打开菜单时通过 JavaScript 添加。下拉菜单仅在按钮存在该样式类时可见。下拉菜单隐藏前的页面效果,如图 7.7 所示(注意页面左侧位于主图上方的那四个菜单链接)。

【图 7.7 样式生效后的汉堡按钮效果图】

按下切换按钮,以下 JavaScript 代码会添加或删除样式类 is-open。将这些代码添加到 <head> 标签内:

代码清单 7.4 实现下拉功能的 JavaScript 代码

html 复制代码
<script type="module">
  var button = document.getElementById('toggle-menu');
  button.addEventListener('click', function(event) { // 点击事件的监听器(亦即触屏设备的轻触事件监听器)
    event.preventDefault();
    var menu = document.getElementById('main-menu');
    menu.classList.toggle('is-open');  // 在 menu 元素上切换 is-open 样式类
  });
</script>

此时点击汉堡图标,就会打开下拉菜单;同时可以看到,菜单文字出现在了网页内容的前方;再次点击按钮,则菜单关闭。这样就通过 CSS 实现了对应元素的显示与隐藏,而 JavaScript 只负责切换一个样式类即可。

现在下拉菜单可以正常工作了,但 nav-menu 元素还需加些样式。请根据代码清单 7.5 更新样式表:

代码清单 7.5 导航菜单的样式设置

css 复制代码
.nav-menu {
  margin: 0;
  padding-left: 0;
  border: 1px solid #ccc;
  list-style: none;
  background-color: #000;
  color: #fff;
}

.nav-menu > li + li { /* 给每个菜单元素设置上边框 */
  border-top: 1px solid #ccc;
}

.nav-menu > li > a {
  display: block;
  padding: 0.8em 1em; /* 设置适当的内边距以确保点击区域足够大 */
  color: #fff;
  font-weight: normal;
}

上面的样式都没啥新东西,由于菜单是一个列表元素(<ul>),需要覆盖浏览器的默认左内边距并去掉列表项的默认原点图标。相邻兄弟组合选择器则会选中除了第一个菜单项外的所有元素,并给它们指定一个上边框。

有个地方需要特别注意一下:菜单链接元素的内边距设置。因为样式是针对移动端设计的,通常是在触屏设备上显示。因此点击的核心区域应该设计得足够大,方便一根手指进行操作。

提示

在应对移动端触屏设备的样式设计时,要确保所有的关键动作元素(key action items)都足够大,以便用一根手指轻松点击。切忌让用户为了准确点中某个小小的按钮或者链接而不得不放大页面。

7.1.2 给视口添加 meta 标签 Adding the viewport meta tag

至此,移动端设计业已完成,但还漏了一个关键细节:视口的 meta 标签(meta tag。该 HTML 标签会告诉移动端设备,该页面已经特地为小尺寸屏做了适配。如果不加的话,移动端的浏览器就会认定该页面并非响应式设计,并试图模拟桌面端浏览器进行渲染,之前所做的那些移动端设计就都白费了。这种事可干不得。

因此需要根据代码清单 7.6 更新 HTML 中的 <head> 元素,将 meta 标签包含进去。这也是给浏览器以明示,您已经专门考虑了网站的响应式行为。

代码清单 7.6 为移动端的响应式设计添加视口 meta 标签

html 复制代码
<head>
  <meta charset="UTF-8">
  <!-- 视口 meta 标签: -->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Wombat Coffee Roasters</title>
  <link href="styles.css" rel="stylesheet" type="text/css" />
</head>

meta 标签的 content 属性包含两个选项。首先,它告诉浏览器在解析 CSS 时要将设备的宽度作为假定宽度,而不是一个全屏的桌面版浏览器的宽度;其次,在页面加载时,要用 initial-scale 将缩放比例设置为 100%

提示

现代浏览器的开发者工具(DevTools)提供了模拟移动端浏览器的功能,包括较小的视口尺寸和视口 meta 标签的行为。这些实用工具能帮助我们测试响应式设计。更多信息,请参阅 https://mng.bz/ppa5Chrome 浏览器)或者 https://mng.bz/OZnKFirefox 浏览器)

视口 meta 标签还提供了其他配置选项,但以上配置应该最能满足实际需求。例如,可以明确设置 width=320 让浏览器假定视口宽度为 320px,但通常并不建议这样设置,因为移动端的设备尺寸范围很广。借助 device-width 就能让内容以最合适的尺寸进行渲染。

此外,开发人员偶尔还会在 content 属性中添加第三个配置项 user-scalable=no,用于阻止用户在移动端设备上通过两个手指进行缩放。通常该设置在实践中并不友好,不推荐使用。当链接太小无法点击,或者用户想把某个图片看得更清楚时,该设置会阻止他们缩放页面。有关视口 meta 标签的更多信息,请参阅 MDN 文档:https://mng.bz/Y7po



关于《CSS in Depth》(中译本书名《深入解析 CSS》)

第 1 版 第 2 版
读者评分 原版:4.7 (亚马逊);中文版:9.3(豆瓣) 原版:5.0(亚马逊);中文版:暂无,待出版
出版时间 原版:2018 年 3 月 ;中文版:2020 年 4 月 原版:2024 年 7 月;中文版:暂无,待出版
原价 原版:$44.99 ;中文版:¥139.00 原版:$59.99;中文版:暂无,待出版
现价 原版:$36.49 ;中文版:¥52.54 起步 原版:$52.09;中文版:暂无,待出版
原版国内预订 起步价 ¥461.00 起步价 ¥750.00

本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!

相关推荐
活宝小娜1 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点1 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow1 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o1 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā2 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年3 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder3 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727574 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart4 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter