Sắp xếp các thay đổi về cách xếp chồng thành vị trí:đã sửa các phần tử

Tom Wiltzius
Tom Wiltzius

Trong Chrome 22, hành vi bố cục của các phần tử position:fixed có phần khác so với các phiên bản trước. Tất cả phần tử position:fixed hiện tạo thành ngữ cảnh xếp chồng mới. Điều này sẽ thay đổi thứ tự xếp chồng của một số trang, có khả năng làm hỏng bố cục trang. Hành vi mới này khớp với hành vi của trình duyệt WebKit trên thiết bị di động (iOS Safari và Chrome cho Android).

Kết hợp những gì?

Mọi người đều biết và yêu thích z-index để xác định thứ tự chiều sâu của các phần tử trên một trang. Tuy nhiên, không phải mọi chỉ mục z đều được tạo như nhau: z-index của một phần tử chỉ xác định thứ tự của phần tử đó so với các phần tử khác trong cùng ngữ cảnh xếp chồng. Hầu hết các phần tử trên một trang đều nằm trong một ngữ cảnh xếp chồng gốc, nhưng các phần tử được định vị tuyệt đối hoặc tương đối có giá trị z-index không phải tự động sẽ tạo thành ngữ cảnh xếp chồng riêng (tức là tất cả phần tử con của chúng sẽ được sắp xếp theo thứ tự z trong phần tử mẹ và không được xen kẽ với nội dung bên ngoài phần tử mẹ). Kể từ Chrome 22, các phần tử position:fixed cũng sẽ tạo ngữ cảnh xếp chồng riêng.

Để biết thông tin tổng quan chung về ngữ cảnh xếp chồng, bạn nên đọc bài viết này trên MDN.

So sánh position:fixed với thuộc tính position:sticky mới: để tham khảo, position:sticky luôn tạo một ngữ cảnh xếp chồng mới.

Động lực

Các trình duyệt dành cho thiết bị di động (Safari dành cho thiết bị di động, trình duyệt Android, trình duyệt dựa trên Qt) đặt các phần tử position:fixed trong ngữ cảnh xếp chồng riêng và đã có trong một thời gian (kể từ iOS5, Android Gingerbread, v.v.) vì nó cho phép tối ưu hoá một số thao tác cuộn nhất định, giúp các trang web phản hồi thao tác chạm nhanh hơn nhiều. Chúng tôi sẽ áp dụng thay đổi này cho phiên bản dành cho máy tính vì 3 lý do sau:

  1. Hành vi hiển thị khác nhau trên trình duyệt "thiết bị di động" và "máy tính" là một rào cản đối với các tác giả web; CSS phải hoạt động giống nhau ở mọi nơi khi có thể.
  2. Đối với máy tính bảng, không rõ thuật toán tạo ngữ cảnh xếp chồng "thiết bị di động" hay "máy tính để bàn" nào phù hợp hơn.
  3. Việc mang tính năng tối ưu hoá hiệu suất cuộn từ thiết bị di động sang máy tính sẽ mang lại lợi ích cho cả người dùng và tác giả.

Thông tin chi tiết về thay đổi

Dưới đây là ví dụ minh hoạ các hành vi bố cục khác nhau: https://codepen.io/paulirish/pen/CgAof

Với thay đổi này, cả hai phiên bản sẽ hiển thị giống như phiên bản bên phải.

Trong ví dụ này, hộp màu xanh lục có z-index: 1, hộp màu hồng có z-index: 3 và hộp màu cam có z-index: 2. Hộp màu xanh dương là thành phần cấp trên của hộp màu cam và có position:fixed.

Nếu hộp màu xanh dương có ngữ cảnh xếp chồng riêng, thì z-index của hộp màu cam sẽ được tính toán tương ứng với ngữ cảnh xếp chồng của hộp màu xanh dương. Vì hộp màu xanh dương có z-indexauto, nên hộp này có cấp độ xếp chồng là 0 trong ngữ cảnh xếp chồng gốc, điều này có nghĩa là hộp màu cam sẽ nằm sau hộp màu xanh lục và hộp màu hồng, có chỉ mục z là 1 và 3 (tương ứng) trong ngữ cảnh gốc.

Nếu hộp màu xanh dương không có ngữ cảnh xếp chồng riêng, thì z-index của hộp màu cam sẽ được tính toán tương ứng với ngữ cảnh xếp chồng gốc (cùng với hộp màu xanh lục và hồng). Do đó, hộp màu cam kết thúc bằng cách xen kẽ với hộp màu hồng và xanh lục.

Để biết thêm thông tin chi tiết về các tiêu chí tạo ngữ cảnh xếp chồng (và cách thức hoạt động chung của ngữ cảnh xếp chồng), hãy tham khảo lại bài viết này trên MDN. Trong ví dụ này, phiên bản bên phải luôn cung cấp cho hộp màu xanh dương ngữ cảnh xếp chồng riêng vì độ mờ của hộp này nhỏ hơn 1. Thay đổi về hành vi đang được thực hiện một cách hiệu quả sẽ thêm một tiêu chí khác để tạo ngữ cảnh xếp chồng riêng biệt, cụ thể là một phần tử có position:fixed.

Thử nghiệm và tương lai

Để kiểm tra xem trang của bạn có thay đổi hay không, hãy chuyển đến about:flags của Chrome rồi bật/tắt "các phần tử vị trí cố định tạo ngữ cảnh xếp chồng". Nếu bố cục của bạn hoạt động giống nhau trong cả hai trường hợp, thì bạn đã thiết lập xong. Nếu không, hãy đảm bảo rằng bạn chấp nhận được giao diện khi bật cờ đó, vì đó sẽ là giao diện mặc định trong Chrome 22.

Thay đổi này xoá một chức năng – khả năng xen kẽ nội dung trong một cây con position:fixed với nội dung không cuộn từ bên ngoài. Rất khó có nhà phát triển web nào cố tình làm việc này và bạn có thể tạo hiệu ứng tương tự bằng cách cung cấp nhiều phần tử position:fixed cho các phần khác nhau của DOM. Ví dụ: hãy xem xét hai ví dụ sau:

https://codepen.io/wiltzius/pen/gcjCk

Trang này cố gắng lấy hai div con (overlayA và overlayB) của phần tử position:fixed và đặt một div phía trên một div nội dung riêng biệt và một div phía dưới cùng div nội dung riêng biệt đó. Hiện tại, bạn không thể thực hiện việc này vì phần tử position:fixed là ngữ cảnh xếp chồng riêng và phần tử này (cùng với tất cả phần tử con) sẽ nằm hoàn toàn phía trên hoặc hoàn toàn phía dưới div nội dung. Xin lưu ý rằng ví dụ này hoạt động trong Chrome 21 trở xuống nhưng không còn hoạt động trong Chrome 22.

Để khắc phục vấn đề này, bạn có thể chia hai lớp phủ thành vị trí riêng:các phần tử cố định. Mỗi phần tử là một ngữ cảnh xếp chồng riêng, một phần tử có thể nằm phía trên div nội dung và một phần tử có thể nằm phía dưới div nội dung. Hãy xem ví dụ đã sửa, hoạt động trong Chrome 21 và 22:

https://codepen.io/wiltzius/pen/vhFzG

Công lao tạo ra ví dụ này thuộc về hixie không thể bắt chước.

Chrome là trình duyệt dành cho máy tính đầu tiên khiến các phần tử position:fixed tạo ngữ cảnh xếp chồng riêng. Tiêu chuẩn có liên quan là quy cách chỉ số z của CSS (xem ví dụ: https://www.w3.org/TR/CSS21/zindex.html). Hiện chưa có sự đồng thuận về việc nên làm gì đối với sự khác biệt giữa trình duyệt dành cho thiết bị di động và máy tính. Tuy nhiên, do sự nhầm lẫn khi có hai hành vi khác nhau trên thiết bị di động và máy tính, nên Chrome đã chọn chuyển sang hành vi duy nhất này trên cả hai nền tảng trong thời gian này.

Cập nhật ngày 1 tháng 10 năm 2012: Phiên bản gốc của bài viết này cho biết rằng thông số kỹ thuật z-index CSS đã được thay đổi để phản ánh hành vi mới của phần tử position: fixed. Thông tin này không chính xác; vấn đề này đã được thảo luận trên danh sách kiểu www nhưng hiện chưa có thay đổi nào được đưa vào thông số kỹ thuật.