Xem một số cách hữu ích và sáng tạo để tạo kiểu cho danh sách.
Bạn liên tưởng đến điều gì khi nghĩ về danh sách? Ví dụ rõ ràng nhất là danh sách mua sắm – danh sách đơn giản nhất, một tập hợp các mặt hàng không theo thứ tự cụ thể. Tuy nhiên, chúng ta sử dụng danh sách theo nhiều cách trên web. Một tập hợp các buổi biểu diễn sắp tới tại một địa điểm? Rất có thể là một danh sách. Quy trình đặt trước gồm nhiều bước? Có thể là một danh sách. Một thư viện hình ảnh? Ngay cả điều đó cũng có thể được coi là danh sách hình ảnh có chú thích.
Trong bài viết này, chúng ta sẽ tìm hiểu các loại danh sách HTML có sẵn trên web và thời điểm sử dụng các loại danh sách đó, bao gồm cả một số thuộc tính mà bạn có thể chưa quen thuộc. Chúng ta cũng sẽ xem xét một số cách hữu ích và sáng tạo để tạo kiểu cho các thành phần này bằng CSS.
Trường hợp sử dụng danh sách
Bạn nên sử dụng phần tử danh sách HTML khi cần nhóm các mục theo ngữ nghĩa. Các công nghệ hỗ trợ (chẳng hạn như trình đọc màn hình) sẽ thông báo cho người dùng về việc có một danh sách và số lượng mục. Nếu bạn nghĩ đến một lưới sản phẩm trên một trang web mua sắm, thì việc biết thông tin này sẽ rất hữu ích. Do đó, việc sử dụng phần tử danh sách có thể là lựa chọn phù hợp.
Loại danh sách
Khi nói đến việc đánh dấu, chúng ta có thể chọn trong số 3 phần tử danh sách sau:
- Danh sách không theo thứ tự
- Danh sách theo thứ tự
- Danh sách mô tả
Việc chọn loại nào sẽ phụ thuộc vào trường hợp sử dụng.
Danh sách không theo thứ tự (ul)
Phần tử danh sách không theo thứ tự (<ul>
) hữu ích nhất khi các mục trong danh sách không tương ứng với bất kỳ thứ tự cụ thể nào. Theo mặc định, mục này sẽ hiển thị dưới dạng danh sách có dấu đầu dòng. Một ví dụ là danh sách mua sắm, trong đó thứ tự không quan trọng.
Một ví dụ phổ biến hơn trên web là trình đơn điều hướng. Khi tạo trình đơn, bạn nên gói ul
trong phần tử nav
và xác định trình đơn bằng nhãn để hỗ trợ các công nghệ hỗ trợ. Chúng ta cũng nên xác định trang hiện tại trong trình đơn. Chúng ta có thể thực hiện việc này bằng cách sử dụng thuộc tính aria-current
:
<nav aria-label="Main">
<ul>
<li>
<a href="/page-1" aria-current="page">Menu item 1</a>
</li>
<li>
<a href="/page-2">Menu item 2</a>
</li>
<li>
<a href="/page-2">Menu item 2</a>
</li>
…
</ul>
</nav>
Bài viết này về cấu trúc trình đơn trình bày một số đề xuất để đảm bảo rằng mọi người đều có thể sử dụng trình đơn điều hướng của chúng tôi.
Danh sách theo thứ tự (ol)
Phần tử danh sách có thứ tự (<ol>
) là lựa chọn tốt nhất khi thứ tự của các mục là quan trọng, chẳng hạn như một quy trình nhiều bước. Theo mặc định, các mục danh sách được đánh số. Ví dụ: một tập hợp hướng dẫn, trong đó các bước phải được hoàn thành theo thứ tự.
Cả phần tử <ol>
và <ul>
chỉ có thể chứa phần tử <li>
làm phần tử con trực tiếp.
Danh sách mô tả (dl)
Danh sách mô tả chứa các thuật ngữ (phần tử <dt>
) và nội dung mô tả (<dd>
). Mỗi thuật ngữ có thể đi kèm với nhiều nội dung mô tả. Các trường hợp sử dụng có thể bao gồm một từ điển thuật ngữ hoặc có thể là một thực đơn nhà hàng. Theo mặc định, danh sách mô tả không hiển thị bất kỳ điểm đánh dấu nào, mặc dù trình duyệt có xu hướng thụt lề phần tử <dd>
.
Trong HTML, bạn được phép nhóm các thuật ngữ với nội dung mô tả đi kèm bằng cách sử dụng <div>
. Điều này có thể hữu ích cho mục đích tạo kiểu, như chúng ta sẽ tìm hiểu về sau.
<!-- This is valid -->
<dl>
<dt>Term 1</dt>
<dd>This is the first description of the first term in the list</dd>
<dd>This is the second description of the first term in the list</dd>
<dt>Term 2</dt>
<dd>This is the description of the second term in the list</dd>
</dl>
<!-- This is also valid -->
<dl>
<div>
<dt>Term 1</dt>
<dd>This is the first description of the first term in the list</dd>
<dd>This is the second description of the first term in the list</dd>
</div>
<div>
<dt>Term 2</dt>
<dd>This is the description of the second term in the list</dd>
</div>
</dl>
Định kiểu danh sách đơn giản
Một trong những cách sử dụng đơn giản nhất của danh sách là trong một khối văn bản nội dung. Thông thường, những danh sách đơn giản này không cần được tạo kiểu phức tạp, nhưng chúng ta có thể muốn tuỳ chỉnh các điểm đánh dấu của danh sách có thứ tự hoặc không có thứ tự ở một mức độ nào đó, chẳng hạn như bằng màu sắc thương hiệu hoặc bằng cách sử dụng hình ảnh tuỳ chỉnh cho các dấu đầu dòng. Chúng ta có thể làm được rất nhiều việc với list-style
và phần tử giả ::marker
!
::marker
Ngoài việc cung cấp cho điểm đánh dấu danh sách một số kiểu cơ bản, chúng ta có thể tạo dấu đầu dòng theo chu kỳ. Ở đây, chúng ta đang sử dụng 3 URL hình ảnh khác nhau cho giá trị content
của phần tử giả ::marker
, giúp tăng thêm cảm giác viết tay cho ví dụ về danh sách mua sắm (thay vì chỉ sử dụng một hình ảnh duy nhất cho tất cả):
::marker {
content: url("/marker-1.svg") ' ';
}
li:nth-child(3n)::marker {
content: url("/marker-2.svg") ' ';
}
li:nth-child(3n - 1)::marker {
content: url("/marker-3.svg") ' ';
}
Bộ đếm tuỳ chỉnh
Đối với một số danh sách đã sắp xếp, chúng ta có thể muốn sử dụng giá trị bộ đếm, nhưng thêm một giá trị khác vào đó. Chúng ta có thể sử dụng bộ đếm list-item
làm giá trị cho thuộc tính content
của điểm đánh dấu và nối bất kỳ nội dung nào khác:
::marker {
content: counter(list-item) '🐈 ';
}
Bộ đếm của chúng ta tự động tăng thêm một, nhưng chúng ta có thể cho phép bộ đếm tăng thêm một giá trị khác nếu muốn bằng cách thiết lập thuộc tính counter-increment
trên mục danh sách. Ví dụ: thao tác này sẽ tăng bộ đếm lên 3 mỗi lần:
li {
counter-increment: list-item 3;
}
Chúng ta có thể tìm hiểu thêm nhiều điều về bộ đếm. Bài viết Danh sách, điểm đánh dấu và bộ đếm CSS giải thích chi tiết hơn về một số khả năng.
Các điểm hạn chế của ::marker tạo kiểu
Đôi khi, chúng ta có thể muốn kiểm soát nhiều hơn vị trí và kiểu của điểm đánh dấu. Ví dụ: bạn không thể định vị điểm đánh dấu bằng cách sử dụng flexbox hoặc lưới. Đôi khi, đây có thể là một điểm hạn chế nếu bạn yêu cầu một số căn chỉnh khác. ::marker
hiển thị một số ít thuộc tính CSS để tạo kiểu. Nếu thiết kế của chúng ta yêu cầu bất kỳ nội dung nào khác ngoài kiểu cơ bản, thì tốt hơn hết chúng ta nên sử dụng một phần tử giả mạo khác.
Định kiểu cho các danh sách không giống danh sách
Đôi khi, chúng ta có thể muốn tạo kiểu cho danh sách theo cách hoàn toàn khác với kiểu mặc định. Đây thường là trường hợp với trình đơn điều hướng, ví dụ: chúng ta thường muốn xoá tất cả điểm đánh dấu và có thể hiển thị danh sách theo chiều ngang bằng cách sử dụng flexbox. Một phương pháp phổ biến là đặt thuộc tính list-style
thành none
. Điều này có nghĩa là bạn sẽ không truy cập được phần tử giả mạo điểm đánh dấu trong DOM nữa.
Điểm đánh dấu tuỳ chỉnh có ::before
Tạo kiểu cho phần tử giả ::before
là một cách phổ biến để tạo điểm đánh dấu danh sách tuỳ chỉnh trước khi ::marker
xuất hiện. Tuy nhiên, ngay cả bây giờ, tính năng này cũng có thể cho phép chúng ta linh hoạt hơn (khi cần) để tạo kiểu danh sách phức tạp về mặt hình ảnh.
Giống như ::marker
, chúng ta có thể thêm kiểu dấu đầu dòng tuỳ chỉnh của riêng mình bằng thuộc tính content
. Không giống như việc sử dụng ::marker
, chúng ta cần định vị thủ công một số vị trí vì chúng ta không nhận được các lợi ích tự động do list-style-position
cung cấp. Tuy nhiên, chúng ta có thể định vị phần tử này tương đối dễ dàng bằng flexbox và nó mở ra nhiều khả năng căn chỉnh hơn. Ví dụ: chúng ta có thể thay đổi vị trí của điểm đánh dấu:
Nếu đang tạo kiểu cho danh sách đã sắp xếp bằng phần tử ::before
, chúng ta cũng có thể sử dụng bộ đếm để thêm các điểm đánh dấu dạng số.
li::before {
counter-increment: list-item;
content: counter(list-item);
}
Việc sử dụng ::before
thay vì ::marker
cho phép chúng ta có toàn quyền truy cập vào các thuộc tính CSS để tạo kiểu tuỳ chỉnh, cũng như cho phép ảnh động và hiệu ứng chuyển đổi – những tính năng này chỉ được hỗ trợ hạn chế cho ::marker
.
Liệt kê các thuộc tính
Các phần tử danh sách đã sắp xếp chấp nhận một số thuộc tính không bắt buộc, có thể giúp chúng ta trong nhiều trường hợp sử dụng.
Danh sách đảo ngược
Nếu có danh sách 10 đĩa nhạc hàng đầu trong năm qua, chúng ta có thể muốn đếm ngược từ 10 đến 1. Chúng ta có thể sử dụng bộ đếm tuỳ chỉnh cho việc đó và tăng bộ đếm theo chiều âm. Hoặc chúng ta chỉ cần sử dụng thuộc tính reversed
trong HTML. Tôi cho rằng việc sử dụng thuộc tính reversed
thường có ý nghĩa về mặt ngữ nghĩa thay vì tăng âm bộ đếm trong CSS, trừ phi bộ đếm chỉ đơn thuần mang tính trình bày. Nếu CSS không tải được, bạn vẫn sẽ thấy số liệu đếm ngược chính xác trong HTML. Ngoài ra, chúng ta cần xem xét cách trình đọc màn hình diễn giải danh sách.
Hãy xem bản minh hoạ này về 10 album hàng đầu năm 2021. Nếu chỉ tăng bộ đếm bằng CSS, thì người truy cập trang bằng trình đọc màn hình có thể kết luận rằng các số được đếm lên, vì vậy, số 10 thực sự là số 1.
Bạn có thể thấy trong bản minh hoạ rằng bằng cách sử dụng thuộc tính reversed
, các điểm đánh dấu của chúng ta đã có giá trị chính xác mà không cần chúng ta phải nỗ lực thêm! Tuy nhiên, nếu đang tạo điểm đánh dấu danh sách tuỳ chỉnh bằng phần tử giả ::before
, chúng ta cần điều chỉnh bộ đếm. Chúng ta chỉ cần hướng dẫn bộ đếm mục trong danh sách tăng theo chiều âm:
li::before {
counter-increment: list-item -1;
content: counter(list-item);
}
Điều này là đủ trong Firefox, nhưng trong Chrome và Safari, các điểm đánh dấu sẽ đếm ngược từ 0 đến -10. Chúng ta có thể khắc phục vấn đề đó bằng cách thêm thuộc tính start
vào danh sách.
Tách danh sách
Thuộc tính start
cho phép chúng ta chỉ định giá trị số mà danh sách sẽ bắt đầu từ đó. Cách này có thể hữu ích trong trường hợp bạn muốn chia danh sách thành các nhóm.
Hãy xây dựng dựa trên ví dụ về 10 đĩa nhạc hàng đầu. Có thể chúng ta thực sự muốn đếm ngược 20 album hàng đầu, nhưng theo nhóm 10 album. Giữa hai nhóm này có một số nội dung trang khác.
Chúng ta cần tạo hai danh sách riêng biệt trong HTML, nhưng làm cách nào để đảm bảo rằng bộ đếm sẽ chính xác? Hiện tại, cả hai danh sách sẽ đếm ngược từ 10 đến 1, đây không phải là điều chúng ta muốn. Tuy nhiên, trong HTML, chúng ta có thể chỉ định giá trị thuộc tính start
. Nếu chúng ta thêm giá trị start
là 20 vào danh sách đầu tiên, thì các điểm đánh dấu sẽ tự động được cập nhật một lần nữa!
<ol reversed start="20">
<li>...</li>
<li>...</li>
<li>...</li>
</ol>
Bố cục danh sách nhiều cột
Bố cục nhiều cột đôi khi có thể phù hợp với danh sách của chúng ta, như bạn có thể thấy trong các bản minh hoạ trước. Bằng cách đặt chiều rộng cột, chúng ta có thể đảm bảo danh sách tự động thích ứng, tự đặt trên hai hoặc nhiều cột chỉ khi có đủ không gian. Chúng ta cũng có thể đặt khoảng cách giữa các cột và để hiệu quả hơn, hãy thêm quy tắc cột theo kiểu (sử dụng cách viết tắt tương tự như thuộc tính border
):
ol {
columns: 25rem;
column-gap: 7rem;
column-rule: 4px dotted turquoise;
}
Đôi khi, khi sử dụng cột, chúng ta có thể gặp phải các dòng ngắt không đẹp mắt trong các mục danh sách – không phải lúc nào cũng là hiệu ứng chúng ta muốn.
Chúng ta có thể ngăn các ngắt buộc này bằng cách sử dụng break-inside: avoid
trên các mục danh sách:
li {
break-inside: avoid;
}
Thuộc tính tuỳ chỉnh
Các thuộc tính tuỳ chỉnh CSS mở ra nhiều khả năng tạo kiểu cho danh sách. Nếu biết chỉ mục của mục danh sách, chúng ta có thể sử dụng chỉ mục đó để tính toán giá trị thuộc tính. Rất tiếc, hiện tại không có cách nào để xác định chỉ mục của phần tử (theo cách hữu dụng) chỉ trong CSS. Bộ đếm chỉ cho phép chúng tôi sử dụng giá trị của chúng trong thuộc tính content
và không cho phép tính toán.
Tuy nhiên, chúng ta có thể đặt chỉ mục của phần tử trong thuộc tính style
trong HTML. Việc này có thể giúp các phép tính trở nên khả thi hơn, đặc biệt là khi chúng ta đang dùng ngôn ngữ tạo mẫu. Ví dụ này cho thấy cách chúng ta sẽ thiết lập điều đó bằng Nunjucks:
<ol style="--length: items|length">
</ol>
Splitting.js là một thư viện thực hiện chức năng tương tự ở phía máy khách.
Bằng cách sử dụng giá trị thuộc tính tuỳ chỉnh, chúng ta có thể hiển thị tiến trình thông qua danh sách theo nhiều cách. Bạn có thể dùng thanh tiến trình để hiển thị danh sách các bước. Trong ví dụ này, chúng ta đang sử dụng một phần tử giả có độ dốc tuyến tính để tạo một thanh cho mỗi mục cho biết người dùng đã xem được bao nhiêu mục trong danh sách.
li::before {
--stop: calc(100% / var(--length) * var(--i));
--color1: deeppink;
--color2: pink;
content: '';
background: linear-gradient(to right, var(--color1) var(--stop), var(--color2) 0);
}
Chúng ta cũng có thể điều chỉnh sắc độ khi danh sách tiến triển bằng cách sử dụng hàm màu hsl()
. Chúng ta có thể tính toán giá trị hue
bằng cách sử dụng thuộc tính tuỳ chỉnh.
Tạo kiểu danh sách mô tả
Như đã đề cập trước đó, chúng ta có thể chọn gói các thuật ngữ và định nghĩa của chúng trong div
trong dl
để có thêm nhiều lựa chọn định kiểu. Ví dụ: chúng ta có thể muốn hiển thị danh sách dưới dạng lưới. Việc đặt display: grid
trên danh sách mà không có trình bao bọc div
xung quanh mỗi nhóm sẽ có nghĩa là các điều khoản và nội dung mô tả của chúng ta được đặt trong các ô lưới khác nhau. Đôi khi, việc này rất hữu ích, như trong ví dụ sau, hiển thị một trình đơn gồm các bánh với nội dung mô tả.
Chúng ta có thể xác định một lưới trên chính danh sách và đảm bảo rằng các thuật ngữ và nội dung mô tả sẽ luôn căn chỉnh trong các cột, với chiều rộng cột được xác định theo thuật ngữ dài nhất.
Mặt khác, nếu chúng ta muốn nhóm các thuật ngữ một cách rõ ràng theo kiểu thẻ mô tả, thì trình bao bọc <div>
sẽ rất hữu ích.
Tài nguyên
- Danh sách Giới thiệu về danh sách và ::marker
- Điểm đánh dấu tuỳ chỉnh bằng ::marker
- Danh sách CSS có bộ đếm