Geliştirici Günlüğü: Firma Sayfalarında Sekme Sistemi İyileştirmesi

Firma Sayfalarında Sekme Sistemi İyileştirmesi

Tarih: 2025-09-26 • Kapsam: UI/UX, CSS, JS, Erişilebilirlik, Performans

Amaç

Firma sayfalarımızda yer alan Genel / Ürünler / Hizmetler / Blog / Sayfalar sekme yapısının mobilde tam görünür olmaması ve aktif sekmenin yeterince vurgulanmaması sorunlarını gidererek; kaydırılabilir, akıcı, erişilebilir ve performanslı bir sekme deneyimi sunmak.

Mevcut Durum & Sorun Tespiti

  • Mobilde sekmeler taşma yapıyor, tamamı görülemiyordu.
  • Aktif sekmenin görsel vurgusu zayıftı; kullanıcı hangi sekmede olduğunu anlık ayırt edemiyordu.
  • Klavye/okunabilirlik (a11y) ögeleri eksikti (rol, aria-attributes).

Yapılan İyileştirmeler (Özet)

  1. Kayar Sekme Çubuğu: Mobilde yatay kaydırma için overflow-x:auto ve scroll-snap-x uygulanarak sekmeler tek tek “oturur” hale getirildi.
  2. Aktif Göstergesi (Active Bar): CSS ile altta akıcı bir gösterge çubuğu eklendi; JS ile aktif sekmeye hizalanıyor.
  3. Odak & Erişilebilirlik: role="tablist", role="tab", aria-selected ve aria-controls eklendi; klavye ile gezinme desteklendi.
  4. Mikro Animasyon: Kaydırma sırasında sekme çubuğunda hafif hareket ve gölge efekti ile yön algısı güçlendirildi.
  5. Performans: Pasif event listener, hafif JS (vanilla), GPU hızlandırmalı transform ve prefers-reduced-motion desteği eklendi.

Teknik Uygulama

1) HTML (Rol & ARIA Yapısı)

<nav class="firma-tabs" role="tablist" aria-label="Firma Sekmeleri">
  <button role="tab" class="tab is-active" aria-selected="true" aria-controls="panel-genel" id="tab-genel">Genel</button>
  <button role="tab" class="tab" aria-selected="false" aria-controls="panel-urunler" id="tab-urunler">Ürünler</button>
  <button role="tab" class="tab" aria-selected="false" aria-controls="panel-hizmetler" id="tab-hizmetler">Hizmetler</button>
  <button role="tab" class="tab" aria-selected="false" aria-controls="panel-blog" id="tab-blog">Blog</button>
  <button role="tab" class="tab" aria-selected="false" aria-controls="panel-sayfalar" id="tab-sayfalar">Sayfalar</button>
  <span class="tab-active-bar" aria-hidden="true"></span>
</nav>

<section id="panel-genel" role="tabpanel" aria-labelledby="tab-genel">...</section>
<section id="panel-urunler" role="tabpanel" aria-labelledby="tab-urunler" hidden>...</section>
<section id="panel-hizmetler" role="tabpanel" aria-labelledby="tab-hizmetler" hidden>...</section>
<section id="panel-blog" role="tabpanel" aria-labelledby="tab-blog" hidden>...</section>
<section id="panel-sayfalar" role="tabpanel" aria-labelledby="tab-sayfalar" hidden>...</section>

2) CSS (Kayar Çubuk, Scroll Snap, Active Bar)

.firma-tabs{
  display:flex; gap:.5rem; align-items:center; position:relative;
  overflow-x:auto; padding:.5rem .75rem; scroll-snap-type:x mandatory;
  border-bottom:1px solid var(--kadence-border, #e5e7eb);
  -webkit-overflow-scrolling:touch;
}
.firma-tabs::-webkit-scrollbar{ height:6px; }
.firma-tabs::-webkit-scrollbar-thumb{ background:#d1d5db; border-radius:999px; }

.tab{
  white-space:nowrap; scroll-snap-align:start;
  border:none; background:transparent; padding:.5rem .75rem; border-radius:.5rem;
  font-weight:600; color:#1f2937; position:relative;
}
.tab:is(:hover,:focus){ background:#f3f4f6; outline:none; }
.tab.is-active{ color:#0f66ff; }

.tab-active-bar{
  position:absolute; left:0; bottom:0; height:2px; width:0;
  background:#0f66ff; border-radius:2px; transition:transform .25s ease, width .25s ease;
  transform:translateX(0);
}

/* Kaydırma yönünü hissettiren hafif gölge */
.firma-tabs.scrolling::after{
  content:""; position:absolute; right:0; top:0; bottom:0; width:24px;
  pointer-events:none; background:linear-gradient(to left, rgba(0,0,0,.06), rgba(0,0,0,0));
}

/* Hareket hassasiyeti olan kullanıcılar için animasyon azalt */
@media (prefers-reduced-motion: reduce){
  .tab-active-bar{ transition:none; }
}

3) JS (Aktif Çubuk Konumlama, ARIA & Klavye, Scroll İpuçları)

document.addEventListener('DOMContentLoaded',function(){
  const nav = document.querySelector('.firma-tabs');
  const tabs = Array.from(nav.querySelectorAll('.tab'));
  const bar  = nav.querySelector('.tab-active-bar');

  function positionBar(el){
    const r = el.getBoundingClientRect();
    const nr = nav.getBoundingClientRect();
    bar.style.width = r.width + 'px';
    bar.style.transform = 'translateX(' + (r.left - nr.left + nav.scrollLeft) + 'px)';
  }

  function setActive(next){
    tabs.forEach(t => {
      const active = (t === next);
      t.classList.toggle('is-active', active);
      t.setAttribute('aria-selected', active ? 'true' : 'false');
      const panel = document.getElementById(t.getAttribute('aria-controls'));
      if(panel){ panel.hidden = !active; }
    });
    positionBar(next);
    // görünür alana kaydır
    next.scrollIntoView({behavior:'smooth', inline:'center', block:'nearest'});
  }

  // ilk konum
  const current = tabs.find(t => t.classList.contains('is-active')) || tabs[0];
  setActive(current);

  // tıklama
  tabs.forEach(t => t.addEventListener('click', () => setActive(t)));

  // klavye (← → Home End)
  nav.addEventListener('keydown', e => {
    const i = tabs.indexOf(document.activeElement);
    if(i < 0) return;
    if(e.key === 'ArrowRight'){ e.preventDefault(); (tabs[i+1]||tabs[0]).focus(); setActive(tabs[i+1]||tabs[0]); }
    if(e.key === 'ArrowLeft'){ e.preventDefault(); (tabs[i-1]||tabs.at(-1)).focus(); setActive(tabs[i-1]||tabs.at(-1)); }
    if(e.key === 'Home'){ e.preventDefault(); tabs[0].focus(); setActive(tabs[0]); }
    if(e.key === 'End'){ e.preventDefault(); tabs.at(-1).focus(); setActive(tabs.at(-1)); }
  });

  // kaydırma ipucu (gölge)
  let scrollingTimer;
  nav.addEventListener('scroll', () => {
    nav.classList.add('scrolling');
    clearTimeout(scrollingTimer);
    scrollingTimer = setTimeout(() => nav.classList.remove('scrolling'), 150);
    // aktif bar konumunu scroll ile güncel tut
    const active = nav.querySelector('.tab.is-active');
    if(active) positionBar(active);
  }, {passive:true});

  // pencere boyutu değişince hizalama
  window.addEventListener('resize', () => {
    const active = nav.querySelector('.tab.is-active');
    if(active) positionBar(active);
  });
});

Erişilebilirlik (a11y)

  • Sekme yapısına uygun role ve aria-* öznitelikleri eklendi.
  • Klavye ile gezinme sağlandı (← → Home End).
  • prefers-reduced-motion ile animasyonlar azaltılabiliyor.

Performans Önlemleri

  • Vanilla JS; ek kütüphane kullanılmadı.
  • Pasif scroll dinleyicileri ve GPU hızlandırmalı transform kullanıldı.
  • DOM ölçümlendirme minimal tutuldu; yalnızca aktif sekmede hesaplama yapılıyor.

Test Sonuçları

  • Cihazlar: Android (Chrome), iOS (Safari), masaüstü (Chrome/Firefox).
  • Davranış: Sekmeler sorunsuz kayıyor, aktif çubuk doğru konumlanıyor.
  • Erişilebilirlik: Klavye navigasyonu ve ekran okuyucu etiketleri başarılı.

Sonuç & Yol Haritası

Mobil kullanılabilirlik, erişilebilirlik ve görsel geri bildirimler belirgin şekilde iyileştirildi. Bir sonraki adımda:

  1. Sekme başlıklarına hafif ikon seti (opsiyonel, metin öncelikli).
  2. Hızlı erişim için yatay kaydırma “ok butonu” (a11y uyumlu).
  3. Şehir/firma bazlı A/B test: sekme yerleşimi ve sırası ölçülerek en iyi varyantın seçilmesi.

Not: Bu iyileştirmeler, mevcut “scrollable sekme sistemi” mimarisiyle %100 uyumludur ve modüler yapıda devreye alınmıştır.

Similar Posts

Fikirleriniz, bizim için çok değerli ,lütfen paylaşın.

Yaka Metal sitesinden daha fazla şey keşfedin

Okumaya devam etmek ve tüm arşive erişim kazanmak için hemen abone olun.

Okumaya Devam Edin