实际定位示例
本文展示了如何构建一些真实世界的示例,以说明您可以通过定位实现哪些功能。
| 预备知识 | HTML 基础知识(学习 使用 HTML 结构化内容)以及 CSS 的工作原理(学习 CSS 样式基础)。 |
|---|---|
| 目标 | 了解定位的实际应用 |
带标签的信息框
我们将看到的第一个示例是一个经典的带标签信息框——当您想将大量信息打包到小区域时,这是一个非常常见的功能。这包括信息密集型应用程序,如策略/战争游戏、屏幕狭窄且空间有限的网站移动版本,以及紧凑型信息框,您可能希望提供大量信息而无需它填满整个 UI。我们的简单示例完成后将如下所示:

注意: 您可以在 tabbed-info-box.html (源代码) 上查看正在运行的完整示例。查看它以了解您将在本文的这一部分中构建什么。
您可能正在想“为什么不将单独的选项卡创建为单独的网页,然后让选项卡单击以切换到单独的页面以创建效果?”这种代码会更简单,是的,但随后每个单独的“页面”视图实际上是一个新加载的网页,这将使跨视图保存信息变得更加困难,并难以将此功能集成到更大的 UI 设计中。
首先,我们希望您制作起始文件的本地副本 — tabbed-info-box-start.html 和 tabs-manual.js。将它们保存到您本地计算机上一个合理的位置,并在文本编辑器中打开 tabbed-info-box-start.html。让我们看看正文中包含的 HTML:
<section class="info-box">
<div role="tablist" class="manual">
<button
id="tab-1"
type="button"
role="tab"
aria-selected="true"
aria-controls="tabpanel-1">
<span>Tab 1</span>
</button>
<button
id="tab-2"
type="button"
role="tab"
aria-selected="false"
aria-controls="tabpanel-2">
<span>Tab 2</span>
</button>
<button
id="tab-3"
type="button"
role="tab"
aria-selected="false"
aria-controls="tabpanel-3">
<span>Tab 3</span>
</button>
</div>
<div class="panels">
<article id="tabpanel-1" role="tabpanel" aria-labelledby="tab-1">
<h2>The first tab</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque
turpis nibh, porttitor nec venenatis eu, pulvinar in augue. Vestibulum
et orci scelerisque, vulputate tellus quis, lobortis dui. Vivamus varius
libero at ipsum mattis efficitur ut nec nisl. Nullam eget tincidunt
metus. Donec ultrices, urna maximus consequat aliquet, dui neque
eleifend lorem, a auctor libero turpis at sem. Aliquam ut porttitor
urna. Nulla facilisi.
</p>
</article>
<article id="tabpanel-2" role="tabpanel" aria-labelledby="tab-2">
<h2>The second tab</h2>
<p>
This tab hasn't got any Lorem Ipsum in it. But the content isn't very
exciting all the same.
</p>
</article>
<article id="tabpanel-3" role="tabpanel" aria-labelledby="tab-3">
<h2>The third tab</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque
turpis nibh, porttitor nec venenatis eu, pulvinar in augue. And now an
ordered list: how exciting!
</p>
<ol>
<li>dui neque eleifend lorem, a auctor libero turpis at sem.</li>
<li>Aliquam ut porttitor urna.</li>
<li>Nulla facilisi</li>
</ol>
</article>
</div>
</section>
所以这里我们有一个带有 info-box 类的 <section> 元素,其中包含两个 <div>。第一个 div 包含三个按钮,它们将成为实际的选项卡,用于点击显示我们的内容面板。第二个 div 包含三个 <article> 元素,它们将构成与每个选项卡对应的内容面板。每个面板都包含一些示例内容。
这里的想法是,我们将把选项卡样式化为标准的水平导航菜单,并使用绝对定位将面板样式化为相互堆叠。我们还将为您提供一些 JavaScript,将其包含在您的页面中,以便在按下选项卡时显示相应的面板,并样式化选项卡本身。您暂时不需要理解 JavaScript 代码本身,但您应该尽快考虑学习一些基本的 JavaScript — 您的 UI 功能越复杂,您就越有可能需要一些 JavaScript 来实现所需的功能。
通用设置
首先,在您的起始和结束 <style> 标签之间添加以下内容:
html {
font-family: sans-serif;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
这只是设置页面上的无衬线字体,使用 border-box box-sizing 模型,并去除默认的 <body> 外边距的一些通用设置。
接下来,在您之前的 CSS 下方添加以下内容:
.info-box {
width: 452px;
height: 400px;
margin: 1.25rem auto 0;
}
这设置了内容的特定宽度和高度,并使用旧的 margin: 1.25rem auto 0 将其居中显示在屏幕上。之前在课程中,我们建议尽可能避免为内容容器设置固定高度;在这种情况下是可以的,因为我们的选项卡中有固定内容。
样式化我们的选项卡
现在我们想将选项卡样式化为选项卡——基本上,这些是一个水平导航菜单,但它们不像我们之前在课程中看到的那样在单击时加载不同的网页,而是导致不同的面板显示在同一页面上。首先,在 CSS 底部添加以下规则,使 tablist 成为 flex 容器并使其跨越 100% 宽度:
.info-box [role="tablist"] {
min-width: 100%;
display: flex;
}
注意: 在本示例中,我们始终使用以 .info-box 开头的后代选择器——这样做的目的是我们可以将此功能插入到已经有其他内容的页面中,而不必担心干扰应用于页面其他部分的样式。
接下来,我们将按钮样式化为选项卡。添加以下 CSS:
.info-box [role="tab"] {
padding: 0 1rem;
line-height: 3rem;
background: white;
color: #b60000;
font-weight: bold;
border: none;
outline: none;
}
接下来,我们将设置选项卡的 :focus 和 :hover 状态,使其在获得焦点/悬停时看起来不同,为用户提供一些视觉反馈。
.info-box [role="tab"]:focus span,
.info-box [role="tab"]:hover span {
outline: 1px solid blue;
outline-offset: 6px;
border-radius: 4px;
}
然后我们将设置一条规则,当其上设置了 aria-selected 属性为 true 时,突出显示其中一个选项卡。我们将在单击选项卡时使用 JavaScript 设置此属性。将以下 CSS 放在其他样式下方:
.info-box [role="tab"][aria-selected="true"] {
background-color: #b60000;
color: white;
}
样式化面板
接下来的工作是样式化我们的面板。让我们开始吧!
首先,添加以下规则来样式化 .panels <div> 容器。这里我们设置了固定的 height 以确保面板紧密地适应信息框,position 为 relative 以将 <div> 设置为定位上下文,这样您就可以相对于它而不是初始视口放置定位的子元素,最后我们 clear 了上面 CSS 中设置的浮动,这样它就不会干扰布局的其余部分。
.info-box .panels {
height: 352px;
clear: both;
position: relative;
}
本节的最后一点是,我们将对组成我们面板的单个 <article> 元素进行样式设置。我们将添加的第一条规则将绝对 position 定位面板,并使它们都与其 <div> 容器的 top 和 left 对齐——这部分是整个布局功能的关键,因为它使面板相互堆叠。该规则还为面板提供了与容器相同的固定高度,并为内容提供了一些内边距、文本 color 和 background-color。
.info-box [role="tabpanel"] {
background-color: #b60000;
color: white;
position: absolute;
padding: 0.8rem 1.2rem;
height: 352px;
top: 0;
left: 0;
}
我们将在这里添加的第二条规则将使具有 is-hidden 类的面板被隐藏。同样,我们将在适当的时候使用 JavaScript 添加/删除此类。当选择一个选项卡时,相应的面板将删除其 is-hidden 类,所有其他面板将设置 is-hidden 类,因此一次只有一个面板可见。
.info-box [role="tabpanel"].is-hidden {
display: none;
}
JavaScript
使此功能工作的最后一部分是 JavaScript 代码。tabs-manual.js 文件已使用 <script> 标签包含:
<script src="tabs-manual.js"></script>
此代码执行以下操作:
-
创建
TabsManual对象时,在构造函数中,所有选项卡和面板引用都收集在tabs和tabpanels变量中,因此我们以后可以轻松地对它们进行操作。 -
构造函数还会在所有选项卡上注册
click和keydown事件处理程序。事件处理程序包含有关使用点击或按键选择选项卡时应发生的情况的逻辑。 -
在
setSelectedTab(currentTab)函数中,发生以下情况:- 使用
for循环遍历所有选项卡并取消选择它们,方法是将aria-selected属性设置为false,并为相应的面板设置is-hidden类。 - 在选定的选项卡(
currentTab)上,aria-selected被设置为true,并且从相应的面板中删除了is-hidden类。
- 使用
-
该代码还包含支持使用
左箭头、右箭头、Home和End键进行键盘导航的逻辑。
固定位置的带标签信息框
在我们的第二个示例中,我们将采用第一个示例——我们的信息框——并将其添加到完整网页的上下文中。不仅如此——我们还会给它一个固定位置,以便它在浏览器窗口中保持在同一位置。当主内容滚动时,信息框将保持在屏幕上的同一位置。我们完成的示例将如下所示:

注意: 您可以在 fixed-info-box.html (源代码) 上查看正在运行的完整示例。查看它以了解您将在本文的这一部分中构建什么。
作为起点,您可以使用本文第一部分中已完成的示例,或者从我们的 GitHub 存储库中制作 tabbed-info-box.html 的本地副本。
HTML 添加
首先,我们需要一些额外的 HTML 来表示网页的主要内容。在您的起始 <body> 标签下方,紧邻现有部分之前,添加以下 <section>:
<section class="fake-content">
<h1>Fake content</h1>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
<p>
This is fake content. Your main web page contents would probably go here.
</p>
</section>
注意: 如果您愿意,可以随意将假内容更改为真实内容。
对现有 CSS 的更改
接下来,我们需要对现有 CSS 进行一些小的更改,以放置和定位信息框。更改您的 .info-box 规则,以去除 margin: 0 auto;(我们不再希望信息框居中),添加 position: fixed;,并将其固定在浏览器视口的 top。
它现在应该看起来像这样:
.info-box {
width: 452px;
height: 400px;
margin: 0 auto;
position: fixed;
top: 0;
}
样式化主内容
本例只剩下为主内容提供一些样式。在所有其他 CSS 下面添加以下规则:
.fake-content {
background-color: #a60000;
color: white;
padding: 10px;
height: 2000px;
margin-left: 470px;
}
.fake-content p {
margin-bottom: 200px;
}
首先,我们为内容提供与信息框面板相同的 background-color、color 和 padding。然后我们给它一个大的 margin-left 将其向右移动,为信息框留出空间,使其不与任何其他内容重叠。
到此,第二个示例结束;我们希望您会觉得第三个示例同样有趣。
滑动隐藏面板
我们将在这里展示的最后一个示例是一个面板,它在按下图标时在屏幕上滑动进出——如前所述,这在移动布局等情况下很受欢迎,因为可用屏幕空间很小,所以您不希望通过显示菜单或信息面板而不是有用内容来占用大部分空间。
我们完成的示例将如下所示:

注意: 您可以在 hidden-info-panel.html (源代码) 上查看正在运行的完整示例。查看它以了解您将在本文的这一部分中构建什么。
作为起点,请从我们的 GitHub 存储库中制作 hidden-info-panel-start.html 的本地副本。这不承接前面的示例,因此需要一个新的起始文件。让我们看一下文件中的 HTML:
<button
type="button"
id="menu-button"
aria-haspopup="true"
aria-controls="info-panel"
aria-expanded="false">
❔
</button>
<aside id="info-panel" aria-labelledby="menu-button">
…
</aside>
首先,我们在这里有一个 <button> 元素,其按钮文本是一个特殊的问号字符。该按钮将被按下以显示/隐藏 aside 信息面板。在下面的部分中,我们将解释这一切是如何工作的。
样式化按钮
首先,让我们处理按钮——在您的 <style> 标签之间添加以下 CSS:
#menu-button {
position: absolute;
top: 0.5rem;
right: 0.5rem;
z-index: 1;
font-size: 3rem;
cursor: pointer;
border: none;
background-color: transparent;
}
第一条规则样式化了 <button>;在这里我们:
样式化面板
现在是时候为滑动面板本身设置样式了。将以下规则添加到您的 CSS 底部:
#info-panel {
background-color: #a60000;
color: white;
width: 340px;
height: 100%;
padding: 0 20px;
position: fixed;
top: 0;
right: -370px;
transition: 0.6s right ease-out;
}
这里有很多内容——让我们一点一点地讨论:
- 首先,我们为信息框设置了一些简单的
background-color和color。 - 接下来,我们为面板设置固定的
width,并使其height为浏览器视口的整个高度。 - 我们还包含了一些水平
padding以使其稍微分开。 - 接下来,我们为面板设置
position: fixed;,这样它将始终出现在相同的位置,即使页面有内容需要滚动。我们将其固定在视口的top,并将其设置为默认情况下在right边外。 - 最后,我们对元素设置了
transition。Transition 是一个有趣的特性,它允许您使状态之间的变化平滑发生,而不是突然“打开”或“关闭”。在这种情况下,我们打算在选中复选框时(或者换句话说,当单击问号图标时)使面板平滑地滑入屏幕。
设置选中状态
还有最后一点 CSS 需要添加——将其放在 CSS 底部:
#info-panel.open {
right: 0px;
}
该规则指出,当信息面板设置了 .open 类时,将 <aside> 的 right 属性设置为 0px,这将使面板再次显示在屏幕上(由于过渡而平滑)。删除 .open 类会再次隐藏面板。
要通过单击按钮从信息面板添加/删除 .open 类,我们需要使用一些 JavaScript。在 <script> 标签之间添加以下代码:
const button = document.querySelector("#menu-button");
const panel = document.querySelector("#info-panel");
button.addEventListener("click", () => {
panel.classList.toggle("open");
button.setAttribute("aria-expanded", panel.classList.contains("open"));
});
此代码为按钮添加了一个点击事件处理程序。点击处理程序会切换信息框面板上的 open 类,从而使面板滑入或滑出视图。事件处理程序还会设置按钮上的 aria-expanded 属性,以提高可访问性。
所以,这就是创建可切换信息面板效果的最简单方法。
总结
至此,我们对定位的介绍就告一段落了——现在,您应该对基本机制的工作原理有所了解,并理解如何开始将这些应用于构建一些有趣的 UI 功能。如果一开始没有完全理解,也不用担心——定位是一个相当高级的主题,您可以随时重新阅读这些文章以加深理解。