CSS (11) - Bộ chọn theo trạng thái & thuộc tính

1.1       Bộ chọn theo trạng thái & thuộc tính

Như đã biết, trong CSS, các bộ chọn được chia thành 4 loại, gồm: Bộ chọn cơ bản (basic selector), Bộ chọn gộp (grouping selector), Bộ chọn tổ hợp (combinator) và Bộ chọn theo trạng thái (pseudo-class, pseudo-element).

Trong đó, 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à chọn theo 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 "phần tử giả" là chọn các phần tử không tồn tại một cách tường minh trong tài liệu HTML, ví dụ p::first-line{} chọn hàng đầu tiên của phần tử p

Phần này sẽ tìm hiểu kĩ hơn về Bộ chọn lớp giả và Bộ chọn phần tử giả. Ngoài ra, chúng ta cũng tìm hiểu thêm về Bộ chọn theo thuộc tính (thuộc Bộ chọn cơ bản).

1.1.1       Bộ chọn lớp giả (pseudo-class)

Để ý các liên kết (link) trên một trang web, nếu chưa được bấm chuột vào chúng sẽ có màu xanh, ngược lại, nếu đã được bấm chuột vào, chúng sẽ có màu tím. Có hiện tượng này là do trình duyệt đã lưu lại trạng thái của các liên kết, cho biết chúng đã được bấm chuột hay chưa (clicked, visited).

Ngoài ra, trình duyệt cũng cung cấp một số thông tin trạng thái khác, như khi người dùng đang rê chuột lên một phần tử (hover), một phần tử có là cái đầu tiên của một loại, là con đầu tiên/cuối cùng của một phần tử cha; phần tử có được chọn không (checked) hay phần tử có bị vô hiệu không (disabled).

Trong CSS, chúng có thể định dạng phần tử dựa trên các trạng thái như vậy, bằng cách sử dụng bộ chọn pseudo-class.

Pseudo-class được gọi nôm na là “lớp giả”. Sao lại gọi là “lớp giả”? Như đã biết, thuộc tính class được sử dụng để gán định danh cho phần tử, các phần tử có cùng giá trị class (cùng định danh) sẽ được xem là cùng một lớp. Tuy nhiên, trạng thái của phần tử không được thể hiện tường minh trong mã nguồn, nghĩa là không có định danh, mà nó được xác định ngầm (dựa vào vị trí của phần tử trong mã nguồn hoặc tương tác của người dùng), các phần tử có cùng trạng thái cũng được xem là cùng một lớp, nhưng lớp này không tường minh, nên gọi là “lớp giả”.

Cú pháp của pseudo-class thường được bắt đầu bằng tên một phần tử, tiếp theo là dấu hai chấm (:), cuối cùng là tên của trạng thái, ví dụ: li:first-child.

Có rất nhiều loại bộ chọn pseudo-class, ví dụ:

– Bộ chọn pseudo-class cho liên kết

– Bộ chọn pseudo-class dựa trên thao tác người dùng

– Bộ chọn pseudo-class dựa trên cấu trúc tài liệu HTML

– Bộ chọn pseudo-class cho các input của form

Bộ chọn pseudo-class cho liên kết

Bộ chọn pseudo-class cho liên kết được sử dụng để định dạng các liên kết dựa trên trạng thái của nó. Cụ thể,

– :link dùng để định dạng cho liên kết chưa được người dùng bấm vào

– :visited dùng để định dạng cho liên kết đã được người dùng bấm vào

Ví dụ: mặc định, liên kết người dùng chưa bấm vào sẽ có màu xanh, bấm vào rồi sẽ có màu tím. Tuy nhiên, chúng ta có thể sử dụng CSS để thay đổi màu mặc định của liên kết thành các màu khác,

a:link {

color: maroon;

}

a:visited {

color: gray;

}

Bộ chọn pseudo-class dựa trên thao tác người dùng

Phần này sẽ tìm hiểu các bộ chọn pseudo-class dựa trên thao tác của người dùng, gồm ba bộ chọn sau:

– :focus áp dụng khi người dùng chọn phần tử để nhập nội dung, phần tử được chọn sẽ nổi bật hơn so với các phần tử còn lại, bộ chọn này hay áp dụng cho các ô nhập liệu của form. Ví dụ, ô nhập liệu sau sẽ có nền màu vàng khi người dùng chọn,

input:focus { background-color: yellow; }

– :hover áp dụng khi người dùng rê con trỏ chuột trên một phần tử, mặc dù có thể áp dụng trên mọi phần tử HTML, tuy nhiên, bộ chọn này hay được áp dụng trên các liên kết, nhằm gây chú ý cho người sử dụng. Ví dụ, liên kết sẽ đổi màu nền khi người dùng rê chuột lên,

a:hover {

color: maroon;

background-color: #ffd9d9;

}

– :active áp dụng khi một phần tử (nút hoặc liên kết) đang được bấm chuột. Ví dụ, liên kết sẽ đổi màu nền khi người dùng đang bấm chuột lên,

a:active {

color: red;

background-color: # ffd9d9;

}

CSS cho các trạng thái của một liên kết

Nhà thiết kế web thường định dạng CSS cho tất cả các trạng thái của một liên kết, nhằm làm cho giao diện sinh động, cuốn hút hơn. Nói chung, tâm lý người dùng luôn muốn nhận lại một kết quả gì đó sau mỗi thao tác của họ, như cập nhật các liên kết họ đã ghé thăm, khi rê chuột lên một liên kết sẽ có hiệu ứng xuất hiện, hoặc khi bấm chuột vào liên kết nó sẽ chuyển màu để báo việc bấm chuột đã có tác dụng.

Chú ý: khi áp dụng các bộ chọn pseudo-class vừa tìm hiểu ở trên cho một liên kết, cần để ý đến thứ tự của các bộ chọn, nếu thứ tự không phù hợp sẽ dẫn đến chúng hoạt động không đúng. Ví dụ, nếu để hai bộ chọn :link:visited sau cùng, nó sẽ làm mất tác dụng của các bộ chọn khác. Thứ tự của các bộ chọn nên theo là, :link, :visited, :focus, :hover, :active

Ví dụ,

a { text-decoration: none; } /* bỏ dấu gạch chân */

a:link { color: maroon; }

a:visited { color: gray; }

a:focus { color: maroon; background-color: #ffd9d9; }

a:hover { color: maroon; background-color: #ffd9d9; }

a:active { color: red; background-color: #ffd9d9; }

Bộ chọn pseudo-class dựa trên cấu trúc tài liệu HTML

Chúng ta có thể sử dụng bộ chọn pseudo-class để chọn ra các phần tử dựa vào vị trí của nó trong cấu trúc tài liệu HTML. Dưới đây là một số bộ chọn,

:root

:empty

:first-child

:last-child

:only-child

:first-of-type

:last-of-type

:only-of-type

:nth-child()

:nth-last-child()

:nth-of-type()

:nth-last-of-type()

 

 

 

Bạn có thể lên mạng để tìm hiểu thêm về các bộ chọn này, hoặc có thể đọc thêm ở đây: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#tree-structural_pseudo-classes

Ví dụ: để chọn phần tử đầu tiên trong một nhóm các phần tử cùng cấp (anh em), chúng ta sử dụng :first-child.

[HTML]

    <p>Một số nội dung cần học để làm web front-end</p>

    <ul>

        <li>HTML</li>

        <li>CSS</li>

        <li>JS</li>

        <li>React</li>

    </ul>

[CSS]

    li:first-child { color: red; }

[Kết quả]

Dòng chữ HTML có màu đỏ

Bộ chọn pseudo-class cho các input của form

Bộ chọn pseudo-class cho các input của form sẽ chọn ra các phần tử dựa vào thuộc tính HTML và trạng thái của các input trước và sau khi tương tác. Ví dụ,

:autofill

:enabled

:disabled

:read-only

:placeholder-show

:default

:checked

:indeterminate

:blank

:valid

:invalid

:in-range

:out-of-range

:required

:optional

Ví dụ:

[HTML]

    <div>

        <input type="checkbox" name="my-checkbox" id="opt-in">

        <label for="opt-in">Chọn</label>

    </div>

[CSS]

    /* Định dạng label khi người dùng đánh dấu chọn */

    input:checked + label {

        color: red;

    }

    /* Định dạng ô chọn khi được chọn */

    input[type="checkbox"]:checked {

        box-shadow: 0 0 0 3px hotpink;

    }

Các bộ chọn pseudo-class khác

Ngoài 4 bộ chọn chúng ta đã tìm hiểu, còn có nhiều bộ chọn pseudo-class khác. Bạn có thể tìm hiểu thêm ở trên mạng hoặc tại đây: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes

1.1.2       Bộ chọn phần tử giả (pseudo-element)

Trong CSS, không chỉ có bộ-chọn-lớp-giả (pseudo-class), mà nó còn có bộ-chọn-phần-tử-giả (pseudo-element). Bộ chọn pseudo-element không chọn các phần tử trong tài liệu HTML, cũng không chọn phần tử dựa vào trạng thái của nó, mà sẽ chọn các đối tượng “giả”, dựa vào vị trí hiển thị của các đối tượng trên cửa sổ trình duyệt. Có nhiều bộ chọn pseudo-element, phần này chúng ta sẽ tìm hiểu một số bộ chọn gồm: ::first-line, ::first-letter, ::before::after.

Bộ chọn ::first-line

Bộ chọn ::first-line được sử dụng để chọn hàng đầu tiên của một phần tử văn bản (khi văn bản hiển thị trên trình duyệt). Tuy nhiên, với bộ chọn này, chỉ có thể áp dụng được các thuộc tính sau,

color, font, background

word-spacing,  letter-spacing, text-decoration

vertical-align, text-transform, line-height

Ví dụ,

  p::first-line {

    color: red;

  }

Bộ chọn ::first-letter

Bộ chọn ::first-letter được sử dụng để chọn kí tự đầu tiên của một phần tử văn bản (khi văn bản hiển thị trên trình duyệt). Tuy nhiên, với bộ chọn này, chỉ có thể áp dụng được các thuộc tính sau,

color, font, text-decoration

text-transform, vertical-align, padding

background, margin, line-height

border, float, letter-spacing, word-spacing

Ví dụ, chúng ta sẽ làm nổi chữ cái đầu tiên của một đoạn (tạo drop cap):

[HTML]

    <p>Ví dụ, chúng ta sẽ làm nổi chữ cái đầu tiên của một đoạn </p>

[CSS]

    p::first-letter {

        color: white;

        background-color: #333;

        border-radius: 2px;

        font-size: 200%;

        box-shadow: 3px 3px 0 yellow;

        padding: 6px 3px;

        margin-right: 5px;

    }

Bộ chọn ::before

Bộ chọn ::before được sử dụng để chèn thêm nội dung vào trước một phần tử mà không cần chỉnh sửa mã nguồn HTML (cái này được gọi là thêm nội dung bằng CSS).

Ví dụ, đoạn mã CSS sau sẽ thêm cụm từ “Đọc thêm: ” vào trước phần tử p,

  p::before {

    content: "Đọc thêm: ";

    color: red;

    font-weight: bold;

  }

Bộ chọn ::after

Bộ chọn ::after được sử dụng để chèn thêm nội dung vào sau một phần tử mà không cần chỉnh sửa mã nguồn HTML (cái này được gọi là thêm nội dung bằng CSS).

Ví dụ, đoạn mã CSS sau sẽ thêm cụm từ “(Kết thúc)” vào sau phần tử p,

  p::after {

    content: "(Kết thúc)";

    color: red;

    font-weight: bold;

  }

1.1.3       Bộ chọn dựa vào thuộc tính

Chúng ta có thể tạo bộ chọn dựa vào tên và giá trị thuộc tính của phần tử. Cách làm này giúp tạo ra các bộ chọn rất linh hoạt mà không cần phải thêm thuộc tính class hoặc id vào các phần tử.

element[attribute]

Đây là bộ chọn đơn giản, nó sẽ chọn ra các phần tử với tên thuộc tính cụ thể, không quan tâm tới giá trị của thuộc tính.

Ví dụ, bộ chọn sau sẽ chọn ra tất cả các phần tử img, có thuộc tính title

img[title] {border: 3px solid;}

element[attribute=“giá trị”]

Bộ chọn này sẽ chọn ra các phần tử với tên và giá trị thuộc tính cụ thể. Vì giá trị có phân biệt chữ hoa/chữ thường nên cần xác định giá trị chính xác.

Ví dụ, bộ chọn sau sẽ chọn ra tất cả các phần tử img, có tên thuộc tính là title và giá trị là “con vịt”,

img[title="con vịt"] {border: 3px solid;}

element[attribute~=“giá trị”]

Bộ chọn này sẽ chọn ra các phần tử với tên thuộc tính và một phần giá trị của thuộc tính.

Ví dụ, bộ chọn sau sẽ chọn ra tất cả các phần tử img, mà trong giá trị thuộc tính title có chứa từ “con”, như vậy, các phần tử img với title có giá trị là “con gà” hay “ vịt con” đều được chọn.

img[title~="con"] {border: 3px solid;}

element[attribute|=“giá trị”]

Bộ chọn này sẽ chọn ra các phần tử với tên thuộc tính và giá trị thuộc tính sẽ bắt đầu bằng một từ cụ thể, sau đó là dấu gạch nối (hyphen) (-).

Ví dụ, bộ chọn sau sẽ chọn ra tất cả các phần tử img, mà trong giá trị thuộc tính title bắt đầu là từ “con”, sau đó là dấu (-), như vậy các phần tử img với title có giá trị là “con-gà” hay “con-vịt” đều được chọn.

img[title|="con"] {border: 3px solid;}

element[attribute^=“phần đầu của giá trị”]

Bộ chọn này sẽ chọn ra các phần tử, với tên thuộc tính và phần đầu của giá trị được xác định trước.

Ví dụ, bộ chọn sau sẽ chọn ra tất cả các phần tử img, mà trong giá trị thuộc tính src bắt đầu là chuỗi “/images/icons”.

img[src^="/images/icons"] {border: 3px solid;}

element[attribute$=“phần cuối của giá trị”]

Bộ chọn này sẽ chọn ra các phần tử, với tên thuộc tính và phần cuối của giá trị được xác định trước.

Ví dụ, bộ chọn sau sẽ chọn ra tất cả các phần tử img, mà trong giá trị thuộc tính src kết thúc là chuỗi “.jpg”.

img[src^=".jpg"] {border: 3px solid;}

element[attribute*=“một phần giá trị bất kì”]

Bộ chọn này sẽ chọn ra các phần tử, với tên thuộc tính và một phần bất kì trong giá trị thuộc tính.

Ví dụ, bộ chọn sau sẽ chọn ra tất cả các phần tử img, mà trong giá trị thuộc tính title có chứa chuỗi “on”. Như vậy các phần tử img với title có giá trị là “con-gà” hay “con-vịt” hay “anh-chon” đều được chọn.

img[title*="on"] {border: 3px solid;}

1.1.4       Xem và đọc thêm

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

– [2] Pseudo-class: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes

[3] Pseudo-element: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements

1.1.5       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. Làm một menu đơn giản như hình sau:


Khi rê chuột vào một mục của menu, nền của nó sẽ chuyển thành mà xám, chữ chuyển thành màu trắng.

Bạn có thể làm theo clip: https://www.youtube.com/watch?v=OXGznpKZ_sA&t=9151s. Hoặc dựa vào clip và tự làm một cái mới.

[Gợi ý làm bài tập]

[Bài tập 2]. Phần này chúng ta sẽ tự làm một menu.

– Tạo thư mục cho dự án (ví dụ menu)

– Trong thư mục menu, tạo thư mục css

Trong thư mục menu tạo 4 tập tin frontend.html, backend.htmldevops.html với nội dung bất kì và tập tin index.html.

– Trong thư mục css tạo tập tin style.css.

[index.html]

<!DOCTYPE html >

<html>

 

<head>

    <meta charset="utf-8">

    <title>Menu</title>

    <link rel="stylesheet" href="css/style.css">

<style>

 

</style>

</head>

<body>

    <nav>

        <h2>Học làm web</h2>

        <ul>

            <li><a href="frontend.html">Front-end</a></li>

            <li><a href="backend.html">Back-end</a></li>

            <li><a href="devops.html">Devops</a></li>

        </ul>

    </nav>

    <p>Để học thêm về làm web, mời bạn vào trang web của <a href="https://legiacong.blogspot.com">nhóm Langbiang</a></p>

</body>

</html>

 

[CSS]

/* sử dụng phông chữ Roboto của Google, vào trang font của Google, lấy đường dẫn về đây */

@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;1,400&display=swap');

/* thiết đặt CSS mặc định của trình duyệt về dạng chuẩn - reset CSS */

* {

    margin: 0;

    padding: 0;

    box-sizing: border-box;

}

 

body {

    margin: 0.5rem;

    font-family: Roboto, sans-serif;

    text-align: center;

}

 

nav {

    border: 2px solid #333;

    border-radius: 2rem;

    /* giới hạn chiều ngang của nav */

    max-width: 600px;

    /* căn giữa cái hộp nav */

    margin: 0 auto 1rem;

    font-size: 3rem;

    line-height: 7rem;

}

 

h2 {

    padding: 1rem;

    background-color: gold;

    /* bo 2 góc phía trên*/

    border-radius: 2rem 2rem 0 0;

}

 

ul {

    list-style-type: none;

}

 

li {

    border-top: 1px solid #333;

}

/* hiển thị mỗi mục menu là một khối để làm hiệu ứng cho đẹp */

li a {

    display: block;

}

li a,

li a:visited {

    text-decoration: none;

    color: #333;

}

 

li a:hover,

li a:focus {

    background: #333;

    color: whitesmoke;

    cursor: pointer;

}

 

/* bo 2 góc dưới cho mục cuối của menu */

li:last-child a{

    border-radius: 0 0 2rem 2rem;

}

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

Câu 1. A _______ is a selector that selects elements that are in a specific state, e.g. they are the first element of their type, or they are being hovered over by the mouse pointer.

A. pseudo-element

B. pseudo-class

C. id

D. class

Câu 2. In CSS, a _________ selector applies styles to parts of your document content in scenarios where there isn't a specific HTML element to select.

A. element

B. pseudo-class

C. id

D. pseudo-element

Câu 3. Ví dụ, mã nguồn HTML có nhiều phần tử img, trong đó có 2 phần tử img với title có giá trị lần lượt là “con gà” và “ vịt con”. Bạn chỉ muốn chọn ra 2 phần tử img này, vậy bạn sẽ sử dụng bộ chọn nào dưới đây:

A. img[title] {border: 3px solid;}

B. img[title~="con"] {border: 3px solid;}

C. img[title|="con"] {border: 3px solid;}

D. img[title="con"] {border: 3px solid;}

Câu 4. Ví dụ, mã nguồn HTML có nhiều phần tử img, trong đó có một số phần tử img có thuộc tính title. Bạn chỉ muốn chọn ra các phần tử img với thuộc tính title đi kèm (mà không quan tâm tới giá trị của thuộc tính), thì bạn sẽ sử dụng bộ chọn nào dưới đây:

A. img[title] {border: 3px solid;}

B. img[title~=*] {border: 3px solid;}

C. img[title|="*"] {border: 3px solid;}

D. img[title="*"] {border: 3px solid;}

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

-----

Cập nhật: 22/6/2023

-----

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