文章目录
《CSS in Depth》新版封面
7.1.1 创建移动端菜单 Creating a mobile menu
至此,页面中要实现的最复杂的部分就只剩菜单了。完成后的页面效果将如图 7.6 所示:
【图 7.6 在移动端设备打开的导航菜单效果图】
不管用什么语言写代码都有个迭代过程,CSS 也不例外。在本页中,菜单的设计就经过了一番深思熟虑。<nav>
原本是放在 <header>
中的,因为希望汉堡图标出现在 <header>
元素内;后来写 CSS 的时候发觉不对,应该将这两个元素设计成并列的兄弟节点,这样才能在桌面端中呈自然的上下排列。HTML 里的某些内容有时候也需要像这样反复调试,才能达到最佳的预期效果。
从功能上看,该菜单很像上一章(代码清单 6.9)里的下拉菜单:先隐藏 menu-dropdown
元素,再用 JavaScript
添加一些交互功能;用户一点击(或轻触)menu-dropdown
元素,就会出现下拉菜单;再点一次,菜单就隐藏。
根据代码清单 7.1 的 HTML 标记内容,<nav>
作为同级元素出现在了 <header>
之后,这意味着它将随文档流来到标题区的下方位置显示。为了达到既定的设计要求,只能采用一种不太常用的做法,将 menu-toggle
按钮元素绝对定位到上面的标题栏区域内。根据代码清单 7.3 更新菜单样式:
代码清单 7.3 移动端菜单样式代码
.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 代码
<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 导航菜单的样式设置
.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>
),需要覆盖浏览器的默认左内边距并去掉列表项的默认原点图标。相邻兄弟组合选择器则会选中除了第一个菜单项外的所有元素,并给它们指定一个上边框。
有个地方需要特别注意一下:菜单链接元素的内边距设置。因为样式是针对移动端设计的,通常是在触屏设备上显示。因此点击的核心区域应该设计得足够大,方便一根手指进行操作。
7.1.2 给视口添加 meta 标签 Adding the viewport meta tag
至此,移动端设计业已完成,但还漏了一个关键细节:视口的 meta 标签(meta tag)。该 HTML 标签会告诉移动端设备,该页面已经特地为小尺寸屏做了适配。如果不加的话,移动端的浏览器就会认定该页面并非响应式设计,并试图模拟桌面端浏览器进行渲染,之前所做的那些移动端设计就都白费了。这种事可干不得。
因此需要根据代码清单 7.6 更新 HTML 中的 <head>
元素,将 meta
标签包含进去。这也是给浏览器以明示,您已经专门考虑了网站的响应式行为。
代码清单 7.6 为移动端的响应式设计添加视口 meta 标签
<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%
。
视口 meta
标签还提供了其他配置选项,但以上配置应该最能满足实际需求。例如,可以明确设置 width=320
让浏览器假定视口宽度为 320px
,但通常并不建议这样设置,因为移动端的设备尺寸范围很广。借助 device-width
就能让内容以最合适的尺寸进行渲染。
此外,开发人员偶尔还会在 content
属性中添加第三个配置项 user-scalable=no
,用于阻止用户在移动端设备上通过两个手指进行缩放。通常该设置在实践中并不友好,不推荐使用。当链接太小无法点击,或者用户想把某个图片看得更清楚时,该设置会阻止他们缩放页面。有关视口 meta
标签的更多信息,请参阅 MDN 文档:https://mng.bz/Y7po。
第 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 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!