Hộp thoại

Hộp thoại phương thức là một loại hộp bật lên đặc biệt trên trang web: cửa sổ bật lên làm người dùng ngừng tập trung vào chính nó. Có một số trường hợp sử dụng hợp lệ để mở hộp thoại, nhưng bạn cũng nên cân nhắc nên được thực hiện trước khi thực hiện. Hộp thoại mô-đun buộc người dùng tập trung vào nội dung cụ thể và tạm thời bỏ qua phần còn lại của trang.

Hộp thoại có thể là hộp thoại theo phương thức (chỉ có thể tương tác với nội dung trong hộp thoại) hoặc không theo phương thức (bạn vẫn có thể tương tác với nội dung nằm ngoài hộp thoại). Hộp thoại mô-đun xuất hiện ở đầu phần nội dung còn lại của trang. Phần còn lại của trang ở giữa và theo mặc định, bị phông nền bán trong suốt che khuất.

Phần tử HTML <dialog> ngữ nghĩa để tạo hộp thoại đi kèm với ngữ nghĩa, hoạt động tương tác với bàn phím, cũng như tất cả các thuộc tính và phương thức của giao diện HTMLDialogElement.

Dưới đây là ví dụ về một phương thức <dialog>. Mở hộp thoại có mục "Mở hộp thoại phương thức" . Sau khi mở hộp thoại, có ba cách để đóng hộp thoại: dùng phím Escape, gửi biểu mẫu có một nút có formmethod="dialog" đặt (hoặc nếu chính biểu mẫu đã đặt method="dialog") và phương thức HTMLDialogElement.close().

HTMLDialogElement có 3 phương thức chính, cùng với tất cả các phương thức kế thừa từ HTMLElement.

dialog.show() /* opens the dialog */
dialog.showModal() /* opens the dialog as a modal */
dialog.close() /* closes the dialog */

<dialog> này được mở qua HTMLDialogElement.showModal() đó là một hộp thoại phương thức. Thao tác mở hộp thoại phương thức sẽ tắt và che khuất mọi thứ trừ chính hộp thoại đó. Nếu bạn di chuột qua giao diện người dùng bên ngoài hộp thoại, bạn sẽ thấy tất cả các thành phần đang hoạt động như thể pointer-events: none; đã được đặt; ngay cả nút mở hộp thoại cũng không phản ứng với tương tác.

Khi hộp thoại mở ra, tiêu điểm sẽ di chuyển vào hộp thoại đó. Tiêu điểm được đặt trên phần tử đầu tiên theo thứ tự điều hướng bằng bàn phím tuần tự trong hộp thoại đó. Nếu nhấn phím tab nhiều lần, bạn sẽ lưu ý rằng chỉ nội dung trong hộp thoại mới có thể được lấy tiêu điểm khi hộp thoại phương thức mở. Mọi nội dung bên ngoài hộp thoại phương thức đều ở chế độ trơ miễn là hộp thoại này đang mở.

Khi hộp thoại đóng, dù là ở chế độ hay không, tiêu điểm sẽ được trả về phần tử đã mở hộp thoại đó. Nếu bạn lập trình khi mở một hộp thoại không dựa trên hành động của người dùng, hãy xem xét lại. Nếu phải, hãy đảm bảo đặt tiêu điểm về vị trí trước khi hộp thoại mở, đặc biệt nếu người dùng đóng hộp thoại mà không tương tác.

Bạn có thể dùng một thuộc tính chung inert để vô hiệu hoá một phần tử và tất cả các phần tử con cháu của phần tử đó, trừ bất kỳ phần tử nào đang hoạt động . Khi bạn mở một hộp thoại phương thức bằng showModal(), trạng thái trơ hoặc huỷ kích hoạt sẽ không bị ảnh hưởng; thuộc tính không được đặt rõ ràng.

Bạn có thể tạo kiểu cho phông nền che khuất mọi thứ khác ngoài hộp thoại bằng ::backdrop phần tử giả. Phông nền chỉ hiển thị khi một <dialog> được hiển thị bằng phương thức .showModal(). Phần tử giả này khớp với tất cả phông nền, bao gồm cả phông nền hiển thị khi sử dụng FullScreen API, chẳng hạn như khi xem video ở chế độ toàn màn hình mà không có cùng tỷ lệ khung hình như màn hình hoặc màn hình.

Hộp thoại phi phương thức

Tương tự như vậy, HTMLDialogElement.show() cũng mở ra một hộp thoại, nhưng không thêm phông nền hoặc khiến mọi thứ trở nên trơ. Phím Escape không đóng các hộp thoại không theo phương thức. Do đó, bạn cần phải đảm bảo bao gồm cả phương thức về việc đóng hộp thoại không theo phương thức. Khi làm vậy, nếu càng ở gần bên ngoài hộp thoại hơn, thì tiêu điểm sẽ chuyển đến phần tử đã mở hộp thoại, đây có thể không phải là trải nghiệm người dùng tốt nhất.

Mặc dù thông số kỹ thuật không yêu cầu nút đóng hộp thoại chính thức, nhưng hãy xem đây là nút bắt buộc. Phím Escape sẽ đóng hộp thoại theo phương thức nhưng không đóng hộp thoại không theo phương thức. Nút hiển thị có thể nhận tiêu điểm sẽ cải thiện khả năng hỗ trợ tiếp cận và trải nghiệm người dùng.

Đóng hộp thoại

Bạn không cần sử dụng phương thức HTMLDialogElement.close() để đóng hộp thoại. Bạn hoàn toàn không cần JavaScript. Để đóng <dialog> nếu không có JavaScript, hãy thêm biểu mẫu có phương thức hộp thoại bằng cách đặt method="dialog" trên <form> hoặc formmethod="dialog" trên nút.

Khi người dùng gửi thông qua phương thức dialog, trạng thái của dữ liệu do người dùng nhập sẽ được duy trì. Mặc dù có một sự kiện gửi: biểu mẫu sẽ trải qua quy trình xác thực điều kiện ràng buộc (trừ phi bạn đặt novalidate) – dữ liệu người dùng sẽ không bị xoá hay gửi. Nút đóng không có JavaScript có thể được viết là:

<dialog open>
  <form method="dialog">
    <button type="submit" autofocus>close</button>
  </form>
</dialog>

Bạn có thể đã thấy thuộc tính autofocus được đặt vào <button> đóng trong ví dụ này. Các phần tử có thuộc tính autofocus được đặt trong <dialog> sẽ không nhận được tập trung vào tải trang (trừ khi trang được tải với hộp thoại hiển thị). Tuy nhiên, các ảnh này sẽ được lấy tiêu điểm khi hộp thoại mở.

Theo mặc định, khi một hộp thoại được mở, phần tử có thể làm tâm điểm đầu tiên trong hộp thoại đó sẽ nhận tiêu điểm trừ phi một phần tử khác trong hộp thoại có tập hợp thuộc tính autofocus. Việc đặt thuộc tính autofocus trên nút đóng sẽ đảm bảo nó sẽ nhận được tiêu điểm khi hộp thoại được mở. Nhưng bao gồm autofocus trong <dialog> chỉ nên được cân nhắc thật kỹ. Tất cả các thành phần trong trình tự xuất hiện trước thành phần lấy nét tự động đều bị bỏ qua. Chúng ta sẽ thảo luận kỹ hơn về thuộc tính này trong bài học về trọng tâm.

Giao diện HTMLDialogElement bao gồm returnValue thuộc tính này. Việc gửi biểu mẫu bằng method="dialog" sẽ đặt returnValue thành name (nếu có) của nút gửi dùng để gửi biểu mẫu. Nếu chúng ta viết <button type="submit" name="toasty">close</button>, returnValue sẽ là toasty.

Khi một hộp thoại được mở, thuộc tính boolean open có tồn tại, nghĩa là hộp thoại đang hoạt động và có thể tương tác. Khi một hộp thoại được mở bằng cách thêm thuộc tính open thay vì so với qua .show() hoặc .showModal(), hộp thoại sẽ không có phương thức. HTMLDialogElement.open thuộc tính sẽ trả về true hoặc false, tuỳ thuộc vào việc hộp thoại có sẵn để tương tác hay không, chứ không phải là hộp thoại đó có phương thức hay không.

Mặc dù JavaScript là phương thức ưu tiên để mở hộp thoại, bao gồm cả thuộc tính open khi tải trang rồi xoá bằng .close(), có thể giúp đảm bảo hộp thoại hoạt động ngay cả khi JavaScript không hoạt động.

Thông tin chi tiết khác

Không sử dụng tabindex

Phần tử được kích hoạt để mở hộp thoại và nút đóng có trong đó (và có thể cả nội dung khác) có thể nhận tập trung và có tính tương tác. Phần tử <dialog> không tương tác và không nhận được tiêu điểm. Không thêm thuộc tính tabindex vào chính hộp thoại.

Vai trò ARIA

Vai trò ngầm ẩn là dialog. Nếu hộp thoại là cửa sổ xác nhận thông báo một thông báo quan trọng yêu cầu xác nhận hoặc phản hồi khác của người dùng, đặt role="alertdialog". Hộp thoại cũng phải có tên thành phần hỗ trợ tiếp cận. Nếu văn bản hiển thị có thể là tên thành phần hỗ trợ tiếp cận, hãy thêm aria-labelledby="idOfLabelingText".

Giá trị mặc định của CSS

Xin lưu ý rằng trình duyệt định kiểu mặc định cho dialog. Firefox, Chrome và Edge đã đặt color: CanvasText; background-color: Canvas; và Safari sẽ đặt color: black; background-color: white; trong biểu định kiểu tác nhân người dùng. color được kế thừa từ dialog chứ không phải từ body hoặc :root. Đây có thể là những thông tin ngoài dự kiến. Thuộc tính background-color không được kế thừa.

Kiểm tra kiến thức

Kiểm tra kiến thức của bạn về phần tử hộp thoại.

Bạn tạo kiểu cho vùng phía sau hộp thoại này như thế nào?

Với phần tử giả ::background.
Hãy thử lại.
Với phần tử giả ::backdrop.
Chính xác!
Với thuộc tính background.
Hãy thử lại.