Phần tử hộp thoại là một phần tử hữu ích để biểu thị mọi loại hộp thoại trong HTML, hãy tìm hiểu cách hoạt động của phần tử này.
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à 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 phải phương thức (vẫn có thể tương tác với nội dung bên ngoài hộp thoại). Hộp thoại phương thức sẽ 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, 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
.
Hộp thoại phương thức
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ở, có ba cách để đóng hộp thoại: phím thoát, gửi biểu mẫu bằng một nút đã đặt formmethod="dialog"
(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 */
Vì <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. Việc mở hộp thoại phương thức sẽ vô hiệu hoá và làm mờ mọi thứ ngoại 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 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ẽ thấy rằng chỉ nội dung trong hộp thoại mới có thể nhận được tiêu điểm khi hộp thoại phương thức được mở. Mọi thứ bên ngoài hộp thoại phương thức đều không hoạt động miễn là hộp thoại đang mở.
Khi một hộp thoại đóng, dù có ở chế độ phương thức 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 một hộp thoại phương thức mở được mở bằng showModal()
, trạng thái không hoạt động hoặc huỷ kích hoạt sẽ tự động diễn ra; thuộc tính này 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ứ ngoại trừ hộp thoại bằng cách sử dụng phần tử giả ::backdrop
. Phông nền chỉ hiển thị khi <dialog>
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 không có cùng tỷ lệ khung hình với 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()
sẽ mở một hộp thoại, nhưng không thêm phông nền hoặc khiến bất kỳ nội dung nào trở nên bất động.
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 đó, điều quan trọng hơn là bạn phải đảm bảo thêm một phương thức đóng hộp thoại không theo phương thức phương thức. Khi làm như vậy, nếu trình đóng nằm bên ngoài hộp thoại, hãy nhận ra 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ù quy cách không chính thức yêu cầu nút đóng hộp thoại, nhưng bạn nên coi đó là yêu cầu bắt buộc. Phím thoát sẽ đóng hộp thoại phương thức, nhưng không đóng hộp thoại không 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 phương thức HTMLDialogElement.close()
để đóng hộp thoại. Bạn không cần JavaScript. Để đóng <dialog>
mà không cần JavaScript, hãy thêm một 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 quy tắc ràng buộc (trừ khi bạn đặt novalidate
) – nhưng dữ liệu người dùng sẽ không bị xoá hoặc gửi đ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 đảm bảo rằng nút này nhận được tiêu điểm khi hộp thoại mở ra. 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 một thuộc tính returnValue
. 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>
, thì returnValue
sẽ là toasty
.
Khi một hộp thoại được mở, thuộc tính boolean open
sẽ xuất hiện, nghĩa là hộp thoại đang hoạt động và có thể tương tác. Khi hộp thoại mở ra bằng cách thêm thuộc tính open
thay vì thông qua .show()
hoặc .showModal()
, hộp thoại sẽ không có phương thức. Thuộc tính HTMLDialogElement.open
trả về true
hoặc false
, tuỳ thuộc vào việc hộp thoại có thể tương tác hay không, chứ không phải tuỳ thuộc vào việc hộp thoại có phải là hộp thoại 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 hộp thoại đó (và có thể là nội dung khác) có thể nhận được tiêu điểm 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à một cửa sổ xác nhận 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, hãy đặt role="alertdialog"
.
Hộp thoại cũng phải có tên dễ 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 cung cấp kiểu mặc định cho dialog
. Firefox, Chrome và Edge đặt color: CanvasText;
background-color: Canvas;
và Safari đặt color: black; background-color: white;
trong các tệp kiểu của 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
, điều này có thể là ngoài dự kiến. Thuộc tính background-color
không được kế thừa.
Kiểm tra mức độ hiểu biết
Kiểm tra kiến thức của bạn về phần tử hộp thoại.
Bạn định kiểu cho khu vực phía sau hộp thoại như thế nào?
::background
.::backdrop
.background
.