- vừa được xem lúc

10 Tính năng hiện đại của CSS bạn nên sử dụng

0 0 3

Người đăng: Thái Thịnh

Theo Viblo Asia

Cũng giống như JavaScript, CSS không có tiếng tăm tốt lắm trong mắt các lập trình viên (đặc biệt là Rails). Và cũng giống như JavaScript (nghĩ đến Turbo hoặc CoffeeScript), CSS có một lịch sử dài về các trình tiền xử lý, hậu xử lý và các dạng trừu tượng hóa (như Tailwind CSS).

Trong một thời gian dài, những công cụ này thực sự cần thiết. Thật khó để tưởng tượng CSS mà không có khả năng lồng selector, đúng không?

Nhưng bây giờ đã là năm 2025 và CSS đang phát triển với tốc độ chóng mặt. Thời của spacer.gif hay tạo ảnh riêng cho từng góc của một thẻ để giả lập bo góc đã qua rồi.

Nếu bạn đã "bỏ bê" CSS một thời gian (ví dụ vì bạn dùng Tailwind CSS), thì dưới đây là một số tính năng CSS mới mà tôi đang rất thích sử dụng trong vài dự án (tự làm hoặc cho khách hàng). Dù vẫn dùng Tailwind CSS, tôi cho rằng hiểu và thật sự sử dụng CSS gốc rất quan trọng. Web được xây dựng trên các chuẩn mở – điều này giúp nó dễ tiếp cận, dễ bảo trì và có thể phát triển về lâu dài.

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

Chúng có liên quan nên được gộp lại.

1. min()

/* Keeps buttons from getting too wide on large screens */
.pricing-button { width: min(300px, 90%);
}

min() giúp giới hạn tối đa. Nó chọn giá trị nhỏ hơn. Rất tiện để giữ phần tử không quá lớn trong khi vẫn đáp ứng tốt trên nhiều kích thước màn hình.

2. max()

/* Ensures text stays readable even on tiny screens */
.terms-container { font-size: max(16px, 1.2vw);
}

Ngược lại với min(), max() đặt ra giới hạn tối thiểu bằng cách chọn giá trị lớn hơn. Rất hữu ích để ngăn phần tử bị thu nhỏ quá mức.

3. clamp()

/* Creates perfectly fluid typography that's never too big or small */
.dashboard-title { font-size: clamp(1.5rem, 5vw, 3rem);
}

clamp() kết hợp cả min()max()! Nó nhận 3 giá trị:

  • Giá trị tối thiểu
  • Giá trị ưu tiên
  • Giá trị tối đa

Container Queries

Giúp phần tử phản ứng với kích thước của thành phần cha thay vì kích thước toàn bộ trình duyệt như trước.

/* Step 1: Mark the parent as a containment context */
.cards { container-type: inline-size;
} /* Step 2: Base styles for the card component */
.card { padding: .75 1.25rem; background: white; border-radius: 1rem; /* Default to stacked layout */ display: flex; flex-direction: column; gap: .5rem;
} .card__value { font-size: 2rem;
} /* Step 3: Layout changes based on container width */
@container (width > 200px) { .card { /* Switch to horizontal layout when there's enough space */ flex-direction: row; align-items: center; justify-content: space-between; }
}

text-wrap: Cân bằng & đẹp mắt

Điều khiển cách văn bản xuống dòng nhằm tăng khả năng đọc.

/* text-wrap: balance - ideal for headings */
.section-title { text-wrap: balance; /* Makes lines more visually equal: "Welcome to our Platform" becomes: "Welcome to our Platform" Instead of: "Welcome to our Platform" */
} /* text-wrap: pretty - ideal for paragraphs */
.card-description { text-wrap: pretty; /* Prevents orphaned words: Adds extra line break to avoid: "This is a long description about features" Creates instead: "This is a long description about features" */
}

@starting-style

Cho phép tạo animation từ trạng thái display: none.

.modal { /* Hidden state */ display: none; opacity: 1;
} .modal.open { display: block; /* Regular transition works now */ transition: opacity 300ms; opacity: 1;
} /* Define starting styles when modal becomes displayed */
@starting-style { .modal.open { opacity: 0; }
}

:has()

Cho phép chọn phần tử cha dựa vào phần tử con – điều mà CSS trước đây không thể làm.


/* Card changes style if it contains an error message */
.card:has(.error-message) { border-color: red; background: rgb(255 0 0 / .05);
} /* Form groups that have required inputs */
.form-group:has(input[required]) { /* Show required indicator */ &::before { content: "*"; color: red; }
}

Media Query Ranges

Cú pháp đơn giản hơn cho min-widthmax-width.

/* Old syntax */
@media (min-width: 768px) and (max-width: 1199px) { .card { width: 65ch; }
} /* New range syntax */
@media (768px <= width <= 1199px) { .card { width: 65ch; }
} /* Common breakpoint patterns */
.container { /* Smaller than 768px */ @media (width < 768px) { padding: 1rem; } /* Larger than 1200px */ @media (width >= 1200px) { max-width: 1140px; } /* Between breakpoints */ @media (480px <= width < 768px) { margin: 1.5rem; }
}

light-dark

Viết gọn để thay đổi giao diện theo theme sáng hoặc tối.

.card { /* Basic color values */ background: light-dark(#f1f5f9, #0f172a); color: light-dark(#0f172a, #f1f5f9); /* Works with any color format */ border: 1px solid light-dark(rgb(226, 232, 240), rgb(51, 65, 85));
}

color-scheme

Thông báo cho trình duyệt biết thành phần hỗ trợ theme nào.

/* Global level - typically in :root */
:root { /* Support both schemes, dark listed first means dark is preferred */ color-scheme: dark light;
} /* Component level - useful for cards or modals that differ from global scheme */
.themed-card { /* This card only supports light mode */ color-scheme: light; /* System UI elements inside will stay light */ input { /* Inputs remain light-styled even in dark mode */ border: 1px solid #ddd; }
} /* Dark-only interface section */
.code-editor { /* Force dark appearance for all system UI within */ color-scheme: dark;
}

Nesting (Lồng selector)

Tính năng trước đây chỉ có trong Sass/Less – nay đã được hỗ trợ gốc.

.card { padding: .75 1.25rem; background-color: #fff; border-radius: 1rem; /* Nest direct children with & */ & .header { font-size: 1.7rem; } /* Nest state changes */ &:hover { background: #f1f5f9; } /* Nest multiple selectors */ & .title, & .subtitle { font-weight: 600; } /* Nest media queries */ @media (width > 768px) { padding: 1 1.375rem; }
}

Đơn vị đo trong CSS

Font-based:

  • em: so với cỡ chữ của phần tử cha
  • rem: so với cỡ chữ của :root
  • ex: chiều cao ký tự "x"
  • ch: độ rộng ký tự "0"
  • lh: bằng với line-height hiện tại

Viewport-based:

  • vh, vw: 1% chiều cao/rộng màn hình
  • vmin, vmax: dựa trên chiều nhỏ/lớn hơn

Viewport hiện đại:

  • dvh, dvw: điều chỉnh theo thanh điều hướng
  • svh, svw: chiều nhỏ nhất có thể
  • lvh, lvw: chiều lớn nhất có thể

@layer

Nếu bạn đã dùng Tailwind CSS, thì @layer sẽ quen thuộc. Giúp kiểm soát thứ tự ưu tiên giữa các nhóm CSS.

/* Define layer order - order here determines priority */
@layer reset, components, utilities; /* Reset layer: lowest priority */
@layer reset { * { margin: 0; padding: 0; box-sizing: border-box; }
} /* Components layer: middle priority */
@layer components { .button { /* Even if utilities have lower specificity, they'll still override these styles */ padding: .5rem 1rem; background: blue; }
} /* Utilities layer: highest priority */
@layer utilities { .p-4 { /* This wins over component padding */ padding: 1.25rem; } .bg-red { /* This wins over component background */ background: red; }
}

Đây chỉ là phần nổi bật trong số những tính năng CSS hiện đại mà tôi đang sử dụng trong các sản phẩm gần đây. Bạn có học được điều gì mới không? Hãy cho tôi biết nhé!

Cảm ơn các bạn đã theo dõi!

Bình luận

Bài viết tương tự

- vừa được xem lúc

The Twelve-Factor App, cẩm nang gối đầu giường trong xây dựng application (Phần 1)

Giới thiệu. Ngày nay các phần mềm được triển khai dưới dạng các dịch vụ, chúng được gọi là các web apps hay software-as-a-service (SaaS).

0 0 42

- vừa được xem lúc

8 Sai lầm phổ biến khi lập trình Android

1. Hard code.

0 0 203

- vừa được xem lúc

Popular interview question: What is the difference between Process and Thread? 10 seconds a day

Video được đăng tại channel Tips Javascript

0 0 41

- vừa được xem lúc

Thuật toán và ứng dụng - P1

Mục đích series. . Những bài toán gắn liền với thực tế. Từ đó thấy được tầm quan trọng của thuật toán trong lập trình.

0 0 44

- vừa được xem lúc

Tác dụng của Docker trong quá trình học tập

Docker bây giờ gần như là kiến thức bắt buộc đối với các anh em Dev và Devops, nhưng mà đối với sinh viên IT nói chung vẫn còn khá mơ hồ và không biết tác dụng thực tế của nó. Hôm nay mình sẽ chia sẻ

0 0 50

- vừa được xem lúc

Làm giàu trong ngành IT

Hầu như mọi người đều đi làm để kiếm tiền, ít người đi làm vì thấy cái nghề đó thú vị lắm. Bây giờ vất cho mình 100 tỷ bảo mình bỏ nghề thì mình cũng bỏ thôi.

0 0 52