Viết CSS không khó. Nhưng viết CSS sạch, dễ bảo trì, hiệu suất cao là một kỹ năng khác. Khi bạn làm việc với team, hoặc dự án lớn, CSS bừa bộn sẽ trở thành cơn ác mộng — khó debug, khó mở rộng, khó bảo trì.
Bài này sẽ dạy bạn những best practice CSS để viết code sạch, performant, và dễ bảo trì — những kỹ năng sẽ giúp bạn trở thành một lập trình viên web chuyên nghiệp.
Naming Conventions – Đặt tên class khôn ngoan
Tên class tốt là tên mô tả chức năng, không phải vị trí hoặc kiểu.
| ❌ SAI | ✅ ĐÚNG | Lý do |
|---|---|---|
red-text | error-message | Mô tả tác dụng, không phải màu |
left-column | sidebar | Mô tả chức năng, không phải vị trí |
big-font | heading-primary | Mô tả phân cấp, không phải kích thước |
mt-20 | card-spacing | Mô tả dụng ý, không phải giá trị |
/* ❌ SAI: Class dựa trên style */
.blue-button {
background-color: blue;
}
.red-text {
color: red;
}
.left-sidebar {
position: absolute;
left: 0;
}
/* ✅ ĐÚNG: Class dựa trên function/component */
.button-primary {
background-color: #3498db;
}
.alert-error {
color: #e74c3c;
}
.sidebar {
position: absolute;
left: 0;
}
.card {
background: white;
padding: 20px;
border-radius: 8px;
}BEM – Block Element Modifier (Naming Methodology)
BEM là cách đặt tên class theo quy tắc: Block__Element--Modifier
- 🔹 Block: Component độc lập (button, card, navbar)
- 🔹 Element: Phần của block (button__text, card__image)
- 🔹 Modifier: Biến thể (button–primary, card–featured)
<!-- HTML -->
<button class="button button--primary">
<span class="button__text">Gửi</span>
</button>
<button class="button button--secondary button--disabled">
<span class="button__text">Hủy</span>
</button>
<div class="card card--featured">
<img class="card__image" src="image.jpg">
<h3 class="card__title">Tiêu đề</h3>
<p class="card__description">Mô tả</p>
</div>/* CSS */
/* Block */
.button {
padding: 12px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s;
}
/* Element */
.button__text {
display: block;
}
/* Modifier */
.button--primary {
background-color: #3498db;
color: white;
}
.button--primary:hover {
background-color: #2980b9;
}
.button--secondary {
background-color: #ecf0f1;
color: #333;
}
.button--disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Card block */
.card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.card__image {
width: 100%;
height: 200px;
object-fit: cover;
}
.card__title {
padding: 15px;
font-size: 18px;
color: #2c3e50;
}
.card__description {
padding: 0 15px 15px;
color: #666;
}
.card--featured {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
border: 2px solid #f39c12;
}CSS Performance – Tối ưu hiệu suất
1. Selector Performance – Chọn phương pháp chính xác
/* ❌ CHẬM: Selector quá dài và phức tạp */
div.container div.row div.column p.text {
color: #333;
}
body > header > nav > ul > li > a {
color: white;
}
/* ✅ NHANH: Selector ngắn, dùng class */
.paragraph-text {
color: #333;
}
.nav-link {
color: white;
}2. Avoid Unnecessary Specificity
/* ❌ SAI: Specificity quá cao */
#header .nav li a.active {
color: blue;
}
div.container > div.row > div.col > p {
font-size: 16px;
}
/* ✅ ĐÚNG: Specificity vừa phải */
.nav-link--active {
color: blue;
}
.col-paragraph {
font-size: 16px;
}3. Minimize CSS – Xóa code không dùng
/* ❌ SAI: Có code không dùng */
.old-style {
color: red;
/* Lớp này không còn dùng nhưng vẫn nằm trong file */
}
.unused-class {
margin: 10px;
padding: 20px;
}
/* ✅ ĐÚNG: Chỉ giữ code cần dùng */
.error-message {
color: #e74c3c;
font-weight: bold;
}
.spacing-default {
margin: 10px;
padding: 20px;
}4. Media Query Strategy – Chỉ load CSS cần thiết
/* ❌ SAI: Desktop CSS mặc định, mobile CSS trong query */
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 3 cột desktop */
}
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr; /* Phải override */
}
}
/* ✅ ĐÚNG: Mobile CSS mặc định, desktop CSS trong query */
.container {
display: grid;
grid-template-columns: 1fr; /* 1 cột mobile */
}
@media (min-width: 769px) {
.container {
grid-template-columns: 1fr 1fr 1fr; /* Thêm cho desktop */
}
}CSS Organization – Tổ chức code sạch
Phân chia CSS thành sections
/* ========== RESET ========== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
/* ========== VARIABLES & COLORS ========== */
:root {
--primary-color: #3498db;
--secondary-color: #2c3e50;
--error-color: #e74c3c;
--success-color: #27ae60;
--spacing-small: 10px;
--spacing-medium: 20px;
--spacing-large: 40px;
--font-size-body: 16px;
--font-size-heading: 24px;
--border-radius: 8px;
}
/* ========== TYPOGRAPHY ========== */
h1, h2, h3 {
font-weight: bold;
margin-bottom: var(--spacing-medium);
}
h1 {
font-size: var(--font-size-heading);
}
p {
line-height: 1.8;
margin-bottom: var(--spacing-medium);
}
/* ========== LAYOUT ========== */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-medium);
}
/* ========== COMPONENTS ========== */
.button {
padding: var(--spacing-small) var(--spacing-medium);
background-color: var(--primary-color);
color: white;
border: none;
border-radius: var(--border-radius);
cursor: pointer;
transition: background-color 0.3s;
}
.button:hover {
background-color: var(--secondary-color);
}
/* ========== UTILITIES ========== */
.text-center {
text-align: center;
}
.text-bold {
font-weight: bold;
}
.margin-bottom {
margin-bottom: var(--spacing-medium);
}
/* ========== RESPONSIVE ========== */
@media (min-width: 481px) {
/* Tablet styles */
}
@media (min-width: 769px) {
/* Desktop styles */
}Accessibility Best Practices
1. Color Contrast – Tương phản màu đủ
/* ❌ SAI: Tương phản thấp (khó đọc) */
.light-text {
color: #f0f0f0; /* Chữ trắng nhạt */
background-color: #ffffff; /* Nền trắng */
}
/* ✅ ĐÚNG: Tương phản cao (dễ đọc) */
.main-text {
color: #2c3e50; /* Chữ đen tối */
background-color: #f9f9f9; /* Nền xám nhạt */
}2. Focus States – Hiển thị focus cho keyboard navigation
/* ❌ SAI: Không có focus state */
.link {
color: #3498db;
}
/* ✅ ĐÚNG: Có focus, hover, active state */
.link {
color: #3498db;
text-decoration: none;
transition: all 0.3s;
}
.link:hover {
text-decoration: underline;
}
.link:focus {
outline: 2px solid #3498db; /* Keyboard navigation */
outline-offset: 2px;
}
.link:active {
color: #2980b9;
}3. Skip Navigation Link
<!-- Skip navigation link cho screen reader -->
<a href="#main" class="skip-link">Skip to main content</a>.skip-link {
position: absolute;
top: -40px;
left: 0;
background-color: #000;
color: white;
padding: 8px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0; /* Hiển thị khi focus */
}Ví dụ: Clean CSS Structure
/* ========== RESET & GLOBAL ========== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--color-primary: #3498db;
--color-secondary: #2c3e50;
--color-error: #e74c3c;
--spacing-xs: 8px;
--spacing-sm: 12px;
--spacing-md: 20px;
--spacing-lg: 40px;
--font-size-sm: 14px;
--font-size-base: 16px;
--font-size-lg: 20px;
--font-size-xl: 28px;
--border-radius: 8px;
--shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f9f9f9;
}
/* ========== TYPOGRAPHY ========== */
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
line-height: 1.2;
margin-bottom: var(--spacing-md);
}
h1 { font-size: var(--font-size-xl); }
h2 { font-size: var(--font-size-lg); }
h3 { font-size: var(--font-size-base); }
p {
margin-bottom: var(--spacing-md);
}
a {
color: var(--color-primary);
text-decoration: none;
transition: color 0.3s;
}
a:hover {
color: var(--color-secondary);
}
a:focus {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* ========== LAYOUT ========== */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-md);
}
/* ========== COMPONENTS ========== */
/* Button */
.btn {
display: inline-block;
padding: var(--spacing-sm) var(--spacing-md);
background-color: var(--color-primary);
color: white;
border: none;
border-radius: var(--border-radius);
cursor: pointer;
font-weight: 600;
transition: all 0.3s;
font-size: var(--font-size-base);
}
.btn:hover {
background-color: var(--color-secondary);
transform: translateY(-2px);
box-shadow: var(--shadow);
}
.btn:focus {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
.btn--secondary {
background-color: var(--color-secondary);
}
.btn--error {
background-color: var(--color-error);
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* Card */
.card {
background: white;
border-radius: var(--border-radius);
box-shadow: var(--shadow);
padding: var(--spacing-md);
transition: all 0.3s;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transform: translateY(-4px);
}
.card__title {
font-size: var(--font-size-lg);
margin-bottom: var(--spacing-sm);
}
.card__description {
color: #666;
margin-bottom: var(--spacing-md);
}
/* ========== UTILITIES ========== */
.text-center {
text-align: center;
}
.text-bold {
font-weight: 700;
}
.mb-sm { margin-bottom: var(--spacing-sm); }
.mb-md { margin-bottom: var(--spacing-md); }
.mb-lg { margin-bottom: var(--spacing-lg); }
.mt-sm { margin-top: var(--spacing-sm); }
.mt-md { margin-top: var(--spacing-md); }
.mt-lg { margin-top: var(--spacing-lg); }
/* ========== RESPONSIVE ========== */
@media (min-width: 481px) {
.container {
padding: 0 var(--spacing-lg);
}
}
@media (min-width: 769px) {
.container {
padding: 0 var(--spacing-lg);
}
}CSS Performance Checklist
✅ Performance Checklist:
- □ Xóa code không dùng (unused CSS)
- □ Minimize CSS file (remove whitespace)
- □ Dùng CSS variables cho colors, spacing
- □ Selector đơn giản, không quá specific
- □ Mobile-first CSS (min-width queries)
- □ Avoid !important (chỉ dùng khi cần)
- □ Lazy load heavy stylesheets
- □ Compress images
- □ Prefetch Google Fonts
- □ Test PageSpeed Insights
Tóm tắt Best Practices
- ✅ Naming convention: Dùng tên class mô tả chức năng
- ✅ BEM: Block__Element–Modifier cho naming
- ✅ CSS variables: :root { –color, –spacing, –font-size }
- ✅ Mobile-first: min-width media query
- ✅ Organization: Reset → Variables → Typography → Layout → Components → Utilities → Responsive
- ✅ Selector performance: Simple, specific selectors
- ✅ Accessibility: Color contrast, focus states, semantic HTML
- ✅ Code quality: No unused CSS, readable formatting
- ✅ Performance: Minimize, lazy load, compress images
- ✅ Testing: Test accessibility, performance, responsiveness
🎯 Bài tập hoàn thành
✅ Áp dụng Best Practices vào dự án của bạn:
- Refactor naming conventions (theo BEM nếu có thể)
- Tổ chức CSS thành sections
- Sử dụng CSS variables cho colors, spacing
- Kiểm tra color contrast (dùng WebAIM contrast checker)
- Thêm focus states cho tất cả interactive elements
- Xóa unused CSS
- Test accessibility (dùng axe DevTools extension)
- Test performance (dùng Google PageSpeed Insights)
- Minify CSS file
- Deploy lại và kiểm tra trên thực tế
🎓 Chúc mừng! Bạn đã hoàn thành toàn bộ 18 bài học HTML & CSS cơ bản từ A-Z. Bạn đã biết:
✅ HTML semantic và cấu trúc trang web
✅ CSS styling (colors, fonts, shadows, gradients)
✅ Layout (Flexbox, Grid, Positioning)
✅ Responsive design & Mobile-first
✅ Animations & Transitions
✅ Best practices & Performance optimization
Đây là nền tảng vững chắc để bạn tiếp tục học JavaScript, React, Vue, hoặc Backend. Hành trình lập trình web của bạn vừa mới bắt đầu! 🚀