Thêm chế độ tối (dark mode) cho ứng dụng di động đúng cách

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Rất nhiều người bật chế độ tối trên điện thoại để dịu mắt vào ban đêm hoặc tiết kiệm pin trên màn hình OLED. Một ứng dụng không hỗ trợ sẽ trông chói và lạc lõng. Bài viết hướng dẫn cách làm dark mode có hệ thống thay vì đổi màu thủ công từng màn hình.

Nguyên tắc thiết kế chế độ tối

  • Không chỉ đảo màu: đảo ngược trắng đen đơn thuần thường cho kết quả xấu và khó đọc.
  • Dùng xám đậm thay vì đen tuyệt đối cho nền chính ở hầu hết trường hợp, giúp bề mặt có chiều sâu; bề mặt nổi hơn có thể sáng hơn một chút.
  • Giảm độ bão hòa của màu nhấn vì màu rực trên nền tối dễ gây chói.
  • Giữ độ tương phản đủ giữa chữ và nền ở cả hai chế độ.
  • Chữ không nên trắng tuyệt đối trên nền rất tối; trắng hơi dịu thường dễ chịu hơn.

Dùng token màu theo vai trò

Thay vì viết mã màu cụ thể khắp nơi, hãy định nghĩa màu theo vai trò: nền, bề mặt, chữ chính, chữ phụ, màu nhấn, màu lỗi. Mỗi chế độ ánh xạ vai trò đó sang một giá trị riêng. Giao diện chỉ tham chiếu vai trò, nên đổi chế độ không phải sửa từng màn hình.

Cách làm trong Flutter

MaterialApp(
  theme: ThemeData(
    useMaterial3: true,
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.indigo,
      brightness: Brightness.light,
    ),
  ),
  darkTheme: ThemeData(
    useMaterial3: true,
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.indigo,
      brightness: Brightness.dark,
    ),
  ),
  themeMode: ThemeMode.system, // theo cài đặt hệ thống
  home: const HomePage(),
);

Trong widget, lấy màu từ theme thay vì cố định:

final scheme = Theme.of(context).colorScheme;
Container(
  color: scheme.surface,
  child: Text('Nội dung', style: TextStyle(color: scheme.onSurface)),
)

Để cho người dùng chọn Sáng, Tối hoặc Theo hệ thống, lưu lựa chọn (ví dụ bằng shared_preferences) và gán vào themeMode thông qua một giải pháp quản lý state.

Cách làm trong Jetpack Compose

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colors = if (darkTheme) darkColorScheme() else lightColorScheme()
    MaterialTheme(colorScheme = colors, content = content)
}

Cách làm trong SwiftUI

SwiftUI tự thích ứng khi bạn dùng màu ngữ nghĩa của hệ thống như .primary, .secondary hay màu trong Asset Catalog có biến thể sáng và tối. Đọc chế độ hiện tại bằng môi trường:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text(colorScheme == .dark ? "Đang ở chế độ tối" : "Đang ở chế độ sáng")
            .padding()
            .background(Color(.systemBackground))
    }
}

Cách làm trong React Native

import { useColorScheme } from 'react-native';

const palettes = {
  light: { bg: '#FFFFFF', text: '#111111' },
  dark: { bg: '#121212', text: '#EEEEEE' },
};

export function useTheme() {
  const scheme = useColorScheme() ?? 'light';
  return palettes[scheme];
}

Những chi tiết hay bị bỏ sót

  1. Hình ảnh và biểu tượng: logo đen trên nền tối sẽ biến mất; chuẩn bị phiên bản cho chế độ tối hoặc dùng tint theo theme.
  2. Đổ bóng: bóng khó thấy trên nền tối, dùng khác biệt sắc độ bề mặt để thể hiện độ cao.
  3. Thanh trạng thái và thanh điều hướng hệ thống: đổi màu biểu tượng cho phù hợp nền.
  4. Nội dung web trong ứng dụng (WebView): cần hỗ trợ riêng nếu muốn đồng bộ.
  5. Biểu đồ và bản đồ: cũng cần bảng màu cho chế độ tối.
  6. Màn hình khởi động: tránh nháy sáng chói khi mở ứng dụng ở chế độ tối.

Kiểm thử

Chuyển qua lại hai chế độ khi ứng dụng đang mở và kiểm tra từng màn hình, hộp thoại, bàn phím, trạng thái lỗi. Kiểm tra độ tương phản bằng công cụ đo hoặc tính năng kiểm tra khả năng tiếp cận có sẵn.

Kết luận

Dark mode làm tốt không phải đảo màu mà là một bảng màu thứ hai được thiết kế cẩn thận. Hãy dùng token theo vai trò, theo dõi cài đặt hệ thống và cho người dùng tùy chọn, bạn sẽ có giao diện nhất quán dễ bảo trì.

Cho người dùng quyền lựa chọn

Ba lựa chọn hợp lý là Sáng, Tối và Theo hệ thống. Mặc định nên theo hệ thống, vì đó là mong muốn tổng quát của người dùng. Khi họ chọn thủ công, hãy lưu lại và ưu tiên lựa chọn đó. Áp dụng thay đổi ngay mà không cần khởi động lại ứng dụng, và nhớ cập nhật cả màu thanh trạng thái. Nếu ứng dụng có nhiều ảnh nền hay minh họa, hãy xem lại chúng ở chế độ tối để tránh những mảng sáng chói bất ngờ.

Đảm bảo độ tương phản

Ở chế độ tối, chữ xám trên nền xám đậm rất dễ khó đọc. Hãy kiểm tra tỉ lệ tương phản bằng công cụ đo và nhắm tới mức khuyến nghị trong hướng dẫn khả năng tiếp cận. Chú ý cả trạng thái vô hiệu hóa, văn bản gợi ý trong ô nhập và đường viền.

Để học cách xây dựng giao diện theo hệ thống thiết kế, hãy xem thêm các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment