Erişilebilir bir bölünmüş düğme bileşeninin nasıl oluşturulacağına ilişkin temel bir genel bakış.
Bu gönderide, bölme düğmesi oluşturmanın bir yolu üzerine düşüncelerimi paylaşmak istiyorum . Demoyu deneyin.
Video kullanmayı tercih ederseniz bu gönderinin YouTube versiyonunu kullanabilirsiniz:
Genel Bakış
Bölünmüş düğmeler birer düğmedir birincil düğmeyi ve ek düğmelerin listesini gizleyen reklam öğeleri bulunur. Yararlıdır ikincil dosyayı iç içe yerleştirirken sık kullanılan bir işlemi açığa çıkarmak için (daha az kullanılanlar) işlem gerçekleştiremez. Bölünmüş düğme, yoğun bir tasarım için çok önemli olabilir çok az bile olabilir. Gelişmiş bölme düğmesi, kullanıcının son işlemini bile hatırlayabilir ve birincil sıraya yükseltiyoruz.
Sık kullanılan bir bölme düğmesi e-posta uygulamanızda bulunur. Birincil işlem gönderildi, ancak dilerseniz daha sonra gönderebilir veya taslak kaydedebilirsiniz:
Kullanıcının etrafa bakması gerekmediğinden, paylaşılan işlem alanı güzel. Onlar Temel e-posta işlemlerinin bölme düğmesinde olduğunu bilmeniz yeterli.
Parçalar
Bölünmüş düğmenin temel parçalarını ayrıntılarıyla ele almadan önce son kullanıcı deneyimini sağlamak için tasarlanmıştı. VisBug'un erişilebilirliği İnceleme aracı burada, bileşenin makro görünümünü göstermek için kullanılır. her ana bölüm için HTML, stil ve erişilebilirlik özellikleri.
Üst düzey bölünmüş düğme kapsayıcısı
En üst düzey bileşen,
Birincil işlemi içeren gui-split-button
ve .gui-popup-button
.
Birincil işlem düğmesi
Başlangıçta görünür ve odaklanılabilir <button>
, kapsayıcının içine
iki eşleşen köşe şekli
odak,
fareyle ve
aktif olarak
.gui-split-button
içinde yer alır.
Pop-up açma/kapatma düğmesi
"Pop-up düğmesi" destek öğesi, listenin etkin olmasını ve
ikincil düğmeler. Bunun bir <button>
olmadığına ve odaklanılabilir olmadığına dikkat edin. Ancak,
.gui-popup
için konumlandırma sabiti ve :focus-within
için kullanılan ana makinedir.
pop-up'ı gösterir.
Pop-up kart
Bu, çapasına kayan kart alt öğesidir
.gui-popup-button
, konumlandırılmış mutlak ve
düğme listesini anlamsal olarak sarmalama.
İkincil işlemler
Birincil öğeden biraz daha küçük yazı tipi boyutuna sahip, odaklanılabilir bir <button>
işlem düğmesinde bir simge ve ücretsiz bir
stilini birincil düğmeye ekleyin.
Özel özellikler
Aşağıdaki değişkenler renk uyumunu oluşturmaya yardımcı olur ve renk uyumunu oluştururken bileşen genelinde kullanılan değerleri değiştirebilirsiniz.
@custom-media --motionOK (prefers-reduced-motion: no-preference);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --light (prefers-color-scheme: light);
.gui-split-button {
--theme: hsl(220 75% 50%);
--theme-hover: hsl(220 75% 45%);
--theme-active: hsl(220 75% 40%);
--theme-text: hsl(220 75% 25%);
--theme-border: hsl(220 50% 75%);
--ontheme: hsl(220 90% 98%);
--popupbg: hsl(220 0% 100%);
--border: 1px solid var(--theme-border);
--radius: 6px;
--in-speed: 50ms;
--out-speed: 300ms;
@media (--dark) {
--theme: hsl(220 50% 60%);
--theme-hover: hsl(220 50% 65%);
--theme-active: hsl(220 75% 70%);
--theme-text: hsl(220 10% 85%);
--theme-border: hsl(220 20% 70%);
--ontheme: hsl(220 90% 5%);
--popupbg: hsl(220 10% 30%);
}
}
Düzenler ve renk
Brüt kar
Öğe, özel sınıf adına sahip bir <div>
ile başlar.
<div class="gui-split-button"></div>
Birincil düğmeyi ve .gui-popup-button
öğelerini ekleyin.
<div class="gui-split-button">
<button>Send</button>
<span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions"></span>
</div>
Aria özelliklerine aria-haspopup
ve aria-expanded
dikkat edin. Bu işaretler
ekran okuyucuların bölme özelliği ve durumunun farkında olması açısından
düğme deneyimi. title
özelliği herkesin işine yarar.
Bir <svg>
simgesi ve .gui-popup
kapsayıcı öğesini ekleyin.
<div class="gui-split-button">
<button>Send</button>
<span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions">
<svg aria-hidden="true" viewBox="0 0 20 20">
<path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
</svg>
<ul class="gui-popup"></ul>
</span>
</div>
Basit pop-up yerleşimi için .gui-popup
, düğmenin alt öğesidir.
tarafından genişletilir. Bu stratejinin yakaladığı tek sorun .gui-split-button
kapsayıcı overflow: hidden
etiketini kullanamaz, çünkü pop-up'ın
yardımcı olur.
<li><button>
içerikle doldurulmuş bir <ul>
kendini "düğme olarak" duyurur
liste" Örneğin, ekran okuyucularla tam olarak sunulan arayüz.
<div class="gui-split-button">
<button>Send</button>
<span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions">
<svg aria-hidden="true" viewBox="0 0 20 20">
<path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
</svg>
<ul class="gui-popup">
<li>
<button>Schedule for later</button>
</li>
<li>
<button>Delete</button>
</li>
<li>
<button>Save draft</button>
</li>
</ul>
</span>
</div>
Zevk kazanmak ve renklerle eğlenmek için ikincil düğmelere simgeler ekledim https://heroicons.com adresinde bulabilirsiniz. Her ikisi için simgeler isteğe bağlıdır birincil ve ikincil düğmeleri tıklayın.
<div class="gui-split-button">
<button>Send</button>
<span class="gui-popup-button" aria-haspopup="true" aria-expanded="false" title="Open for more actions">
<svg aria-hidden="true" viewBox="0 0 20 20">
<path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
</svg>
<ul class="gui-popup">
<li><button>
<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
Schedule for later
</button></li>
<li><button>
<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
Delete
</button></li>
<li><button>
<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z" />
</svg>
Save draft
</button></li>
</ul>
</span>
</div>
Stiller
HTML ve içerik yerine, stiller renk ve düzen sağlamaya hazır olur.
Bölünmüş düğme kapsayıcısının stilini belirleme
inline-flex
görüntülü reklam türü, bu sarmalama bileşeni için
diğer bölme düğmeleri, işlemleri veya öğeleri ile satır içine sığmalıdır.
.gui-split-button {
display: inline-flex;
border-radius: var(--radius);
background: var(--theme);
color: var(--ontheme);
fill: var(--ontheme);
touch-action: manipulation;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
<button>
stili
Düğmeler ne kadar kod gerektiğini gizleme konusunda çok başarılıdır. Şunları yapmanız gerekebilir: varsayılan stillerini geri alabilir veya değiştirebilir, ancak aynı zamanda bazı devralma, etkileşim durumları ekleme, çeşitli kullanıcı tercihlerine ve giriş türleri. Düğme stilleri hızlıca eklenir.
Bu düğmeler, arka planı ortak oldukları için normal düğmelerden farklıdır üst öğe içerir. Genellikle bir düğmenin arka planı ve metin rengi kendine ait olur. Fakat bunlar bunu paylaşır ve yalnızca etkileşimle ilgili kendi geçmişlerini uygular.
.gui-split-button button {
cursor: pointer;
appearance: none;
background: none;
border: none;
display: inline-flex;
align-items: center;
gap: 1ch;
white-space: nowrap;
font-family: inherit;
font-size: inherit;
font-weight: 500;
padding-block: 1.25ch;
padding-inline: 2.5ch;
color: var(--ontheme);
outline-color: var(--theme);
outline-offset: -5px;
}
Birkaç CSS içeren etkileşim durumları ekleyin sözde sınıflar ve eşleştirme kullanımı eyalete ilişkin özel özellikler:
.gui-split-button button {
…
&:is(:hover, :focus-visible) {
background: var(--theme-hover);
color: var(--ontheme);
& > svg {
stroke: currentColor;
fill: none;
}
}
&:active {
background: var(--theme-active);
}
}
Birincil düğmenin tasarım efektini tamamlaması için birkaç özel stile ihtiyacı vardır:
.gui-split-button > button {
border-end-start-radius: var(--radius);
border-start-start-radius: var(--radius);
& > svg {
fill: none;
stroke: var(--ontheme);
}
}
Son olarak, biraz daha şık olması için açık tema düğmesi ve simgesi gölge:
.gui-split-button {
@media (--light) {
& > button,
& button:is(:focus-visible, :hover) {
text-shadow: 0 1px 0 var(--theme-active);
}
& > .gui-popup-button > svg,
& button:is(:focus-visible, :hover) > svg {
filter: drop-shadow(0 1px 0 var(--theme-active));
}
}
}
İyi bir düğme, mikro etkileşimlere ve çok küçük ayrıntılara dikkat çekmiş.
:focus-visible
ile ilgili bir not
Düğme stillerinin :focus
yerine :focus-visible
özelliğini nasıl kullandığına dikkat edin. :focus
.
erişilebilir bir kullanıcı arayüzü oluşturmak için çok önemli bir
dezavantaj: kullanıcının reklamı görmesinin gerekip gerekmediği
her odak için geçerlidir.
Aşağıdaki video, bu mikro etkileşimi kırmaya ve böylece
:focus-visible
akıllı bir alternatiftir.
Pop-up düğmesinin stilini belirleme
Bir simgeyi ortalamak ve pop-up düğme listesini sabitlemek için kullanılan 4ch
flex kutusu. Beğenme
birincil düğme, üzerine gelinceye veya etkileşimde bulunulana kadar şeffaf
ve dolduracak şekilde esnetilmişti.
.gui-popup-button {
inline-size: 4ch;
cursor: pointer;
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
border-inline-start: var(--border);
border-start-end-radius: var(--radius);
border-end-end-radius: var(--radius);
}
CSS ile fareyle üzerine gelin, odak ve etkin durumlarda katman oluşturun
İç içe yerleştirme ve
:is()
işlevsel seçici:
.gui-popup-button {
…
&:is(:hover,:focus-within) {
background: var(--theme-hover);
}
/* fixes iOS trying to be helpful */
&:focus {
outline: none;
}
&:active {
background: var(--theme-active);
}
}
Bu stiller, pop-up'ın gösterilmesi ve gizlenmesi için en önemli unsurdur.
.gui-popup-button
, alt öğelerinden herhangi birinde focus
konumuna sahip (opacity
olarak ayarlanmış)
ve pointer-events
, simge ve pop-up'ta gösterilir.
.gui-popup-button {
…
&:focus-within {
& > svg {
transition-duration: var(--in-speed);
transform: rotateZ(.5turn);
}
& > .gui-popup {
transition-duration: var(--in-speed);
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
}
}
Giriş ve çıkış stilleri tamamlandığında, son parça koşullu olarak kullanıcının hareket tercihine bağlı olarak değiştirilir:
.gui-popup-button {
…
@media (--motionOK) {
& > svg {
transition: transform var(--out-speed) ease;
}
& > .gui-popup {
transform: translateY(5px);
transition:
opacity var(--out-speed) ease,
transform var(--out-speed) ease;
}
}
}
Koda dikkat edildiğinde kullanıcılar için opaklık geçişinin hâlâ devam ettiğini fark edebilirsiniz daha az hareket etmeyi tercih eder.
Pop-up'ın stilini belirleme
.gui-popup
öğesi, özel özellikler kullanan bir kayan kart düğmesi listesidir
ve göreceli birimlerin daha küçük, etkileşimli olarak birincil öğe ile eşleştirilmesi
düğmesini ve renk kullanımıyla ilgili markayı dikkate alın. Simgelerin kontrastının daha az olduğuna dikkat edin.
daha ince ve gölgenin de göze hitap eden mavi bir tonu var. Düğmelerde olduğu gibi
güçlü bir kullanıcı arayüzü ve kullanıcı deneyimi sunmak, bu küçük ayrıntıların bir araya gelmesinden kaynaklanır.
.gui-popup {
--shadow: 220 70% 15%;
--shadow-strength: 1%;
opacity: 0;
pointer-events: none;
position: absolute;
bottom: 80%;
left: -1.5ch;
list-style-type: none;
background: var(--popupbg);
color: var(--theme-text);
padding-inline: 0;
padding-block: .5ch;
border-radius: var(--radius);
overflow: hidden;
display: flex;
flex-direction: column;
font-size: .9em;
transition: opacity var(--out-speed) ease;
box-shadow:
0 -2px 5px 0 hsl(var(--shadow) / calc(var(--shadow-strength) + 5%)),
0 1px 1px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 10%)),
0 2px 2px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 12%)),
0 5px 5px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 13%)),
0 9px 9px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 14%)),
0 16px 16px -2px hsl(var(--shadow) / calc(var(--shadow-strength) + 20%))
;
}
Simgelere ve düğmelere, her koyu temada güzel bir stil vermek için marka renkleri verilmiştir ve ışık temalı kart:
.gui-popup {
…
& svg {
fill: var(--popupbg);
stroke: var(--theme);
@media (prefers-color-scheme: dark) {
stroke: var(--theme-border);
}
}
& button {
color: var(--theme-text);
width: 100%;
}
}
Koyu tema pop-up'ında metin ve simge gölgesi eklemelerinin yanı sıra biraz daha fazla yoğun kutu gölgesi:
.gui-popup {
…
@media (--dark) {
--shadow-strength: 5%;
--shadow: 220 3% 2%;
& button:not(:focus-visible, :hover) {
text-shadow: 0 1px 0 var(--ontheme);
}
& button:not(:focus-visible, :hover) > svg {
filter: drop-shadow(0 1px 0 var(--ontheme));
}
}
}
Genel <svg>
simgesi stilleri
Tüm simgeler, Google tarafından kullanılan düğmeye font-size
göre büyüktür.
olarak ch
birimini
inline-size
. Simgelerin yumuşak ve sade olması için her birine
gerekir.
.gui-split-button svg {
inline-size: 2ch;
box-sizing: content-box;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2px;
}
Sağdan sola düzen
Tüm karmaşık işleri mantıksal özellikler yapar.
Kullanılan mantıksal özelliklerin listesi aşağıda verilmiştir:
- display: inline-flex
satır içi esnek öğe oluşturur.
- padding
yerine padding-block
ve padding-inline
mantıksal kenarları doldurmanın avantajlarından yararlanın.
- border-end-start-radius
ve
arkadaşlarınız
köşeleri belgenin yönüne göre yuvarlatın.
- width
yerine inline-size
, boyutun fiziksel boyutlara bağlı kalmamasını sağlar.
- border-inline-start
, başlangıca bir kenarlık ekler. Bu kenarlık komut dosyası yönüne bağlı olarak sağda veya solda olabilir.
JavaScript
Aşağıdaki JavaScript'lerin neredeyse tümü erişilebilirliği artırmak içindir. Bunlardan ikisi görevleri biraz kolaylaştırmak için yardımcı kitaplıklar kullanılır. BlingBlingJS, kısa ve öz ifadeler için kullanılır. DOM sorguları ve kolay etkinlik işleyici kurulumu roving-ux, erişimi kolaylaştırır. klavye ve oyun kumandası etkileşimlerini takip eder.
import $ from 'blingblingjs'
import {rovingIndex} from 'roving-ux'
const splitButtons = $('.gui-split-button')
const popupButtons = $('.gui-popup-button')
Yukarıdaki kitaplıklar içe aktarıldıktan ve öğeler seçilip değişkenlerini kullanarak, deneyimi yükseltmek işlevin tamamlanmasına birkaç adım uzanıyor.
Dönme indeksi
Bir klavye veya ekran okuyucu .gui-popup-button
cihazına odaklandığında
odağı alan adındaki ilk (veya en son odaklanılan) düğmeye
.gui-popup
. Kitaplık, element
ve target
ile bunu yapmamıza yardımcı olur
parametreleridir.
popupButtons.forEach(element =>
rovingIndex({
element,
target: 'button',
}))
Öğe artık odağı hedef <button>
alt öğesine iletir ve
seçeneklere göz atmak için standart ok tuşuyla gezinme.
aria-expanded
değiştiriliyor
Bir pop-up'ın gösterilip saklandığı görsel olarak açıkça görülse de ekran okuyucuların görsel ipuçlarından daha fazlasına ihtiyacı vardır. Ekran okuyucuya uygun bir özelliği açıp kapatarak burada CSS'ye dayalı :focus-within
etkileşimini tamamlamak için JavaScript kullanılır.
popupButtons.on('focusin', e => {
e.currentTarget.setAttribute('aria-expanded', true)
})
popupButtons.on('focusout', e => {
e.currentTarget.setAttribute('aria-expanded', false)
})
Escape
anahtarını etkinleştirme
Kullanıcının odağı kasıtlı olarak bir tuzağa düşürüldü. Bu da onu
bir çıkış yolu sağlar. En yaygın yöntem, Escape
anahtarının kullanılmasına izin vermektir.
Bunu yapmak için pop-up düğmesine basıldığından emin olun, çünkü klavyedeki herhangi bir etkinlik
bu ebeveyne yükselir.
popupButtons.on('keyup', e => {
if (e.code === 'Escape')
e.target.blur()
})
Pop-up düğmesi Escape
tuşuna basıldığını görürse odağı kendisinden kaldırır
şununla:
blur()
Böl düğmesi tıklamaları
Son olarak, kullanıcı düğmeleri tıklarsa, dokunursa veya klavyeyle etkileşimde bulunursa
uygun işlemi gerçekleştirmesi gerekir. Etkinlik baloncuğu kullanılıyor
burada tekrar ediyorum, ancak bu sefer .gui-split-button
kapsayıcısında
çocuk pop-up'ından veya birincil işlemden gelen tıklama sayısı.
splitButtons.on('click', event => {
if (event.target.nodeName !== 'BUTTON') return
console.info(event.target.innerText)
})
Sonuç
Şimdi bunu nasıl yaptığımı öğrendiğinize göre siz nasıl ‽ 🙂
Gelin, yaklaşımlarımızı çeşitlendirelim ve web'de içerik geliştirmenin tüm yollarını öğrenelim. Bir demo oluşturup beni tweet'le bağlantıları eklerim aşağıdaki topluluk remiksleri bölümüne gidin!