实用定位示例

本文介绍了如何构建一些现实世界的示例,以说明使用定位可以完成哪些操作。

先决条件 HTML 基础知识(学习 HTML 简介)以及对 CSS 工作原理的了解(学习 CSS 简介)。
目标 了解定位的实际应用。

带选项卡的信息框

我们将首先介绍一个经典的选项卡信息框,这是一个非常常见的特性,用于在有限的区域内容纳大量信息。这包括信息量大的应用程序(如策略/战争游戏)、网站的移动版本(屏幕较窄,空间有限)以及紧凑的信息框(您可能希望提供大量信息,而不会让信息占据整个用户界面)。在我们完成示例后,它将看起来像这样:

Tab 1 is selected. 'Tab 2' and 'Tab 3' are the other two tabs. Only the contents of the selected tab are visible. When a tab is selected, its text-color changes from black to white and its background-color changes from orange-red to saddle-brown.

注意:您可以访问 tabbed-info-box.html源代码)查看正在运行的最终示例。查看它可以了解您将在本文节中构建的内容。

您可能会想,“为什么不将单独的选项卡创建为单独的网页,然后让选项卡点击切换到单独的页面来实现效果?” 这种代码确实会更简单,但是,每个单独的“页面”视图实际上都是一个新加载的网页,这将使跨视图保存信息变得更加困难,并且会使此功能更难集成到更大的用户界面设计中。

首先,我们希望您创建起始文件的本地副本 - tabbed-info-box-start.htmltabs-manual.js。将它们保存在本地计算机上的某个合理位置,并在文本编辑器中打开 tabbed-info-box-start.html。让我们看一下 body 中包含的 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>

因此,这里有一个带有 classinfo-box<section> 元素,它包含两个 <div>。第一个 div 包含三个按钮,这些按钮将成为用于显示我们内容面板的实际选项卡。第二个 div 包含三个 <article> 元素,它们将构成与每个选项卡相对应的内容面板。每个面板都包含一些示例内容。

这里的想法是,我们将对选项卡进行样式设置,使其看起来像一个标准的水平导航菜单,并对面板进行样式设置,使其使用绝对定位叠加在一起。我们还将提供一些 JavaScript 代码供您在页面中包含,以在按下选项卡时显示相应的面板,并对选项卡本身进行样式设置。您现在不需要理解 JavaScript 代码本身,但您应该考虑尽快学习一些基本的 JavaScript - 您的用户界面功能越复杂,就越有可能需要一些 JavaScript 来实现您想要的功能。

常规设置

首先,在 <style> 的开始和结束标签之间添加以下内容:

css
html {
  font-family: sans-serif;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

这只是一些常规设置,用于在我们的页面上设置无衬线字体,使用 border-box box-sizing 模型,并删除默认的 <body> 边距。

接下来,在您之前的 CSS 下面添加以下内容:

css
.info-box {
  width: 452px;
  height: 400px;
  margin: 1.25rem auto 0;
}

这会对内容设置特定的宽度和高度,并使用旧的 margin: 1.25rem auto 0 将其居中在屏幕上。之前在课程中,我们建议尽可能避免对内容容器设置固定高度;在这种情况下是可以的,因为我们在选项卡中具有固定内容。

对选项卡进行样式设置

现在,我们希望对选项卡进行样式设置,使其看起来像选项卡 - 基本上,它们是水平导航菜单,但与我们在课程中之前看到的点击时加载不同的网页不同,它们会使同一个页面上显示不同的面板。首先,在 CSS 底部添加以下规则,使 tablist 成为一个 flex 容器,并使其跨越 100% 的宽度:

css
.info-box [role="tablist"] {
  min-width: 100%;
  display: flex;
}

注意:在本示例中,我们在整个链中使用后代选择器,并在开头使用 .info-box - 这样可以将此功能插入到已经存在其他内容的页面中,而不用担心会干扰应用于页面其他部分的样式。

接下来,我们将对按钮进行样式设置,使其看起来像选项卡。添加以下 CSS:

css
.info-box [role="tab"] {
  padding: 0 1rem 0 1rem;
  line-height: 3rem;
  background: white;
  color: #b60000;
  font-weight: bold;
  border: none;
  outline: none;
}

接下来,我们将设置选项卡的 :focus:hover 状态,使其在获得焦点/悬停时看起来不同,为用户提供一些视觉反馈。

css
.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 放置在其他样式的下方:

css
.info-box [role="tab"][aria-selected="true"] {
  background-color: #b60000;
  color: white;
}

对面板进行样式设置

下一步是为我们的面板进行样式设置。让我们开始吧!

首先,添加以下规则以对 .panels <div> 容器进行样式设置。在这里,我们设置了固定 height,以确保面板紧密地适合信息框内部,position relative<div> 设置为定位上下文,这样您就可以将定位子元素相对于它而不是初始视窗进行定位,最后,我们 clear 在上面的 CSS 中设置的浮动,这样就不会干扰布局的其余部分。

css
.info-box .panels {
  height: 352px;
  clear: both;
  position: relative;
}

最后,在本节中,我们将对构成我们面板的单个 <article> 元素进行样式设置。我们将添加的第一条规则将对面板进行绝对 position 设置,并使它们都紧贴 topleft 它们的 <div> 容器 - 这一部分是整个布局功能的关键,因为它使面板叠加在一起。该规则还为面板提供了与容器相同的高度,并为内容提供了一些填充、文本 colorbackground-color

css
.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 类,因此一次只能看到一个面板。

css
.info-box [role="tabpanel"].is-hidden {
  display: none;
}

JavaScript

使此功能生效的最后一部分是 JavaScript 代码。tabs-manual.js 文件已使用 <script> 标签包含在内:

html
<script src="tabs-manual.js"></script>

这段代码执行以下操作:

  • 窗口加载事件 中,它为所有 tablist 元素初始化 TabsManual
  • 当创建一个 TabsManual 对象时,构造函数会将所有选项卡和面板引用收集到 tabstabpanels 变量中,这样我们以后就可以轻松地对它们进行操作。
  • 构造函数还会在所有选项卡上注册 clickkeydown 事件处理程序。事件处理程序包括有关使用点击或按键选择选项卡时应该发生什么的逻辑。
  • setSelectedTab(currentTab) 函数中,会发生以下情况:
    • 使用 for 循环遍历所有选项卡,并通过将 aria-selected 属性设置为 false 以及在相应面板上设置 is-hidden 类来取消选择它们。
    • 在选定的选项卡(currentTab)上,aria-selected 设置为 true,并且从相应的面板中删除了 is-hidden 类。
  • 该代码还包含使用 向左箭头向右箭头HomeEnd 键进行键盘导航的逻辑。

固定位置带选项卡的信息框

在我们的第二个示例中,我们将使用第一个示例(我们的信息框),并将它添加到完整网页的上下文中。但不仅如此,我们还将为它提供固定位置,使其始终保持在浏览器窗口的相同位置。当主要内容滚动时,信息框将保持在屏幕上的相同位置。我们完成的示例将看起来像这样:

Info-box is a container with 3 tabs with the first tab selected and only the contents of the first tab are displayed. It is given a fixed position. The info-box is positioned at the top left corner of the window with a width of 452 pixels. A container of fake content occupies the rest right half of the window; the fake content container is taller than the window and is scrollable. When the page is scrolled, the right-hand side container moves while the info-box stays fixed in the same position on the screen.

注意:您可以访问 fixed-info-box.html源代码)查看正在运行的最终示例。查看它可以了解您将在本文节中构建的内容。

作为起点,您可以使用您在本文第一节中完成的示例,或者从我们的 GitHub 存储库中创建 info-box.html 的本地副本。

HTML 添加

首先,我们需要一些额外的 HTML 代码来表示网页的主要内容。在 <body> 的开始标签之后,现有 section 之前添加以下 <section>

html
<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 处。

它现在应该看起来像这样:

css
.info-box {
  width: 452px;
  height: 400px;
  margin: 0 auto;
  position: fixed;
  top: 0;
}

对主要内容进行样式设置

本示例中剩下的唯一事情是为主要内容提供一些样式。在 CSS 的其余部分下方添加以下规则:

css
.fake-content {
  background-color: #a60000;
  color: white;
  padding: 10px;
  height: 2000px;
  margin-left: 470px;
}

.fake-content p {
  margin-bottom: 200px;
}

首先,我们为内容提供与信息框面板相同的 background-colorcolorpadding。然后,我们为它提供一个较大的 margin-left,以便将其移到右侧,为信息框腾出空间,因此它不会与任何其他内容重叠。

这标志着第二个示例的结束;我们希望您会发现第三个示例同样有趣。

滑动隐藏面板

我们将在此处介绍的最后一个示例是一个面板,它会在点击图标时滑入和滑出屏幕 - 正如前面提到的,这在移动布局等情况下很受欢迎,在移动布局中,可用的屏幕空间很小,因此您不希望通过显示菜单或信息面板而不是有用的内容来占用大部分空间。

我们完成的示例将看起来像这样:

A blank screen on the left 60% of the screen with a 40% width panel displaying information on the right. A 'question mark' icon is in the top-right corner. The panel slides on and off the screen at the press of this 'question mark' icon.

注意:您可以访问 hidden-info-panel.html源代码)查看正在运行的最终示例。查看它可以了解您将在本文节中构建的内容。

首先,从我们的 GitHub 仓库中创建一个 hidden-info-panel-start.html 的本地副本。这与之前的示例无关,因此需要一个新的起始文件。让我们看一下文件中的 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 代码

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> 设置样式;在这里我们已经

  • 设置了一个较大的 font-size 使图标更大更醒目。
  • 移除边框并使背景透明,这样就不会显示按钮,而只会显示 ? 图标。
  • 为其设置 position absolute,并使用 topright 将其定位在右上角。
  • 为其设置 z-index 为 1 - 这样当信息面板被设置样式并显示时,它不会遮盖图标;相反,图标会位于信息面板的顶部,以便再次按下它来隐藏信息面板。
  • 使用 cursor 属性将鼠标悬停在图标上时光标更改为手型指针(类似于鼠标悬停在链接上时看到的指针),作为对用户的一种额外的视觉提示,表明图标具有特殊的功能。

为面板设置样式

现在该为实际的滑动面板本身设置样式了。在你的 CSS 代码底部添加以下规则

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-colorcolor 属性。
  • 接下来,我们为面板设置了一个固定的 width,并使它的 height 占据浏览器视窗的整个高度。
  • 我们还包括一些水平 padding 来增加间距。
  • 接下来,我们为面板设置 position: fixed;,这样它将始终出现在相同的位置,即使页面有内容需要滚动。我们将它固定在视窗的 top 位置,并默认将其设置为在 right 方向超出屏幕。
  • 最后,我们为元素设置一个 transition。Transition 是一个有趣的特性,它允许你使状态之间的变化平滑过渡,而不是突然地“开启”或“关闭”。在本例中,我们打算在复选框被选中时使面板平滑地滑入屏幕。(或者换句话说,当问号图标被点击时。)

设置选中状态

最后需要添加一段 CSS 代码 - 将以下代码放在你的 CSS 代码底部

css
#info-panel.open {
  right: 0px;
}

该规则表明,当信息面板上设置了 .open 类时,将 <aside>right 属性设置为 0px,这会导致面板再次出现在屏幕上(由于过渡而平滑过渡)。移除 .open 类将再次隐藏面板。

为了通过点击按钮在信息面板上添加/移除 .open 类,我们需要使用一些 JavaScript 代码。在 <script> 标签之间添加以下代码

js
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 功能有了了解。如果你没有立即理解所有内容,不要担心 - 定位是一个相当高级的主题,你可以随时再次阅读文章来帮助你理解。