Bỏ qua tới nội dung
Performance· ·10 phút đọc

Loại bỏ CSS thừa (unused CSS) đúng cách

Nguyen Hien
Loại bỏ CSS thừa (unused CSS) đúng cách
Cỡ chữ

Mở một trang WordPress hay một site dựng bằng framework, bạn sẽ thấy trình duyệt tải về vài trăm KB CSS — nhưng trang chỉ thực sự dùng một phần nhỏ trong số đó. Phần còn lại nằm im trong file, vẫn phải tải về và phân tích cú pháp (parse) trước khi trang được vẽ. Đó là CSS thừa, và nó kéo lùi tốc độ hiển thị mà không mang lại gì.

Vì sao theme và framework luôn tải dư CSS

CSS thừa không phải lỗi của bạn — nó là hệ quả tự nhiên của cách các công cụ phổ biến hoạt động:

  • Theme/plugin “đa năng”: một theme WordPress phải phục vụ hàng nghìn site khác nhau, nên nó gói sẵn style cho slider, mega menu, bảng giá, form… dù trang của bạn chỉ dùng một vài thứ. Tất cả nạp chung trong một file.
  • Framework CSS: Bootstrap hay các bộ tiện ích nạp toàn bộ hệ thống lớp (class), trong khi một trang thực tế chỉ chạm tới chừng 5–10%.
  • Mỗi plugin một file CSS: plugin form, plugin chat, plugin chia sẻ mạng xã hội đều enqueue CSS riêng trên MỌI trang, kể cả trang không có chúng.
  • CSS tích tụ theo thời gian: code cũ, component đã gỡ nhưng style vẫn còn nằm lại trong stylesheet.

Theo tài liệu của Google, CSS mặc định là tài nguyên chặn render (render-blocking) — trình duyệt phải tải và xử lý hết file trước khi vẽ khung trang. File càng to, thời điểm nội dung lớn nhất hiện ra (LCP — Largest Contentful Paint) càng bị đẩy lùi.

Sơ đồ phân biệt loại bỏ CSS thừa với critical CSS và minify CSS
Ba việc khác nhau: xoá hẳn style không dùng, ưu tiên render đầu, và viết gọn cú pháp.

Loại bỏ CSS thừa khác critical CSS và minify thế nào

Ba kỹ thuật này hay bị gộp làm một, nhưng chúng giải quyết ba việc khác nhau và nên làm cùng nhau:

Kỹ thuậtLàm gìMục tiêu
Loại bỏ CSS thừaXOÁ hẳn các quy tắc không trang nào dùngFile nhỏ lại tận gốc
MinifyRÚT GỌN ký tự (bỏ khoảng trắng, xuống dòng) — không xoá quy tắc nàoNén nhẹ phần còn lại
Critical CSSTÁCH style của phần đầu màn hình ra inline, hoãn phần dướiVẽ above-fold ngay lập tức

Hiểu đơn giản: loại bỏ CSS thừa quyết định còn lại bao nhiêu quy tắc; minify CSS và JS quyết định mỗi quy tắc gọn cỡ nào; còn việc ưu tiên phần nào hiện trước là chuyện của critical CSS. Làm cả ba mới ra file CSS gọn và hiển thị nhanh. Bài này đào sâu việc đầu tiên — xoá CSS thừa.

Cách dò CSS thừa bằng Coverage tab

Trình duyệt có sẵn công cụ đo chính xác bao nhiêu CSS bị bỏ phí trên một trang — tab Coverage (độ phủ) trong DevTools:

  1. Mở DevTools (F12), nhấn Ctrl+Shift+P, gõ “Coverage”, chọn Show Coverage.
  2. Bấm nút tải lại (reload) trong tab Coverage để bắt đầu đo.
  3. Lọc theo .css. Cột Unused Bytes (số byte không dùng) và thanh đỏ/xanh cho thấy tỉ lệ thừa của từng file.

Một thanh đỏ chiếm 80–90% nghĩa là file đó gần như toàn CSS thừa cho trang hiện tại. Lưu ý đọc số đúng cách: Coverage chỉ đo một trang tại một thời điểm. Một quy tắc “thừa” ở trang chủ có thể lại cần thiết ở trang liên hệ. Vì vậy đừng xoá tay theo Coverage — hãy dùng nó để biết file nào đáng xử lý, rồi giao việc xoá cho công cụ tự động quét nhiều trang.

Loại bỏ tự động bằng PurgeCSS và lớp build

Cách an toàn và bền nhất là để công cụ quét toàn bộ HTML, JavaScript và template của bạn, lập danh sách những lớp thực sự được dùng, rồi cắt bỏ phần còn lại ngay trong bước build (đóng gói).

  • PurgeCSS: chạy trên Node.js, tích hợp PostCSS, webpack hoặc Vite. Nó dùng “extractor” (bộ trích) đọc các file template tìm tên lớp, rồi bỏ mọi selector không xuất hiện. Theo các tài liệu tối ưu, kết hợp xoá CSS thừa với minify có thể cắt rất sâu dung lượng so với chỉ minify.
  • Tailwind: bản mới quét sẵn các file trong cấu hình content và chỉ sinh ra đúng những lớp bạn dùng ngay khi build production — bạn gần như không cần cấu hình thêm, miễn khai báo đúng đường dẫn template.
  • Trên WordPress: nếu không có bước build, các plugin cache như LiteSpeed Cache, WP Rocket có tính năng “Remove Unused CSS” sinh stylesheet riêng cho từng URL. Tiện nhưng cần kiểm thử kỹ vì chúng dò theo từng trang đã được crawl.

Cấu hình PurgeCSS qua PostCSS thường gọn như sau — chỉ rõ những file cần quét tìm tên lớp:

// postcss.config.js
module.exports = {
  plugins: [
    require('@fullhuman/postcss-purgecss')({
      content: ['./src/**/*.html', './src/**/*.js'],
      safelist: ['is-active', 'has-error', /^modal-/],
      defaultExtractor: c => c.match(/[w-/:]+(?<!:)/g) || [],
    }),
  ],
};

Bẫy lớn nhất: class động

Đây là chỗ làm hỏng cả site nếu loại bỏ ẩu. Công cụ quét tìm chuỗi tên lớp xuất hiện y nguyên trong file. Nhưng nhiều lớp chỉ sinh ra lúc chạy (runtime), chứ không nằm sẵn trong template:

  • Lớp gắn bằng JavaScript khi người dùng tương tác: el.classList.add('is-open').
  • Tên lớp ghép chuỗi: `btn-${variant}` — công cụ thấy btn- nhưng không biết variant là gì.
  • HTML đến từ API, CMS, hoặc Markdown render lúc chạy mà công cụ không quét.

Những lớp này hợp lệ nhưng không có trong file tĩnh, nên dễ bị cắt nhầm — kết quả là menu không mở, thông báo lỗi mất màu, modal vỡ. Cách phòng:

  1. Khai báo safelist (danh sách giữ lại): liệt kê các lớp/biểu thức chính quy cần chừa, như ví dụ safelist ở trên.
  2. Tránh ghép tên lớp; viết đầy đủ tên trong template để công cụ thấy được.
  3. Kiểm thử sau khi loại bỏ: bấm qua mọi trạng thái tương tác (mở menu, submit form lỗi, mở modal), so trước/sau, và đo lại bằng Lighthouse để xác nhận giao diện không vỡ.
Sơ đồ quy trình loại bỏ CSS thừa an toàn từ dò bằng Coverage tới purge và kiểm lại
Dò trước, lọc bằng PurgeCSS, giữ lại class động rồi kiểm lại để không vỡ giao diện.

Quy trình loại bỏ CSS thừa an toàn

  1. Đo bằng Coverage để biết file CSS nào thừa nhiều nhất — đó là chỗ đáng làm trước.
  2. Chọn cách xoá tự động hợp với stack: PurgeCSS/Tailwind cho dự án có bước build; plugin cache cho WordPress thuần.
  3. Lập safelist cho các lớp động đã biết.
  4. Build/sinh CSS mới, rồi kiểm thử mọi luồng tương tác trên trang thật.
  5. Đo lại Coverage và Lighthouse để xác nhận CSS đã nhẹ và LCP cải thiện.

Khi vận hành web22.dev trên nền LiteSpeed kèm Cloudflare, Web22 xử lý CSS thừa bằng cách để công cụ build sinh đúng phần style cần dùng, giữ safelist cho các lớp trạng thái, rồi đo lại Core Web Vitals bằng PageSpeed thật trước và sau — chứ không xoá tay theo cảm tính. Sau khi gọn CSS, bước tiếp theo thường là tối ưu Core Web Vitals tổng thể.

Câu hỏi thường gặp

Loại bỏ CSS thừa có giúp tăng điểm PageSpeed không?

Có. Lighthouse có cảnh báo “Reduce unused CSS” riêng. Cắt CSS thừa giảm dung lượng file chặn render, giúp FCP và LCP nhanh hơn, qua đó cải thiện điểm.

Tôi có nên xoá tay các dòng CSS mà Coverage báo là thừa không?

Không nên. Coverage chỉ đo một trang một thời điểm; một quy tắc “thừa” ở đây có thể cần ở trang khác hoặc khi tương tác. Hãy để công cụ tự động quét nhiều trang lo việc xoá.

PurgeCSS có làm hỏng các lớp do JavaScript thêm vào không?

Có thể, nếu lớp đó chỉ sinh lúc chạy và không có trong file tĩnh. Dùng safelist để giữ chúng lại và luôn kiểm thử các luồng tương tác sau khi loại bỏ.

Đọc tiếp

Bài viết
cùng chủ đề.

Tất cả bài viết