Tổng quan cơ bản về cách tạo một thành phần thông báo ngắn thích ứng và dễ tiếp cận.
Trong bài đăng này, tôi muốn chia sẻ cách tạo thành phần thông báo ngắn. Dùng thử bản minh hoạ.
Nếu bạn thích xem video hơn, sau đây là phiên bản của bài đăng này trên YouTube:
Tổng quan
Thông báo ngắn là các thông báo ngắn không tương tác, thụ động và không đồng bộ cho người dùng. Nói chung, các API này được dùng làm mẫu phản hồi về giao diện để thông báo cho người dùng về kết quả của một hành động.
Lượt tương tác
Thông báo ngắn không giống như thông báo, cảnh báo và lời nhắc vì chúng không tương tác; chúng không bị loại bỏ hay tồn tại. Thông báo dùng cho thông tin quan trọng hơn, thông báo đồng bộ mà yêu cầu sự tương tác hoặc thông báo ở cấp hệ thống (thay vì thông báo ở cấp trang). Thông báo ngắn là cách thụ động hơn so với các chiến lược thông báo khác.
Markup (note: đây là tên ứng dụng)
Chiến lược phát hành đĩa đơn
<output>
là một lựa chọn phù hợp cho thông báo ngắn vì nó được thông báo trên màn hình
độc giả. HTML đúng cung cấp cơ sở an toàn để chúng tôi nâng cao bằng JavaScript và
CSS và sẽ có nhiều JavaScript.
Một thông báo ngắn
<output class="gui-toast">Item added to cart</output>
Có thể nhiều hơn
dành cho tất cả mọi người
bằng cách thêm role="status"
. Điều này mang lại
dự phòng nếu trình duyệt không cung cấp ngầm ẩn cho các phần tử <output>
vai trò
theo thông số kỹ thuật.
<output role="status" class="gui-toast">Item added to cart</output>
Vùng chứa thông báo ngắn
Có thể hiển thị nhiều thông báo ngắn cùng một lúc. Để sắp xếp nhiều thông báo ngắn, một vùng chứa được sử dụng. Vùng chứa này cũng xử lý vị trí của thông báo ngắn trên màn hình.
<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>
Bố cục
Tôi chọn ghim thông báo ngắn vào
inset-block-end
của khung nhìn và nếu bạn thêm nhiều thông báo ngắn, chúng sẽ được xếp chồng từ cạnh màn hình đó.
Vùng chứa GUI
Vùng chứa thông báo ngắn sẽ thực hiện toàn bộ bố cục để trình bày thông báo ngắn. Bây giờ
fixed
cho khung nhìn và sử dụng thuộc tính logic
inset
để chỉ định
các cạnh để ghim, cộng với một chút padding
từ cùng một cạnh block-end
.
.gui-toast-group {
position: fixed;
z-index: 1;
inset-block-end: 0;
inset-inline: 0;
padding-block-end: 5vh;
}
Ngoài việc tự định vị trong khung nhìn, vùng chứa thông báo ngắn còn là một
vùng chứa lưới có thể căn chỉnh và phân phối thông báo ngắn. Các mục được căn giữa dưới dạng
nhóm với justify-content
và từng được căn giữa bằng justify-items
.
Cho một chút gap
để thông báo ngắn không chạm vào.
.gui-toast-group {
display: grid;
justify-items: center;
justify-content: center;
gap: 1vh;
}
Chào mừng GUI (Giao diện người dùng đồ hoạ)
Một thông báo ngắn có một số padding
, một số góc mềm hơn
border-radius
,
và một hàm min()
để
hỗ trợ kích thước thiết bị di động và máy tính. Kích thước đáp ứng trong CSS sau
ngăn thông báo ngắn mở rộng hơn 90% khung nhìn hoặc
25ch
.
.gui-toast {
max-inline-size: min(25ch, 90vw);
padding-block: .5ch;
padding-inline: 1ch;
border-radius: 3px;
font-size: 1rem;
}
Kiểu
Sau khi thiết lập bố cục và vị trí, hãy thêm CSS giúp thích ứng với người dùng cài đặt và tương tác.
Dụng cụ đựng bánh mì
Các thông báo ngắn không mang tính tương tác, việc nhấn hay vuốt lên chúng không có tác dụng gì, nhưng chúng hiện sử dụng các sự kiện con trỏ. Ngăn không cho thông báo ngắn bị trộm với CSS sau.
.gui-toast-group {
pointer-events: none;
}
Chào mừng GUI (Giao diện người dùng đồ hoạ)
Hiển thị cho thông báo ngắn về giao diện thích ứng sáng hoặc tối bằng các thuộc tính tuỳ chỉnh, HSL và truy vấn phương tiện tuỳ chọn.
.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%;
}
}
Hoạt ảnh
Một thông báo ngắn mới sẽ hiển thị bằng ảnh động khi xuất hiện trên màn hình.
Để điều chỉnh chuyển động giảm đi, hãy đặt giá trị translate
thành 0
bằng cách
mặc định, nhưng cập nhật giá trị chuyển động thành độ dài trong nội dung nghe nhìn ưu tiên chuyển động
truy vấn . Mọi người đều thấy một số ảnh động, nhưng chỉ một số người dùng thấy thông báo ngắn di chuyển
một khoảng cách.
Sau đây là các khung hình chính dùng cho ảnh động thông báo ngắn. CSS sẽ kiểm soát lối vào, thời gian chờ và thoát của thông báo ngắn, tất cả đều trong một ảnh động.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
Sau đó, phần tử thông báo ngắn sẽ thiết lập các biến và sắp xếp các khung hình chính.
.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
Khi các kiểu và trình đọc màn hình đã sẵn sàng cho HTML, cần có JavaScript để phối hợp tạo, thêm và huỷ thông báo ngắn dựa trên người dùng sự kiện. Trải nghiệm của nhà phát triển đối với thành phần thông báo ngắn nên ở mức tối thiểu và dễ bắt đầu, chẳng hạn như:
import Toast from './toast.js'
Toast('My first toast')
Tạo nhóm thông báo ngắn và thông báo ngắn
Khi mô-đun thông báo ngắn tải từ JavaScript, mô-đun thông báo ngắn phải tạo một vùng chứa thông báo ngắn
rồi thêm đoạn thông tin đó vào trang. Tôi đã chọn thêm phần tử trước body
, thao tác này sẽ
Ít có khả năng vấn đề xếp chồng z-index
xảy ra vì vùng chứa nằm phía trên vùng chứa cho
tất cả các thành phần nội dung.
const init = () => {
const node = document.createElement('section')
node.classList.add('gui-toast-group')
document.firstElementChild.insertBefore(node, document.body)
return node
}
Hàm init()
được gọi nội bộ đến mô-đun, lưu trữ phần tử
dưới tên Toaster
:
const Toaster = init()
Việc tạo phần tử HTML cho thông báo nhanh được thực hiện bằng hàm createToast()
. Chiến lược phát hành đĩa đơn
hàm yêu cầu một số văn bản để hiển thị thông báo ngắn, tạo phần tử <output>
, trang trí
nó với một số lớp và thuộc tính, thiết lập văn bản và trả về nút.
const createToast = text => {
const node = document.createElement('output')
node.innerText = text
node.classList.add('gui-toast')
node.setAttribute('role', 'status')
return node
}
Quản lý một hoặc nhiều thông báo ngắn
JavaScript hiện thêm một vùng chứa vào tài liệu để chứa thông báo ngắn và là
sẵn sàng thêm các thông báo ngắn đã tạo. Hàm addToast()
phối hợp xử lý một hàm
hoặc nhiều thông báo ngắn. Trước tiên, hãy kiểm tra số lượng thông báo ngắn và xem liệu chuyển động có ổn không,
sau đó sử dụng thông tin này để nối thêm thông báo ngắn hoặc làm thêm
ảnh động để các thông báo ngắn khác xuất hiện để "tạo chỗ trống" để xem thông báo ngắn mới.
const addToast = toast => {
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Toaster.children.length && motionOK
? flipToast(toast)
: Toaster.appendChild(toast)
}
Khi thêm thông báo ngắn đầu tiên, Toaster.appendChild(toast)
sẽ thêm một thông báo ngắn vào
trang kích hoạt ảnh động CSS: tạo hiệu ứng động, chờ 3s
, tạo hiệu ứng động.
flipToast()
được gọi khi đã có thông báo ngắn, sử dụng một kỹ thuật
có tên là FLIP bởi Paul
Lewis. Ý tưởng là tính toán mức chênh lệch
ở các vị trí của vùng chứa, trước và sau khi thêm thông báo ngắn mới.
Hãy nghĩ về điều này giống như việc đánh dấu vị trí hiện tại của Máy nướng bánh mì, vị trí của nó, sau đó
tạo ảnh động từ vị trí ban đầu đến vị trí hiện tại.
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',
})
}
Lưới CSS thực hiện việc nâng bố cục. Khi thêm một thông báo ngắn mới, chế độ lưới sẽ đặt thông báo đó ở đầu và tạo dấu cách với các quảng cáo khác. Trong khi đó, web ảnh động là dùng để tạo ảnh động cho vùng chứa từ vị trí cũ.
Kết hợp tất cả JavaScript lại
Khi Toast('my first toast')
được gọi, một thông báo ngắn sẽ được tạo và thêm vào trang
(thậm chí có thể vùng chứa được tạo ảnh động để phù hợp với thông báo ngắn mới), một
lời hứa
sẽ được trả về và thông báo ngắn đã tạo là
đã xem trong
Hoàn thành hoạt ảnh CSS (ba hoạt ảnh khung hình chính) để có độ phân giải hứa hẹn.
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()
})
}
Tôi cảm thấy phần khó hiểu của mã này là trong hàm Promise.allSettled()
và toast.getAnimations()
liên kết. Vì tôi đã dùng nhiều ảnh động khung hình chính
cho thông báo ngắn, để tự tin biết rằng tất cả tin nhắn đã hoàn tất, mỗi thông báo phải
được yêu cầu từ JavaScript và mỗi
finished
hứa hẹn hoàn thành.
allSettled
điều đó có giúp ích cho chúng tôi không, tự giải quyết vấn đề một khi đã thực hiện tất cả lời hứa
đã được thực hiện. Sử dụng await Promise.allSettled()
có nghĩa là dòng tiếp theo của
mã có thể tự tin xoá phần tử và giả định rằng thông báo ngắn đã hoàn tất
vòng đời. Cuối cùng, việc gọi resolve()
cũng thực hiện được hứa hẹn cấp cao của Toast.
nhà phát triển có thể dọn dẹp hoặc làm công việc khác sau khi thông báo ngắn xuất hiện.
export default Toast
Cuối cùng, hàm Toast
được xuất từ mô-đun còn các tập lệnh khác sẽ được xuất
nhập và sử dụng.
Sử dụng thành phần Thông báo nhanh
Bạn có thể sử dụng thông báo ngắn hoặc trải nghiệm của nhà phát triển đối với thông báo ngắn này bằng cách nhập
Toast
và gọi hàm đó bằng một chuỗi thông báo.
import Toast from './toast.js'
Toast('Wizard Rose added to cart')
Nếu nhà phát triển muốn dọn dẹp công việc hoặc bất cứ việc gì sau khi thông báo ngắn xuất hiện hiển thị, chúng có thể sử dụng chế độ không đồng bộ chờ.
import Toast from './toast.js'
async function example() {
await Toast('Wizard Rose added to cart')
console.log('toast finished')
}
Kết luận
Giờ bạn đã biết cách tôi thực hiện điều đó, bạn sẽ làm cách nào‽ 🙂
Hãy đa dạng hoá phương pháp tiếp cận và tìm hiểu tất cả các cách xây dựng ứng dụng trên web. Tạo một bản minh hoạ, tweet cho tôi các đường liên kết và tôi sẽ thêm vào vào phần bản phối lại của cộng đồng dưới đây!
Bản phối lại của cộng đồng
- @_developit với HTML/CSS/JS: bản minh hoạ & mã
- Joost van der Schee với HTML/CSS/JS: bản minh hoạ & mã