mikebui
Posted on May 13, 2022
Bài viết được dịch từ:
https://ishadeed.com/article/building-real-life-components/
Nhiều hình đại diện trong trò chuyện nhóm
Trong trường hợp trò chuyện với nhiều người, khu vực hình đại diện sẽ có hai hình đại diện với mỗi hình đại diện được đặt lần lượt ở trên cùng bên phải và dưới cùng bên trái.
Để giữ cho một hình đại diện và nhiều hình đại diện được căn chỉnh, chúng ta cần đặt một kích thước cố định cho thẻ cha chứa nhiều hình đại diện.
.card__avatar {
width: 56px;
height: 56px;
}
Biến thể này yêu cầu thay đổi HTML, xem đoạn code HTML dưới.
<div class="card__avatar card__avatar--multiple">
<svg
class="avatar avatar-1"
role="none"
style="height: 36px; width: 36px"
></svg>
<svg
class="avatar avatar-2"
role="none"
style="height: 36px; width: 36px"
></svg>
<div class="badge"></div>
</div>
.card__avatar--multiple {
position: relative;
width: 56px;
height: 56px;
}
.card__avatar--multiple .avatar {
position: absolute;
}
.card__avatar--multiple .avatar-1 {
right: 0;
top: 0;
}
.card__avatar--multiple .avatar-2 {
left: 0;
bottom: 0;
}
.card__avatar--multiple .badge {
right: 6px;
bottom: 6px;
}
Nội dung
Khu vực này là nơi người dùng có thể nhìn thấy tên của người mà họ đang trò chuyện và nội dung của tin nhắn hoặc hành động (không rõ lắm chắc là status).
Tôi có thể tưởng tượng phần code HTML này được chia thành hai phần, một phần cho nội dung văn bản (tên, tin nhắn hoặc hành động) và phần thứ hai cho chỉ báo ở phía bên phải (tin nhắn mới, đã xem, đã tắt tiếng, đã gửi).
Phần đầu tiên
Hãy cùng khám phá code HTML cho khu vực nội dung.
<div class="card__content">
<div class="card__content__start">
<h3>Ahmad Shadeed</h3>
<div class="row">
<p>You: Thanks, sounds good. What about doing a webinar, too?</p>
<span class="separator">.</span>
<time>8hr</time>
</div>
</div>
<div class="card__content__end">
<!-- The indicator (new message, seen, muted, sent) -->
</div>
</div>
.card__content {
display: flex;
flex: 1;
}
.card__content__start {
display: flex;
flex: 1;
}
.card__content__start .row {
display: flex;
align-items: center;
}
.card__content__end {
display: flex;
justify-content: center;
align-items: center;
margin-left: 12px;
}
.separator {
margin-left: 4px;
margin-right: 4px;
}
Với phần trên, khu vực nội dung sẽ giống như bên dưới (Đây là ảnh chụp màn hình được chụp từ Firefox).
Độ dài của tên hoặc tin nhắn có thể rất dài. Quan trọng là phải tính đến điều đó ngay từ đầu. Trước tiên, chúng ta hãy khám phá phương pháp "flow as you like".
Trong hình trên, nội dung thẻ thứ hai bao gồm nhiều dòng. Điều này có vẻ không tốt cho một component. Để tránh điều đó, đây là những thứ cần làm:
- Đặt
min-width: 0
trên các item con (dùng flex cho parent component). Vì sao? Tôi sẽ cho bạn biết sau đây. - Cắt bớt văn bản bằng cách sử dụng các thuộc tính
overflow
,white-space
vàtext-overflow
.
Tôi thêm code CSS cho phần Tên và ở thẻ p
:
.card__content__start h3,
.card__content__start p {
overflow-x: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
Tuy nhiên, điều này không thể giải quyết vấn đề khi chúng ta đang sử dụng flexbox. Lưu ý kết quả sau khi áp dụng CSS ở trên:
Lý do là các flex items
sẽ không thu nhỏ dưới kích thước nội dung tối thiểu của chúng. Để giải quyết vấn đề này, chúng ta cần đặt min-width: 0
trên các phần tử .card__content
và card__content__start
.
Phần thứ hai
Mỗi tin nhắn có một indicator (status) và chúng ta nên tính đến tất cả chúng. Đây là tất cả các indicator mà tôi biết. Có thể còn nhiều điều mà tôi không biết (Nếu có, vui lòng cho tôi biết).
Đối với phần này, chúng ta sẽ tập trung vào phần tử .card__content__end
và nội dung bên trong của nó.
<div class="card__content">
<div class="card__content__start">
<!-- The name and message -->
</div>
<div class="card__content__end">
<!-- The indicator (new message, seen, muted, sent) -->
</div>
</div>
Bằng cách có một phần tử chung, bất kỳ component nào cũng có thể đặt trong nó. Phần tử .card__content__end
không được có bất kỳ styles nào như color hoặc font, nó sẽ chỉ đóng vai trò là ngôi nhà cho một component cụ thể.
Tin nhắn mới
Trong khi kiểm tra cách Facebook thực hiện chỉ báo (indicator) tin nhắn mới, hóa ra đó là một button có nhãn “Mark as read”.
<div role="button" aria-label="Mark as read" tabindex="0"></div>
Tôi không hiểu bối cảnh tại sao nhóm tại Facebook lại chọn một phần tử div
thay vì một phần tử button
thực tế. Với button
, chúng ta không cần sử dụng role
, aria-label
và tabindex
. Thay vào đó, tất cả những thứ đó đều có sẵn miễn phí.
Hình đại diện Seen
Tương tự như hình đại diện của người dùng, hình đại diện Seen không có gì khác biệt. Nó sử dụng phần tử svg
cho hình đại diện có nhãn aria-label
cho biết tên của người dùng.
<svg aria-label="Ahmad Shadeed" role="img">
<!-- Mask and image -->
</svg>
Nhiều hình đại diện Seen
Thành thật mà nói, đây là một trong những yêu thích của tôi. Tôi thực sự thích cách team tại Facebook thực hiện nó.
Bạn có nhận thấy đường viền giữa hai hình đại diện không? Ngay từ cái nhìn đầu tiên, bạn có thể nghĩ rằng đây là đường viền bởi CSS cho hình đại diện đầu tiên. Nếu bạn nghĩ như vậy, rất tiếc phải thông báo cho bạn biết rằng bạn đã sai (đúng như suy nghĩ ban đầu của tôi).
Điều này có được do áp dụng SVG mask.
<svg role="none">
<mask id="circle">
<circle cx="8" cy="8" fill="white" r="8"></circle>
<circle cx="-4" cy="8" fill="black" r="10"></circle>
</mask>
<g mask="url(#circle)">
<image></image>
<circle class="border" cx="28" cy="28" r="28"></circle>
</g>
</svg>
Đây là hình ảnh về cách hoạt động của nó.
Thật đáng kinh ngạc. Phải không? Tôi thực sự thích sử dụng SVG cho trường hợp cụ thể như này.
Hết phần 3
Posted on May 13, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.