Genel Bakış
Kalıcı ve kalıcı olmayan iletişim kutuları için yerel <dialog> öğesini kullanın. Özel yer paylaşımlarının manuel olarak yeniden oluşturması gereken erişilebilirlik semantiği, odak işleme, üst katman oluşturma ve Esc işleme özelliklerini sağlar.
Yer paylaşımı türünü seçme
Eşleşen ilk kuralı seçin. Emin değilseniz 1. kuralı kullanın.
1. kural: Yer paylaşımı, kullanıcının deneyimini kesintiye uğratır ve sayfayı engeller (varsayılan)
Onaylar, formlar, oturum açma, yıkıcı işlemler ve aksi belirtilmeyen tüm "kalıcı", "iletişim kutusu", "lightbox" veya "pop-up" istekleri için kullanın.
<dialog> öğesini kalıcı olarak açılmış şekilde, command="show-modal" ile bildirimli olarak (Bildirimli İletişim Kutusu ve Popover Kontrolü bölümüne bakın) veya showModal() ile komut dosyasından kullanın.
<button type="button" command="show-modal" commandfor="confirm">Delete</button>
<!-- MANDATORY: no role="dialog" or aria-modal; the native modal already provides them -->
<dialog id="confirm" aria-labelledby="confirm-title">
<h2 id="confirm-title">Delete this item?</h2>
<form method="dialog">
<button value="cancel" autofocus>Cancel</button>
<button value="delete">Delete</button>
</form>
</dialog>
Tarayıcı; inert sayfa, odak sınırlama, üst katman, ::backdrop, Esc ve geri hareketiyle kapatma ve odağın çağırana geri dönmesini sağlar.
role="dialog",aria-modal, odak tuzağı,inertaçma/kapatma veyaEscişleyici EKLEMEYİN.show()veyaopenözelliğiyle açmayın.- DO stop the page scrolling behind it with the CSS below. Ayrıntılar için Kalıcı iletişim kutusunun altındaki sayfanın kaydırılmasını önleme başlıklı makaleyi inceleyin.
htmlveyabodyüzerindeoverflow: hiddenya daposition: fixedile kaydırmayı KİLİTLEMEYİN.
/* MANDATORY (both rules): without them, scrolling over the backdrop or inside the dialog scrolls the page behind it */
dialog:modal {
overscroll-behavior: contain; /* stops scroll gestures in the dialog chaining to the page */
}
dialog::backdrop {
overflow: hidden; /* ::backdrop is not a scroll container by default, so it would ignore overscroll-behavior */
overscroll-behavior: contain;
}
Menüler veya ipuçları için kullanılmaz: 3. kurala bakın.
2. kural: Panel açıkken kullanıcı sayfada çalışmaya devam eder
Anlamsal olarak hâlâ iletişim kutusu olan bulma çubukları, denetleyiciler, paletler ve oluşturma bölmeleri için kullanılır.
Pop-over kapatma özelliğine sahip üst katman paneli için <dialog popover> kullanın (auto hafif kapatma özelliğine sahiptir, manual ise yoktur). dialog.show() özelliğini yalnızca panelin üst katmanda olmaması gerektiğinde kullanın.
<button type="button" popovertarget="find">Find</button>
<dialog id="find" popover="manual" aria-labelledby="find-title">
<h2 id="find-title">Find</h2>
<input type="search" aria-label="Search">
<button type="button" popovertarget="find" popovertargetaction="hide">Close</button>
</dialog>
Sayfa etkileşimli kalır ve devre dışı bırakılmaz.
- Görünür bir kapat düğmesi EKLEYİN.
- Sayfayı engelleyen
showModal()yönergesini KULLANMAYIN.
Onayları engellemek için kullanılmaz: 1. kurala bakın.
3. kural: Yer paylaşımı bir iletişim kutusu değildir
Menüler, açılır listeler, ipuçları, fareyle üzerine gelindiğinde gösterilen kartlar ve kısa süreli bildirimler için kullanılır.
<dialog> yerine popover özelliğine sahip bir semantik öğe kullanın.
<button type="button" popovertarget="menu">Actions</button>
<ul id="menu" popover>
<li><a href="/rename">Rename</a></li>
</ul>
Nasıl kapatılabileceğini seçin
Varsayılan yöntem, iletişim kutusunun nasıl açıldığına bağlıdır. closedby yoksa veya geçersizse showModal(), closerequest olarak davranır ve diğer açma yöntemleri none olarak davranır.
- Yalnızca Esc ve geri hareketi (kalıcı varsayılan): Hiçbir şey ayarlamayın veya
closedby="closerequest". - Kapatmak için dışarıyı da tıklayabilirsiniz:
closedby="any"kullanın. - Yalnızca geliştirici kapatır (örneğin, kaydedilmemiş değişiklikler içeren bir form):
closedby="none"kullanın ve bir onay yolu ekleyin. Aşağıdaki "Kapanış" bölümüne bakın.
Yönergeler
Erişilebilir özellikli ad ve ilk odaklanılan nokta
- Her iletişim kutusunu, başlığına işaret eden
aria-labelledbyile veya görünür bir başlık yoksaaria-labelile adlandırın. autofocusöğesini birincil kontrole veya ilk alana YERLEŞTİRİN.- Yıkıcı bir onayda güvenli işleme (İptal veya Sakla gibi)
autofocusEKLEYİN. - Kapatma işleminde odağı geri döndürmek için kod YAZMAYIN. Tarayıcı, bu değeri çağırana döndürür.
Açılma
<button>üzerindecommand="show-modal"vecommandforile bildirimli olarak açın. Bildirimli İletişim Kutusu ve Popover Kontrolü başlıklı makaleyi inceleyin.- Komut dosyasından açarken
dialog.showModal()KULLANIN.
Kapanma
- DO close with
<form method="dialog">buttons orcommand="close". closedbydeğerini bilinçli olarak seçin:any(hafif kapatma veEsc),closerequest(yalnızcaEsc, kalıcı varsayılan) veyanone(yalnızca geliştirici tarafından kontrol edilen kapatma).- Kaydedilmemiş değişiklikler mantığına uyması gereken İptal düğmeleri için
command="request-close"veyarequestClose()KULLANIN. Öncecanceltetiklenir veclosedbyyok sayılır. closedbyözelliğini progresif geliştirme olarak KULLANIN.Escve mobil geri hareketi, bu özellik olmadan da modalları kapatıyor.
Kapatma işlemine bağlanma
- Hangi düğmenin kullanıldığını öğrenmek için
dialog.returnValuedeğerini birclosedinleyicide OKUYUN, ardındandialog.returnValue = ''ile sıfırlayın.Escve diğer kapatma istekleri değer ayarlamaz ve tarayıcılar önceki değeri temizleyip temizlememe konusunda farklılık gösterir. Bu nedenle, sıfırlama yapılmazsa eski bir değer sızdırılabilir.'', "seçim yapılmadan kapatıldı" olarak değerlendirilir. - DO use
cancelto interceptEscandrequest-close, but do not rely onpreventDefault()for repeatedEscpresses without user activation. - Kirli formlar için açık bir onay adımıyla
closedby="none"KULLANIN. cancelengellendiğinde iletişim kutusunun neden açık kaldığını kullanıcıya SÖYLEYİN: Görünür bir mesaj gösterin ve odaklanan kontrolden (ör. Sil)aria-describedbyile bu mesaja referans verin. Böylece odak taşındığında ekran okuyucu bu mesajı okur. Bu özellik olmadan, odak yeni bir düğmeye taşındığında yalnızca o düğmenin adı duyurulur.- Onay taşıma kontrollerinin işaretçinin altında kalmasına İZİN VERMEYİN. Mesajın alanını ayırın (
displayveyahiddenile değil,visibilityile gizleyin) ve yıkıcı düğmeyi mevcut düğmelerin hareket etmeyeceği bir yere (örneğin, sağa hizalı bir satırda ilk sıraya) ekleyin. Böylece aynı noktaya ikinci kez tıklandığında kullanıcının değişiklikleri silinmez.
Kalıcı olmayan iletişim kutuları
- Üst katman panel için
<dialog popover>(autoveyamanual) ve üst katmanı istemediğinizdedialog.show()KULLANIN. - Kalıcı olmayan her iletişim kutusuna görünür bir kapatma düğmesi EKLEYİN.
Arka plan ve stil
- DO style
::backdropand usedialog:modalto target modal-only styles. - DO leave animation to Animate Elements To and From Top Layer, dragging to Build a Draggable Element, and reparenting to Persistent Top Layer UI.
dialogüzerindedisplayayarını koşulsuz olarak YAPMAYIN. Kapalı durumunu geçersiz kılar.dialog[open]ile kapsamını belirleyin.
Erişilebilirlik
role="dialog",aria-modal, manuel odaklama tuzağı veya yerel bir kalıcı pencereye geçiş yapaninertEKLEMEYİN.- Kapatma kontrolleri için erişilebilir özellikli adı olan yerel bir
<button>KULLANIN. - İletişim kutusu başlıkları için tek bir tutarlı başlık düzeyi KULLANIN.
Yedek stratejiler
closedby (dialog-closedby)
closedby olmadan da kalıcı pencere Esc ve geri hareketiyle kapatılabilir. Yalnızca dışarı tıklama özelliği kullanılamaz. Bu nedenle, bu durum kontrollü azalma olarak kabul edilir. closedby="none" da aynı şekilde yoksayılır: Esc, cancel işlemini tetikler ve ardından iletişim kutusunu kapatır. Kaydedilmemiş değişiklik korumasını yalnızca closedby="none" içinde değil, cancel işleyicisinde tutun. Böylece closedby eksik olduğunda da koruma sağlanır. Baseline hedefiniz için hafif kapatma gerekiyorsa closedby eksik olan yere şunu ekleyin:
if (!('closedBy' in HTMLDialogElement.prototype)) {
// Test the pointer position, not event.target: the <dialog> is also the target for its own
// padding and the gaps between its children, so a target check would close on those clicks
const outside = (e, dialog) => {
const r = dialog.getBoundingClientRect();
return e.clientX < r.left || e.clientX > r.right || e.clientY < r.top || e.clientY > r.bottom;
};
for (const dialog of document.querySelectorAll('dialog[closedby="any"]')) {
let pressedOutside = false;
dialog.addEventListener('pointerdown', (e) => { pressedOutside = outside(e, dialog); });
// Require the press and the release outside, so a text-selection drag that ends on the backdrop does not dismiss
dialog.addEventListener('pointerup', (e) => { if (pressedOutside && outside(e, dialog)) dialog.close(); });
}
}
overscroll-behavior
Kaydırma sınırlamasını progresif geliştirme olarak değerlendirin. Özellik algılama kullanmayın: @supports, kaydırılamayan kapsayıcılar tarafından yoksayılsa bile özelliği destekleniyor olarak bildirir. Uygulanmadığı durumlarda, iletişim kutusu kendi içeriği taştığında kaydırma çubuğunu içerir ve showModal(), sayfayı yine de devre dışı bırakır. html veya body üzerinde overflow: hidden ya da position: fixed değerine geri dönmeyin. Bu, kök kaydırma çubuğunu kaldırır ve düzeni değiştirir.
Çağırıcı Komutları (command / commandfor)
Baseline hedefiniz Invoker Commands'i içermiyorsa aynı işaretlemeyi kullanın ve polyfill'i koşullu olarak yükleyin (progresif geliştirme ile aynı deneyim). Arayüzde algılayın ve hiçbir zaman koşulsuz olarak yüklemeyin:
// MANDATORY: feature detect on HTMLButtonElement.prototype and load only when native support is missing
if (!('commandForElement' in HTMLButtonElement.prototype)) {
import('invokers-polyfill'); // npm install invokers-polyfill
}
Yalnızca 2. ve 3. kurallarda popover kullanılır.
Popover için yedekler ve tarayıcı desteği
Popover API çoğunlukla progresif geliştirme ile ilgilidir ancak tanımlayıcı davranışlarının (üst katman tanıtımı, hafif kapatma ve popovertarget çağrısı) yalnızca CSS'ye dayalı bir eşdeğeri yoktur. Eski tarayıcılar için polyfill veya polyfill kullanmak istemiyorsanız manuel yedek gerekir.
Polyfill: Eski tarayıcılarda popover özelliğini desteklemek için @oddbird/popover-polyfill öğesini koşullu olarak yükleyin. ZORUNLU: HTMLElement.prototype üzerinde popover özelliğini kontrol ederek özelliği tespit edin ve polyfill'i yalnızca yerel destek eksik olduğunda yükleyin. Koşulsuz olarak YÜKLEMEYİN.
Paketleyici veya içe aktarma eşlemesiyle:
// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
import("@oddbird/popover-polyfill");
}
Paketleyici olmadan, <script type="module"> içindeki bir CDN'den içe aktarın:
<script type="module">
if (!("popover" in HTMLElement.prototype)) {
import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
}
</script>
Stil uyarısı: Polyfill, gerçek :popover-open sözde sınıfını tanımlayamadığı için bunun yerine .\:popover-open sınıfını uygular. ZORUNLU: İkisini :is() veya :where() ile birleştirin. Aksi takdirde, :popover-open içermeyen tarayıcılar kuralın tamamını siler:
[popover]:is(:popover-open, .\:popover-open) {
display: block;
}
Alternatif olarak, polyfill içermeyen eski bir yedek için position: fixed kullanın ve koordinatları getBoundingClientRect() aracılığıyla manuel olarak hesaplayın veya kullanım alanına uygunsa inset: auto ile varsayılan konumlandırmayı kullanın.