Hộp thoại

Phần tử hộp thoại là phần tử hữu ích để trình bày bất kỳ loại hộp thoại nào trong HTML, tìm hiểu cách hoạt động của HTML.

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: một hộp bật lên làm gián đoạn người dùng để tập trung vào chính hộp đó. Có một số trường hợp sử dụng hợp lệ để bật hộp thoại, nhưng bạn cần cân nhắc kỹ trước khi làm như vậy. Hộp thoại phương thức buộc người dùng tập trung vào một nội dung cụ thể và ít nhất là 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 là không hoạt động và theo mặc định, bị che khuất bởi một phông nền bán trong suốt.

Phần tử <dialog> HTML ngữ nghĩa để tạo hộp thoại đi kèm với ngữ nghĩa, các hoạt động tương tác bằng bàn phím và tất 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 <dialog> phương thức. Mở hộp thoại bằng nút "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ó ba 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ở thông qua phương thức HTMLDialogElement.showModal(), nên đây 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 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 phần tử đ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 các lượt tương tác.

Khi hộp thoại được mở, 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 mở hộp thoại không dựa trên hành động của người dùng theo phương thức lập trình, hãy cân nhắc lại. Nếu cần, hãy đảm bảo rằng tiêu điểm được đưa về vị trí trước khi mở hộp thoại, đặc biệt là nếu người dùng đóng hộp thoại mà không tương tác với hộp thoại đó.

Có một thuộc tính inert chung có thể dùng để tắt một phần tử và tất cả phần tử con của phần tử đó, ngoại trừ mọi hộp thoại đ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 không theo phương thức 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 thoát không đóng các hộp thoại không theo phương thức 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 đó, nếu trình đóng nằm bên ngoài hộp thoại, hãy nhận ra rằng 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. Bạn có thể viết nút đóng không có JavaScript như sau:

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

Bạn có thể nhận thấy thuộc tính autofocus được đặt trên <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 tiêu điểm khi tải trang (trừ khi trang được tải với hộp thoại hiển thị). Tuy nhiên, các nút này sẽ nhận được tiêu điểm khi hộp thoại mở ra.

Theo mặc định, khi một hộp thoại được mở, phần tử có thể lấy tiêu điểm đầu tiên trong hộp thoại sẽ nhận được tiêu điểm, trừ phi một phần tử khác trong hộp thoại có thuộc tính autofocus được đặt. 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ở. Tuy nhiên, bạn chỉ nên đưa autofocus vào <dialog> sau khi cân nhắc kỹ lưỡng. Tất cả các phần tử trong trình tự xuất hiện trước phần tử được lấy tiêu điểm tự động sẽ bị bỏ qua. Chúng ta sẽ thảo luận thêm về thuộc tính này trong bài học về tiêu điể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, nhưng việc thêm thuộc tính open khi tải trang, sau đó xoá thuộc tính đó bằng .close() có thể giúp đảm bảo hộp thoại có sẵn ngay cả khi không có JavaScript.

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 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ể cung cấp tê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.
Với phần tử giả ::backdrop.
Với thuộc tính background.