Medya kaydırma bileşeni oluşturma

TV'ler, telefonlar, masaüstü bilgisayarlar vb. için duyarlı bir yatay kaydırma görünümü oluşturma hakkında temel bilgiler.

Bu yayında, web için minimum, duyarlı, erişilebilir ve tarayıcılar ile platformlarda (ör. TV'ler) çalışan yatay kaydırma deneyimleri oluşturma yöntemleri hakkındaki düşüncelerimi paylaşmak istiyorum. Demoyu deneyin.

Demo

Video tercih ediyorsanız bu yayının YouTube versiyonunu aşağıda bulabilirsiniz:

Genel Bakış

Medya veya ürünlerin küçük resimlerini barındırmak için yatay kaydırma düzeni oluşturacağız. Bu bileşen, basit bir <ul> liste olarak başlar ancak CSS ile dönüştürülerek tatmin edici ve sorunsuz bir kaydırma deneyimi sunar. Bu deneyimde, resimler gösterilir ve bir ızgaraya yerleştirilir. JavaScript, gezinme dizini etkileşimlerini kolaylaştırmak için eklenir. Bu sayede klavye kullanıcıları 100'den fazla öğeyi gezinmeyi atlayabilir. Ayrıca, medya kaydırma çubuğunu hafif bir başlık kaydırma çubuğu deneyimine dönüştürmek için deneysel bir medya sorgusu (prefers-reduced-data) kullanılır.

Erişilebilir işaretlemeyle başlayın

Medya kaydırıcı, yalnızca birkaç temel bileşenden (öğeler içeren bir liste) oluşur. En basit haliyle bir liste, dünyanın her yerinde kullanılabilir ve herkes tarafından kolayca anlaşılabilir. Bu sayfaya gelen bir kullanıcı, bir listeye göz atabilir ve bir öğeyi görüntülemek için bir bağlantıyı tıklayabilir. Bu, erişilebilen tabanımızdır.

<ul> öğesi içeren bir liste sun:

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

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

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

Bir resmi ve altyazısını semantik olarak temsil etmek için <figure> öğesini kullanın:

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

<img> öğesindeki alt ve loading özelliklerine dikkat edin. Medya kaydırma çubuğu için alternatif metin, küçük resme ek bağlam sağlamaya yardımcı olan veya resim yüklenmediğinde yedek metin olarak kullanılan bir kullanıcı deneyimi fırsatıdır. Ayrıca, ekran okuyucu gibi yardımcı teknolojileri kullanan kullanıcılar için sözlü bir kullanıcı arayüzü sağlar. Uygun alternatif metin için beş altın kural başlıklı makaleden daha fazla bilgi edinin.

loading özelliği, bu resim kaynağının yalnızca resim görünüm alanında olduğunda getirilmesi gerektiğini belirtmek için lazy anahtar kelimesini kabul eder. Bu özellik, kullanıcılar yalnızca kaydırarak görüntüledikleri öğelerin resimlerini indireceğinden büyük listeler için çok kullanışlı olabilir.

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

Tarayıcıya sayfanızın hem açık hem de koyu modda sağlanan kullanıcı aracısı stillerini istediğini bildirmek için color-scheme öğesini <meta> etiketi olarak kullanın. Bu, nasıl baktığınıza bağlı olarak ücretsiz bir koyu mod veya açık moddur:

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

Meta etiketi, mümkün olan en erken sinyali sağlar. Bu nedenle, kullanıcı koyu tema tercihine sahipse tarayıcı varsayılan koyu tuval rengini seçebilir. Bu, site sayfaları arasında gezinirken yüklemeler arasında beyaz bir tuval arka planının görünmeyeceği anlamına gelir. Yüklemeler arasında sorunsuz koyu tema geçişi sayesinde gözleriniz daha az yorulur.

Thomas Steiner'in https://web.dev/color-scheme/ adresindeki makalesinden çok daha fazla bilgi edinebilirsiniz.

İçerik ekle

ul > li > a > figure > picture > img ile ilgili yukarıdaki içerik yapısı göz önüne alındığında, bir sonraki görev, kaydırılacak resimler ve başlıklar eklemektir. Demoyu statik yer tutucu resimler ve metinlerle doldurdum ancak bu demoyu istediğiniz veri kaynağıyla destekleyebilirsiniz.

CSS ile stil ekleme

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

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

Düzenlerde içeriğin kesilmesinden veya üç nokta ile metin kısaltmaya başvurmaktan kaçınmak önemlidir. Birçok televizyonda bu tür medya kaydırma çubukları bulunur ancak içerik genellikle üç nokta ile kısaltılır. Bu düzen desteklemez. Ayrıca medya içeriğinin sütun boyutunu geçersiz kılmasına da olanak tanır. Bu sayede 1 düzen, birçok ilginç kombinasyonu işleyebilecek kadar esnek hale gelir.

2
kaydırma satırı gösteriliyor. Birinde üç nokta yok. Bu, daha uzun olduğu ve her başlığın tamamen okunabilir olduğu anlamına gelir. Diğeri daha kısa ve birçok başlık üç nokta ile kesiliyor.

Kapsayıcı, varsayılan boyutu özel bir özellik olarak sağlayarak sütun boyutunun geçersiz kılınmasına olanak tanır. Bu ızgara düzeni, sütun boyutuyla ilgili olarak yalnızca aralık ve yön yönetimi yapar:

.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:

.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ırma çubuğunun temel iskeletini 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 ayarı, <ul> öğesini listesinde kaydırmaya ve klavye ile gezinmeye izin verecek şekilde ayarlar. Ardından, her doğrudan alt <li> öğesinin ::marker özelliği, inline-block yeni bir görüntüleme türü alarak kaldırılır.

Ancak resimler henüz duyarlı değil ve bulundukları kutuların dışına çıkıyor. Boyut, sığdırma ve kenarlık stilleriyle, tembel yükleme sırasında kullanılacak bir arka plan gradyanıyla bunları kontrol altına alın:

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ğiyle hizalama ve uçtan uca kaydırma yüzey alanı, uyumlu ve minimalist bir bileşen için kritik öneme sahiptir.

Tipografimiz ve düzen çizgilerimizle uyumlu, kenardan kenara kaydırma düzeni oluşturmak 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 hatası düzeltildi Yukarıdaki örnekte, kaydırma container'ına dolgu eklemenin ne kadar kolay olduğu gösteriliyor. Ancak bu özellik, Chromium 91 ve sonraki sürümlerde düzeltilmiş olsa da uyumluluk sorunları içeriyor. Geçmişle ilgili kısa bilgiyi burada bulabilirsiniz. Ancak kısa özet olarak, dolgunun her zaman kaydırma görünümünde dikkate alınmadığını söyleyebiliriz.

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

Tarayıcıları, dolguyu kaydırma çubuğunun sonuna yerleştirmesi için kandırmak amacıyla her listedeki son rakamı hedefleyip istenen dolgu miktarı kadar bir sözde öğe ekleyeceğim.

.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 özelliklerin kullanılması, medya kaydırıcının herhangi bir yazma modunda ve belge yönünde çalışmasını sağlar.

Kaydırarak tutturma

Taşma içeren kaydırma kapsayıcısı, tek bir CSS satırıyla tutturma görünüm alanı haline gelebilir. Ardından, alt öğeler bu görünüm alanıyla nasıl hizalanmak istediklerini belirleyebilir.

.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ğı, TV'lerde, uygulama mağazalarında ve diğer platformlardaki büyük popülerliğidir. Birçok video oyunu platformu, birincil ana ekran düzeni olarak buna çok benzer bir medya kaydırıcı kullanır. Odaklanma, burada yalnızca küçük bir ekleme değil, büyük bir kullanıcı deneyimi anıdır. Bu medya kaydırma çubuğunu uzaktan kumandayla kanepenizden kullandığınızı düşünün. Bu etkileşimi biraz daha iyi hale getirmek için:

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

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

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

Bu, odak ana hattı stilini 7px kutudan uzaklaştırarak kutuya biraz alan kazandırır. Kullanıcının hareketi azaltmayla ilgili bir tercihi yoksa odak etkinliğine ince bir hareket kazandırmak için kaydırma geçişi yapılır.

Gezici dizin

Kaydırılan içerik ve seçeneklerin yer aldığı bu uzun listelerde gamepad ve klavye kullanıcılarına özel dikkat gösterilmesi gerekir. Bu sorunu çözmek için kullanılan yaygın yöntem dolaşan dizin olarak adlandırılır. Öğelerden oluşan bir kapsayıcıya klavye odağı verildiğinde ancak aynı anda yalnızca 1 alt öğenin odağı tutmasına izin verildiğinde bu durum oluşur. Bu deneyim, her seferinde tek bir odaklanılabilir öğe olacak şekilde tasarlanmıştır. Böylece, listenin sonuna ulaşmak için 50'den fazla kez sekme tuşuna basmak yerine öğe listesini atlayabilirsiniz.

Demonun ilk kaydırma çubuğunda 300 öğe var. Bir sonraki bölüme ulaşmak için tüm bölümleri geçmelerini sağlamak yerine daha iyi bir çözüm sunabiliriz.

Bu deneyimi oluşturmak için JavaScript'in klavye etkinliklerini ve odak etkinliklerini gözlemlemesi gerekir. Bu kullanıcı deneyimini kolaylaştırmak için npm'de küçük bir açık kaynak kitaplığı oluşturdum. 3 kaydırma çubuğu için bu özelliği nasıl kullanacağınız aşağıda açıklanmıştır:

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

Bu demo, dokümanda kaydırma çubuklarını sorgular ve her biri için rovingIndex() işlevini çağırır. Gezinme deneyimini elde etmek için öğeyi (ör. liste kapsayıcısı) ve odak hedefler doğrudan alt öğeler değilse hedef sorgu seçiciyi rovingIndex() olarak iletin.

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

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

En-boy oranı

Bu gönderi yazıldığı sırada, aspect-ratio desteği Firefox'ta bir işaretin arkasında yer alıyordu ancak Chromium tarayıcılarda veya set üstü kutularda kullanılabiliyordu. Medya kaydırma ızgarası düzeni yalnızca yön ve aralığı belirttiğinden, boyutlandırma, en-boy oranı desteğini kontrol eden bir medya sorgusunda değişebilir. Bazı dinamik medya kaydırıcılarına yönelik aşamalı iyileştirme

16:9 ve 4:3 en boy oranlarının kullanıldığı 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 kullandığınızda her resmin en-boy oranı, birinci, ikinci veya üçüncü satırda olmasına bağlı olarak değişir. İç içe yerleştirme söz dizimi, diğer boyutlandırma mantığıyla birlikte bazı küçük görüntü alanı ayarlamalarının da yapılmasını sağlar.

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

Daha az veri tercih etme

Bu sonraki teknik yalnızca Canary'de bir işaretin arkasında kullanılabilir olsa da birkaç satır CSS ile önemli ölçüde sayfa yükleme süresi ve veri kullanımı tasarrufu sağlayabildiğimi paylaşmak istedim. prefers-reduced-data 5. seviyedeki medya sorgusu, cihazın veri tasarrufu modu gibi herhangi bir azaltılmış veri durumunda olup olmadığını sormaya olanak tanır. Bu durumda belgeyi değiştirebilir ve resimleri gizleyebilirim.

ALT_TEXT_HERE

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

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

İçerikte gezinmeye devam edebilirsiniz ancak ağır resimler indirilmez. prefers-reduced-data CSS'si eklenmeden önceki site:

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

ALT_TEXT_HERE

prefers-reduced-data CSS'si eklendikten sonraki site performansı:

ALT_TEXT_HERE

(71 istek, 1,07 saniyede 1,2 MB kaynak)

64 daha az istek, bu tarayıcı sekmesinin görüntü alanındaki yaklaşık 60 resim (testler geniş ekranlı bir ekranda yapılmıştır), yaklaşık %80'lik bir sayfa yükleme artışı ve kablo üzerinden aktarılan verilerin% 10'u. Çok güçlü bir CSS, değil mi?

Sonuç

Benim nasıl yaptığımı öğrendiğinize göre, siz nasıl yapardınız? 🙂

Yaklaşımlarımızı çeşitlendirelim ve web'de içerik oluşturmanın tüm yollarını öğrenelim. Codepen oluşturun veya kendi demoyu barındırın, bunu içeren bir tweet ile bana ulaşın. Ben de demoyu aşağıdaki Topluluk remiksleri bölümüne ekleyeyim.

Kaynak

Topluluk remiksleri

Henüz burada gösterilecek bir şey yok.