Tổng hợp đầy đủ kiến thức CSS từ cơ bản đến nâng cao

CSS là nền tảng quyết định cách một trang web được trình bày trên màn hình. Nếu HTML chịu trách nhiệm xây dựng cấu trúc nội dung thì CSS đảm nhận phần giao diện: màu sắc, kích thước, khoảng cách, bố cục, kiểu chữ, hiệu ứng, khả năng thích ứng với nhiều thiết bị và cả những tương tác trực quan phức tạp.

Tuy nhiên, học CSS không đơn giản là ghi nhớ hàng trăm thuộc tính. Phần khó của CSS nằm ở việc hiểu trình duyệt tính toán kiểu dáng như thế nào, các selector tác động ra sao, kích thước được xác định theo quy tắc nào, phần tử tham gia bố cục theo cơ chế gì và tại sao một đoạn CSS tưởng như đúng lại không hoạt động như mong muốn.

Tài liệu này tổng hợp CSS theo một lộ trình từ cơ bản đến nâng cao. Thay vì liệt kê thuộc tính một cách rời rạc, nội dung tập trung vào mối quan hệ giữa các khái niệm để bạn có thể áp dụng CSS vào website thực tế, đồng thời hiểu được cách xử lý những vấn đề thường gặp khi giao diện ngày càng phức tạp.

Tổng hợp đầy đủ kiến thức CSS từ cơ bản đến nâng cao
Tổng hợp đầy đủ kiến thức CSS từ cơ bản đến nâng cao

CSS là gì và CSS có vai trò gì trong website?

CSS là viết tắt của Cascading Style Sheets, một ngôn ngữ dùng để mô tả cách các phần tử HTML được hiển thị. CSS không tạo ra nội dung của trang mà định nghĩa cách nội dung đó xuất hiện.

Ví dụ, HTML có thể tạo một tiêu đề:

<h2>Học CSS</h2>

CSS có thể quyết định tiêu đề đó có màu gì, cỡ chữ bao nhiêu, khoảng cách phía trên và phía dưới ra sao:

h2 {
    color: #222;
    font-size: 28px;
    margin-bottom: 16px;
}

Cách phân chia này giúp nội dung và phần trình bày không bị trộn lẫn. Một cấu trúc HTML có thể được sử dụng với nhiều thiết kế khác nhau chỉ bằng cách thay đổi CSS.

CSS khác HTML và JavaScript như thế nào?

Ba công nghệ thường xuất hiện cùng nhau nhưng có nhiệm vụ khác nhau:

  • HTML: xác định cấu trúc và ý nghĩa của nội dung.
  • CSS: quyết định cách nội dung được trình bày.
  • JavaScript: xử lý hành vi, logic và tương tác động.

Có thể hình dung một trang web như một công trình: HTML tạo nên cấu trúc, CSS hoàn thiện hình thức và JavaScript giúp công trình phản ứng với hành động của người dùng.

Cú pháp CSS và cách một quy tắc CSS hoạt động

Một quy tắc CSS cơ bản gồm selector và một hoặc nhiều declaration:

p {
    color: #333;
    line-height: 1.7;
}

Trong ví dụ trên, p là selector. Hai dòng bên trong là các declaration. Mỗi declaration gồm property và value.

  • Selector: xác định phần tử cần áp dụng.
  • Property: thuộc tính muốn thay đổi.
  • Value: giá trị của thuộc tính.

CSS phân biệt chữ hoa và chữ thường trong nhiều thành phần nhất định, vì vậy nên duy trì cách viết nhất quán, đặc biệt với tên class và custom property.

Comment trong CSS

Comment được viết giữa /**/:

/* Thiết lập kiểu chữ cho nội dung */
.content {
    font-size: 16px;
}

Comment không được trình duyệt áp dụng như một quy tắc CSS. Chúng hữu ích khi tổ chức những stylesheet lớn.

Các cách đưa CSS vào HTML

Có ba cách phổ biến để sử dụng CSS.

Inline CSS

<p style="color: red;">Nội dung</p>

Cách này phù hợp với một số trường hợp đặc biệt nhưng không nên dùng làm phương pháp chính cho toàn bộ website vì CSS nhanh chóng trở nên khó quản lý.

Internal CSS

<style>
    p {
        color: #333;
    }
</style>

CSS được đặt trong phần của tài liệu HTML. Cách này phù hợp với những trang đơn lẻ hoặc trường hợp cần style cục bộ.

External CSS

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

Đây thường là phương án tốt nhất đối với website thực tế. CSS được tách khỏi HTML, dễ tái sử dụng, bảo trì và tổ chức thành các phần riêng biệt.

CSS Selectors: nền tảng quan trọng nhất khi làm CSS

Selector quyết định phần tử nào nhận một quy tắc CSS. Hiểu selector tốt sẽ giúp giảm rất nhiều tình trạng phải dùng CSS phức tạp để sửa những vấn đề vốn có thể giải quyết ngay từ đầu.

Element selector

p {
    color: #333;
}

Selector này tác động đến tất cả phần tử p.

Class selector

.button {
    padding: 10px 18px;
}

Class selector bắt đầu bằng dấu chấm và thường là loại selector được sử dụng nhiều nhất trong giao diện.

ID selector

#header {
    min-height: 70px;
}

ID có tính đặc thù cao và thường dành cho một phần tử có định danh duy nhất. Trong hệ thống CSS lớn, class thường được ưu tiên hơn ID để giảm độ đặc hiệu không cần thiết.

Universal selector

* {
    box-sizing: border-box;
}

Selector * chọn mọi phần tử phù hợp với phạm vi áp dụng.

Attribute selector

input[type="email"] {
    border-color: #999;
}

Attribute selector cho phép chọn phần tử dựa trên thuộc tính HTML.

Selector kết hợp

CSS hỗ trợ nhiều kiểu kết hợp selector:

.menu a {
    text-decoration: none;
}

.menu > a {
    font-weight: 600;
}

h2 + p {
    margin-top: 0;
}

h2 ~ p {
    color: #555;
}

Khoảng trắng biểu thị quan hệ hậu duệ, > biểu thị phần tử con trực tiếp, + chọn phần tử ngay sau và ~ chọn các phần tử anh em đứng sau cùng cấp.

Selector giả và pseudo-elements

Pseudo-class và pseudo-element mở rộng khả năng chọn phần tử mà không cần thêm class cho mọi trạng thái hoặc nội dung trang trí.

Pseudo-class

a:hover {
    text-decoration: underline;
}

input:focus {
    outline: 2px solid currentColor;
}

li:first-child {
    font-weight: 600;
}

Một số pseudo-class thường gặp gồm :hover, :focus, :active, :visited, :checked, :disabled, :first-child, :last-child, :nth-child():not().

Pseudo-element

.title::before {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    margin-right: 8px;
    border-radius: 50%;
}

Pseudo-element thường dùng để tạo thành phần trang trí hoặc thao tác với một phần nội dung mà không cần thêm HTML.

Các pseudo-element phổ biến gồm ::before, ::after, ::first-letter, ::first-line::selection.

CSS Cascade, Specificity và thứ tự ưu tiên

Đây là một trong những phần quan trọng nhất của CSS nâng cao. Khi nhiều quy tắc cùng tác động lên một phần tử, trình duyệt phải xác định quy tắc nào được ưu tiên.

Không nên hiểu đơn giản rằng “CSS viết sau sẽ luôn thắng CSS viết trước”. Kết quả còn phụ thuộc vào nguồn CSS, cascade layer, specificity, thứ tự xuất hiện và các quy tắc đặc biệt như !important.

Specificity

Về cơ bản, selector có độ đặc hiệu cao hơn thường có ưu tiên cao hơn selector có độ đặc hiệu thấp hơn.

Có thể hình dung thứ tự tổng quát từ thấp đến cao như sau:

  • Universal selector và selector phần tử.
  • Class, attribute và pseudo-class.
  • ID selector.
  • Inline style.

Thay vì liên tục tăng specificity để “đè” CSS cũ, cách tốt hơn là xây dựng hệ thống class và cấu trúc stylesheet có tính nhất quán.

!important

.button {
    color: red !important;
}

!important có thể thay đổi thứ tự ưu tiên của declaration nhưng không nên được sử dụng như cách sửa lỗi mặc định. Lạm dụng nó thường dẫn đến một stylesheet khó kiểm soát.

Cascade layers

CSS hiện đại cung cấp @layer để kiểm soát thứ tự ưu tiên giữa các nhóm CSS:

@layer reset, base, components, utilities;

@layer base {
    body {
        margin: 0;
    }
}

@layer components {
    .button {
        padding: 10px 16px;
    }
}

Đây là công cụ hữu ích khi dự án có nhiều nguồn CSS hoặc sử dụng hệ thống component lớn.

Inheritance: thuộc tính CSS có được kế thừa hay không?

Một số thuộc tính CSS có thể được phần tử con kế thừa từ phần tử cha. Màu chữ và font là những ví dụ điển hình.

body {
    color: #222;
    font-family: Arial, sans-serif;
}

Những phần tử nằm bên trong body có thể nhận các giá trị này nếu không có quy tắc riêng ghi đè.

Có thể điều khiển inheritance bằng các giá trị như inherit, initial, unsetrevert.

CSS Box Model

Box Model là khái niệm bắt buộc phải hiểu nếu muốn kiểm soát kích thước và khoảng cách chính xác.

Mỗi phần tử có thể được nhìn nhận qua các lớp:

  • Content: vùng nội dung.
  • Padding: khoảng cách giữa nội dung và border.
  • Border: đường viền.
  • Margin: khoảng cách bên ngoài phần tử.

box-sizing

Thiết lập phổ biến:

*,
*::before,
*::after {
    box-sizing: border-box;
}

Với border-box, giá trị widthheight bao gồm content, padding và border. Điều này thường giúp việc tính toán kích thước dễ dự đoán hơn.

Margin collapse

Margin dọc giữa một số phần tử block có thể xảy ra hiện tượng gộp margin thay vì cộng trực tiếp hai giá trị. Đây là một nguyên nhân phổ biến khiến người mới học CSS cảm thấy khoảng cách hiển thị “không đúng với phép tính”.

Không nên cố xử lý mọi trường hợp bằng cách cộng hoặc trừ margin. Khi cần tạo khoảng cách trong một layout, gap hoặc padding của container thường tạo ra kết quả dễ kiểm soát hơn.

Đơn vị trong CSS

CSS có nhiều loại đơn vị và việc lựa chọn đơn vị phù hợp ảnh hưởng trực tiếp đến khả năng responsive.

Đơn vị tuyệt đối

px thường được sử dụng khi cần giá trị tương đối ổn định và dễ kiểm soát.

Đơn vị tương đối

  • %: phụ thuộc vào một giá trị tham chiếu.
  • em: thường phụ thuộc vào kích thước font của phần tử hoặc ngữ cảnh liên quan.
  • rem: dựa trên kích thước font của phần tử gốc.
  • vw: phần trăm chiều rộng viewport.
  • vh: phần trăm chiều cao viewport.
  • vminvmax: dựa trên kích thước nhỏ hơn hoặc lớn hơn của viewport.

Min, max và clamp

CSS hiện đại cho phép xây dựng kích thước linh hoạt mà không cần quá nhiều breakpoint:

.title {
    font-size: clamp(24px, 4vw, 48px);
}

clamp() nhận giá trị tối thiểu, giá trị linh hoạt và giá trị tối đa. Đây là một trong những hàm rất hữu ích khi xây dựng giao diện responsive.

Màu sắc trong CSS

CSS hỗ trợ nhiều cách biểu diễn màu:

.box {
    color: red;
    color: #d3801f;
    color: rgb(211 128 31);
    color: rgba(211, 128, 31, 0.8);
    color: hsl(31 74% 47%);
}

Ngoài màu đơn sắc, CSS còn hỗ trợ gradient và nhiều hệ màu hiện đại hơn.

Gradient

.banner {
    background: linear-gradient(135deg, #222, #555);
}

Gradient có thể được sử dụng cho nền, lớp phủ hình ảnh, nút bấm và nhiều thành phần giao diện khác.

Typography trong CSS

Typography ảnh hưởng rất lớn đến khả năng đọc và cảm nhận chất lượng của website.

Các thuộc tính quan trọng gồm:

  • font-family
  • font-size
  • font-weight
  • line-height
  • letter-spacing
  • text-align
  • text-transform
  • text-decoration
  • white-space
  • word-break
  • overflow-wrap

line-height

Khoảng cách dòng ảnh hưởng trực tiếp đến khả năng đọc. Với văn bản dài, một giá trị line-height phù hợp thường quan trọng hơn việc chỉ tăng kích thước font.

body {
    font-size: 16px;
    line-height: 1.7;
}

Font fallback

Không nên phụ thuộc vào duy nhất một font. Có thể cung cấp chuỗi fallback:

body {
    font-family: "Inter", Arial, sans-serif;
}

Nếu font đầu tiên không khả dụng, trình duyệt sẽ thử font tiếp theo.

Display và cách phần tử tham gia bố cục

Thuộc tính display quyết định mô hình hiển thị của phần tử.

Một số giá trị quan trọng:

  • block
  • inline
  • inline-block
  • flex
  • grid
  • none
  • contents

Hiểu sự khác nhau giữa block và inline là nền tảng để giải thích nhiều hành vi CSS tưởng như bất thường.

Position và hệ tọa độ của phần tử

position được sử dụng để thay đổi cách phần tử được định vị.

  • static: trạng thái mặc định.
  • relative: vẫn giữ vị trí trong flow nhưng tạo cơ sở định vị cho phần tử con.
  • absolute: phần tử được định vị tương đối với containing block thích hợp.
  • fixed: thường được định vị theo viewport.
  • sticky: kết hợp hành vi trong flow với cơ chế bám theo ngưỡng cuộn.

relative và absolute

.card {
    position: relative;
}

.badge {
    position: absolute;
    top: 12px;
    right: 12px;
}

Đây là mô hình rất phổ biến để đặt badge, nút đóng, biểu tượng hoặc lớp phủ bên trong một component.

Flexbox

Flexbox là hệ thống layout một chiều, rất phù hợp để sắp xếp các phần tử theo hàng hoặc cột.

Container của Flexbox

.menu {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 20px;
}

Các thuộc tính quan trọng của flex container gồm:

  • flex-direction
  • flex-wrap
  • justify-content
  • align-items
  • align-content
  • gap

Flex item

Các thuộc tính quan trọng của phần tử con gồm:

  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self
  • order

Ví dụ:

.sidebar {
    flex: 0 0 280px;
}

.main {
    flex: 1;
}

Trong layout hai cột, sidebar có thể giữ chiều rộng cố định trong khi phần nội dung chính chiếm phần không gian còn lại.

CSS Grid

Grid phù hợp với những bố cục cần kiểm soát đồng thời hàng và cột. Nếu Flexbox thường giải quyết tốt layout một chiều thì Grid đặc biệt mạnh khi giao diện có cấu trúc hai chiều.

Tạo Grid cơ bản

.products {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
}

fr đại diện cho một phần không gian còn lại trong grid container.

Grid responsive

.products {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 20px;
}

Cách này cho phép số lượng cột thay đổi theo không gian mà không nhất thiết phải tạo một media query cho từng kích thước màn hình.

Các thuộc tính Grid quan trọng

  • grid-template-columns
  • grid-template-rows
  • grid-template-areas
  • grid-column
  • grid-row
  • gap
  • place-items
  • place-content
  • justify-items
  • align-items

Responsive Web Design

Responsive không chỉ là làm cho website “co lại” trên điện thoại. Một giao diện responsive tốt phải thích ứng với không gian, cách tương tác và điều kiện hiển thị khác nhau.

Viewport

Website cần khai báo viewport phù hợp trong HTML:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Media query

@media (max-width: 768px) {
    .layout {
        grid-template-columns: 1fr;
    }
}

Media query cho phép thay đổi CSS dựa trên điều kiện môi trường hiển thị.

Mobile-first

Mobile-first nghĩa là xây dựng giao diện cơ bản cho màn hình nhỏ trước, sau đó mở rộng khi có thêm không gian:

.layout {
    display: block;
}

@media (min-width: 768px) {
    .layout {
        display: grid;
        grid-template-columns: 280px 1fr;
    }
}

Cách tiếp cận này thường giúp stylesheet dễ tổ chức hơn vì các breakpoint chủ yếu dùng để bổ sung khả năng thay vì liên tục ghi đè thiết kế ban đầu.

Overflow và xử lý nội dung vượt quá kích thước

Khi nội dung lớn hơn vùng chứa, overflow quyết định cách trình duyệt xử lý phần vượt ra ngoài.

.box {
    overflow: hidden;
}

Các giá trị phổ biến gồm visible, hidden, autoscroll.

Đối với văn bản dài hoặc URL không có khoảng trắng, có thể cần kết hợp overflow-wrap, word-break hoặc các kỹ thuật giới hạn dòng.

Background và hình ảnh nền

CSS hỗ trợ nhiều thuộc tính liên quan đến nền:

  • background-color
  • background-image
  • background-position
  • background-size
  • background-repeat
  • background-attachment

Một cấu hình phổ biến:

.hero {
    background-image: url("hero.jpg");
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}

cover giúp hình ảnh phủ kín vùng chứa nhưng có thể làm mất một phần hình ảnh. Vì vậy, việc lựa chọn ảnh phù hợp và kiểm soát vị trí hiển thị vẫn rất quan trọng.

Border, border-radius và box-shadow

Đây là nhóm thuộc tính thường dùng để xây dựng card, button, input và các thành phần giao diện.

.card {
    border: 1px solid #ddd;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgb(0 0 0 / 8%);
}

Không nên lạm dụng shadow hoặc border-radius. Thiết kế tốt không đến từ việc thêm thật nhiều hiệu ứng mà đến từ sự nhất quán và đúng mục đích.

Opacity, visibility và display none khác nhau thế nào?

Ba cách ẩn phần tử thường bị nhầm lẫn:

  • display: none: phần tử không tham gia layout.
  • visibility: hidden: phần tử vẫn chiếm không gian nhưng không hiển thị.
  • opacity: 0: phần tử trở nên trong suốt nhưng về cơ bản vẫn tồn tại trong layout và có thể tiếp tục tương tác tùy trường hợp.

Vì vậy, lựa chọn cách ẩn phải dựa trên mục đích thực tế thay vì chỉ nhìn thấy kết quả trên màn hình.

Transform trong CSS

transform cho phép dịch chuyển, xoay, phóng to, thu nhỏ hoặc biến dạng phần tử.

.card:hover {
    transform: translateY(-4px);
}

Các hàm thường gặp gồm:

  • translate()
  • translateX()
  • translateY()
  • scale()
  • rotate()
  • skew()

Transition và Animation

Transition

Transition phù hợp với những thay đổi xảy ra từ một trạng thái sang trạng thái khác:

.button {
    background: #222;
    transition: background 0.2s ease, transform 0.2s ease;
}

.button:hover {
    background: #444;
    transform: translateY(-2px);
}

Animation

Animation phù hợp với chuỗi trạng thái được mô tả bằng keyframes:

@keyframes fade-in {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.box {
    animation: fade-in 0.5s ease;
}

Khi tạo animation, cần cân nhắc hiệu năng và khả năng tiếp cận. Những chuyển động quá mạnh hoặc quá nhiều có thể khiến giao diện khó sử dụng.

prefers-reduced-motion

Một số người dùng thiết bị được cấu hình giảm chuyển động. CSS có thể tôn trọng thiết lập này:

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms;
        animation-iteration-count: 1;
        transition-duration: 0.01ms;
        scroll-behavior: auto;
    }
}

Đây là một ví dụ cho thấy CSS hiện đại không chỉ tập trung vào hình thức mà còn liên quan đến khả năng tiếp cận.

CSS Variables và Custom Properties

Custom properties giúp lưu trữ những giá trị có thể tái sử dụng:

:root {
    --primary-color: #d3801f;
    --text-color: #222;
    --radius: 10px;
    --container-width: 1200px;
}

.button {
    color: white;
    background: var(--primary-color);
    border-radius: var(--radius);
}

Đây là nền tảng quan trọng để xây dựng design system và quản lý giao diện lớn.

Giá trị dự phòng với var()

.title {
    color: var(--heading-color, #222);
}

Nếu custom property không tồn tại, CSS sẽ sử dụng giá trị dự phòng.

calc(), min(), max() và clamp()

CSS hiện đại có khả năng thực hiện các phép tính trực tiếp:

.container {
    width: calc(100% - 32px);
}

.sidebar {
    width: min(320px, 100%);
}

.content {
    width: max(300px, 40%);
}

.title {
    font-size: clamp(24px, 4vw, 48px);
}

Những hàm này giúp xây dựng layout linh hoạt hơn và giảm nhu cầu sử dụng quá nhiều breakpoint.

Logical Properties trong CSS

CSS truyền thống thường sử dụng left, right, topbottom. Logical properties cho phép mô tả theo hướng viết và trục logic của nội dung.

.box {
    margin-inline: auto;
    padding-inline: 20px;
    padding-block: 16px;
}

Cách viết này đặc biệt hữu ích khi xây dựng giao diện hỗ trợ nhiều hướng viết hoặc muốn CSS có tính linh hoạt cao hơn.

Container Queries

Media query thường dựa vào kích thước viewport. Container query cho phép component phản ứng dựa trên kích thước container chứa nó.

.card-wrapper {
    container-type: inline-size;
}

@container (min-width: 600px) {
    .card {
        display: grid;
        grid-template-columns: 180px 1fr;
    }
}

Đây là bước tiến quan trọng đối với kiến trúc component. Một component có thể tự thích ứng với nơi nó được đặt thay vì phải biết toàn bộ kích thước màn hình.

CSS Nesting

CSS hiện đại hỗ trợ nesting giúp nhóm các quy tắc liên quan:

.card {
    padding: 20px;

    & .title {
        font-size: 20px;
    }

    &:hover {
        transform: translateY(-2px);
    }
}

Nesting có thể giúp stylesheet dễ đọc hơn, nhưng vẫn nên giữ cấu trúc selector đơn giản. Nesting quá sâu có thể khiến specificity và khả năng bảo trì trở nên khó kiểm soát.

CSS Functions nâng cao

Ngoài những hàm quen thuộc, CSS ngày càng cung cấp nhiều hàm mạnh hơn cho các giao diện phức tạp.

attr()

attr() có thể lấy giá trị từ attribute của phần tử trong một số ngữ cảnh CSS được hỗ trợ.

color-mix()

color-mix() cho phép tạo màu mới bằng cách phối trộn các màu trong một color space:

.button:hover {
    background: color-mix(in srgb, #d3801f 85%, black);
}

CSS math functions

Các hàm như calc(), min(), max()clamp() có thể kết hợp với nhau để xây dựng kích thước thích ứng rất linh hoạt.

Aspect Ratio

aspect-ratio giúp giữ tỷ lệ của một phần tử mà không cần tự tính chiều cao.

.thumbnail {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

Đây là kỹ thuật hữu ích cho ảnh, video, thumbnail và các component cần tỷ lệ ổn định.

Object-fit và Object-position

Đối với ảnh hoặc video nằm trong một vùng có kích thước xác định:

.image {
    width: 100%;
    height: 300px;
    object-fit: cover;
    object-position: center;
}

cover giúp nội dung phủ kín vùng chứa, trong khi contain giữ toàn bộ nội dung nhưng có thể xuất hiện khoảng trống.

Z-index và Stacking Context

z-index thường được dùng để kiểm soát phần tử nào nằm trên phần tử nào:

.modal {
    position: fixed;
    z-index: 1000;
}

Tuy nhiên, z-index không hoạt động đơn giản như một “con số càng lớn càng nằm trên”. Stacking context có thể tạo ra phạm vi xếp lớp riêng. Một phần tử có z-index: 999999 vẫn có thể nằm dưới phần tử khác nếu nó thuộc stacking context thấp hơn trong cây hiển thị.

Đây là nguyên nhân phổ biến của những lỗi như menu có z-index rất lớn nhưng vẫn bị một thành phần khác che khuất.

Containing Block và cách trình duyệt định vị phần tử

Đối với các phần tử position: absolute, việc xác định “cha tham chiếu” là rất quan trọng. Không phải lúc nào phần tử cũng được định vị trực tiếp theo viewport.

Đó là lý do mô hình:

.parent {
    position: relative;
}

.child {
    position: absolute;
    top: 0;
    right: 0;
}

thường được sử dụng khi muốn đặt phần tử con ở một vị trí xác định bên trong component cha.

CSS Subgrid

subgrid cho phép một grid con sử dụng track của grid cha thay vì tạo một hệ thống track hoàn toàn độc lập.

.layout {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.card-list {
    display: grid;
    grid-template-columns: subgrid;
}

Subgrid đặc biệt hữu ích khi nhiều component cần căn chỉnh theo cùng một hệ thống hàng hoặc cột.

CSS cho Form và trạng thái tương tác

Form cần được thiết kế không chỉ dựa trên trạng thái bình thường mà còn phải thể hiện rõ khi người dùng đang tương tác hoặc nhập dữ liệu không hợp lệ.

input {
    border: 1px solid #ccc;
}

input:focus {
    outline: 2px solid #222;
    outline-offset: 2px;
}

input:disabled {
    opacity: 0.6;
}

input:invalid {
    border-color: #c00;
}

Không nên xóa hoàn toàn outline khi focus nếu không thay thế bằng một cơ chế hiển thị focus đủ rõ.

CSS Accessibility

CSS có ảnh hưởng trực tiếp đến khả năng tiếp cận website. Một giao diện đẹp nhưng khó đọc, thiếu trạng thái focus hoặc phụ thuộc hoàn toàn vào màu sắc vẫn là một giao diện có vấn đề.

Một số nguyên tắc quan trọng:

  • Đảm bảo độ tương phản phù hợp giữa chữ và nền.
  • Không dùng màu sắc là tín hiệu duy nhất để truyền tải thông tin.
  • Giữ trạng thái focus dễ nhận biết.
  • Cho phép nội dung phóng to mà không bị phá vỡ nghiêm trọng.
  • Tôn trọng prefers-reduced-motion.
  • Không khóa kích thước văn bản theo cách khiến người dùng khó điều chỉnh.

CSS Reset và Normalize

Các trình duyệt có stylesheet mặc định cho nhiều phần tử HTML. Vì vậy, cùng một HTML có thể bắt đầu với một số margin, padding hoặc kiểu hiển thị mặc định.

Một reset tối giản có thể bắt đầu như sau:

*,
*::before,
*::after {
    box-sizing: border-box;
}

html,
body {
    margin: 0;
    padding: 0;
}

Không nhất thiết phải xóa mọi style mặc định. Reset nên phục vụ kiến trúc giao diện thay vì trở thành một danh sách khổng lồ khó hiểu.

Thiết kế hệ thống CSS dễ bảo trì

Khi dự án nhỏ, CSS có thể được viết khá tự do. Nhưng khi website có hàng trăm component, vấn đề lớn nhất không còn là “viết được CSS” mà là duy trì được CSS.

Đặt tên class có quy ước

Một hệ thống tên rõ ràng giúp giảm phụ thuộc vào cấu trúc HTML:

.card {}
.card__title {}
.card__content {}
.card--featured {}

Đây là một cách tiếp cận tương tự tư duy BEM. Không nhất thiết phải sử dụng BEM tuyệt đối, nhưng ý tưởng quan trọng là tên class nên thể hiện vai trò thay vì phụ thuộc quá sâu vào vị trí.

Hạn chế selector quá sâu

Selector như:

.header .menu ul li a span {
    color: red;
}

thường tạo ra sự phụ thuộc không cần thiết vào cấu trúc HTML. Khi markup thay đổi, CSS dễ bị hỏng.

Trong nhiều trường hợp, một class trực tiếp sẽ dễ bảo trì hơn:

.menu-link {
    color: red;
}

Design Tokens bằng CSS Variables

CSS Variables có thể được sử dụng để tạo một hệ thống giá trị thống nhất:

:root {
    --color-primary: #d3801f;
    --color-text: #222;
    --color-muted: #666;
    --color-border: #ddd;

    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;

    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 16px;
}

Khi hệ thống thiết kế thay đổi, chỉ cần điều chỉnh token thay vì sửa hàng chục hoặc hàng trăm component.

Dark Mode bằng CSS

CSS có thể phản ứng với thiết lập giao diện của hệ điều hành:

@media (prefers-color-scheme: dark) {
    :root {
        --color-bg: #111;
        --color-text: #eee;
    }
}

Nếu website có nút chuyển Light/Dark riêng, CSS Variables thường là nền tảng thuận tiện để thay đổi toàn bộ hệ màu.

CSS Performance

CSS thường không phải nguyên nhân duy nhất khiến website chậm, nhưng stylesheet lớn, selector phức tạp, animation không phù hợp và quá nhiều tài nguyên liên quan đến font hoặc hình ảnh có thể ảnh hưởng đến trải nghiệm.

Một số nguyên tắc thực tế:

  • Loại bỏ CSS không còn sử dụng.
  • Tránh tạo quá nhiều quy tắc trùng lặp.
  • Giữ selector đơn giản khi có thể.
  • Không animation những thuộc tính không cần thiết.
  • Ưu tiên các animation có khả năng được xử lý hiệu quả như transform và opacity.
  • Hạn chế tải quá nhiều font và weight không cần thiết.
  • Tách CSS theo kiến trúc hợp lý thay vì tạo một file khổng lồ không kiểm soát.

CSS và Rendering của trình duyệt

Để hiểu CSS nâng cao, cần biết rằng trình duyệt không chỉ đọc CSS rồi “vẽ ngay” lên màn hình. HTML và CSS được phân tích để xây dựng cấu trúc hiển thị, sau đó trình duyệt tính toán layout, paint và composite.

Thay đổi một số thuộc tính có thể khiến trình duyệt phải tính toán lại layout. Một số thay đổi khác chủ yếu ảnh hưởng đến quá trình paint hoặc compositing.

Điều này giải thích tại sao việc animation bằng transform thường được ưu tiên hơn việc liên tục thay đổi các thuộc tính hình học như top hoặc left trong những trường hợp phù hợp.

Debug CSS hiệu quả

DevTools của trình duyệt là công cụ quan trọng nhất khi xử lý CSS.

Khi một thuộc tính không hoạt động, không nên lập tức viết thêm một selector khác. Hãy kiểm tra lần lượt:

  1. Phần tử có đúng selector hay không.
  2. Quy tắc có thực sự được áp dụng hay đang bị gạch bỏ.
  3. Specificity có vấn đề không.
  4. Có declaration khác ghi đè không.
  5. Thuộc tính đó có bị inheritance ảnh hưởng không.
  6. Phần tử có đang nằm trong layout hoặc stacking context khác không.
  7. Giá trị kích thước có bị giới hạn bởi parent không.
  8. Overflow có đang che nội dung không.

Cách debug theo nguyên nhân sẽ hiệu quả hơn việc liên tục thêm !important, tăng z-index hoặc thêm margin âm.

Những lỗi CSS phổ biến

Dùng margin để sửa mọi vấn đề bố cục

Margin không phải công cụ duy nhất để tạo khoảng cách. Với Flexbox và Grid, gap thường phù hợp hơn khi khoảng cách nằm giữa các item.

Lạm dụng position absolute

Absolute rất hữu ích cho các thành phần được đặt tương đối với một vùng chứa, nhưng không nên dùng để xây dựng toàn bộ layout. Flexbox và Grid phù hợp hơn với bố cục chính.

Dùng chiều rộng và chiều cao cố định quá nhiều

Thiết lập widthheight cứng cho mọi thành phần dễ làm giao diện vỡ khi nội dung thay đổi hoặc màn hình nhỏ hơn dự kiến.

Selector quá phức tạp

Selector càng phụ thuộc vào cấu trúc HTML thì stylesheet càng dễ hỏng khi markup thay đổi.

Dùng !important để giải quyết mọi lỗi

Điều này thường chỉ che giấu nguyên nhân. Khi dự án lớn hơn, các quy tắc !important sẽ bắt đầu “đè” lẫn nhau và làm quá trình sửa lỗi khó hơn.

Cách học CSS từ cơ bản đến nâng cao

Nếu học CSS theo thứ tự ngẫu nhiên, bạn rất dễ biết nhiều thuộc tính nhưng vẫn không dựng được layout hoàn chỉnh. Một lộ trình hợp lý nên đi theo sự phụ thuộc giữa các kiến thức.

Giai đoạn 1: Nắm nền tảng

  • Cú pháp CSS.
  • Selector.
  • Class và ID.
  • Color.
  • Font và typography.
  • Margin, padding, border.
  • Box Model.
  • Width và height.
  • Display.

Giai đoạn 2: Làm chủ layout

  • Normal flow.
  • Position.
  • Flexbox.
  • Grid.
  • Overflow.
  • Responsive.
  • Media query.

Giai đoạn 3: Xây dựng giao diện thực tế

  • Header.
  • Navigation.
  • Hero section.
  • Card.
  • Form.
  • Modal.
  • Dropdown.
  • Sidebar.
  • Footer.
  • Responsive mobile.

Giai đoạn 4: CSS nâng cao

  • Cascade.
  • Specificity.
  • Inheritance.
  • Custom properties.
  • calc(), min(), max(), clamp().
  • Container queries.
  • Logical properties.
  • Subgrid.
  • Nesting.
  • Animation và transition.
  • Accessibility.
  • Performance.

Cách tư duy khi viết CSS chuyên nghiệp

CSS giỏi không nằm ở việc nhớ nhiều thuộc tính nhất. Người viết CSS tốt thường bắt đầu bằng việc xác định layout model phù hợp rồi mới chọn thuộc tính.

Ví dụ, nếu cần xếp các item theo hàng và căn giữa chúng, hãy nghĩ đến Flexbox. Nếu cần kiểm soát đồng thời hàng và cột, hãy nghĩ đến Grid. Nếu cần đặt một badge ở góc card, hãy nghĩ đến relative và absolute. Nếu cần component tự thay đổi theo không gian chứa, hãy nghĩ đến container query.

Thay vì hỏi “CSS nào để đẩy phần tử này sang phải?”, nên hỏi “mô hình bố cục nào khiến phần tử này nằm đúng vị trí ngay từ đầu?”. Đây là sự khác biệt giữa việc sửa từng lỗi giao diện và xây dựng một hệ thống CSS có cấu trúc.

CSS hiện đại không chỉ là danh sách thuộc tính

CSS đã phát triển rất xa so với cách viết giao diện bằng những thuộc tính cơ bản như color, margin và float. Flexbox và Grid thay đổi cách xây dựng layout; custom properties biến CSS thành một hệ thống có khả năng quản lý giá trị; container queries đưa responsive xuống cấp độ component; cascade layers giúp kiểm soát stylesheet lớn; logical properties làm CSS linh hoạt hơn; các hàm như clamp(), min()max() giúp giao diện thích ứng tự nhiên hơn.

Nhưng càng đi sâu, điều quan trọng càng không phải là học thêm thật nhiều property. Điều quan trọng là hiểu mối quan hệ giữa cascade, specificity, inheritance, box model, formatting context, layout, kích thước, stacking context và responsive design.

Khi những nền tảng này đã vững, việc học một thuộc tính CSS mới sẽ trở nên dễ dàng hơn rất nhiều. Bạn không còn phải học thuộc từng đoạn code riêng lẻ mà có thể suy luận xem CSS nên được sử dụng ở đâu, vì sao nó hoạt động và lựa chọn nào phù hợp nhất với cấu trúc website.

Tóm tắt kiến thức CSS cần nắm vững

Có thể cô đọng toàn bộ quá trình học CSS thành những nhóm kiến thức quan trọng sau:

  • Nền tảng: cú pháp, selector, property, value.
  • Cascade: specificity, inheritance, source order, layers.
  • Box Model: content, padding, border, margin, box-sizing.
  • Typography: font, kích thước, line-height, spacing, wrapping.
  • Layout: normal flow, display, position.
  • Flexbox: layout một chiều.
  • Grid: layout hai chiều.
  • Responsive: viewport, media query, fluid layout.
  • Visual: màu sắc, background, border, shadow.
  • Interaction: pseudo-class, transition, transform, animation.
  • CSS hiện đại: variables, clamp, container query, nesting, logical properties, subgrid.
  • Chất lượng: accessibility, performance, maintainability.
  • Debug: DevTools, cascade inspection, layout inspection và stacking context.

Nắm chắc những nhóm kiến thức này sẽ tạo thành một nền tảng CSS đủ mạnh để xây dựng từ trang web đơn giản đến giao diện responsive có nhiều component. Sau đó, các framework hoặc thư viện CSS chỉ nên được xem là công cụ hỗ trợ; nền tảng CSS vẫn là thứ quyết định bạn có thực sự hiểu và kiểm soát được giao diện hay không.

  • 0 Bình luận
Trần Thị Vân | Content Creator Web Mới
Trần Thị Vân
Trần Thị Vân là Content Creator tại Web Mới, phụ trách nghiên cứu, biên soạn nội dung và chia sẻ kiến thức về website, SEO, lập trình cùng các xu hướng công nghệ
Đánh giá
Chia sẻ nội dung đánh giá của bạn về Tổng hợp đầy đủ kiến thức CSS từ cơ bản đến nâng cao
Email, Điện thoại của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *
Đánh giá của bạn
Tên *
Email
Số điện thoại *
Bình luận, Hỏi đáp
Yêu Cầu Báo Giá
Gửi trang web mẫu cần làm theo, chúng tôi sẽ báo giá đến bạn từ Email (tanlucit09@gmail.com - Bùi Tấn Lực) hoặc Zalo (Lực IT - 0398259259) !