CSS (8) - Bộ chọn

1.1       Bộ chọn

1.1.1       Các loại bộ chọn

Ở các phần trước, chúng ta đã biết cách sử dụng tên của phần tử để làm bộ chọn (selector). Trong phần này, chúng ta sẽ tìm hiểu chi tiết hơn về bộ chọn.

Có một số loại bộ chọn phổ biến sau:

– Bộ chọn cơ bản (basic selector)

– Bộ chọn gộp (grouping selector)

– Bộ chọn tổ hợp (combinator)

– Bộ chọn theo trạng thái (pseudo-class, pseudo-element)

Bộ chọn cơ bản

Bảng sau liệt kê một số bộ chọn cơ bản:

Bộ chọn

Cú pháp

Bộ chọn phổ quát (universal selector): chọn mọi phần tử

* {}

ns | * {}

* | * {}

Bộ chọn theo tên phần tử (type selector, element selector): chọn các phần tử theo tên.

elementname {}

Ví dụ:

p {}// chọn mọi phần tử p trong tài liệu HTML

Bộ chọn theo class: chọn các phần tử theo giá trị của thuộc tính class

.classname{}

Ví dụ:

.menu{} // chọn mọi phần tử có thuộc tính class="menu"

Bộ chọn theo ID: chọn phần tử theo giá trị của thuộc tính ID

#idname{}

#top{} // chọn phần tử có thuộc tính id="top"

Bộ chọn theo thuộc tính (attribute): chọn các phần tử theo tên, hoặc giá trị của thuộc tính

[attr]  [attr=value]  [attr~=value]  [attr|=value]  [attr^=value]  [attr$=value] [attr*=value]

Ví dụ:

[autoplay] {} // chọn các phần tử có thuộc tính tên là autoplay, mà không cần quan tâm tới giá trị của thuộc tính

Bộ chọn gộp

Trường hợp cần định dạng giống nhau cho nhiều phần tử HTML, thì chúng ta có thể gộp các bộ chọn lại, giúp dễ đọc và rút gọn mã nguồn. Sử dụng dấu phẩy (,) để ngăn cách giữa các bộ chọn.

Ví dụ:

p, h1, div { color: red; }

Bộ chọn tổ hợp

Là bộ chọn được tạo ra bằng cách tổ hợp (kết hợp) từ hai thành phần trở lên.

Bảng sau liệt kê một số bộ chọn tổ hợp:

Bộ chọn

Cú pháp

Bộ chọn theo hậu duệ (descendant combinator): chọn các phần tử là hậu duệ (con, cháu, chắt,…v.v) của một phần tử

A B{}

Ví dụ:

div span{} // chọn các span nằm trong div

Bộ chọn gồm các con trực tiếp (child combinator)

A > B{}

Ví dụ:

ul > li // chọn các li là con của ul

Bộ chọn gồm các “phần tử em” (general sibling combinator): chọn các phần tử cùng cha, nằm bên phải một phần tử

A ~ B{}

Ví dụ:

p ~ span{} // chọn các span nằm phía sau (tính từ trái sang phải), cùng cấp (cùng phần tử cha) với p

Bộ chọn gồm một "phần tử em" (adjacent sibling combinator)

A + B{}

Ví dụ:

h2 + p{} // chọn một phần tử p nằm ngay sau h2

Bộ chọn theo trạng thái

Bộ chọn theo trạng thái gồm 2 loại:

– Bộ chọn lớp giả (pseudo class): chọn “lớp giả” là các trạng thái của phần tử, ví dụ a:visited{} sẽ chọn các phần tử a đã được người dùng duyệt qua

– Bộ chọn phần tử giả (pseudo element): chọn các "phần tử giả", là các phần tử không tồn tại  trong tài liệu HTML, ví dụ p::first-line{} chọn hàng đầu tiên của phần tử p

1.1.2       Cú pháp của bộ chọn

Về mặt thực hành, chúng ta có nhiều cách để viết bộ chọn. Trong phần này, chúng ta sẽ hệ thống lại các cách viết, để tiện khi lập trình.

Chúng ta có các cách viết bộ chọn sau:

– Bộ chọn đơn (simple selector): là các bộ chọn chỉ gồm một thành phần. Ví dụ: các bộ chọn cơ bản, bộ chọn theo trạng thái.

– Bộ chọn hỗn hợp (compound selector): là bộ chọn gồm một dãy liên tục (không có khoảng trắng) các bộ chọn đơn. Ví dụ a#selected {} // chọn các phần tử có tên là a và có thuộc tính id="selected"

– Bộ chọn phức (complex selector): là bộ chọn gồm một hoặc nhiều bộ chọn đơn/bộ chọn hỗn hợp, ngăn cách nhau bằng các dấu tổ hợp. Ví dụ: a#selected > .icon {},  .box h2 + p {}

– Bộ chọn gộp (gộp các bộ chọn): là một dãy các bộ chọn, ngăn cách nhau bằng dấu phẩy (,). Ví dụ: #main, article.heading {}.

1.1.3       Thực hành với một số bộ chọn

Chúng ta đã biết về các loại bộ chọn trong CSS, phần này sẽ thực hành với một số bộ chọn, giúp chúng ta hiểu kĩ hơn về chúng.

Để tiện thực hành, theo dõi và kiểm tra kết quả, chúng ta sẽ sử dụng đoạn mã HTML sau:

[index.html]

<!DOCTYPE html>

<html>

 

<head>

    <meta charset="utf-8">

    <title>Selectors</title>

    <style>

   

    </style>

</head>

 

<body>

    <h2 class="greencolor">The Back of the New $20</h2>

    <p>Have you seen the "Series <em>2004</em> $20 Notes"? The U.S. Treasury has rolled out yet another revamp of the

        U.S. <a href=""><em>twenty</em></a> dollar bill in an effort to stop those pesky counterfeiters once and for

        all.</p>

    <h2 class="greencolor">The first 20s</h2>

    <ul>

        <li>

            <h3>This is <em>first</em> item</h3>

        </li>

        <li>This is <em>second</em> item</li>

        <li>

            <h2>This is <em>third</em> item</h2>

        </li>

    </ul>

    <h2 id="yellowcolor">Too Many <em>20s</em></h2>

    <p class="violetcolor">The last paragraph</p>

    <h2>Another 20s</h2>

</body>

 

</html>

– Bộ chọn phổ quát

 * { color: red; } /* mọi phần tử đều có chữ màu đỏ */

Để tiện quan sát kết quả, sau mỗi ví dụ, chúng ta sẽ xóa đoạn mã CSS của ví dụ trước, rồi mới viết thêm đoạn mã CSS.

– Bộ chọn là tên phần tử

h2 { color: red; } /* các phần tử h2 có chữ màu đỏ */

– Bộ chọn theo class

Thuộc tính class sẽ thực hiện phân lớp các phần tử vào các nhóm một cách logic, tất cả các phần tử giá trị class giống nhau sẽ cùng thuộc về một nhóm. Nhiều phần tử có thể có class giống nhau, và một phần tử có thể thuộc về nhiều class.

Sử dụng class để tạo ra bộ chọn gồm các phần tử có giá trị class giống nhau, trước class sẽ có thêm dấu chấm (.).

.greencolor { color: green; } /* phần tử nào có giá trị class là greencolor sẽ có màu xanh */

– Bộ chọn theo ID

Như đã biết, thuộc tính id được sử dụng để gán định danh (identifier) cho một phần tử bất kì, định danh này là duy nhất trong tài liệu HTML. Trong CSS, có thể sử dụng id làm bộ chọn để thực hiện định dạng cho phần tử, trước id sẽ có thêm dấu thăng (#) (octothorpe hoặc hash symbol).

#yellowcolor { color: yellow; } /* phần tử có giá trị ID là yellowcolor sẽ có màu vàng */

– Bộ chọn theo thuộc tính

 [class] { color: violet; } /* phần tử có thuộc tính là class sẽ có màu tím, không quan tâm giá trị class là gì */

– Bộ chọn gộp

h3, p, #yellowcolor { color: blue } /* các phần tử h3, p và phần tử có id="yellowcolor" sẽ có màu blue*/

– Bộ chọn theo hậu duệ

Bộ chọn theo hậu duệ sẽ chọn các phần tử là con, cháu, chắt,…v.v của một phần tử.

Để chọn theo hậu duệ, sử dụng một dãy các bộ chọn, mỗi bộ chọn ngăn cách nhau bằng một khoảng trắng. Khoảng trắng này có nghĩa là phần tử phía sau sẽ là hậu duệ của phần tử phía trước. Ví dụ,

li em { color: red }

Bộ chọn trên có nghĩa là: chỉ có các phần tử em là hậu duệ của phần tử li mới có chữ màu đỏ, trong khi các phần tử em còn lại sẽ không bị tác động bởi chỉ dẫn CSS này. Xem hình ví dụ,


Ví dụ sau sẽ kết hợp bộ chọn gộp và chọn theo hậu duệ, mọi phần tử em nằm trong h1, hoặc h2, hoặc h3 sẽ có chữ màu đỏ.

h1 em, h2 em, h3 em { color: red; }

Bộ chọn theo hậu duệ cũng có thể lồng nhau theo nhiều cấp, ví dụ sau sẽ thiết lập chữ màu đỏ cho các phần tử em nằm trong h3h3 phải nằm trong li.

li h3 em { color: red; }

– Bộ chọn gồm các con trực tiếp

Cách chọn này cũng tương tự như chọn theo các hậu duệ, tuy nhiên, chỉ giới hạn cho các hậu duệ là con trực tiếp. Con trực tiếp của một phần tử được hiểu là các phần tử nằm ở cấp dưới, liền kề trong tài liệu HTML (không có cấp nào xen vào giữa). Sử dụng dấu lớn hơn (>) để thể hiện bộ chọn này.

Ví dụ, chỉ dẫn CSS sau sẽ làm cho chữ trong phần tử em có màu đỏ, tuy nhiên, chỉ có phần tử em là con trực tiếp của p mới chịu tác động, trong khi các phần tử em khác thì không chịu tác động.

p > em { color: red; }

Xem hình minh họa,



– Bộ chọn gồm một "phần tử em"

Các phần tử có cùng cha thì được gọi là anh em; trong tài liệu HTML, phần tử anh sẽ nằm trước, phần tử em nằm sau; trong cấu trúc cây (cây DOM), phần tử anh nằm ở phía trái, phần tử em nằm ở phía phải.

Chọn một em liền kề của một phần tử là chọn duy nhất một phần tử là em liền kề của nó. Sử dụng dấu cộng (+) để thể hiện bộ chọn này.

Ví dụ, chỉ dẫn CSS sau sẽ làm cho chữ trong phần tử h2 có màu đỏ, tuy nhiên, chỉ có một phần tử h2 nằm ngay sau ul mới chịu tác động, trong khi các phần tử h2 khác thì không chịu tác động.

ul + h2 { color: red; }

Xem hình minh họa,



– Bộ chọn gồm các “phần tử em”

Bộ chọn gồm các phần tử em của một phần tử sẽ chọn tất cả các phần tử là em (có tên được chỉ định) của nó. Sử dụng dấu ngã (~) để thể hiện bộ chọn này.

Ví dụ, chỉ dẫn CSS sau sẽ làm cho chữ trong phần tử h2 có màu đỏ, tuy nhiên, chỉ những phần tử h2 nằm sau ul (cùng cha body) mới chịu tác động, trong khi các phần tử h2 nằm phía trước và các vị trí khác thì không chịu tác động.

ul ~ h2 { color: red; }

Xem hình minh họa,



– Bộ chọn hỗn hợp

Ví dụ:

       p.violetcolor { color: violet; }

Chọn phần tử có tên là p và có class="violetcolor".

1.1.4       Tính rõ ràng, chính xác của chỉ-dẫn-CSS

Như đã biết, khi có hai chỉ dẫn CSS bị xung đột thì chỉ dẫn nào càng rõ ràng, càng chính xác thì càng có độ ưu tiên cao hơn.

Trong CSS,  danh sách dưới đây sẽ liệt kê các loại bộ chọn có tính rõ ràng, chính xác từ cao xuống thấp:

– Định dạng CSS trực tiếp trong phần tử HTML bằng thuộc tính style

– ID

– Class

– Bộ chọn là tên phần tử

Tuy nhiên, nếu bộ trọn bao gồm nhiều thành phần thì việc xác định bộ chọn nào có độ ưu tiên cao hơn sẽ được thực hiện như sau:

– Tạo ra 3 cái hộp rỗng [ ] [ ] [ ]

– Đếm số ID có trong bộ chọn, điền vào hộp đầu tiên (tính từ trái qua phải)

– Đếm số class và pseudo-class có trong bộ chọn, điền vào hộp thứ 2

– Đếm số tên phần tử có trong bộ chọn, điền vào hộp thứ 3

– Duyệt từ trái sang phải, bộ chọn nào có thành phần ưu tiên nhiều hơn thì có độ ưu tiên cao hơn

Ví dụ,

Xét hai chỉ dẫn, cùng định dạng CSS cho p:

       p { color: red; }

       p.violetcolor { color: violet; }

Dễ nhận thấy, các phần tử p sẽ có chữ màu đỏ. Tuy nhiên, phần tử p có kèm class="violetcolor" có chữ màu đỏ không? Để biết được, chúng ta đo độ “rõ ràng, chính xác”.

      (1)   p { color: red; }                         [0] [0] [1]

      (2)   p.violetcolor { color: violet; }          [0] [1] [1]

Xét các hộp, từ trái sang phải thấy chỉ dẫn 2 có độ ưu tiên cao hơn. Do vậy, phần tử p có kèm class="violetcolor" sẽ có chữ màu tím.

Quan sát một ví dụ khác:

(1) p { line-height: 1.2em; }             [0] [0] [1]

(2) blockquote p { line-height: 1em; }    [0] [0] [2]

(3) p.intro { line-height: 2em; }         [0] [1] [1]

Xét độ ưu tiên dựa vào tính “rõ ràng, chính xác”: chỉ dẫn (3) có độ ưu tiên cao nhất, vì có 1 class;  tiếp đến là chỉ dẫn 2, vì có 2 tên phần tử; cuối cùng là chỉ dẫn (1). Kết quả là dòng văn bản trong blockquote thấp hơn các đoạn thông thường, và dòng văn bản có class=“intro” là cao nhất (ngay cả khi nó nằm trong blockquote).

Bạn có thể tìm kiếm theo từ khóa “specificity calculator” để sử dụng công cụ tính độ “rõ ràng, chính xác” của bộ chọn. Ví dụ, có thể sử dụng trang web: https://specificity.keegan.st/. Bạn chỉ cần nhập bộ chọn, hệ thống sẽ tính các chỉ số ID, class, element. Hoặc bấm vào nút “Sort by specificity” để hệ thống sắp xếp thứ tự ưu tiên theo độ “rõ ràng, chính xác” của bộ chọn.

1.1.5       Xem và đọc thêm

– [1] Jenifer Niederst Robbins, Learning Web Design, O’Reilly, 2018, trang 281 - 286

– [2] CSS selector: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors

– [3] Specificity Calculator: https://specificity.keegan.st/

1.1.6       Bài tập và thực hành

Bài tập 1. Viết lại các đoạn mã trong phần lý thuyết.

Bài tập 2. Sử dụng mã HTML (menu.html) của Bài tập 2,  trong phần Phông chữ.

This time, we’ll add a few more style rules using descendant, ID, and class selectors combined with the font and color properties we’ve learned about so far.

1. I’d like to add some attention-getting color to the “new item!” elements next to certain menu item names. They are marked up as strong, so we can apply the color property to the strong element. Add this rule to the embedded style sheet, save the file, and reload it in the browser:

strong {

font-style: italic;

color: tomato;

}

That worked, but now the strong element “Very spicy” in the description is “tomato” red too, and that’s not what I want. The solution is to use a contextual selector that targets only the strong elements that appear in dt elements. Remove the color declaration you just wrote from the strong rule, and create a new rule that targets only the strong elements within definition list terms:

dt strong { color: tomato; }

2. Look at the document source, and you will see that the content has been divided into three unique divs: info, appetizers, and entrees. We can use these to our advantage when it comes to styling. For now, let’s do something simple and apply a teal color to the text in the div with the ID “info”. Because color inherits, we need to apply the property only to the div and it will be passed down to the h1 and p:

#info { color: teal; }

3. Now let’s get a little fancier and make the paragraph inside the “info” section italic in a way that doesn’t affect the other paragraphs on the page. Again, a contextual selector is the answer. This rule selects only paragraphs contained within the info section of the document:

#info p { font-style: italic; }

4. I want to give special treatment to all of the prices on the menu. Fortunately, they have all been marked up with span elements:

<span class="price">$3.95</span>

So now all we have to do is write a rule using a class selector to change the font to Georgia or some serif font, make the prices italic, and gray them back:

.price {

font-family: Georgia, serif;

font-style: italic;

color: gray;

}

5. Similarly, in the “info” div, I can change the appearance of the spans that have been marked up as belonging to the “label” class to make the labels stand out:

.label {

font-weight: bold;

font-variant: small-caps;

font-style: normal;

}

6. Finally, there is a warning at the bottom of the page that I want to make small and red. It has been given the class “warning,” so I can use that as a selector to target just that paragraph for

styling. While I’m at it, I’m going to apply the same style to the sup element (the footnote asterisk) earlier on the page so they match. Note that I’ve used a grouped selector, so I don’t need to write a separate rule.

p.warning, sup {

font-size: small;

color: red;

}

[Result]


1.1.7       Câu hỏi ôn tập

Câu 1. Muốn định dạng mọi phần tử divh1 đều có chữ màu đỏ, dùng chỉ dẫn CSS nào?

A. div > h1 { color: red; }

B. div ~ h1 { color: red; }

C. div  h1 { color: red; }

D. div + h1 { color: red; }

Câu 2. Muốn định dạng mọi phần tử div và có thuộc tính class="intro" có chữ màu đỏ, dùng chỉ dẫn CSS nào?

A. div > .intro { color: red; }

B. div.intro { color: red; }

C. div .intro { color: red; }

D. div#intro { color: red; }

Câu 3. Muốn định dạng mọi phần tử div và có thuộc tính id="intro" có chữ màu đỏ, dùng chỉ dẫn CSS nào?

A. div > .intro { color: red; }

B. div.intro { color: red; }

C. div #intro { color: red; }

D. div#intro { color: red; }

Câu 4. Trong 3 chỉ dẫn CSS sau: (1) p { line-height: 1.2em; }, (2) blockquote p { line-height: 1em; }, (3) p.intro { line-height: 2em; }, xét theo độ “rõ ràng, chính xác, specificity”, cái nào có độ ưu tiên cao nhất?

A. 1

B. 2

C. 3

D. 2 và 3

Câu 5. Muốn định dạng hàng đầu tiên của đoạn có chữ màu đỏ, dùng chỉ dẫn CSS nào?

A. p::first-line{ color: red; }

B. p>first-line{ color: red; }

C. p+first-line{ color: red; }

D. p~first-line{ color: red; }

Đáp án: 1(C), 2(B), 3(D), 4(C), 5(A)

-----

Cập nhật: 26/5/2023

-----

Bạn muốn tự học HTML bài bản? Xem thêm