Mobile: Viewport Units, Dynamic Viewport Và Safe Area Insets

Trong kỷ nguyên “Mobile First”, việc kiểm soát hiển thị trên các thiết bị di động không chỉ dừng lại ở việc sử dụng Media Queries. Sự đa dạng về phần cứng (Notch, Dynamic Island) và hành vi của trình duyệt (thanh địa chỉ ẩn/hiện) đã tạo ra những thách thức lớn cho các đơn vị đo lường truyền thống. Bài viết này sẽ phân tích chuyên sâu về sự tiến hóa của Viewport Units và cách ứng dụng Safe Area Insets để xây dựng giao diện chuẩn xác.

1. Hạn chế của Viewport Units truyền thống (vh, vw)

1.1 Khái niệm cơ bản

Đơn vị Viewport truyền thống được xác định dựa trên kích thước của Initial Containing Block.

  • 1vh: Tương đương $1\%$ chiều cao của viewport.
  • 1vw: Tương đương $1\%$ chiều rộng của viewport.
1.2 “Cơn ác mộng” trên trình duyệt di động

Vấn đề lớn nhất của 100vh trên thiết bị di động (đặc biệt là Safari trên iOS và Chrome trên Android) là sự không nhất quán khi thanh địa chỉ (Address Bar) thay đổi trạng thái.

  • Trạng thái thanh địa chỉ hiện hữu: Trình duyệt tính toán 100vh bao gồm cả phần diện tích bên dưới thanh địa chỉ. Kết quả là nội dung quan trọng ở cuối trang (như nút CTA) thường bị che khuất.
  • Hiện tượng Layout Shift: Khi người dùng cuộn trang, thanh địa chỉ thu nhỏ, giá trị thực tế của viewport thay đổi nhưng vh không cập nhật ngay lập tức hoặc gây ra hiện tượng giật (flicker) cho giao diện.

2. Kỷ nguyên mới: Dynamic Viewport Units

Để khắc phục các hạn chế trên, Specification của CSS đã bổ sung các đơn vị viewport mới, cho phép lập trình viên kiểm soát chính xác hơn dựa trên trạng thái của UI trình duyệt.

2.1 Small Viewport (svh, svw)

Đơn vị Small Viewport được tính toán khi các thành phần giao diện của trình duyệt (thanh địa chỉ, thanh công cụ) đang ở trạng thái hiển thị tối đa.

  • Đặc điểm: Đây là giá trị “an toàn” nhất. Nếu bạn đặt height: 100svh, phần tử đó sẽ luôn hiển thị đầy đủ trong vùng nhìn thấy mà không bao giờ bị thanh địa chỉ che mất.
2.2 Large Viewport (lvh, lvw)

Ngược lại, Large Viewport được tính toán khi các thành phần giao diện trình duyệt ở trạng thái thu nhỏ hoặc ẩn hoàn toàn.

  • Đặc điểm: 100lvh tương đương với cách hoạt động của 100vh cũ trên một số trình duyệt. Nó tận dụng tối đa không gian màn hình nhưng có rủi ro bị che khuất nội dung ở các cạnh.
2.3 Dynamic Viewport (dvh, dvw)

Đây là đơn vị linh hoạt nhất. Giá trị của nó sẽ tự động điều chỉnh khi thanh địa chỉ thay đổi trạng thái.

  • Cơ chế: Khi thanh địa chỉ co lại, 100dvh sẽ giãn ra bằng 100lvh. Khi thanh địa chỉ hiện lên, nó thu lại bằng 100svh.
  • Lưu ý hiệu năng: Việc lạm dụng dvh cho quá nhiều phần tử có thể gây áp lực lên tiến trình render (Reflow) vì trình duyệt phải tính toán lại kích thước liên tục trong khi cuộn.

3. Xử lý phần cứng đặc thù với Safe Area Insets

Ngoài các thành phần phần mềm (UI trình duyệt), lập trình viên còn phải đối mặt với các yếu tố phần cứng như “tai thỏ” (Notch), camera đục lỗ, hoặc thanh điều hướng hệ thống (Home Indicator).

3.1 Khái niệm Safe Area

Safe Area là vùng hiển thị không bị che khuất bởi các yếu tố thiết kế phần cứng hoặc giao diện hệ thống. Để truy cập vào các giá trị này, chúng ta sử dụng hàm env() (environment variables) được giới thiệu từ iOS 11.

3.2 Các biến môi trường phổ biến
  • safe-area-inset-top: Khoảng cách từ mép trên màn hình đến vùng an toàn (thường dùng cho các thiết bị có Notch).
  • safe-area-inset-bottom: Khoảng cách từ mép dưới (tránh thanh Home Indicator).
  • safe-area-inset-left / right: Cần thiết khi người dùng xoay ngang điện thoại (Landscape).
3.3 Cách triển khai kỹ thuật

Để sử dụng được env(), bạn bắt buộc phải khai báo thuộc tính viewport-fit=cover trong thẻ meta:

HTML

<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

Sau đó, áp dụng trong CSS để tránh việc nội dung bị đè lên:

CSS

header {
  /* Kết hợp giữa padding chuẩn và khoảng cách an toàn */
  padding-top: calc(20px + env(safe-area-inset-top));
}

4. Phân tích so sánh và Chiến lược áp dụng

Tiêu chívh / vwsvh / svwlvh / lvwdvh / dvw
Tính ổn địnhThấp (biến thiên tùy trình duyệt)Rất cao (cố định theo vùng nhỏ nhất)Cao (cố định theo vùng lớn nhất)Trung bình (thay đổi khi cuộn)
Trải nghiệm người dùngDễ gây mất nội dungAn toàn, dễ dự đoánTận dụng không gian tốtHiện đại, mượt mà
Trường hợp sử dụngDesktop hoặc ứng dụng đơn giảnCác form đăng nhập, Modal, SidebarCác trang Landing page nghệ thuậtHero Section, Full-screen App

5. Các sai lầm thường gặp và Giải pháp

  • Chỉ sử dụng 100vh cho Hero Section: Điều này thường dẫn đến việc nút “Scroll Down” bị che mất trên mobile.
    • Giải pháp: Thay thế bằng 100dvh hoặc 100svh.
  • Quên khai báo viewport-fit=cover: Khiến cho các giá trị env() luôn trả về 0, dẫn đến nội dung bị dính chặt vào mép Notch trên iPhone.
  • Không có Fallback cho trình duyệt cũ: Mặc dù hỗ trợ hiện nay đã rất rộng, nhưng với các hệ điều hành cũ, bạn nên viết fallback:CSS.element { height: 100vh; /* Fallback */ height: 100dvh; }

6. Kết luận

Việc nắm vững sự khác biệt giữa các đơn vị Viewport và Safe Area Insets không chỉ giúp bạn giải quyết các bug hiển thị khó chịu mà còn nâng cao tính chuyên nghiệp cho sản phẩm. Trong hầu hết các trường hợp trên mobile:

  • Hãy dùng svh nếu bạn muốn sự chắc chắn tuyệt đối.
  • Hãy dùng dvh nếu bạn muốn một giao diện thích ứng hoàn hảo.
  • Luôn sử dụng Safe Area Insets để tôn trọng thiết kế phần cứng của thiết bị.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Lên đầu trang