Một website có thể trông rất ổn trên màn hình lớn nhưng trở nên chật chội, vỡ bố cục hoặc khó sử dụng trên điện thoại. Responsive web design không chỉ là dùng Flexbox, CSS Grid hay thêm vài media query. Bạn cần xử lý cả khoảng đệm, chữ, hình ảnh, chiều cao màn hình và khả năng truy cập.
Năm kỹ thuật dưới đây tập trung vào các tính năng CSS và HTML hiện đại, giúp bạn xây dựng giao diện linh hoạt hơn với ít quy tắc riêng cho từng kích thước màn hình. Đây là những chi tiết nhỏ nhưng ảnh hưởng trực tiếp đến trải nghiệm người dùng và chất lượng website doanh nghiệp.
1. Tạo khoảng đệm linh hoạt bằng hàm min()
Một khoảng đệm phù hợp trên màn hình desktop thường quá lớn khi chuyển sang điện thoại. Cách quen thuộc là đặt padding lớn cho desktop, sau đó dùng media query để giảm padding ở một breakpoint nhất định. Cách đó hoàn toàn dùng được, nhưng bạn có thể viết gọn hơn bằng hàm min().
Hàm min() nhận nhiều giá trị CSS và chọn giá trị nhỏ nhất để áp dụng. Ví dụ, với padding: min(5em, 8%);, trình duyệt sẽ so sánh 5em với 8% chiều rộng phần tử cha.
.container {
padding: min(5em, 8%);
}
Trên màn hình rộng, 5em có thể là giá trị nhỏ hơn nên được chọn. Khi màn hình thu hẹp, 8% sẽ giảm theo chiều rộng phần tử cha và trở thành giá trị nhỏ hơn. Kết quả là khoảng đệm tự thích nghi mà không cần viết thêm media query chỉ để thay đổi một con số.
2. Làm cỡ chữ responsive mà vẫn hỗ trợ phóng to
Cỡ chữ cần được xử lý thận trọng, đặc biệt với tiêu đề lớn. Trước hết, bạn nên ưu tiên rem thay vì pixel. Đơn vị rem dựa trên cỡ chữ của phần tử gốc, thường mặc định là 16 pixel. Vì thế, 1.5rem tương đương 24 pixel khi cỡ chữ gốc là 16 pixel.
Với tiêu đề lớn, vw có thể giúp chữ co giãn theo chiều rộng viewport. Chẳng hạn, 10vw khiến cỡ chữ bằng 10% chiều rộng màn hình. Tuy nhiên, chỉ dùng vw sẽ gây ra hai vấn đề: chữ quá lớn trên màn hình siêu rộng và quá nhỏ trên điện thoại.
Hàm clamp() giải quyết phần lớn vấn đề này bằng ba giá trị: mức nhỏ nhất, mức ưu tiên và mức lớn nhất.
h1 {
font-size: clamp(1.8rem, 10vw, 5rem);
}
Trong ví dụ trên, tiêu đề không thể nhỏ hơn 1.8rem và không thể lớn hơn 5rem. Ở vùng giữa hai giới hạn, nó thay đổi theo 10vw. Nếu màn hình quá hẹp, tiêu đề có thể xuống dòng, và đó thường là lựa chọn tốt hơn việc làm chữ quá nhỏ đến mức khó đọc.
Còn một điểm quan trọng về khả năng tiếp cận: vw không phản hồi theo thao tác phóng to trang như rem. Vì vậy, hãy kết hợp đơn vị phụ thuộc viewport với một đơn vị có thể zoom, bằng calc().
h1 {
font-size: clamp(1.8rem, calc(7vw + 1rem), 5rem);
}
Công thức này giúp tiêu đề vừa thay đổi theo màn hình, vừa phản hồi tốt hơn khi người dùng phóng to nội dung. Bạn vẫn cần điều chỉnh các con số theo font chữ, độ dài tiêu đề và thiết kế thực tế của mình.
3. Giữ hình ảnh co giãn đúng tỷ lệ và hạn chế CLS
Hình ảnh HTML không tự động responsive. Khi cửa sổ trình duyệt hẹp đi, ảnh có thể tràn khỏi màn hình. Quy tắc nền tảng để ngăn điều đó là đặt max-width: 100% và height: auto.
img {
max-width: 100%;
height: auto;
}
Bạn vẫn nên khai báo thuộc tính width và height trong HTML. Việc này giúp trình duyệt dành sẵn không gian cho ảnh trước khi ảnh tải xong, từ đó giảm Cumulative Layout Shift, hay CLS. CLS xảy ra khi nội dung đang đọc bị đẩy lệch vì hình ảnh hoặc tài nguyên khác xuất hiện muộn.
Khi một nhóm ảnh có kích thước gốc khác nhau, bạn có thể dùng aspect-ratio để tạo bố cục nhất quán. Ví dụ, 1 / 1 tạo khung vuông, 16 / 9 phù hợp với khung ngang và 9 / 16 phù hợp với khung dọc.
Sau khi ép tỷ lệ khung, ảnh có thể bị méo nếu không khai báo object-fit. Chọn contain khi bạn muốn giữ trọn vẹn hình ảnh, chấp nhận phần trống trong khung. Chọn cover khi bạn muốn lấp đầy khung, chấp nhận việc một phần ảnh bị cắt.
4. Dùng dvh thay cho 100vh trên điện thoại
100vh thường được dùng để làm một khu vực cao bằng toàn bộ màn hình. Trên desktop, cách này hoạt động ổn. Nhưng trên điện thoại thật, phần tử có thể cao hơn vùng hiển thị, khiến bạn phải cuộn dù đã đặt chiều cao là 100 viewport height.
Nguyên nhân là trình duyệt di động có thanh địa chỉ và các thành phần giao diện riêng. Không gian này có thể không được phản ánh đúng trong vh. Công cụ mô phỏng thiết bị trong trình duyệt đôi khi không cho thấy rõ lỗi này, vì vậy bạn nên kiểm tra trên điện thoại thực tế.
Đơn vị dvh, viết tắt của dynamic viewport height, được tạo ra để xử lý tình huống này. Bạn có thể khai báo cả hai giá trị để tăng khả năng tương thích:
.hero {
height: 100vh;
height: 100dvh;
}
Trình duyệt không hỗ trợ dvh sẽ bỏ qua dòng đó và dùng 100vh. Trình duyệt hiện đại sẽ dùng 100dvh, giúp phần tử bám chính xác hơn vào chiều cao vùng hiển thị thực tế trên điện thoại.
5. Ẩn menu hamburger mà không làm hỏng khả năng truy cập
Ở màn hình nhỏ, thanh điều hướng thường được chuyển thành menu hamburger. Nếu muốn tạo hiệu ứng mờ dần hoặc trượt vào, bạn không thể chỉ dùng display: none, vì thuộc tính này không hỗ trợ transition.
Nhiều cách thay thế như đổi opacity về 0 hoặc đẩy menu ra ngoài màn hình bằng position: absolute có thể tạo hiệu ứng đẹp. Nhưng menu đã ẩn vẫn có thể nhận focus hoặc vẫn xuất hiện trong accessibility tree. Điều đó khiến người dùng bàn phím và công nghệ hỗ trợ có thể vô tình tương tác với nội dung không nhìn thấy.
Giải pháp là dùng thuộc tính HTML inert. Thuộc tính này loại phần tử khỏi accessibility tree và ngăn tương tác với các phần tử bên trong. Khi menu đóng, hãy thêm inert; khi menu mở, hãy gỡ nó ra trong logic JavaScript.
inert không tự xây dựng toàn bộ menu accessible cho bạn. Bạn vẫn cần xử lý trạng thái mở đóng, focus và logic điều khiển phù hợp. Tuy nhiên, đây là một bước quan trọng để hiệu ứng chuyển động không đánh đổi khả năng sử dụng.
FAQ
Có thể bỏ hoàn toàn media query khi làm CSS responsive không?
Không nhất thiết. Các hàm như min(), clamp() và đơn vị tương đối có thể giảm số lượng media query, nhưng media query vẫn hữu ích khi bố cục hoặc hành vi cần thay đổi rõ rệt ở một kích thước nhất định.
Nên dùng object-fit contain hay cover?
Dùng contain khi toàn bộ nội dung ảnh phải được nhìn thấy. Dùng cover khi bạn cần các khung ảnh đồng đều và chấp nhận cắt một phần ảnh để lấp đầy khung.
Tại sao menu ẩn bằng opacity vẫn có thể gây vấn đề?
Opacity chỉ làm phần tử trong suốt, không loại nó khỏi khả năng focus hay accessibility tree. Thuộc tính inert giúp phần tử ẩn không thể bị tương tác cho đến khi được hiển thị trở lại.
Nếu website của bạn cần hiển thị ổn định trên desktop lẫn điện thoại, một quy trình thiết kế website chuẩn responsive sẽ giúp kiểm soát đồng thời trải nghiệm, hiệu năng và khả năng truy cập.
