Thông tin tổng quan cơ bản về cách tạo thành phần có tính thích ứng, khả năng thích ứng và khả năng truy cập nhiều lựa chọn để sắp xếp và lọc trải nghiệm người dùng.
Trong bài đăng này, tôi muốn chia sẻ cách tạo một thành phần chọn nhiều đối tượng. 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
Người dùng thường thấy các mục, đôi khi là rất nhiều mục và trong các trường hợp tốt hơn là đưa ra cách giảm danh sách nhằm ngăn chặn quá tải lựa chọn. Chiến dịch này bài đăng trên blog khám phá cách lọc giao diện người dùng như một cách để giảm nhiều lựa chọn. Công cụ này thực hiện việc này bằng cách trình bày các thuộc tính của mặt hàng mà người dùng có thể chọn hoặc bỏ chọn, làm giảm kết quả từ đó giảm tình trạng quá tải lựa chọn.
Lượt tương tác
Mục tiêu là cho phép truyền tải nhanh các tùy chọn bộ lọc cho tất cả người dùng và
các loại dữ liệu đầu vào khác nhau. Quảng cáo này sẽ được phân phối cùng với thông báo
cặp thành phần. Thanh bên truyền thống của hộp đánh dấu cho màn hình, bàn phím
và trình đọc màn hình, cùng với một <select
multiple>
cho người dùng cảm ứng.
Quyết định sử dụng tính năng chọn nhiều mục tích hợp sẵn cho thao tác chạm, chứ không phải cho máy tính để bàn sẽ giúp tiết kiệm công việc và tạo ra công việc. Tuy nhiên, tôi tin rằng sẽ mang lại trải nghiệm phù hợp mà ít phải tốn mã hơn so với việc xây dựng toàn bộ trải nghiệm phản hồi trong một thành phần.
Cảm ứng
Thành phần cảm ứng lưu trên không gian và giúp người dùng tương tác chính xác hơn
thiết bị di động. Tính năng này tiết kiệm không gian bằng cách thu gọn toàn bộ thanh bên của hộp đánh dấu thành một
Trải nghiệm chạm lớp phủ tích hợp sẵn của <select>
. Công cụ này giúp nhập dữ liệu chính xác bằng cách hiện
trải nghiệm lớp phủ cảm ứng lớn do hệ thống cung cấp.
Bàn phím và tay điều khiển trò chơi
Dưới đây là bản minh hoạ cách sử dụng <select multiple>
từ bàn phím.
Tính năng chọn nhiều lựa chọn tích hợp sẵn này không thể tạo kiểu và chỉ được cung cấp trong một thiết bị nhỏ gọn bố cục không phù hợp để hiển thị nhiều tuỳ chọn. Hãy xem cách bạn thực sự không thể bạn thấy vô số lựa chọn trong chiếc hộp nhỏ bé đó? Mặc dù bạn có thể thay đổi kích thước của ảnh, vẫn không hữu dụng như thanh bên của hộp đánh dấu.
Markup (note: đây là tên ứng dụng)
Cả hai thành phần sẽ nằm trong cùng một phần tử <form>
. Kết quả của
biểu mẫu này, dù là hộp đánh dấu hay chọn nhiều đáp án, sẽ được quan sát và sử dụng để
lọc lưới, nhưng cũng có thể được gửi tới máy chủ.
<form>
</form>
Thành phần hộp đánh dấu
Các nhóm hộp đánh dấu nên được gói trong một
<fieldset>
và cho sẵn một phần tử
<legend>
.
Khi HTML được cấu trúc theo cách này, trình đọc màn hình và
FormData sẽ
tự động hiểu mối quan hệ của các phần tử.
<form>
<fieldset>
<legend>New</legend>
… checkboxes …
</fieldset>
</form>
Với nhóm đã sẵn sàng, hãy thêm <label>
và <input type="checkbox">
cho
từng bộ lọc. Tôi đã chọn bao bọc trong <div>
để thuộc tính CSS gap
có thể giãn cách chúng đồng đều và duy trì sự căn chỉnh khi nhãn đi nhiều dòng.
<form>
<fieldset>
<legend>New</legend>
<div>
<input type="checkbox" id="last 30 days" name="new" value="last 30 days">
<label for="last 30 days">Last 30 Days</label>
</div>
<div>
<input type="checkbox" id="last 6 months" name="new" value="last 6 months">
<label for="last 6 months">Last 6 Months</label>
</div>
</fieldset>
</form>
Thành phần <select multiple>
Một tính năng ít dùng của phần tử <select>
là
multiple
.
Khi thuộc tính này được sử dụng cùng với phần tử <select>
, người dùng được phép
hãy chọn nhiều mục trong danh sách. Nó giống như thay đổi lượt tương tác từ một danh sách chọn
vào một danh sách hộp đánh dấu.
<form>
<select multiple="true" title="Filter results by category">
…
</select>
</form>
Để gắn nhãn và tạo nhóm bên trong một <select>
, hãy sử dụng
<optgroup>
rồi cung cấp cho phần tử này thuộc tính và giá trị label
. Phần tử và thuộc tính này
đều giống với phần tử <fieldset>
và <legend>
.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
…
</optgroup>
</select>
</form>
Giờ thì hãy thêm
<option>
cho bộ lọc.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
<option value="last 30 days">Last 30 Days</option>
<option value="last 6 months">Last 6 Months</option>
</optgroup>
</select>
</form>
Theo dõi dữ liệu đầu vào bằng bộ đếm để cung cấp thông tin cho công nghệ hỗ trợ
Trạng thái
vai trò
được áp dụng trong trải nghiệm người dùng này, để theo dõi và duy trì tổng số
bộ lọc cho trình đọc màn hình và các công nghệ hỗ trợ khác. Video trên YouTube
thể hiện tính năng này. Việc tích hợp bắt đầu với HTML và thuộc tính
role="status"
.
<div role="status" class="sr-only" id="applied-filters"></div>
Phần tử này sẽ đọc to những thay đổi đối với nội dung. Chúng tôi có thể cập nhật nội dung bằng CSS bộ đếm khi người dùng tương tác với các hộp đánh dấu. Để làm được điều đó, trước tiên, chúng ta cần tạo một bộ đếm có tên trên phần tử mẹ của đầu vào và phần tử trạng thái.
aside {
counter-reset: filters;
}
Theo mặc định, số lượng sẽ là 0
. Rất tốt, không có gì là :checked
mặc định trong thiết kế này.
Tiếp theo, để tăng bộ đếm mới tạo, chúng ta sẽ nhắm mục tiêu con của
Phần tử <aside>
:checked
. Khi người dùng thay đổi trạng thái của đầu vào,
bộ đếm filters
sẽ kiểm đếm.
aside :checked {
counter-increment: filters;
}
CSS hiện đã biết về kết quả kiểm kê chung của giao diện người dùng hộp đánh dấu và vai trò trạng thái
phần tử trống và đang chờ giá trị. Vì CSS đang duy trì số lượng trong
bộ nhớ,
counter()
cho phép truy cập giá trị từ pseudo
nội dung của phần tử:
aside #applied-filters::before {
content: counter(filters) " filters ";
}
HTML cho phần tử vai trò trạng thái giờ đây sẽ thông báo "2 bộ lọc" lên một màn hình người đọc. Đây là một khởi đầu tốt, nhưng chúng ta có thể làm tốt hơn, chẳng hạn như chia sẻ số liệu các kết quả mà bộ lọc đã cập nhật. Chúng tôi sẽ thực hiện công việc này từ JavaScript, ngoài những gì bộ đếm có thể làm.
Lồng ghép sự phấn khích
Thuật toán bộ đếm hoạt động hiệu quả với CSS lồng-1, vì tôi có thể đặt tất cả thành một khối. Tạo cảm giác dễ di chuyển và tập trung để đọc và cập nhật.
aside {
counter-reset: filters;
& :checked {
counter-increment: filters;
}
& #applied-filters::before {
content: counter(filters) " filters ";
}
}
Bố cục
Phần này mô tả bố cục giữa 2 thành phần. Hầu hết kiểu bố cục là dành cho thành phần hộp đánh dấu trên màn hình.
Biểu mẫu
Để giúp người dùng dễ đọc và dễ đọc nội dung biểu mẫu hơn, biểu mẫu này được cấp tối đa
chiều rộng là 30 ký tự, về cơ bản thiết lập độ rộng đường quang học cho mỗi
nhãn bộ lọc. Biểu mẫu này sử dụng bố cục lưới và thuộc tính gap
để giãn cách
nhóm trường.
form {
display: grid;
gap: 2ch;
max-inline-size: 30ch;
}
Phần tử <select>
Danh sách nhãn và hộp đánh dấu đều chiếm quá nhiều không gian trên thiết bị di động. Do đó, bố cục sẽ kiểm tra xem thiết bị trỏ chính của người dùng cần thay đổi trải nghiệm chạm.
@media (pointer: coarse) {
select[multiple] {
display: block;
}
}
Giá trị coarse
cho biết người dùng sẽ không thể tương tác
màn hình với độ chính xác cao với thiết bị đầu vào chính. Trên
thiết bị di động, giá trị của con trỏ thường là coarse
, là tương tác chính
là chạm. Trên thiết bị máy tính, giá trị con trỏ thường là fine
vì đây là giá trị phổ biến
để kết nối chuột hoặc thiết bị đầu vào có độ chính xác cao khác.
Các nhóm trường
Kiểu và bố cục mặc định của <fieldset>
có <legend>
là duy nhất:
Thông thường, để tạo khoảng trống cho các phần tử con, tôi sẽ sử dụng thuộc tính gap
, nhưng loại duy nhất
vị trí của <legend>
khiến khó tạo tập hợp có khoảng cách đồng đều
trẻ em. Thay vì gap
, thành phần đồng cấp liền kề
bộ chọn và
margin-block-start
được dùng.
fieldset {
padding: 2ch;
& > div + div {
margin-block-start: 2ch;
}
}
Thao tác này bỏ qua việc điều chỉnh không gian của <legend>
bằng cách chỉ nhắm mục tiêu
<div>
trẻ em.
Nhãn và hộp đánh dấu bộ lọc
Là phần tử con trực tiếp của <fieldset>
và nằm trong chiều rộng tối đa của biểu mẫu
30ch
, văn bản nhãn có thể xuống dòng nếu quá dài. Bao bọc văn bản thật tuyệt, nhưng
không khớp giữa văn bản và hộp đánh dấu. Hộp linh hoạt là lựa chọn lý tưởng cho việc này.
fieldset > div {
display: flex;
gap: 2ch;
align-items: baseline;
}
Lưới ảnh động
Ảnh động bố cục do Isotope thực hiện. Đáp hiệu quả và mạnh mẽ cho việc sắp xếp và lọc tương tác.
JavaScript
Ngoài việc giúp sắp xếp một lưới ảnh động gọn gàng, tương tác, JavaScript được dùng để đánh bóng một vài cạnh nhám.
Chuẩn hoá hoạt động đầu vào của người dùng
Thiết kế này có một biểu mẫu với hai cách khác nhau để cung cấp thông tin đầu vào và không nên chuyển đổi tuần tự . Tuy nhiên, với một số JavaScript, chúng ta có thể chuẩn hoá dữ liệu.
Tôi đã chọn căn chỉnh cấu trúc dữ liệu của phần tử <select>
theo các hộp đánh dấu đã được nhóm
cấu trúc. Để làm được điều này, một
input
trình nghe sự kiện được thêm vào phần tử <select>
, lúc đó trình nghe sự kiện
selectedOptions
được ánh xạ.
document.querySelector('select').addEventListener('input', event => {
// make selectedOptions iterable then reduce a new array object
let selectData = Array.from(event.target.selectedOptions).reduce((data, opt) => {
// parent optgroup label and option value are added to the reduce aggregator
data.push([opt.parentElement.label.toLowerCase(), opt.value])
return data
}, [])
})
Bây giờ, bạn có thể gửi biểu mẫu một cách an toàn. Trong trường hợp có bản minh hoạ này, hãy hướng dẫn Isotope về những gì để lọc.
Hoàn tất phần tử vai trò trạng thái
Phần tử này chỉ kiểm đếm và thông báo số lượng bộ lọc dựa trên hộp đánh dấu
tương tác nhiều hơn, nhưng tôi cho rằng tốt hơn là nên chia sẻ thêm
kết quả và đảm bảo các lựa chọn phần tử <select>
cũng được tính.
Lựa chọn phần tử <select>
được phản ánh trong counter()
Trong mục chuẩn hoá dữ liệu, hệ thống đã tạo một trình nghe khi nhập dữ liệu. Tại số bộ lọc và số kết quả đã chọn ở cuối hàm này cho các bộ lọc đó. Các giá trị có thể được chuyển đến phần tử vai trò trạng thái như thế này.
let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length
Kết quả được phản ánh trong phần tử role="status"
:checked
cung cấp phương thức tích hợp sẵn để truyền số lượng bộ lọc đã chọn tới
phần tử vai trò trạng thái, nhưng thiếu khả năng hiển thị số lượng kết quả được lọc.
JavaScript có thể theo dõi sự tương tác với các hộp đánh dấu và sau khi lọc
lưới, hãy thêm textContent
như phần tử <select>
đã làm.
document
.querySelector('aside form')
.addEventListener('input', e => {
// isotope demo code
let filterResults = IsotopeGrid.getFilteredItemElements().length
document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})
Tổng cộng, công việc này hoàn tất thông báo "2 bộ lọc cho 25 kết quả".
Giờ đây, trải nghiệm công nghệ hỗ trợ tuyệt vời của chúng tôi sẽ được cung cấp cho tất cả người dùng theo cách họ tương tác với ứng dụng đó.
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
Chưa có gì để xem ở đây!