Hoàn Thiện Dark Mode với Tailwind Typography và Highlight.js
Xây dựng blog cho developer có nghĩa là một điều không thể thương lượng: Code block phải trông đẹp.
Khi sử dụng plugin @tailwindcss/typography (class prose tiêu chuẩn), bạn có được mặc định tốt cho text, nhưng code block thường gặp vấn đề. Chúng có thể thiếu syntax highlighting, hoặc màu nền của chúng xung đột khi chuyển đổi giữa chế độ Light và Dark.
Đây là cách tôi giải quyết vấn đề này cho chính blog này.
1. Thách Thức
Chúng ta có ba phần chuyển động:
- Tailwind Prose: Xử lý styling text chung.
- Highlight.js: Xử lý logic syntax highlighting.
- Theme: Chúng ta cần một Light theme (ví dụ: GitHub Light) và một Dark theme (GitHub Dark) để tải động.
2. Thiết Lập Highlight.js
Thay vì bundle một file CSS khổng lồ, chúng ta tải hai stylesheet và toggle chúng.
Trong file layout (app.blade.php), thêm cả hai stylesheet nhưng đặt ID cho chúng:
<link id="hljs-light" rel="stylesheet" href=".../github.min.css">
<link id="hljs-dark" rel="stylesheet" href=".../github-dark.min.css" disabled>
Chúng ta mặc định Light mode (hoặc bất kỳ mặc định hệ thống nào của bạn). Thuộc tính disabled ngăn trình duyệt áp dụng style dark ban đầu.
3. Logic Toggle JavaScript
Khi người dùng toggle theme, chúng ta cần đảo trạng thái disabled của các link này.
const hljsLight = document.getElementById('hljs-light');
const hljsDark = document.getElementById('hljs-dark');
function setHljsTheme(isDark) {
hljsLight.disabled = isDark; // Nếu dark, vô hiệu hóa light
hljsDark.disabled = !isDark; // Nếu dark, kích hoạt dark
}
// Gọi function này trong event listener toggle Dark Mode hiện có của bạn
themeToggleBtn.addEventListener('click', function() {
// ... logic toggle ...
setHljsTheme(isDark);
});
Điều này đảm bảo code block của bạn chuyển đổi ngay lập tức từ nền trắng với text tối sang nền tối với text sáng.
4. Tùy Chỉnh Tailwind Prose
Style prose mặc định bao gồm nền xám cho phần tử code có thể xung đột với Highlight.js. Chúng ta cần ghi đè chúng trong CSS.
Trong resources/css/app.css:
/* 1. Làm cho container pre trông như code block */
.prose pre {
border-radius: 0.5rem;
padding: 1rem;
border: 1px solid var(--color-gray-200);
}
.dark .prose pre {
border-color: var(--color-gray-700);
background-color: #0d1117; /* Khớp với GitHub Dark */
}
/* 2. Xóa backtick và nền mặc định khỏi inline code */
.prose code::before,
.prose code::after {
content: ''; /* Xóa backtick */
}
/* 3. Reset style container Highlight.js */
.hljs {
background: transparent !important;
padding: 0 !important;
}
5. Cải Thiện Inline Code
Đừng quên các inline code marker (như this). Chúng thường không được Highlight.js xử lý, nhưng chúng cần nổi bật.
.prose code:not(pre code) {
background-color: var(--color-gray-100);
padding: 0.125rem 0.25rem;
border-radius: 0.25rem;
font-weight: 400;
color: #eb5757; /* Tùy chọn: màu đỏ cho biến */
}
.dark .prose code:not(pre code) {
background-color: var(--color-gray-800);
color: #ff7b72;
}
Kết Quả
Với những thay đổi này, bạn có được:
- Mặc định nhận biết hệ thống: Tải đúng theme khi truy cập lần đầu.
- Chuyển đổi tức thì: Không có flash màu sai khi toggle.
- UI nhất quán: Code block hòa quyện hoàn hảo với phần còn lại của typography.
Hãy xem các code block trong bài viết này—chúng là demo trực tiếp!