Xử lý horizontal scrollbar khi set width 100vw

 @ 

Vấn đề:

Khi set width cho một phần tử là 100vw, trình duyệt hiển thị thêm thanh scroll ngang.

100vw unexpected
100vw unexpected

Phân tích:

Chiều rộng viewport có thể hiểu nôm na là chiều rộng của cửa sổ trình duyệt hoặc chiều rộng của màn hình (đối với các thiết bị mobile).

Tạm gọi phần tử được set 100vw là A.

Nếu để hiển thị A, trình duyệt không cần hiển thị thêm thanh scroll dọc thì sẽ chẳng có vấn đề gì xảy ra, 100vw tràn đẹp chiều ngang trình duyệt.

Tuy nhiên nếu trình duyệt hiển thị thanh scroll dọc (do nội dung bên trong A vượt quá kích thước chiều dọc của nó) thì lúc này một phần nội dung bên phải của A bị che mất bởi thanh scroll dọc. Chính vì vậy, để giúp người dùng có thể ngó ngiêng nốt phần nội dung đã bị che khuất, trình duyệt buộc lòng phải hiển thị thêm thanh scroll ngang (horizontal scrollbar).

Cách giải quyết:

Thay vì set "cứng" chiều ngang của A là 100% độ rộng của viewport(100vw) thì mình phải tính toán được độ rộng chiều ngang tối đa của A mà không bị overlap với thanh scroll dọc (nếu có).

Công thức : A'width = 100% viewport's width - vertical scrollbar's width

Đầu tiên là phải tìm ra được, độ rộng của thanh scroll dọc.

Độ rộng viewport: window.innerWidth

Window.innerWidth - MDN
Window.innerWidth - MDN

Độ rộng viewport không tính đến thanh scroll dọc: document.body.clientWidth

Element.clientWidth (MDN)
Element.clientWidth (MDN)

Từ đó có được độ rộng thanh scroll dọc:

const scrollbarWidth = window.innerWidth - document.body.clientWidth;

Lưu giá trị này vào một biến css (css variable) để tiện cho việc CSS:

document.body.style.setProperty("--scrollbarWidth", `${scrollbarWidth}px`);

Lưu ý thực hiện việc tính toán này sớm nhất có thể ngay sau khi page được load:

Cuối cùng, set style cho phần tử A:

Done.

;