3 điểm bởi GN⁺ 2024-12-08 | Chưa có bình luận nào. | Chia sẻ qua WhatsApp
  • Phần tử HTML `` tạo hộp thoại modal và không modal gốc của trình duyệt; hộp thoại modal sẽ đưa phần còn lại của trang vào trạng thái inert để chặn tương tác
  • Cách mở và đóng cơ bản là showModal(), show(), close(); cũng có thể điều khiển theo kiểu khai báo bằng ``, Invoker Commands API và Popover API
  • Thuộc tính closedby chia các cách người dùng có thể đóng hộp thoại thành any, closerequest, none, và hành vi mặc định thay đổi tùy theo cách hộp thoại được mở
  • Về khả năng truy cập, tiêu điểm ban đầu và nút đóng tường minh rất quan trọng; hộp thoại mở bằng showModal() mặc định sẽ đưa tiêu điểm tới phần tử đầu tiên có thể nhận focus và hỗ trợ đóng bằng phím Esc
  • Có thể tạo kiểu bằng :modal, :open, ::backdrop; với hoạt ảnh cần xử lý chuyển đổi rời rạc như display, overlay, @starting-style, transition-behavior: allow-discrete

Vai trò của `` và hành vi modal

  • Phần tử HTML `` dùng để tạo hộp thoại modal và không modal
  • Hộp thoại modal chặn tương tác với các thành phần UI khác và đưa phần còn lại của trang vào trạng thái inert
  • Hộp thoại không modal vẫn cho phép tiếp tục tương tác với phần còn lại của trang khi đang mở

Trạng thái mở và chính sách đóng

  • `` hỗ trợ các thuộc tính toàn cục, nhưng không nên dùng thuộc tính tabindex
    • Bản thân `` không phải là phần tử tương tác và không nhận focus
    • Nội dung bên trong và nút đóng có thể nhận focus và tương tác
  • Thuộc tính open cho biết hộp thoại đang hoạt động và có thể tương tác
    • Nếu không có thuộc tính open thì hộp thoại sẽ không hiển thị với người dùng
    • Khi hiển thị hộp thoại, nên dùng .show() hoặc .showModal() thay vì thuộc tính open
    • `` được mở bằng thuộc tính open là hộp thoại không modal
    • Có thể đổi trạng thái mở/đóng của hộp thoại không modal bằng cách bật/tắt thuộc tính open, nhưng không được khuyến nghị
  • Thuộc tính closedby chỉ định người dùng có thể đóng hộp thoại theo cách nào
    • any: có thể đóng bằng cả ba cách
      • light dismiss như nhấp hoặc chạm bên ngoài hộp thoại
      • Hành động đặc thù nền tảng như phím Esc, nút quay lại trên di động hoặc cử chỉ dismiss
      • Cách do lập trình viên chỉ định như nút gọi HTMLDialogElement.close() hoặc gửi ``
    • closerequest: có thể đóng bằng hành động đặc thù nền tảng và cách do lập trình viên chỉ định
    • none: chỉ có thể đóng bằng cách do lập trình viên chỉ định
    • Nếu không có giá trị closedby hợp lệ, hộp thoại mở bằng showModal() sẽ hoạt động như closerequest, còn các trường hợp khác sẽ như none

JavaScript và điều khiển khai báo

  • Có thể điều khiển trực tiếp việc hiển thị và đóng `` bằng JavaScript
    • showModal(): hiển thị hộp thoại modal
    • show(): hiển thị hộp thoại không modal
    • close(): đóng hộp thoại
    • Cũng có thể đóng bằng cách gửi bên trong với method="dialog"
    • Hộp thoại modal cũng có thể đóng bằng phím Esc
  • Invoker Commands API cho phép mở và đóng hộp thoại modal chỉ bằng thuộc tính trên nút
    • Khai báo commandforcommand trên ``
    • Các lệnh dùng được cho hộp thoại là "show-modal", "close", "request-close"
Open dialog

  This dialog was opened using an invoker command.

  Close

  • Popover API cho phép mở, đóng và chuyển trạng thái hộp thoại không modal theo kiểu khai báo
    • Thêm thuộc tính popover vào `` để biến nó thành popover
    • Chỉ định popovertarget, popovertargetaction trên nút hoặc phần tử nhập liệu
    • Hộp thoại popover là không modal nên có thể đóng bằng cách nhấp bên ngoài
    • Nếu không chỉ định giá trị cho popover, giá trị mặc định "auto" sẽ được dùng và light dismiss được bật
    • popover="manual" sẽ tắt light dismiss, nên cần cách đóng khác như nút đóng
    • Nếu bỏ qua popovertargetaction, giá trị mặc định toggle sẽ được dùng

Gửi biểu mẫu và xử lý đóng

  • Mọi `` đều cần có cơ chế đóng và phải hoạt động cả trên thiết bị không có bàn phím vật lý
  • Có nhiều cách để đóng
    • Gửi bên trong với method="dialog"
    • Nhấp bên ngoài hộp thoại khi light dismiss đang bật
    • Nhấn phím Esc trên các hộp thoại được cho phép
    • Gọi HTMLDialogElement.close()
  • `` hoặc nút gửi với formmethod="dialog" sẽ đóng hộp thoại
    • Trạng thái của các điều khiển biểu mẫu được giữ lại nhưng biểu mẫu không được gửi đi
    • returnValue được đặt thành giá trị của nút đang kích hoạt
  • Với biểu mẫu có trường bắt buộc, user agent sẽ không cho phép đóng hộp thoại bằng gửi thông thường cho tới khi có giá trị
    • Có thể dùng formnovalidate trên nút đóng để bỏ qua kiểm tra biểu mẫu
    • Hoặc gọi dialog.close() bằng JavaScript để đóng

Focus và khả năng truy cập

  • Khi mở `` bằng showModal(), mặc định focus sẽ được đặt vào phần tử lồng bên trong đầu tiên có thể nhận focus
  • Có thể dùng thuộc tính autofocus để chỉ định vị trí focus ban đầu phù hợp nhất cho một hộp thoại cụ thể
    • Nếu không có phần tử nào cần tương tác ngay, nên đặt autofocus vào nút đóng
    • Nếu vị trí focus ban đầu không chắc chắn, như với hộp thoại render động, chính `` có thể là vị trí focus ban đầu phù hợp
  • Cách chắc chắn nhất để mọi người dùng đều đóng được là đưa vào các nút tường minh như xác nhận, hủy, đóng
  • Hộp thoại được gọi bằng showModal() mặc định sẽ đóng bằng phím Esc
    • Hộp thoại không modal mặc định không đóng bằng phím Esc
    • Người dùng bàn phím thường kỳ vọng hộp thoại modal có thể đóng bằng phím Esc
    • Nếu có nhiều hộp thoại modal đang mở, phím Esc chỉ nên đóng hộp thoại được hiển thị cuối cùng; khi dùng ``, trình duyệt sẽ cung cấp hành vi này
  • `` gốc cung cấp các tính năng về khả dụng và khả năng truy cập mà hộp thoại tùy biến làm từ phần tử khác phải tự sao chép thủ công
  • Trình duyệt công khai `` tương tự như hộp thoại tùy biến dùng ARIA role="dialog"
    • `` được gọi bằng showModal() ngầm có aria-modal="true"
    • `` được hiển thị bằng show(), thuộc tính open hoặc thay đổi display mặc định sẽ được công khai với aria-modal="false"
    • Khi triển khai hộp thoại modal, mọi thứ ngoài `` và nội dung của nó cần được render là inert; khi dùng showModal(), trình duyệt sẽ cung cấp hành vi này

Tạo kiểu CSS và backdrop

  • Có thể chọn `` bằng tên phần tử như phần tử thông thường
  • Với tạo kiểu theo trạng thái, có thể dùng các pseudo-class :modal, :open
  • Nền của hộp thoại modal có thể được tạo kiểu bằng pseudo-element ::backdrop
    • Áp dụng cho backdrop xuất hiện phía sau `` khi hiển thị hộp thoại bằng showModal()
    • Có thể làm mờ, làm tối hoặc che nội dung phía sau đang ở trạng thái inert

Mẫu sử dụng qua ví dụ

  • Ví dụ Invoker Commands API mở hộp thoại bằng nút command="show-modal" và đóng bằng nút command="close"
    • Có thể mở bằng nút “Open dialog”
    • Có thể đóng bằng nút “Close” hoặc phím Esc
  • Ví dụ Popover API mở và đóng hộp thoại không modal bằng popover, popovertarget, popovertargetaction
    • Có thể đóng bằng nút “Close”, phím Esc hoặc chọn ra ngoài hộp thoại
    • Nếu dùng popover="manual" thì light dismiss sẽ bị tắt
  • Ví dụ thuộc tính open tạo một hộp thoại không modal chỉ bằng HTML đã mở sẵn khi tải trang
    • Có thể đóng bằng nút “OK” trong ``
    • Sau khi đóng sẽ không có cách mở lại được cung cấp
    • Để hiển thị hộp thoại không modal, nên ưu tiên dùng HTMLDialogElement.show()
  • Ví dụ hộp thoại modal mở bằng .showModal() và đóng bằng close()
    • Dùng ::backdrop để tạo kiểu nền chuyển sắc
    • Khi hộp thoại mở, phần ngoài hộp thoại sẽ ở trạng thái inert nên không thể tương tác với tài liệu
  • Ví dụ returnValue xử lý giá trị trả về của hộp thoại bằng biểu mẫu và giá trị nút
    • returnValue mặc định là chuỗi rỗng hoặc giá trị của nút đã gửi biểu mẫu trong hộp thoại
    • Nút “Confirm” truyền giá trị lựa chọn vào close() để dùng làm giá trị trả về
    • Nếu đóng bằng phím Esc thì returnValue không được cập nhật và sự kiện close cũng không phát sinh, nên nội dung `` sẽ không được cập nhật

Hoạt ảnh cho ``

  • bị ẩn sẽ có `display: none`, còn hiển thị sẽ có display: block
  • Khi trạng thái hiển thị thay đổi, nó sẽ được thêm vào hoặc loại khỏi top layer và cây khả năng truy cập
  • Để tạo hoạt ảnh cho ``, thuộc tính display cần có thể animate
    • Trình duyệt hỗ trợ sẽ xử lý display bằng cơ chế hoạt ảnh rời rạc
    • Khi đổi từ none sang block, nó chuyển sang block tại mốc 0% nên hiển thị suốt toàn bộ hoạt ảnh
    • Khi đổi từ block sang none, nó chuyển sang none tại mốc 100% nên hiển thị suốt toàn bộ hoạt ảnh
  • Tạo hoạt ảnh bằng CSS transition

    • Để animate `` bằng CSS transition, cần các tính năng sau
    • @starting-style: cung cấp giá trị bắt đầu chuyển tiếp mỗi khi hộp thoại mở
    • Chuyển tiếp display: giữ hộp thoại ở giá trị display nhìn thấy được trong suốt quá trình chuyển tiếp
    • Chuyển tiếp overlay: trì hoãn việc loại khỏi top layer cho tới khi hoàn tất chuyển tiếp
    • transition-behavior: allow-discrete: bật chuyển tiếp rời rạc cho display, overlay vốn mặc định không animate
    • Trên trình duyệt không hỗ trợ pseudo-class :open, có thể dùng bộ chọn thuộc tính dialog[open] để tạo kiểu cho trạng thái mở
    • Vì `` mỗi lần hiển thị đều đổi từ display: none sang display: block, nên ở mỗi lần chuyển tiếp đi vào, nó sẽ chuyển từ @starting-style sang kiểu dialog:open
  • Hoạt ảnh keyframe

    • Hoạt ảnh keyframe CSS có các ràng buộc khác với transition
    • Không cung cấp @starting-style
    • Bao gồm giá trị display bên trong keyframe
    • Không cần bật allow-discrete một cách tường minh
    • Cũng không cần đặt overlay trong keyframe
    • Hiệu ứng fade-out của backdrop không thể animate khi hộp thoại đóng vì backdrop bị xóa khỏi DOM ngay lập tức

Tóm tắt kỹ thuật

  • Danh mục nội dung: flow content, sectioning root
  • Nội dung được phép: flow content
  • Cả thẻ mở và thẻ đóng đều bắt buộc, không được lược bỏ thẻ
  • Phần tử cha được phép: mọi phần tử chấp nhận flow content
  • Vai trò ARIA ngầm định: dialog
  • Vai trò ARIA được phép: alertdialog
  • Giao diện DOM: HTMLDialogElement
  • Đặc tả: HTML # the-dialog-element

Chưa có bình luận nào.

Chưa có bình luận nào.