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

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

Bu yayında, web için minimal, duyarlı, erişilebilir ve tarayıcılar ile platformlarda (ör. TV'ler) çalışan yatay kaydırma deneyimleri oluşturma yöntemleriyle ilgili düşüncelerimizi paylaşmak istiyoruz. Demoyu deneyin.

Demo

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 yatay kaydırma düzeni oluşturacağız. Bileşen, basit bir <ul> listesi olarak başlar ancak CSS ile resimleri sergileyip bir ızgaraya yerleştirerek tatmin edici ve sorunsuz bir kaydırma deneyimine dönüştürülür. JavaScript, klavye kullanıcılarının 100'den fazla öğeyi atlamasına yardımcı olarak sabit kaydırma listesi etkileşimlerini kolaylaştırmak için eklenir. Ayrıca, medya kaydırma çubuğunu hafif bir başlık kaydırma 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ırma çubuğu, yalnızca birkaç temel bileşenden ve öğelerin bulunduğu bir listeden oluşur. En basit haliyle bir liste dünyanın her yerine ulaşabilir ve herkes tarafından net bir şekilde kullanılabilir. Bu sayfaya gelen kullanıcılar bir listeye göz atabilir ve bir öğeyi görüntülemek için bağlantıyı tıklayabilir. Bu, erişilebilir tabanımızdır.

<ul> öğesi içeren bir liste yayınlama:

<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 başlığı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 resmin ek bağlam sağlamasına yardımcı olan bir kullanıcı deneyimi fırsatıdır. Alternatif metin, resim yüklenmemişse yedek metin olarak kullanılabilir veya ekran okuyucu gibi yardımcı teknolojilerden yararlanan kullanıcılar için sözlü kullanıcı arayüzü sağlar. Uyumlu alternatif metinler için beş altın kural başlıklı makaleyi inceleyerek daha fazla bilgi edinin.

loading özelliği, bu resim kaynağının yalnızca resim görüntü alanındayken getirileceğini belirtmek için lazy anahtar kelimesini kabul eder. Kullanıcılar yalnızca ekrana kaydırdıkları öğelerin resimlerini indirdiği için bu özellik, büyük listeler için çok kullanışlı olabilir.

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

Sayfanızın hem açık hem de koyu kullanıcı aracısı stillerini istediğini tarayıcıya bildirmek için <meta> etiketi olarak color-scheme kullanın. Bu, bakış açı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. Böylece tarayıcı, kullanıcının koyu tema tercihi varsa koyu bir varsayılan kanvas rengi seçebilir. Bu, sitenin sayfaları arasında gezinirken yükleme işlemleri arasında beyaz bir kanvas arka planı gösterilmeyeceği anlamına gelir. Yüklemeler arasında sorunsuz koyu tema, göze çok daha hoş geliyor.

Thomas Steiner'in https://web.dev/color-scheme/ adresindeki makalesinde bu konu hakkında daha fazla bilgi edinebilirsiniz.

İçerik ekle

ul > li > a > figure > picture > img için yukarıdaki içerik yapısı göz önüne alındığında, sonraki adımda kaydırılacak resimler ve başlıklar eklemeniz gerekir. Demoyu statik yer tutucu resimler ve metinlerle doldurdum ancak dilerseniz bunu en sevdiğiniz veri kaynağından da besleyebilirsiniz.

CSS ile stil ekleme

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

Kaydırma düzenini oluşturma

Düzenlerde içeriğin kesilmesi veya metnin üç noktayla kısaltılmasından kaçınılması önemlidir. Birçok televizyonda bu gibi medya kaydırma çubuğu bulunur ancak çoğu zaman içerikler elipslerle gösterilir. Bu düzende ise bu durum söz konusu değildir. Ayrıca medya içeriğinin sütun boyutunu geçersiz kılmasına olanak tanır. Böylece 1 düzen, birçok ilginç kombinasyonu işlemek için yeterince esnek olur.

2 kaydırılabilir satır gösterilir. Birinde üç nokta yok. Bu, daha uzun olduğu ve her başlığın tamamen okunaklı olduğu anlamına gelir. Diğeri daha kısadır ve birçok başlık üç noktayla kısaltılır.

Kapsayıcı, varsayılan boyutu özel mülk olarak sağlayarak sütun boyutunun geçersiz kılınmasına olanak tanır. Bu ızgara düzeni, sütun boyutu konusunda fikir sahibidir ve yalnızca aralığı 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 mülk daha sonra <picture> öğesi tarafından temel en boy oranını (bir kutu) 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 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 ayarı, <ul> öğesini listesinde kaydırma ve klavye gezinmesine izin verecek şekilde ayarlar. Ardından, her doğrudan alt <li> öğesinin ::marker özelliği kaldırılır ve inline-block adlı yeni bir görüntüleme türü elde edilir.

Ancak resimler henüz duyarlı değil ve kutuların içinden çıkıyor. Bazı boyutlar, sığdırma ve kenar stilleriyle ve yavaş yüklenirken arka plan degradesiyle 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ırılabilir bir yüzey alanı, uyumlu ve minimal bir bileşen için çok önemlidir.

Yazı tipimiz ve düzen çizgilerimizle uyumlu, kenardan kenara kaydırmalı bir düzen 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 hata düzeltmesi Yukarıdaki görselde, kaydırma kapsayıcısının doldurulmasının ne kadar kolay olması gerektiği gösterilmektedir. Ancak bu konuda önemli uyumluluk sorunları vardır (Chromium 91 ve sonraki sürümlerde düzeltilmiştir). Geçmişe dair biraz bilgi için buraya göz atın. Özet olarak, kaydırma görünümünde dolgu her zaman hesaba katılmamıştır.

Son liste öğesinin satır içi son tarafında, dolgu 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ştirmeye ikna etmek için her listenin sonundaki sayıyı hedefleyecek ve istenen dolgu miktarına eşit 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 özellikler kullanmak, medya kaydırma çubuğunun herhangi bir yazma modunda ve doküman yönünde çalışmasını sağlar.

Kaydırarak tutturma

Taşma içeren bir kaydırma kapsayıcısı, tek satır CSS ile sabitlenen bir görüntü alanı haline gelebilir. Ardından, bu görüntü alanıyla nasıl hizalanacaklarını belirtmek alt öğelere aittir.

.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 platformlarda büyük popülerliğidir. Birçok video oyunu platformu, birincil ana ekran düzeni olarak buna çok benzeyen bir medya kaydırma çubuğu kullanır. Odak, burada yalnızca küçük bir ekleme değil, kullanıcı deneyimi açısından büyük bir adımdır. Bu medya kaydırma çubuğunu koltuğunuzdan uzaktan kumanda ile kullandığınız düşünün. Bu etkileşime küçük iyileştirmeler ekleyin:

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

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

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

Bu, odak dış çizgisi stilini 7px kutudan uzaklaştırır ve güzel bir alan sağlar. Kullanıcının hareketi azaltmayla ilgili hareket tercihi yoksa ofset geçiş yapar ve odak etkinliğine hafif bir hareket verir.

Gezici dizin

Kaydırma içeren uzun içerik ve seçenek listelerinde gamepad ve klavye kullanıcılarına özel dikkat gösterilmelidir. Bu sorunu çözmek için kullanılan yaygın yönteme devriye dizini denir. Öğe kapsayıcısının klavyeyle odaklanıldığı ancak aynı anda yalnızca 1 alt öğenin odağı tutmasına izin verildiği durumdur. Bir seferde tek bir öğeye odaklanabildiğiniz bu deneyim, sonuna ulaşmak için Sekme tuşuna 50'den fazla kez basmak yerine, olası uzun öğe listesini atlamanıza olanak tanıyacak şekilde tasarlanmıştır.

Demo'nun ilk kaydırma çubuğunda 300 öğe var. Kullanıcıların bir sonraki bölüme ulaşmak için bunların tümünü taramasını sağlamak yerine daha iyi bir şey yapabiliriz.

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

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

Bu demo, kaydırma çubuğu olan sayfaları sorgulayarak her biri için rovingIndex() işlevini çağırır. Odak hedefleri doğrudan alt öğeler değilse liste kapsayıcısı gibi bir gezinme deneyimi elde etmek için rovingIndex() öğesini ve hedef sorgu seçicisini iletin.

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 yazıldığı sırada aspect-ratio desteği Firefox'ta bir işaretin arkasındadır ancak Chromium tarayıcılarda veya set üstü kutularda kullanılabilir. 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. Daha dinamik medya kaydırma çubuğuna yönelik aşamalı iyileştirme.

16:9 ve 4:3&#39;te kullanılan diğer tasarım oranlarının yanında 4:4 en boy oranına sahip bir kutu gösterilir.

@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 boyutlandırmasına yükseltilir. Taslak iç içe yerleştirme söz dizimini kullanarak her resim, ilk, ikinci veya üçüncü satırda olup olmadığına bağlı olarak en-boy oranını değiştirir. İç içe yerleştirme söz dizimi, diğer boyutlandırma mantığıyla birlikte bazı küçük görüntü alanı ayarlamaları yapılmasına da olanak tanır.

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

Azaltılmış verileri tercih eder

Bir sonraki teknik, Canary'de yalnızca bir işaretin arkasından kullanılabilir olsa da birkaç satır CSS ile nasıl önemli miktarda sayfa yükleme süresi ve veri kullanımı tasarrufu sağlayabileceğimi paylaşmak istedim. 5. seviye prefers-reduced-data medya sorgusu, cihazın veri tasarrufu modu gibi veri azaltılmış bir durumda olup olmadığını sormaya olanak tanır. Bu durumda, dokümanı 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 sonra site performansı:

ALT_TEXT_HERE

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

64 istek daha az (bu tarayıcı sekmesinin görüntü alanındaki yaklaşık 60 resim (geniş ekranda yapılan testler) anlamına gelir), sayfa yükleme hızında yaklaşık %80 artış ve kablo üzerinden aktarılan verilerin% 10'u. Oldukça güçlü bir CSS.

Sonuç

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

Yaklaşımlarımızı çeşitlendirelim ve web'de uygulama geliştirmenin tüm yollarını öğrenelim. Codepen oluşturun veya kendi demonuzu barındırın, bana tweet atın. Ardından, demoyu aşağıdaki Topluluk remiksleri bölümüne ekleyeceğim.

Kaynak

Topluluk remiksleri

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