實用定位示例

本文介紹瞭如何構建一些現實世界的示例,以說明使用定位可以完成哪些操作。

先決條件 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 功能有了瞭解。如果你沒有立即理解所有內容,不要擔心 - 定位是一個相當高階的主題,你可以隨時再次閱讀文章來幫助你理解。