Bạn đã bao giờ muốn thêm một icon nhỏ, một hiệu ứng đặc biệt mà không muốn làm “bẩn” mã HTML của mình? Đó chính là lúc Pseudo-elements trong CSS phát huy sức mạnh. Đây không phải là ma thuật, mà là một kỹ thuật cực kỳ mạnh mẽ giúp bạn tạo kiểu cho những phần tử không thực sự tồn tại trong DOM. Trong bài viết này, WiWeb sẽ cùng bạn tìm hiểu từ A-Z về Pseudo-elements, đặc biệt là bộ đôi ::before và ::after.
Giới thiệu Pseudo-elements
Trong lĩnh vực thiết kế web, việc giữ cho mã HTML gọn gàng và có cấu trúc là cực kỳ quan trọng. Đây chính là lúc các pseudo-elements tỏa sáng, cho phép chúng ta thêm các yếu tố trang trí và chức năng mà không cần thêm thẻ HTML thừa thãi.
Pseudo-element là gì và tại sao chúng ta cần nó?
Hãy tưởng tượng pseudo-element như một “phần tử ảo” mà bạn có thể chèn vào trước hoặc sau nội dung của một phần tử đã có. Nó được tạo ra và định kiểu hoàn toàn bằng CSS. Nó không tồn tại trong cây DOM (Document Object Model), nghĩa là bạn không thể tương tác với nó bằng JavaScript như các phần tử HTML thông thường.
Lợi ích chính là sự linh hoạt và sạch sẽ. Thay vì thêm một thẻ <span> chỉ để chứa một icon, bạn có thể dùng ::before. Thay vì thêm một <div> chỉ để tạo lớp phủ màu, bạn có thể dùng ::after. Điều này giúp mã nguồn của bạn dễ đọc và bảo trì hơn rất nhiều.
Các ứng dụng thực tế phổ biến của Pseudo-elements
Sức mạnh của chúng không chỉ dừng lại ở lý thuyết. Dưới đây là một vài ứng dụng bạn có thể thấy hàng ngày:
- Thêm icon: Chèn các icon từ thư viện (như Font Awesome) vào trước các nút bấm hoặc liên kết.
- Tạo Tooltip: Hiển thị một hộp thông tin nhỏ khi người dùng di chuột qua một phần tử.
- Dấu ngoặc kép trang trí: Tạo kiểu cho các dấu ngoặc kép trong một trích dẫn (
<blockquote>) để chúng trông nổi bật và nghệ thuật hơn. - Hiệu ứng Overlay: Tạo một lớp phủ màu bán trong suốt lên trên hình ảnh khi di chuột.
- Đánh dấu đầu dòng tùy chỉnh: Thay thế các dấu chấm tròn mặc định của danh sách bằng hình ảnh hoặc ký tự bạn muốn.

Phân biệt Pseudo-elements và Pseudo-classes
Đây là một trong những điểm gây nhầm lẫn nhất cho người mới học CSS. Cả hai đều bắt đầu bằng dấu hai chấm, nhưng chức năng của chúng hoàn toàn khác nhau. Hãy cùng WiWeb làm rõ một lần và mãi mãi nhé.
Pseudo-classes (:hover, :focus): Tạo kiểu cho một trạng thái đặc biệt
Pseudo-classes dùng để định nghĩa một trạng thái đặc biệt của một phần tử. Bạn có thể hiểu đơn giản là nó trả lời cho câu hỏi “Khi nào?”. Phần tử sẽ có kiểu dáng đó khi một điều kiện nào đó xảy ra.
Ví dụ:
:hover: Khi người dùng di chuột qua phần tử.:focus: Khi người dùng nhấp vào hoặc dùng phím Tab để chọn một ô input.:first-child: Khi phần tử là con đầu tiên của một phần tử cha.
Pseudo-elements (::before, ::after): Tạo kiểu cho một phần của phần tử
Ngược lại, Pseudo-elements hoạt động như thể bạn đang thêm một phần tử con ảo vào bên trong phần tử được chọn. Nó trả lời cho câu hỏi “Phần nào?”. Nó cho phép bạn tạo kiểu cho một phần cụ thể của phần tử.
Ví dụ:
::before: Tạo một phần tử ảo trước nội dung của phần tử chính.::after: Tạo một phần tử ảo sau nội dung của phần tử chính.::first-letter: Chỉ định kiểu cho chữ cái đầu tiên của khối văn bản.
Bảng so sánh nhanh: Khi nào dùng loại nào?
| Tiêu chí | Pseudo-classes (Lớp giả) | Pseudo-elements (Phần tử giả) |
| Mục đích | Định kiểu cho một trạng thái | Định kiểu cho một phần của phần tử |
| Từ khóa | Khi nào? (Trạng thái) | Phần nào? (Bộ phận) |
| Ví dụ | :hover, :active, :nth-child | ::before, ::after, ::first-line |
| Cú pháp | Dấu hai chấm đơn (:) | Dấu hai chấm đôi (::) |
Một cách dễ nhớ: Pseudo-class giúp bạn tạo kiểu cho thứ đã có sẵn (một phần tử) trong một trạng thái khác. Pseudo-element giúp bạn tạo ra thứ gì đó mới (một phần tử ảo) để tạo kiểu.

Tìm hiểu Cú pháp: Dấu hai chấm đơn (:) so với Dấu hai chấm đôi (::)
Khi tìm hiểu về css pseudo-elements, bạn sẽ thấy cả hai cách viết : và ::. Điều này có thể hơi khó hiểu, nhưng lý do đằng sau nó khá đơn giản.
Cú pháp hiện đại với dấu hai chấm đôi (::)
Trong CSS3, W3C (tổ chức tiêu chuẩn web) đã quyết định tạo ra một sự phân biệt rõ ràng. Họ quy định rằng tất cả các pseudo-elements sẽ sử dụng cú pháp dấu hai chấm đôi (::).
Ví dụ đúng chuẩn hiện đại:
p::before {
content: 'Hi! ';
}
p::first-letter {
font-size: 200%;
}
Sự thay đổi này giúp các nhà phát triển dễ dàng phân biệt ngay lập tức giữa một pseudo-class (:hover) và một pseudo-element (::before).
Lý do dấu hai chấm đơn (:) vẫn còn tồn tại
Vậy tại sao bạn vẫn thấy cú pháp dấu hai chấm đơn (:) được sử dụng cho ::before và ::after? Câu trả lời là khả năng tương thích ngược.
Các phiên bản trình duyệt cũ, đặc biệt là Internet Explorer 8, không hiểu cú pháp dấu hai chấm đôi. Để đảm bảo các trang web cũ vẫn hiển thị đúng, các trình duyệt hiện đại vẫn chấp nhận cú pháp dấu hai chấm đơn cho các pseudo-elements đã có từ thời CSS2 (như :before, :after, :first-letter, :first-line).
Lời khuyên từ WiWeb:
- Với các dự án mới, bạn luôn nên sử dụng cú pháp
::cho pseudo-elements. - Nếu bạn cần hỗ trợ các trình duyệt rất cũ, bạn có thể sử dụng
:cho::beforevà::after.

Khám phá các Pseudo-elements phổ biến nhất (Kèm ví dụ Code)
Bây giờ, hãy cùng đi sâu vào các pseudo-elements examples mà bạn sẽ sử dụng thường xuyên nhất trong công việc hàng ngày. Chúng tôi sẽ cung cấp mã nguồn để bạn dễ hình dung.
::before và ::after: Bộ đôi mạnh mẽ nhất
Đây là hai pseudo-elements linh hoạt và được sử dụng nhiều nhất. Chúng chèn một phần tử ảo vào bên trong phần tử được chọn, nhưng nằm trước (::before) hoặc sau (::after) nội dung chính của nó. Chúng thường được dùng để thêm các yếu tố trang trí, icon, hoặc tạo hình khối phức tạp.
Thuộc tính ‘content’ là gì và tại sao nó bắt buộc?
Một điểm quan trọng không thể bỏ qua: ::before và ::after sẽ không hiển thị nếu bạn không khai báo thuộc tính content. Đây là quy tắc bắt buộc của pseudo-element content property.
Ngay cả khi bạn chỉ muốn tạo một hình dạng trang trí và không cần nội dung văn bản, bạn vẫn phải khai báo content: ''; (một chuỗi rỗng). Nếu thiếu dòng này, pseudo-element sẽ không được render.
.box::before {
content: '★'; /* Bắt buộc phải có content */
color: gold;
margin-right: 5px;
}
::first-line: Định dạng dòng văn bản đầu tiên
Đúng như tên gọi, ::first-line cho phép bạn áp dụng các kiểu CSS riêng cho dòng đầu tiên của một khối văn bản. Rất hữu ích để tạo điểm nhấn cho phần giới thiệu.
p::first-line {
font-weight: bold;
color: #2c3e50;
}
::first-letter: Tạo hiệu ứng Drop Cap cho chữ cái đầu
::first-letter chọn chữ cái đầu tiên của một khối văn bản. Nó thường được dùng để tạo hiệu ứng “drop cap” cổ điển, làm cho chữ cái đầu tiên lớn hơn và nổi bật.
article p::first-letter {
font-size: 3em; /* Phóng to chữ cái đầu */
font-family: 'Times New Roman', serif;
float: left;
margin-right: 8px;
line-height: 1;
}
::marker: Tùy chỉnh dấu đầu dòng (bullets & numbers)
Trước đây, việc tạo kiểu cho các dấu đầu dòng của thẻ <li> khá phức tạp. Nhưng với ::marker pseudo-element, mọi thứ trở nên đơn giản hơn rất nhiều. Bạn có thể dễ dàng thay đổi màu sắc, kích thước, hoặc thậm chí là nội dung của chúng.
li::marker {
color: #3498db;
font-size: 1.2em;
content: '✓ ';
}
::selection: Thay đổi kiểu khi người dùng bôi đen văn bản
::selection cho phép bạn tùy chỉnh giao diện của phần văn bản khi người dùng chọn (bôi đen) nó. Đây là một cách tinh tế để thêm dấu ấn thương hiệu và cải thiện trải nghiệm người dùng.
::selection {
background-color: #f1c40f;
color: #2c3e50;
}

Ứng dụng Pseudo-elements vào thực tế: Từ cơ bản đến nâng cao
Lý thuyết là vậy, nhưng sức mạnh thực sự của css pseudo-elements chỉ bộc lộ qua các ví dụ thực tế. Hãy cùng WiWeb xem qua một vài ứng dụng sáng tạo.
Ví dụ 1: Thêm icon vào trước các liên kết
Thay vì thêm thẻ <i> vào HTML, chúng ta có thể dùng ::before để chèn icon từ một font-icon hoặc ký tự Unicode.
<a href="#" class="link-external">Visit WiWeb</a>
.link-external::after {
content: ' ↗'; /* Thêm icon mũi tên */
font-size: 0.8em;
display: inline-block;
}
Ví dụ 2: Tạo Tooltip đơn giản với CSS
Chúng ta có thể dùng thuộc tính data-* trong HTML để lưu nội dung tooltip và hiển thị nó bằng ::after khi người dùng di chuột qua.
<button class="tooltip" data-tooltip="Click để lưu!">Lưu</button>
.tooltip {
position: relative;
}
.tooltip:hover::after {
content: attr(data-tooltip); /* Lấy nội dung từ thuộc tính data-tooltip */
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: white;
padding: 5px 10px;
border-radius: 4px;
white-space: nowrap;
margin-bottom: 5px;
}
Ví dụ 3: Tạo các dấu ngoặc kép trang trí (Custom Quotes)
Sử dụng cả ::before và ::after để tạo kiểu cho dấu ngoặc kép của một khối trích dẫn.
<blockquote class="custom-quote">Sáng tạo là trí thông minh đang vui đùa.</blockquote>
.custom-quote {
font-style: italic;
color: #555;
}
.custom-quote::before {
content: '“';
font-size: 4em;
color: #ccc;
position: absolute;
left: -10px;
top: -20px;
}
.custom-quote::after {
content: '”';
/* Tương tự ::before */
}
Ví dụ 4: Tạo lớp phủ (overlay) cho hình ảnh
Đây là một hiệu ứng rất phổ biến. Chúng ta có thể tạo một lớp phủ màu bán trong suốt lên ảnh khi người dùng di chuột qua.
<div class="image-container">
<img src="your-image.jpg" alt="An image">
</div>
.image-container {
position: relative;
display: inline-block;
}
.image-container:hover::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Lớp phủ màu đen 50% */
transition: background-color 0.3s;
}

Lời kết
Qua hướng dẫn toàn tập này, WiWeb hy vọng bạn đã nắm vững sức mạnh của Pseudo-elements. Chúng là công cụ tuyệt vời để giữ cho mã HTML của bạn tinh gọn trong khi vẫn tạo ra những giao diện phức tạp và đẹp mắt.
Hãy nhớ những điểm cốt lõi sau:
- Pseudo-elements tạo ra các “phần tử ảo” để tạo kiểu cho một phần của phần tử.
- Chúng khác với Pseudo-classes, vốn dùng để định nghĩa một trạng thái.
- Hãy luôn dùng cú pháp dấu hai chấm đôi (
::) cho các dự án mới. - Bộ đôi
::beforevà::aftercực kỳ mạnh mẽ nhưng luôn cần thuộc tínhcontentđể hoạt động.
Bạn đã dùng Pseudo-elements cho dự án nào của mình chưa? Hãy chia sẻ ứng dụng sáng tạo của bạn ở phần bình luận bên dưới nhé!
Nếu bạn cần một website chuyên nghiệp để ứng dụng những kỹ thuật CSS hiện đại này, WiWeb luôn sẵn sàng tư vấn. Liên hệ với chúng tôi ngay!


Cho mình hỏi một chút về performance với ạ, nếu trên trang dùng nhiều `::before`/`::after` để trang trí thì có ảnh hưởng nhiều đến tốc độ tải trang không so với việc thêm thẻ `` thật vào HTML ạ?
Câu hỏi của bạn rất hay! Thực tế, dùng `::before`/`::after` thường còn tốt hơn cho hiệu năng nữa ạ, vì chúng không thêm phần tử thật vào HTML, giúp cây DOM gọn nhẹ và trình duyệt xử lý nhanh hơn so với việc dùng nhiều thẻ ``.