建立浮動式訊息元件

如何建構自動調整式且可存取的浮動式訊息元件的基礎總覽。

在這篇文章中,我想分享如何建構浮動式訊息元件。試試 demo」。

示範

如果您喜歡看影片,請參考這篇文章的 YouTube 版本:

總覽

浮動式訊息是指向使用者傳送非互動式、被動式或非同步簡短訊息。 通常做為通知使用者的介面意見回饋模式 關於動作的結果

互動

浮動式訊息與通知不同 快訊提示,因為 不能互動但使用者不應被關閉或持續保留 通知可為您提供更重要的資訊,也就是同步傳送的訊息 要求互動或系統層級訊息 (而非網頁層級訊息)。 浮動式訊息比其他通知策略更具被動性。

標記

<output>敬上 元素是浮動式訊息的理想選擇,因為系統會在畫面上向浮動式訊息發布該元素 讀者。正確的 HTML 提供了安全的基礎,讓我們能運用 JavaScript 和 則會有許多 JavaScript

A 吐司

<output class="gui-toast">Item added to cart</output>

您可以將 包含 新增 role="status"。因此,您可以 如果瀏覽器不為 <output> 元素提供 隱含式 角色

<output role="status" class="gui-toast">Item added to cart</output>

浮動式訊息容器

一次可顯示多個浮動式訊息。為了自動調度管理多個 是使用容器這個容器也會處理 畫面上的浮動式訊息

<section class="gui-toast-group">
  <output role="status">Wizard Rose added to cart</output>
  <output role="status">Self Watering Pot added to cart</output>
</section>

版面配置

我選擇在 inset-block-end敬上 如果加入了更多浮動式訊息,這些浮動式訊息就會從螢幕邊緣堆疊。

統一發票容器

浮動式訊息容器會執行所有版面配置工作,以顯示浮動式訊息。是 fixed 附加至可視區域,並使用邏輯屬性 inset 用於指定 邊連接邊,另外再加上 block-end 邊緣一小段 padding

.gui-toast-group {
  position: fixed;
  z-index: 1;
  inset-block-end: 0;
  inset-inline: 0;
  padding-block-end: 5vh;
}

開發人員工具方塊大小和邊框間距,疊加在 .gui-toast-container 元素上。

除了在可視區域內設定自身位置以外,浮動式訊息容器也會 能夠對齊及分配浮動式訊息的網格容器項目會置中為 群組為 justify-content,且每個群組都位於 justify-items 中。 丟擲 gap 一點,讓浮動式訊息不會碰觸。

.gui-toast-group {
  display: grid;
  justify-items: center;
  justify-content: center;
  gap: 1vh;
}

這張螢幕截圖顯示浮動式訊息群組的 CSS 格線重疊元素
凸顯浮動式訊息子項元素之間的空間和間距。

GUI 浮動式訊息

個別的浮動式訊息具有 padding,而且一些比較柔和的角 border-radius, min() 函式, 用於行動裝置和電腦大小的調整下列 CSS 中的回應式尺寸 避免浮動式訊息成長至超過 90% 可視區域的大小 25ch

.gui-toast {
  max-inline-size: min(25ch, 90vw);
  padding-block: .5ch;
  padding-inline: 1ch;
  border-radius: 3px;
  font-size: 1rem;
}

含有邊框間距和邊框的單一 .gui-toast 元素螢幕截圖
半徑範圍。

樣式

設定版面配置和定位時,請新增 CSS,以便根據使用者需求做出調整 設定和互動方式

浮動式訊息容器

浮動式訊息並無互動功能,輕觸或滑動浮動式訊息沒有任何作用,但 正在使用指標事件避免浮動式訊息遭竊 採用以下 CSS 時,點擊次數

.gui-toast-group {
  pointer-events: none;
}

GUI 浮動式訊息

使用自訂屬性、HSL 和 偏好媒體查詢

.gui-toast {
  --_bg-lightness: 90%;

  color: black;
  background: hsl(0 0% var(--_bg-lightness) / 90%);
}

@media (prefers-color-scheme: dark) {
  .gui-toast {
    color: white;
    --_bg-lightness: 20%;
  }
}

動畫

新的浮動式訊息應在進入螢幕畫面時同時顯示動畫。 藉由將 translate 值設為 0,達到減少動態效果即可達到下列目標: 而是將動作值更新為動作偏好設定媒體中的長度 。每個人都會有一些動畫,但只有部分使用者能獲得浮動式訊息 相隔一條距離

以下是用於浮動式訊息動畫的主要畫面格。CSS 會控制 入口、等待以及浮動式訊息出現時,全都使用單一動畫呈現。

@keyframes fade-in {
  from { opacity: 0 }
}

@keyframes fade-out {
  to { opacity: 0 }
}

@keyframes slide-in {
  from { transform: translateY(var(--_travel-distance, 10px)) }
}

接著,浮動式訊息元素會設定變數,並安排主要畫面格。

.gui-toast {
  --_duration: 3s;
  --_travel-distance: 0;

  will-change: transform;
  animation: 
    fade-in .3s ease,
    slide-in .3s ease,
    fade-out .3s ease var(--_duration);
}

@media (prefers-reduced-motion: no-preference) {
  .gui-toast {
    --_travel-distance: 5vh;
  }
}

JavaScript

備妥樣式和螢幕閱讀器的 HTML 後,您需要啟用 JavaScript,才能 根據使用者的需求來編排、新增和刪除浮動式訊息 事件。浮動式訊息元件的開發人員體驗應盡量精簡 操作起來相當容易,如下所示:

import Toast from './toast.js'

Toast('My first toast')

建立浮動式訊息群組和浮動式訊息

透過 JavaScript 載入浮動式訊息模組時,必須建立浮動式訊息容器 然後新增到網頁中我選擇在 body 之前加入這個元素 z-index堆疊的問題不太可能發生在容器高於容器空間 所有 body 元素中

const init = () => {
  const node = document.createElement('section')
  node.classList.add('gui-toast-group')

  document.firstElementChild.insertBefore(node, document.body)
  return node
}

head 和 body 標記之間的浮動式訊息群組的螢幕截圖。

系統會在內部呼叫模組的 init() 函式,並將元素封裝 模擬 Toaster

const Toaster = init()

您可以使用 createToast() 函式建立浮動式訊息 HTML 元素。 函式需要一些文字做為浮動式訊息,建立 <output> 元素,adorns 含有一些類別和屬性、設定文字,並傳回節點。

const createToast = text => {
  const node = document.createElement('output')
  
  node.innerText = text
  node.classList.add('gui-toast')
  node.setAttribute('role', 'status')

  return node
}

管理一或多個浮動式訊息

JavaScript 現在會在文件中加入容器,讓您包含浮動式訊息 立即新增已建立的浮動式訊息addToast() 函式會自動化調度管理 或多部浮動式訊息首先,檢查浮動式訊息的數量,以及運動是否可行。 然後利用這些資訊來附加浮動式訊息 讓其他浮動式訊息看起來「騰出房間」建立新的浮動式訊息

const addToast = toast => {
  const { matches:motionOK } = window.matchMedia(
    '(prefers-reduced-motion: no-preference)'
  )

  Toaster.children.length && motionOK
    ? flipToast(toast)
    : Toaster.appendChild(toast)
}

新增第一個浮動式訊息時,Toaster.appendChild(toast) 會在 觸發 CSS 動畫的網頁:加入動畫、等待 3s、動畫。 在已有浮動式訊息時,系統會使用技巧呼叫 flipToast() 小飛Paul Lewis:重點在於計算 擺放新浮動式訊息之前和之後 想像一下,你可以標記烤麵包機目前的位置,然後 呈現從位置到現在的動畫

const flipToast = toast => {
  // FIRST
  const first = Toaster.offsetHeight

  // add new child to change container size
  Toaster.appendChild(toast)

  // LAST
  const last = Toaster.offsetHeight

  // INVERT
  const invert = last - first

  // PLAY
  const animation = Toaster.animate([
    { transform: `translateY(${invert}px)` },
    { transform: 'translateY(0)' }
  ], {
    duration: 150,
    easing: 'ease-out',
  })
}

CSS 格線會移動版面配置。新增浮動式訊息時,格線會放入該浮動式訊息 空格鍵和彼此的空格同時,網路 動畫是 用來為容器從舊位置加入動畫效果

將所有 JavaScript 結合在一起

呼叫 Toast('my first toast') 時,系統會建立浮動式訊息並新增至頁面 (甚至容器也可是配合新的浮動式訊息而採用的動畫), 承諾 且已建立的浮動式訊息 已觀看: 呈現保證解析度的 CSS 動畫完成 (三個主要畫面格動畫)。

const Toast = text => {
  let toast = createToast(text)
  addToast(toast)

  return new Promise(async (resolve, reject) => {
    await Promise.allSettled(
      toast.getAnimations().map(animation => 
        animation.finished
      )
    )
    Toaster.removeChild(toast)
    resolve() 
  })
}

我認為這個程式碼會造成混淆的部分位於 Promise.allSettled() 函式 和 toast.getAnimations() 對應。我使用了多個主要畫面格動畫 以便確定所有料理作業都已完成 而各自需要 finished敬上 也會做出承諾 allSettled敬上 已做好萬全準備,並盡全力完成所有承諾 才能正常運作使用 await Promise.allSettled() 代表 即可放心移除元素,並假設浮動式訊息已完成 生命週期最後,呼叫 resolve() 可實現高階浮動式訊息,因此 浮動式訊息顯示後,開發人員就能清理或執行其他工作。

export default Toast

最後,Toast 函式會從模組匯出,供其他指令碼使用 匯入和使用

使用浮動式訊息元件

透過浮動式訊息,或浮動式訊息的開發人員體驗,只需將 Toast 函式,並使用訊息字串呼叫這個函式。

import Toast from './toast.js'

Toast('Wizard Rose added to cart')

如果開發人員想在浮動式訊息之後 他們可以使用非同步模式 await

import Toast from './toast.js'

async function example() {
  await Toast('Wizard Rose added to cart')
  console.log('toast finished')
}

結論

現在你知道我怎麼了,這樣會如何 🙂?

讓我們來體驗多元的方法,瞭解透過網路建立內容的所有方式。 建立示範、將 Twitter 推文連結,我們就會為您新增 前往下方的社群重混專區!

社群重混作品