Bài viết được dịch từ:
https://ishadeed.com/article/building-real-life-components/
Các khu vực của component
Để triển khai một component chuẩn, trước tiên chúng ta cần suy nghĩ kỹ về HTML trước. Trong trường hợp này, chúng ta có hai khu vực của component có nhiều biến thể đó là hình đại diện và khu vực nội dung.
Ảnh đại diện
Để code HTML cho phần avatar, trước tiên chúng ta cần hiểu các trạng thái của nó. Dưới đây là các biến thể có thể có:
- Hình đại diện duy nhất
- Hình đại diện duy nhất có trạng thái trực tuyến
- Nhiều hình đại diện cho trò chuyện nhóm
- Nhiều hình đại diện có trạng thái trực tuyến
Xem xét đoạn HTML sau, chúng ta muốn đảm bảo rằng .card__avatar
có thể xử lý tất cả các biến thể ở trên.
<div class="card">
<div class="card__avatar"></div>
<div class="card__content">
<!-- Name, message, badge.. -->
</div>
</div>
Hình đại diện duy nhất
Hãy tập trung vào biến thể đầu tiên, đó là một hình đại diện duy nhất. Hình đại diện phải có đường viền bên trong (hoặc bóng trong) để làm cho nó trông giống như một vòng tròn ngay cả khi hình đại diện được sử dụng toàn màu trắng.
Trong CSS, không thể áp dụng box-shadow
(inner) cho phần tử img
. Chúng ta có hai lựa chọn:
- Sử dụng thêm một thẻ
div
có đường viền trong suốt. - Sử dụng thẻ
svg
.
Mục tiêu nếu đường viền bên trong là hiển thị đường viền xung quanh hình đại diện trong các trường hợp:
- hình đại diện toàn màu trắng ở chế độ ánh sáng
- hình đại diện toàn màu đen ở chế độ tối
Không có đường viền bên trong, sử dụng hình đại diện toàn màu trắng sẽ làm cho nó hòa trộn với nền gốc của nó. Điều tương tự cũng áp dụng cho chế độ tối. Đây là hình ảnh trực quan về những gì sẽ xảy ra có và không có đường viền bên trong.
Sử dụng thẻ div cho đường viền bên trong
Đối với giải pháp này, một phần tử bổ sung (chính là thẻ div) được đặt hoàn toàn phía trên hình ảnh với độ mờ là 0,1.
<div class="card__avatar">
<img src="assets/shadeed.jpg" alt="" />
<div class="border"></div>
</div>
.card__avatar {
position: relative;
}
.card__avatar img {
width: 56px;
height: 56px;
border-radius: 50%;
}
.border {
position: absolute;
width: 56px;
height: 56px;
border: 2px solid #000;
border-radius: 50%;
opacity: 0.1;
}
Giải pháp này đúng, nhưng có một số hạn chế mà tôi sẽ giải thích sau đây.
Sử dụng thẻ svg
Đối với giải pháp này, chúng tôi sẽ sử dụng một thẻ svg
. Ý tưởng là sử dụng mặt nạ hình tròn cho hình đại diện và phần tử circle
cho đường viền bên trong. SVG hoạt động tuyệt vời cho điều này.
<svg role="none" style="height: 56px; width: 56px">
<mask id="circle">
<circle cx="28" cy="28" fill="white" r="28"></circle>
</mask>
<g mask="url(#circle)">
<image
x="0"
y="0"
height="100%"
preserveAspectRatio="xMidYMid slice"
width="100%"
xlink:href="/assets/shadeed.jpg"
style="height: 56px; width: 56px"
></image>
<circle class="border" cx="28" cy="28" r="28"></circle>
</g>
</svg>
.border {
stroke-width: 3;
stroke: rgba(0, 0, 0, 0.1);
fill: none;
}
Cả hai giải pháp đều hoạt động được khi chỉ xây dựng với ví dụ hình đại diện duy nhất. Tuy nhiên, mọi thứ bắt đầu trở nên thú vị hơn khi chúng ta thêm yếu tố trực tuyến.
Hình đại diện duy nhất có trạng thái trực tuyến
Ở chế độ ánh sáng, hình tròn màu xanh lục có viền trắng. Tuy nhiên, ở chế độ tối, điều này nên được bị khỏi chính hình đại diện. Nói cách khác, nên sử dụng mặt nạ.
Làm thế nào chúng ta có thể làm điều đó? Nếu chúng ta sử dụng giải pháp svg
cho hình đại diện duy nhất, điều này có thể được giải quyết dễ dàng bằng cách sử dụng mặt nạ SVG.
<svg role="none" style="height: 56px; width: 56px">
<mask id="circle">
<!-- [1] -->
<circle cx="28" cy="28" fill="white" r="28"></circle>
<!-- [2] -->
<circle cx="48" cy="48" fill="black" r="7"></circle>
</mask>
<!-- [3] -->
<g mask="url(#circle)">
<image
x="0"
y="0"
height="100%"
preserveAspectRatio="xMidYMid slice"
width="100%"
xlink:href="/assets/shadeed.jpg"
style="height: 56px; width: 56px"
></image>
<circle class="border" cx="28" cy="28" r="28"></circle>
</g>
</svg>
Hãy để tôi chia nhỏ đoạn code SVG trên:
- Một vòng tròn để che hình đại diện thực tế.
- Một hình tròn nhỏ để cắt từ góc dưới bên phải của hình đại diện.
- Một group chứa
image
vàcircle
cho đường viền bên trong trong suốt.
Dưới đây là hình ảnh giải thích cách hoạt động:
Cùng với đó, đây là đoạn code HTML.
<div class="card__avatar">
<svg role="none" style="height: 56px; width: 56px">
<mask id="circle">
<circle cx="28" cy="28" fill="white" r="28"></circle>
<circle cx="48" cy="48" fill="black" r="7"></circle>
</mask>
<g mask="url(#circle)">
<image
x="0"
y="0"
height="100%"
preserveAspectRatio="xMidYMid slice"
width="100%"
xlink:href="/assets/shadeed.jpg"
style="height: 56px; width: 56px"
></image>
<circle class="border" cx="28" cy="28" r="28"></circle>
</g>
</svg>
<div class="badge"></div>
</div>
.card__avatar {
position: relative;
display: flex;
margin-right: 12px;
}
.badge {
position: absolute;
right: 3px;
bottom: 3px;
width: 10px;
height: 10px;
background: #5ad539;
border-radius: 50%;
}
Khi một component như thế này cần phải thích ứng với cả bố cục sáng và tối, bạn nên sử dụng các biến CSS để xử lý nhằm lưu trữ các giá trị của màu cần thay đổi.
:root {
--primary-text: #050505;
--secondary-text: #65676b;
--bg-color: #fff;
}
html.is-dark {
--primary-text: #e4e6eb;
--secondary-text: #b0b3b8;
--bg-color: #242526;
}
.card {
background-color: var(--bg-color);
}
.card__title {
color: var(--primary-text);
}
.card__subtitle {
color: var(--secondary-text);
}
Top comments (0)