實際定位示例

本文展示瞭如何構建一些真實世界的示例,以說明您可以透過定位實現哪些功能。

預備知識 HTML 基礎知識(學習 使用 HTML 結構化內容)以及 CSS 的工作原理(學習 CSS 樣式基礎)。
目標 瞭解定位的實際應用

帶標籤的資訊框

我們將看到的第一個示例是一個經典的帶標籤資訊框——當您想將大量資訊打包到小區域時,這是一個非常常見的功能。這包括資訊密集型應用程式,如策略/戰爭遊戲、螢幕狹窄且空間有限的網站移動版本,以及緊湊型資訊框,您可能希望提供大量資訊而無需它填滿整個 UI。我們的簡單示例完成後將如下所示:

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 (原始碼) 上檢視正在執行的完整示例。檢視它以瞭解您將在本文的這一部分中構建什麼。

您可能正在想“為什麼不將單獨的選項卡建立為單獨的網頁,然後讓選項卡單擊以切換到單獨的頁面以建立效果?”這種程式碼會更簡單,是的,但隨後每個單獨的“頁面”檢視實際上是一個新載入的網頁,這將使跨檢視儲存資訊變得更加困難,並難以將此功能整合到更大的 UI 設計中。

首先,我們希望您製作起始檔案的本地副本 — tabbed-info-box-start.htmltabs-manual.js。將它們儲存到您本地計算機上一個合理的位置,並在文字編輯器中開啟 tabbed-info-box-start.html。讓我們看看正文中包含的 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> 標籤之間新增以下內容:

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;
  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 以確保面板緊密地適應資訊框,positionrelative 以將 <div> 設定為定位上下文,這樣您就可以相對於它而不是初始視口放置定位的子元素,最後我們 clear 了上面 CSS 中設定的浮動,這樣它就不會干擾佈局的其餘部分。

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

本節的最後一點是,我們將對組成我們面板的單個 <article> 元素進行樣式設定。我們將新增的第一條規則將絕對 position 定位面板,並使它們都與其 <div> 容器的 topleft 對齊——這部分是整個佈局功能的關鍵,因為它使面板相互堆疊。該規則還為面板提供了與容器相同的固定高度,併為內容提供了一些內邊距、文字 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 儲存庫中製作 tabbed-info-box.html 的本地副本。

HTML 新增

首先,我們需要一些額外的 HTML 來表示網頁的主要內容。在您的起始 <body> 標籤下方,緊鄰現有部分之前,新增以下 <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 功能。如果一開始沒有完全理解,也不用擔心——定位是一個相當高階的主題,您可以隨時重新閱讀這些文章以加深理解。