Tính kế thừa

Podcast CSS – 005: Inheritance

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ử liên kết vào một bài viết nội dung, có giá trị class.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. Điều này đã xảy ra như thế nào?

Một số tài sản CSS sẽ kế thừa nếu bạn không chỉ định giá trị cho chúng. Trong trường hợp của nút này, nó kế thừa color từ CSS sau:

article a {
  color: maroon;
}

Trong bài học này, bạn sẽ tìm hiểu lý do điều này xảy ra và 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 như thế nào.

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 này:

<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 cứ phần tử nào vì đó 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à thao tác này bắt đầu rơi xuống tài liệu.

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ử htmlcolor: lightslategray, do đó, tất cả các phần tử có thể kế thừa màu sắc giờ đây 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 chứ không sao lưu vào các phần tử mẹ.

Những thuộc tính nào được kế thừa theo mặc định?

Không phải tất cả các thuộc tính CSS đều được kế thừa theo mặc định, nhưng có rất nhiều việc cần làm. Sau đây là toàn bộ danh sách những cơ sở lưu trú đượ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:

Cách hoạt động của tính kế thừa

Mỗi phần tử HTML đều 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 thể tính giá trị cho phần tử đó.

Những tài sản có thể được kế thừa dạng thác nước xuống dưới, và các phần tử con sẽ nhận được giá trị 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ẹ có font-weight được đặt thành bold, thì tất cả các phần tử con sẽ được in đậm, trừ khi bạn đặt font-weight 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 nên CSS có các công cụ để hỗ trợ bạn.

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 thuộc tính gốc 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> thành có font-weight900, 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 sẽ đặ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-weight500.

Bạn có thể đặt giá trị này một cách rõ ràng, nhưng nếu bạn 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> của mình sẽ tự động được cập nhật.

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 mạnh mẽ.

Trước đây, bạn đã biết rằng mỗi tài sản đều có giá trị mặc định trong CSS. Từ khoá initial đặt một thuộc tính trở 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ả các thành phần <strong> bên trong thành phần <aside> và thay vào đó, làm cho chúng có trọng số 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 cho dù một thuộc tính có được kế thừa theo mặc định hay không. Nếu một tài sản được kế thừa theo mặc định, 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ó khăn, 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 nội dung 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;
}

Giờ đây, margin bị xoá và color chuyển về giá trị 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 kiểu p chung nhận được thêm một vài thuộc tính? Chỉ quy tắc được đặt cho margincolor sẽ đượ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, không quan trọng kiểu chung nào được áp dụng cho p trong tương lai, chúng sẽ luôn không được đặt.

aside p {
    margin: unset;
    color: unset;
    all: unset;
}

Kiểm tra kiến thức

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
Ảnh động không được truyền xuống thành phần con.
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
không phải là giá trị hợp lệ, hãy thử lại!
unset
🎉
superset
không phải là giá trị hợp lệ, hãy thử lại!

Tài nguyên