Açılan işlem paneli veya popover düğme grubu, kullanıcıların minimum alan kaplarken ek işlevlere erişmesi için kullanışlı bir kalıptır. Bu yer paylaşımı deseni, panelin görüntü alanı kısıtlamalarına uyum sağlarken bir tetikleyici öğeye bağlı kalması gerektiğinden düzen karmaşıklığına neden olur. Geçmişte bu işlem için konumları hesaplamak ve çakışmaları yönetmek üzere karmaşık JavaScript kitaplıkları (ör. Popper.js veya Floating UI) gerekiyordu.
CSS Sabit Konumlandırma, bu ilişkileri tamamen CSS'de işlemek için açıklayıcı ve performans açısından optimize edilmiş bir yöntem sunar. Böylece tarayıcılar, konumlandırma ve taşma mantığını yerel olarak yönetebilir.
1. Düğme ve panel ilişkisini tanımlama
İlk adım, Popover API'yi kullanarak yer paylaşımı kapsayıcısını açan bir tetikleyici düğme oluşturmaktır.
ZORUNLU Erişilebilirlik Ayrımı: Bu kalıp, gerçek bir ARIA menüsü yerine popover içinde gösterilen bir düğme grubunu açıkça modeller. İlgili klavye ile gezinme sözleşmesini tam olarak uygulamadığınız sürece (ör. öğeler arasında uzamsal ok tuşuyla gezinmeyi işleme) role="menu" veya role="menuitem" kullanmayın. Aynı nedenle, tetikleyiciye aria-haspopup eklemeyin. Değeri (menu, listbox, tree, grid veya eski true), hedefin eşleşen bir rolü gösterdiğini garanti eder ancak bu kalıp bunu yapmaz.
<button popovertarget="action-panel">
Open Actions
</button>
<!-- Use the Popover API (`popover="auto"`) for the overlay to ensure it is placed in the top layer and handled accessibly by the browser. -->
<div id="action-panel" popover="auto" class="panel">
<button class="action-item" type="button">Edit</button>
</div>
Bu, düğme ile panel arasında dolaylı bir sabitleyici ilişkilendirmesi oluşturur. Böylece panel, düğmede anchor-name veya panelde position-anchor kullanılmasına gerek kalmadan düğmeye göre yerel olarak konumlandırılabilir.
2. position-area ile konumlandırma
Manuel top/left ofsetleri yerine, hedefi sabitleyiciye göre 3x3'lük bir ızgaraya yerleştirmek için position-area kullanın.
.panel {
/*
Position the panel below the anchor (block-end),
aligned to the start of the anchor and spanning to its end (span-inline-end).
*/
position-area: block-end span-inline-end;
/* Reset insets to allow the grid to take control */
inset: auto;
}
Sağdan sola ve farklı yazma modlarını otomatik olarak desteklemek için fiziksel anahtar kelimeler (left, top) yerine mantıksal anahtar kelimeleri (span-inline-end, block-start) tercih edin.
ZORUNLU: position-area içinde fiziksel ve mantıksal anahtar kelimeleri karıştırmayın.
3. Uç Nokta Dayanıklılığı (Yedekler) Uygulama
Panelin ekranın kenarında kesilmesini önlemek için varsayılan konum taşarsa tarayıcının denemesi gereken "deneme taktikleri" tanımlayın.
.panel {
/*
If the panel overflows the bottom, flip it to the top (flip-block).
If it overflows the inline edges, flip it horizontally (flip-inline).
If it overflows both (e.g., in a corner), flip on both axes (flip-block flip-inline).
*/
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
}
Açılır listeniz veya açılır menünüz, hangi yedek konumun seçildiğine bağlı olarak stil değiştirmesi gereken bir yön oku veya kenarlık içeriyorsa Konuma Duyarlı İpuçları bölümüne bakın. JavaScript olmadan iletişim kutularının ve popover'ların bildirimli olarak çağrılması için Bildirimli İletişim Kutusu ve Popover Kontrolü başlıklı makaleyi inceleyin.
Yedek stratejiler
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.
Sabit konumlandırma özelliği olmayan tarayıcıları desteklemek için makul bir konum ayarlamanız gerekir. Varsayılan olarak popover'lar ekranın ortasında yer alır. Bu, kullanım alanınıza uygun olabilir.
Bazı kullanım alanlarında, bazı sabitleyici konumlandırma kullanım alanları için destek ekleyen @oddbird/css-anchor-positioning polyfill'i kullanabilirsiniz. Örtük sabitleyiciler desteklenmediğinden tetikleyiciye sabitleyici adları eklemeniz GEREKİR. Ayrıca, position-area polyfill tarafından popover'larda desteklenmez. Bu nedenle, istediğiniz iç kısımlarda anchor() kullanmanız GEREKİR.
<!-- MANDATORY: Conditionally install the anchor positioning polyfill -->
<script type="module">
if (!("anchorName" in document.documentElement.style)) {
await import("https://unpkg.com/@oddbird/css-anchor-positioning");
}
</script>
.panel {
/* Mandatory: use explicit anchor name */
position-anchor: --kebab-anchor;
/* Mandatory: use insets rather than position-area for positioning */
bottom: auto;
right: auto;
top: anchor(bottom);
left: anchor(left);
margin: 0;
}