Konu Başlıkları
Yükleniyor...

Buton Durumları: disabled, Hover ve Focus'ta Sık Yapılan Hatalar

Buton Durumları ve Erişilebilirlik: disabled, :hover, :focus-visible

Bir butonun beş hali var: etkin, devre dışı, üzerinde, odakta, basılı. Listeyi bilmek işin kolay kısmı; sorun bu hallerin CSS ve ARIA'ya çevrilmesinde çıkıyor. Devre dışı buton klavyeyle hiç bulunamıyor, hover mobilde dokunduktan sonra ekranda takılı kalıyor, yükleniyor hali kullanıcının odağını sayfanın en başına atıyor.

Devre dışı: disabled ile aria-disabled aynı şey değil

Native disabled özniteliği butonu tab sırasından çıkarır. Klavyeyle formu gezen kullanıcı o butona hiç ulaşamaz, üzerine gelip "neden gönderemiyorum" sorusunun cevabını alamaz; buton onun için yok. Fare kullanıcısı en azından soluk bir dikdörtgen görür.

aria-disabled="true" ise butonu odaklanabilir bırakır, ekran okuyucu durumu duyurur, tıklamayı sen kendi handler'ında yutarsın. İkisini birlikte yazmak gereksiz: disabled varken ARIA'nın söyleyecek yeni bir şeyi yok.

Seçim şöyle yapılır. Formun gönder butonu gibi kullanıcının arayıp "neden kapalı" diye sorduğu kontrollerde aria-disabled kullan, yanına eksik alanı söyleyen bir metin koy. Şu an gerçekten alakasız olan kontrollerde (hiçbir satır seçilmemişken duran toplu işlem butonu gibi) native disabled yeterli.

Renk tarafında tek sinyal gri ton olmasın. Soluk marka rengi ile kapalı görüntü arasındaki fark, ekran parlaklığına ve kullanıcının görme keskinliğine göre kayboluyor.

Hover'ı mobilde kapat

Dokunmatik ekranda hover yok denir ama tarayıcılar onu yok saymıyor: dokunduğun anda hover kuralları uygulanır ve başka bir yere dokunana kadar butonun üzerinde kalır. Kullanıcı sayfada ilerler, geride hover'da donmuş bir buton bırakır.

@media (hover: hover) { .btn:hover { background: #1b4fd8; } }

Bunu tek media query ile çözersin, cihaz tespitine ya da user agent kontrolüne gerek yok. Geçiş süresini de kısa tut (150 ms üstü hover animasyonlarını, fareyi hızlı gezdiren kullanıcıda arayüzü tembel gösterdiği için abartılı buluyorum).

Odağı silmeden önce :focus-visible

outline: none yazan herkes aynı gerekçeyle yazıyor: fareyle tıklanan butonun etrafındaki çerçeveyi istemiyor. Aynı satır klavye kullanıcısının tek konum göstergesini de siliyor.

:focus-visible tam bu ayrımı yapar: halkayı yalnızca tarayıcı odağın klavyeden geldiğine karar verdiğinde gösterir. Güncel tarayıcıların hepsinde çalışıyor, polyfill dosyasını projeden çıkarabilirsin.

Halkanın kendisi için outline ve outline-offset ikilisi, arka plan rengini değiştirmekten daha güvenilir. Renk değişimi butonun altındaki zemine bağlı, outline değil.

aria-pressed basılı halini anlatmıyor

Buton durumu listelerinde aria-pressed="true" sıkça "buton basıldı" karşılığı olarak geçiyor. Değil. Basılı hal, parmağın ya da farenin buton üzerinde olduğu andaki geçici görünümdür; CSS'te :active ile yazılır ve 100-150 ms sürer.

aria-pressed ise aç/kapa butonlarının kalıcı durumunu taşır: editördeki kalın yazı düğmesi, "Takip et" ile "Takip ediliyor" arasında gidip gelen buton. Sıradan bir gönder butonuna bu özniteliği koyarsan ekran okuyucu onu iki durumlu bir düğme olarak duyurur, kullanıcı da olmayan bir durum değişimini bekler. Örüntünün tanımı ARIA Authoring Practices içinde duruyor.

Yükleniyor hali odağı düşürüyor

En yaygın kalıp: butona tıklanır, handler button.disabled = true yazar, istek gider. O anda odak butondaydı. Devre dışı bırakılan eleman odağı tutamaz, odak body'ye düşer ve kullanıcının sonraki Tab'ı sayfanın en başından başlar. Klavyeyle çalışan biri için bu, her gönderimden sonra baştan gezinmek demek.

Butonu etkin bırak, aria-busy="true" ve aria-disabled="true" ekle, tekrar tıklamaları handler içinde yut. Dönen simge tek başına hiçbir şey söylemediği için etiketi de değiştir: "Kaydet" yerine "Kaydediliyor". Etiket zaten eylemi söylüyorsa ("Formu Gönder", "Siparişi Tamamla") bu geçiş kullanıcıya nerede durduğunu doğrudan anlatır.

Çift göndermeyi arayüzde engellemek kazayı azaltır, sorunu çözmez. Aynı isteğin ikinci kez işlenmemesi sunucu tarafında, istek anahtarına bakan bir kontrolle sağlanır; buton oraya yardımcıdır.

Stil ile durum karışınca maliyet çarpılıyor

Stil butonun hiyerarşideki yerini söyler (birincil, ikincil, metin butonu), durum ise o anda ne olduğunu. Bunlar dik eksenler, o yüzden çarpılıyorlar: üç stil ve beş durum on beş görünüm eder, araya üç boyut varyantı girince kırk beş.

Durumu her stil için ayrı sınıf olarak yazmak bu yüzden hızla dağılır. Durumları stilin üstüne binen tek bir katman olarak tanımla (opaklık, yüzey rengi ve outline değişkenleri), stil sadece taban rengini ve tipografiyi belirlesin. Böylece yeni bir buton stili eklendiğinde beş durumu tekrar yazmak gerekmez.