The CSS Podcast – 005: Kế thừa
Giả sử bạn vừa viết một số CSS để các phần tử trông giống như một nút.
<a href="http://example.com" class="my-button">I am a button link</a>
.my-button {
display: inline-block;
padding: 1rem 2rem;
text-decoration: none;
background: pink;
font: inherit;
text-align: center;
}
Sau đó, bạn thêm một phần tử đường liên kết vào một bài viết nội dung, với giá trị class
là .my-button
. Tuy nhiên, có một vấn đề là văn bản không có màu như bạn mong đợi. Điều này đã xảy ra như thế nào?
Một số thuộc tính CSS sẽ kế thừa nếu bạn không chỉ định giá trị cho các thuộc tính đó.
Trong trường hợp của nút này, nút này kế thừa color
từ CSS này:
article a {
color: maroon;
}
Trong bài học này, bạn sẽ tìm hiểu lý do điều đó xảy ra và cách kế thừa là một tính năng mạnh mẽ giúp bạn viết ít CSS hơn.
Luồng kế thừa
Hãy xem cách hoạt động của tính kế thừa bằng cách sử dụng đoạn mã HTML sau:
<html>
<body>
<article>
<p>Lorem ipsum dolor sit amet.</p>
</article>
</body>
</html>
Phần tử gốc (<html>
) sẽ không kế thừa bất kỳ phần tử nào vì đây là phần tử đầu tiên trong tài liệu.
Thêm một số CSS vào phần tử HTML và CSS sẽ bắt đầu đổ xuống tài liệu.
html {
color: lightslategray;
}
Theo mặc định, các phần tử khác sẽ kế thừa thuộc tính color
.
Phần tử html
có color: lightslategray
, vì vậy, tất cả các phần tử có thể kế thừa màu sắc hiện sẽ có màu lightslategray
.
body {
font-size: 1.2em;
}
p {
font-style: italic;
}
Chỉ <p>
mới có văn bản in nghiêng vì đây là phần tử lồng sâu nhất.
Tính kế thừa chỉ diễn ra theo chiều đi xuống, chứ không quay lại các phần tử mẹ.
Những thuộc tính nào được kế thừa theo mặc định?
Theo mặc định, không phải tất cả các thuộc tính CSS đều được kế thừa, nhưng có rất nhiều thuộc tính được kế thừa. Để tham khảo, sau đây là toàn bộ danh sách các thuộc tính được kế thừa theo mặc định, lấy từ tài liệu tham khảo W3 về tất cả các thuộc tính CSS:
- độ góc phương vị
- border-collapse
- border-spacing
- caption-side
- color
- con trỏ
- direction
- ô-trống
- font-family
- font-size
- font-style
- font-variant
- font-weight
- phông chữ
- letter-spacing
- line-height
- list-style-image
- list-style-position
- list-style-type
- list-style
- trẻ mồ côi
- trích dẫn
- text-align
- text-indent
- text-transform
- visibility
- white-space
- góa phụ
- word-spacing
Cách hoạt động của tính năng kế thừa
Theo mặc định, mọi phần tử HTML đều có mọi thuộc tính CSS được xác định bằng một giá trị ban đầu. Giá trị ban đầu là một thuộc tính không được kế thừa và xuất hiện dưới dạng giá trị mặc định nếu hiệu ứng lũy thừa không tính được giá trị cho phần tử đó.
Các thuộc tính có thể được kế thừa theo kiểu thác nước xuống dưới, và các phần tử con sẽ nhận được một giá trị được tính toán đại diện cho giá trị của phần tử mẹ.
Điều này có nghĩa là nếu phần tử mẹ đặt font-weight
thành bold
, thì tất cả phần tử con sẽ in đậm, trừ phi font-weight
của phần tử đó được đặt thành một giá trị khác hoặc bảng kiểu của tác nhân người dùng có giá trị cho font-weight
cho phần tử đó.
Cách kế thừa và kiểm soát việc kế thừa một cách rõ ràng
Tính kế thừa có thể ảnh hưởng đến các phần tử theo cách không mong muốn, vì vậy, CSS có các công cụ để giúp giải quyết vấn đề đó.
Từ khoá inherit
Bạn có thể khiến bất kỳ thuộc tính nào kế thừa giá trị được tính toán của thuộc tính mẹ bằng từ khoá inherit
.
Một cách hữu ích để sử dụng từ khoá này là tạo ngoại lệ.
strong {
font-weight: 900;
}
Đoạn mã CSS này đặt tất cả phần tử <strong>
có font-weight
là 900
, thay vì giá trị bold
mặc định, tương đương với font-weight: 700
.
.my-component {
font-weight: 500;
}
Thay vào đó, lớp .my-component
đặt font-weight
thành 500
.
Để các phần tử <strong>
bên trong .my-component
cũng là font-weight: 500
, hãy thêm:
.my-component strong {
font-weight: inherit;
}
Giờ đây, các phần tử <strong>
bên trong .my-component
sẽ có font-weight
là 500
.
Bạn có thể đặt giá trị này một cách rõ ràng, nhưng nếu sử dụng inherit
và CSS của .my-component
thay đổi trong tương lai, bạn có thể đảm bảo rằng <strong>
sẽ tự động cập nhật theo.
Từ khoá initial
Tính kế thừa có thể gây ra sự cố với các phần tử và initial
cung cấp cho bạn một tuỳ chọn đặt lại mạnh mẽ.
Trước đó, bạn đã biết rằng mỗi thuộc tính đều có một giá trị mặc định trong CSS.
Từ khoá initial
đặt một thuộc tính về giá trị ban đầu, mặc định đó.
aside strong {
font-weight: initial;
}
Đoạn mã này sẽ xoá độ đậm khỏi tất cả phần tử <strong>
bên trong phần tử <aside>
và thay vào đó,
đặt độ đậm thành độ đậm thông thường, tức là giá trị ban đầu.
Từ khoá unset
Thuộc tính unset
sẽ hoạt động theo cách khác nhau nếu một thuộc tính được kế thừa theo mặc định hay không.
Nếu một thuộc tính được kế thừa theo mặc định, thì từ khoá unset
sẽ giống với inherit
.
Nếu thuộc tính không được kế thừa theo mặc định, thì từ khoá unset
sẽ bằng initial
.
Bạn có thể khó nhớ được thuộc tính CSS nào được kế thừa theo mặc định, unset
có thể hữu ích trong ngữ cảnh đó.
Ví dụ: color
được kế thừa theo mặc định, nhưng margin
thì không, vì vậy, bạn có thể viết như sau:
/* Global color styles for paragraph in authored CSS */
p {
margin-top: 2em;
color: goldenrod;
}
/* The p needs to be reset in asides, so you can use unset */
aside p {
margin: unset;
color: unset;
}
Bây giờ, margin
sẽ bị xoá và color
sẽ trở lại là giá trị được tính toán kế thừa.
Bạn cũng có thể sử dụng giá trị unset
với thuộc tính all
.
Quay lại ví dụ trên, điều gì sẽ xảy ra nếu các kiểu p
toàn cục có thêm một vài thuộc tính?
Chỉ áp dụng quy tắc đã đặt cho margin
và color
.
/* Global color styles for paragraph in authored CSS */
p {
margin-top: 2em;
color: goldenrod;
padding: 2em;
border: 1px solid;
}
/* Not all properties are accounted for anymore */
aside p {
margin: unset;
color: unset;
}
Nếu bạn thay đổi quy tắc aside p
thành all: unset
, thì kiểu toàn cục nào được áp dụng cho p
trong tương lai cũng không quan trọng, vì chúng sẽ luôn bị huỷ thiết lập.
aside p {
margin: unset;
color: unset;
all: unset;
}
Kiểm tra mức độ hiểu biết
Kiểm tra kiến thức của bạn về tính kế thừa
Thuộc tính nào sau đây được kế thừa theo mặc định?
animation
font-size
color
text-align
line-height
Giá trị nào hoạt động như inherit
trừ phi không có gì để kế thừa và sau đó hoạt động như initial
?
reset
unset
superset