Podcast CSS – 005: Tính kế thừa
Giả sử bạn vừa viết một số CSS để làm cho 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 bài viết nội dung, có giá trị class
là .my-button
. Tuy nhiên có một vấn đề, văn bản không phải là màu bạn mong đợi. Việc 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 đã 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 tính 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>
Thành phần gốc (<html>
) sẽ không kế thừa bất cứ thành phần nào vì đó là thành phần đầu tiên trong tài liệu.
Thêm một số CSS vào phần tử HTML và CSS này bắt đầu xếp tầng tài liệu xuống.
html {
color: lightslategray;
}
Thuộc tính color
được các phần tử khác kế thừa theo mặc định.
Phần tử html
có color: lightslategray
,
do đó, tất cả các phần tử có thể kế thừa màu 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ử được lồng sâu nhất.
Tính kế thừa chỉ di chuyển xuống dưới, không sao lưu sang 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 vẫn có nhiều thuộc tính như vậy. Để tham khảo, dưới đây là toàn bộ danh sách các thuộc tính được kế thừa theo mặc định, được lấy từ tệp tham chiếu W3 của tất cả các thuộc tính CSS:
- phương vị
- border-collapse
- border-spacing
- bên phụ đề
- color [màu sắc]
- con trỏ
- direction
- ô trống
- họ phông chữ
- font-size
- font-style
- font-variant
- font-weight
- phông chữ
- giãn cách chữ cái
- line-height
- list-style-image
- list-style-position
- list-style-type
- list-style
- đứa trẻ mồ côi
- trích dẫn
- text-align
- text-indent
- biến đổi văn bản
- khả năng hiển thị
- white-space
- góa phụ
- word-spacing
Cách hoạt động của tính kế thừa
Mỗi phần tử HTML có mọi thuộc tính CSS được xác định theo mặc định với 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 mặc định nếu tầng không tính toán được giá trị cho phần tử đó.
Các thuộc tính có thể kế thừa xếp tầng xuống dưới, còn các phần tử con sẽ nhận được giá trị đã tính toán thể hiện 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ả các phần tử con sẽ được in đậm, trừ khi font-weight
của các phần tử con đó được đặt thành một giá trị khác hoặc biểu định kiểu tác nhân người dùng có giá trị font-weight
cho phần tử đó.
Cách kế thừa và kiểm soát tính 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ụ để trợ giúp việc đó.
Từ khoá inherit
Bạn có thể làm cho bất kỳ thuộc tính nào kế thừa giá trị được tính toán của thành phần mẹ bằng từ khoá inherit
.
Một cách hữu ích để sử dụng từ khoá này là tạo các ngoại lệ.
strong {
font-weight: 900;
}
Đoạn mã CSS này đặt tất cả cá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
.
Để làm cho các phần tử <strong>
bên trong .my-component
cũng font-weight: 500
, hãy thêm:
.my-component strong {
font-weight: inherit;
}
Bây giờ, 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 giá trị đó.
Từ khoá initial
Tính kế thừa có thể gây ra sự cố với các phần tử của bạn và initial
cung cấp cho bạn tuỳ chọn đặt lại hiệu quả.
Bạn đã tìm hiểu trước đó rằng mỗi thuộc tính đều có một giá trị mặc định trong CSS.
Từ khoá initial
sẽ đặt một thuộc tính về giá trị mặc định ban đầu đó.
aside strong {
font-weight: initial;
}
Đoạn mã này sẽ xoá độ đậm in đậm khỏi tất cả phần tử <strong>
bên trong một phần tử <aside>
. Thay vào đó, chúng sẽ có độ đậm bình thường, là giá trị ban đầu.
Từ khoá unset
Thuộc tính unset
sẽ hoạt động theo cách khác 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
.
Việc ghi nhớ những thuộc tính CSS nào được kế thừa theo mặc định có thể không dễ dàng, nhưng unset
có thể hữu ích trong bối 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 mã này:
/* 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
bị xoá và color
chuyển về giá trị kế thừa tính toán.
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 kiểu p
chung có thêm một vài thuộc tính?
Chỉ quy tắc bạn đã đặt cho margin
và color
mới được áp dụng.
/* 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ì bất kể kiểu chung nào được áp dụng cho p
trong tương lai, chúng sẽ luôn bị huỷ đặt.
aside p {
margin: unset;
color: unset;
all: unset;
}
Kiểm tra mức độ hiểu biết của bạn
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ó thể kế thừa?
animation
font-size
color
text-align
line-height
Giá trị nào sẽ hoạt động như inherit
trừ phi không có gì để kế thừa và sau đó sẽ hoạt động như initial
?
reset
unset
superset