Medya kaydırma çubuğu bileşeni oluşturma

TV'ler, telefonlar, masaüstü bilgisayarlar vb. için duyarlı bir yatay kaydırma görünümü oluşturmaya yönelik temel bir genel bakış.

Bu yazıda, web için minimal, duyarlı, erişilebilir ve tarayıcı ve platformlarda (ör. TV'ler!) çalışabilen yatay kaydırma deneyimleri oluşturmanın yolları üzerine düşünmek istiyorum. Demoyu deneyin.

Tanıtım

Videoyu tercih ediyorsanız bu yayının YouTube sürümünü burada bulabilirsiniz:

Genel bakış

Medya veya ürünlerin küçük resimlerini barındırmak için tasarlanan yatay bir kaydırma düzeni oluşturacağız. Bileşen başlangıçta mütevazı bir <ul> listesidir ancak CSS ile tatmin edici ve sorunsuz bir kaydırma deneyimine dönüştürülür. Bu deneyim, resimleri gösterir ve bir ızgaraya tutturur. JavaScript, gelen dizin etkileşimlerini kolaylaştırarak klavye kullanıcılarının 100'den fazla öğe arasında geçiş yapmalarına yardımcı olmak için eklenir. Ayrıca, prefers-reduced-data adlı deneysel medya sorgusu, medya kaydırma çubuğunu basit bir başlık kaydırma çubuğuna dönüştürmek için kullanılır.

Erişilebilir işaretleme ile başlayın

Medya kaydırıcısı, öğelerin bulunduğu bir liste olan yalnızca birkaç temel bileşenden oluşur. Bir liste, en basit haliyle dünyanın dört bir yanına gidebilir ve açık bir şekilde herkes tarafından tüketilebilir. Bu sayfayı açan bir kullanıcı, bir listeye göz atabilir ve bir bağlantıyı tıklayarak öğeyi görüntüleyebilir. Burası erişilebilir tabanımız.

<ul> öğesine sahip bir liste iletin:

<ul class="horizontal-media-scroller">
  <li></li>
  <li></li>
  <li></li>
  ...
<ul>

Liste öğelerini bir <a> öğesiyle etkileşimli hale getirin:

<li>
  <a href="#">
    ...
  </a>
</li>

Bir resmi ve altyazısını anlamsal olarak göstermek için bir <figure> öğesi kullanın:

<figure>
  <picture>
    <img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
  </picture>
  <figcaption>Legends</figcaption>
</figure>

<img> içindeki alt ve loading özelliklerine dikkat edin. Medya kaydırıcısının alternatif metni, küçük resme ekstra bağlam getirmeye yardımcı olan bir kullanıcı deneyimi fırsatı, resim yüklenmediğinde yedek metin olarak veya ekran okuyucu gibi yardımcı teknolojilerden yararlanan kullanıcılara sesli bir kullanıcı arayüzü sağlar. Uyumlu alternatif metin için beş altın kural hakkında daha fazla bilgi edinin.

loading özelliği, bu resim kaynağının yalnızca resim görüntü alanı içindeyken getirilmesi gerektiğini belirtmenin bir yolu olarak lazy anahtar kelimesini kabul eder. Kullanıcılar yalnızca görünümü kaydırdıkları öğelerin resimlerini indireceğinden, bu özellik büyük listeler için gerçekten kullanışlı olabilir.

Kullanıcının renk şeması tercihini destekleme

Tarayıcınıza, sayfanızın hem açık hem de koyu renkli kullanıcı aracısı stillerini istediğini belirtmek için color-scheme etiketini <meta> etiketi olarak kullanın. Nereden baktığınıza bağlı olarak ücretsiz koyu mod veya açık moddur:

<meta name="color-scheme" content="dark light">

Meta etiket, mümkün olan en erken sinyali sağlar. Böylece, kullanıcının koyu bir tema tercihi varsa tarayıcı koyu bir varsayılan tuval rengi seçebilir. Diğer bir deyişle, sitenin sayfaları arasında gezinirken yüklemeler arasında beyaz bir tuval arka planı yanıp sönmez. Yükleme aralarında kusursuz koyu tema, göze daha hoş gelecek.

https://web.dev/color-scheme/ adresine giderek Thomas Steiner'dan çok daha fazla bilgi edinebilirsiniz.

İçerik ekle

ul > li > a > figure > picture > img öğesinin yukarıdaki içerik yapısı dikkate alındığında, bir sonraki görev, kaydırmak için resimler ve başlıklar eklemektir. Demoyu statik yer tutucu resimler ve metinlerle doldurdum, ama isterseniz en sevdiğiniz veri kaynağını kullanabilirsiniz.

CSS ile stil ekleyin

Şimdi sıra CSS'nin bu genel içerik listesini alıp bunu bir deneyime dönüştürmeye geldi. Netflix, uygulama mağazaları ve daha birçok site ve uygulama, görüntü alanını kategoriler ve seçeneklerle doldurmak için yatay kaydırma alanlarını kullanır.

Kaydırma çubuğu düzeni oluşturma

Düzenlerdeki içeriği kesmekten veya üç nokta ile metin kırpmaya odaklanmaktan kaçınmak önemlidir. Birçok televizyon setinde bunun gibi medya kaydırıcıları vardır, ancak çoğu zaman elips yapan içeriğe başvururlar. Bu düzen bunu yapmaz! Ayrıca, medya içeriğinin sütun boyutunu geçersiz kılmasına da olanak tanır. Böylece, 1 düzeni birçok ilgi çekici kombinasyonu işleyecek kadar esnek hale getirir.

2 kaydırma satırı gösteriliyor. Bunlardan birinde üç nokta yok, yani daha uzun ve her başlık tamamen okunabiliyor. Diğeri daha kısadır ve birçok başlık 
üç noktayla kesilir.

Kapsayıcı, özel özellik olarak varsayılan boyutu sağlayarak sütun boyutunun geçersiz kılınmasına olanak tanır. Bu ızgara düzeni sütun boyutu konusunda hassastır, yalnızca alanı ve yönü yönetir:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
  margin: 0;
}

Özel özellik daha sonra <picture> öğesi tarafından temel en boy oranımızı oluşturmak için kullanılır: kutu:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

Yalnızca birkaç küçük stil daha ekleyerek medya kaydırıcısının temel yapısını tamamlayın:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  & > li {
    display: inline-block; /* removes the list-item bullet */
  }

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

overflow ayarlanırsa <ul>, listesinde kaydırma ve klavyeyle gezinmeye izin verecek şekilde ayarlanır. Ardından, yeni inline-block görüntüleme türü alınıp her bir doğrudan alt <li> öğesinin ::marker'i kaldırılır.

Ancak resimler henüz duyarlı değildir ve içindeki kutulardan çıkarılarak çıkar. Bazı boyutlar, sığdırma ve kenarlık stillerinin yanı sıra geç yükleme sırasında kullanmak üzere arka plan gradyanı ile bunları düzeltin:

img {
  /* smash into whatever box it's in */
  inline-size: 100%;
  block-size: 100%;

  /* don't squish but do cover the space */
  object-fit: cover;

  /* soften the edges */
  border-radius: 1ex;
  overflow: hidden;

  /* if empty, show a gradient placeholder */
  background-image:
    linear-gradient(
      to bottom,
      hsl(0 0% 40%),
      hsl(0 0% 20%)
    );
}

Kaydırma dolgusu

Sayfa içeriğinin hizalanması ve kenardan kenara kaydırma yüzey alanı, uyumlu ve minimal bir bileşen için kritik öneme sahiptir.

Yazı şeklimiz ve düzen çizgilerimizle uyumlu olan kenardan kenara kaydırma düzenini uygulamak için scroll-padding ile eşleşen padding kullanın:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}

Yatay kaydırma dolgusu hata düzeltmesi Yukarıda bir kaydırma kapsayıcısını doldurmanın ne kadar kolay olması gerektiği gösterilmektedir, ancak bununla ilgili önemli uyumluluk sorunları vardır (ancak Chromium 91 ve sonraki sürümlerde düzeltilmiştir). Geçmişin bir kısmı için buraya bakın. Kısaca özetlemek gerekirse, kaydırma görünümünde dolgu her zaman dikkate alınmamıştır.

Son liste öğesinin satır içi tarafında, dolgunun ve öğenin istenen hizalamayı oluşturmak için aynı genişliğe sahip olduğunu gösteren bir kutu vurgulanır.

Tarayıcıları, dolguyu kaydırma çubuğunun sonuna yerleştirmeleri için kandırmak amacıyla her listedeki son şekli hedefleyip istenen dolgu miktarında yapay bir öğe ekliyorum.

.horizontal-media-scroller > li:last-of-type figure {
  position: relative;

  &::after {
    content: "";
    position: absolute;

    inline-size: var(--gap);
    block-size: 100%;

    inset-block-start: 0;
    inset-inline-end: calc(var(--gap) * -1);
  }
}

Mantıksal özellikleri kullanmak, medya kaydırıcısının tüm yazma modunda ve belge yönünde çalışabilmesini sağlar.

Kaydırarak tutturma

Taşma içeren bir kaydırma kapsayıcısı, bir CSS satırı içeren tutturma görüntü alanına dönüşebilir. Daha sonra, bu görünümle nasıl hizalanmak istediğini alt öğeler belirler.

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block-end: calc(var(--gap) / 2);

  scroll-snap-type: inline mandatory;

  & figure {
    scroll-snap-align: start;
  }
}

Odak

Bu bileşenin ilham kaynağı, televizyonlar, App Store ve diğer platformlardaki devasa popülerliğidir. Birçok video oyunu platformu, birincil ana ekran düzeni olarak buna çok benzer bir medya kaydırma çubuğu kullanır. Odak, sadece küçük bir ekleme değil, kullanıcı deneyimiyle ilgili büyük bir anı ifade ediyor. Koltuğunuzdaki bu medya kaydırma aracını uzaktan kumandayla kullandığınızı düşünün, etkileşim için küçük geliştirmeler yapın:

.horizontal-media-scroller a {
  outline-offset: 12px;

  &:focus {
    outline-offset: 7px;
  }

  @media (prefers-reduced-motion: no-preference) {
    & {
      transition: outline-offset .25s ease;
    }
  }
}

Bu işlem, odak anahat stilini 7px kutudan uzağa koyarak ona güzel bir alan açar. Kullanıcının hareketi azaltmayla ilgili bir hareket tercihi yoksa belirli uzaklıkta kopyasının geçişi yapılır ve odaklama etkinliğine hafif bir hareket sağlanır.

Fitness endeksi

Oyun kumandası ve klavye kullanıcılarının bu uzun kayan içerik ve seçenek listelerinde özellikle dikkatli olmaları gerekir. Bu sorunu çözmek için yaygın olarak kullanılan kalıp, kargo dizini olarak adlandırılır. Bir öğe kapsayıcısının klavyeye odaklanması ancak aynı anda yalnızca 1 alt öğenin odağı tutmasına izin verilmesi durumudur. Tek seferde odaklanılabilen bu tek öğe deneyimi, sonuna ulaşmak için sekmeye 50 defadan fazla basmak yerine potansiyel olarak uzun öğe listesinin atlanmasına olanak tanıyacak şekilde tasarlanmıştır.

Demonun ilk kaydırıcısında 300 öğe var. Bir sonraki bölüme geçmek için bunların tümünü katetmekten daha iyisini yapabiliriz.

Bu deneyimi oluşturmak için JavaScript'in klavye etkinliklerini ve odaklama etkinliklerini gözlemlemesi gerekir. Bu kullanıcı deneyimini kolaylaştırmaya yardımcı olması için npm'de küçük bir açık kaynak kitaplık oluşturdum. 3 kaydırma aracı için bunu şu şekilde kullanırsınız:

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

Bu demo, kaydırma yapanlar için dokümanı sorgular ve her biri için rovingIndex() işlevini çağırır. Odak hedeflerinin doğrudan alt öğe olmaması durumunda liste kapsayıcısı ve hedef sorgu seçici gibi aktarma deneyimini elde etmek için rovingIndex() öğesini geçirin.

document.querySelectorAll('.horizontal-media-scroller')
  .forEach(scroller =>
    rovingIndex({
      element: scroller,
      target: 'a',
}))

Bu efekt hakkında daha fazla bilgi edinmek için roving-ux açık kaynak kitaplığına bakın.

En boy oranı

Bu yazının hazırlandığı tarihte, aspect-ratio desteği Firefox'ta bir bayrağın arkasında yer almaktadır, ancak Chromium tarayıcılarda veya set üstü kutularda kullanılabilir. Medya kaydırma çubuğu ızgara düzeni yalnızca yönü ve boşluğu belirttiğinden, boyutlandırma, en boy oranı desteğini kontrol eden bir medya sorgusu içinde değişebilir. Kademeli geliştirmeyle daha fazla dinamik medya kaydırma çubuğu eklendi.

16:9 ve 4:3 oranındaki diğer tasarım oranlarının yanında 4:4 en boy oranına sahip bir kutu gösteriliyor

@supports (aspect-ratio: 1) {
  .horizontal-media-scroller figure > picture {
    inline-size: auto; /* for a block-size driven ratio */
    aspect-ratio: 1; /* boxes by default */

    @nest section:nth-child(2) & {
      aspect-ratio: 16/9;
    }

    @nest section:nth-child(3) & {
      /* double the size of the others */
      block-size: calc(var(--size) * 2);
      aspect-ratio: 4/3;

      /* adjust size to fit more items into the viewport */
      @media (width <= 480px) {
        block-size: calc(var(--size) * 1.5);
      }
    }
  }
}

Tarayıcı aspect-ratio söz dizimini destekliyorsa medya kaydırma çubuğu resimleri aspect-ratio boyutuna yükseltilir. Taslak iç içe yerleştirme söz dizimini kullanarak her resim, birinci, ikinci veya üçüncü satır olmasına bağlı olarak en boy oranını değiştirir. Nest söz dizimi, diğer boyutlandırma mantığıyla birlikte bazı küçük görüntü alanı düzenlemeleri de yapılmasına olanak tanır.

Bu CSS ile, özellik daha fazla tarayıcı motorunda kullanılabildiğinden, yönetimi kolay ancak görsel açıdan daha ilgi çekici bir düzen oluşturulur.

Azaltılmış veri tercih eder

Bir sonraki teknik sadece Canary'de bayrağın arkasında kullanılabiliyor olsa da birkaç satır CSS kullanarak sayfa yüklenme süresinden ve veri kullanımından nasıl önemli ölçüde tasarruf edebileceğimi paylaşmak istiyorum. 5. düzeydeki prefers-reduced-data medya sorgusu, cihazın veri tasarrufu modu gibi azaltılmış veri durumunda olup olmadığını sormanıza olanak tanır. Öyleyse belgeyi değiştirip bu örnekte resimleri gizleyebilirim.

ALT_TEXT_HERE

figure {
  @media (prefers-reduced-data: reduce) {
    & {
      min-inline-size: var(--size);

      & > picture {
        display: none;
      }
    }
  }
}

İçerikte gezinmeye devam edilebilir, ancak ağır resimler indirilmesine gerek yoktur. prefers-reduced-data CSS'sini eklemeden önce şu siteyi ziyaret edin:

(7 istek, 131 ms'de 100 KB kaynak)

ALT_TEXT_HERE

prefers-reduced-data CSS eklendikten sonraki site performansı şöyle:

ALT_TEXT_HERE

(71 istek, 1,07 sn.de 1,2 MB kaynak)

Bu, tarayıcı sekmesinin görüntü alanı içindeki yaklaşık 60 resim (geniş ekran ekranında yapılan testler), sayfa yüklemede yaklaşık %80 artış ve kablodan verinin% 10'u kadar daha az istek gerçekleşir. Oldukça güçlü bir CSS.

Sonuç

Nasıl yaptığımı artık bildiğine göre sen ne yaparsın? 🙂

Yaklaşımlarımızı çeşitlendirelim ve web'de geliştirme yapmanın tüm yollarını öğrenelim. Codepen oluşturun veya kendi demonuzu yayınlayın, bana tweet gönderin. Bu kodu aşağıdaki Topluluk remiksleri bölümüne ekleyeceğim.

Kaynak

Topluluk remiksleri

Henüz burada görülecek bir şey yok.