Etkileşimli bilgi kartı oluşturma

Bilgi kartları, kullanıcı bir bağlantıyla ilgilendiğinde (fareyle üzerine gelerek veya odaklanarak) içeriğin etkileşimli bir önizlemesini sunar. Bu, kullanıcılara gezinmeden önce gösterilir ve kullanıcıya ihtiyaç duyduğu içeriği sağlar veya bağlantının aradığı içeriği barındıracağını doğrulamaya yardımcı olur.

Yapılandırılmış bağlantı önizlemeleri yerine düz metin, etkileşimli olmayan ipuçlarına ihtiyacınız varsa Fareyle üzerine gelindiğinde ipucu gösterme başlıklı makaleyi inceleyin.

1. Bilgi kutucuğunu tetikleme

Bilgi kutucuğunu tetiklemek için Interest Invokers API'yi kullanın. Bu sayede kart, hem fareyle üzerine gelindiğinde hem de odaklanıldığında görünür ve erişilebilirlik bağlantıları otomatik olarak yönetilir.

  • Kart kapsayıcınıza popover="hint" özelliğini ekleyin. Açık olabilecek alakasız popover menülerin kapatılmasını önlemek için hint kullanın.
  • Tetikleyici bağlantıya, kartın id değerini işaret eden interestfor özelliğini ekleyin.
<a href="/article" interestfor="article-preview">Article title</a>

<!-- The `id` must match the `interestfor` value on the trigger. -->
<div id="article-preview" popover="hint" class="hovercard">
  <h2>The buzz on hummingbirds</h2>
  <p class="byline">By Delphi Aguilar</p>
  <div>
    <img src="bird.jpg" alt="A vibrant hummingbird">
    <p>Brief summary of the article...</p>
  </div>
</div>

Bilgi kutucuğunun içindeki içeriğe ek bir bağlantı eklemeniz gerekmez. Bu, tetikleyici bağlantı için gereksizdir.

interestfor'da yerleşik erişilebilirlik özellikleri

interestfor kullandığınızda tarayıcı, yardımcı teknoloji bağlantısını sizin için yönetir:

  • Dolaylı semantik: popover="hint" içeren bir hedef, dolaylı olarak minimum tooltip rolü kazanır. role="tooltip" değerini kendiniz AYARLAMAYIN.
  • Dolaylı ilişkilendirme: Tarayıcı, hedef düz metin olduğunda aria-describedby aracılığıyla, hedef etkileşimli içerik barındırdığında ise aria-details aracılığıyla kaynak öğeyi hedefle dolaylı olarak ilişkilendirir. Tetikleyiciye aria-describedby veya aria-details EKLEMEYİN.
  • Etkileşimli içerik: İlişkilendirme gerektiğinde aria-details değerine geçtiğinden, hedef etkileşimli içerik (ör. "ilgi kartı" içindeki bir bağlantı) barındırabilir.

2. Sabit konumlandırma ile konumlandırma

CSS Sabitleme Konumlandırması'nı kullanarak bilgi kutucuğunu tetikleyicisine göre konumlandırın. interestfor kullanıldığında tetikleyici, popover için dolaylı bir sabitleyici olur.

[popover].hovercard {
  /* Position the card below the trigger, aligned with its inline-start edge
     and spanning toward the inline-end, flipping if it overflows the viewport. */
  position-area: block-end span-inline-end;
  position-try-fallbacks: flip-block, flip-inline;
}

3. Giriş ve çıkış animasyonu

Varsayılan olarak, klavye ve fare kullanıcıları için ilgi yarım saniyelik bir gecikmeyle gösterilir ve kaybolur. Bu sayede, bir sayfada sekmeler arasında gezinirken veya farenizi hareket ettirirken hedeflenen popover'ın açılması ve farenizi tetikleyiciden popover'a taşırken kapanması önlenir. Zamanlamayı ayarlamak için interest-delay CSS özelliğini kullanın.

[interestfor]{
  /* Shorthand for interest-delay-start and interest-delay-end */
  interest-delay: 0.2s 0.1s;
}

Kullanıcıların birden fazla tetikleyiciyi hızlı bir şekilde art arda etkinleştirmesi muhtemel ise ve ilgi alanına göre tetiklenen bir popover zaten açıksa ilk gecikmeyi 0s olarak ayarlayın.

:root:has(:interest-source) [interestfor] {
  interest-delay-start: 0s;
}

Giriş animasyonunu tanımlamak için @starting-style, üst katmandan çıkış animasyonunu tanımlamak için ise transition-behavior: allow-discrete (display ve overlay ile birlikte) kullanın. Bu sayede geçişler @media (prefers-reduced-motion: no-preference) ile sınırlandırılır.

[popover].hovercard {
  opacity: 0;
  transform-origin: top;
}

[popover].hovercard:popover-open {
  opacity: 1;
  transform: translateY(0) scale(1);
}

@starting-style {
  [popover].hovercard:popover-open {
    opacity: 0;
    transform: translateY(-10px) scale(0.95);
  }
}

/* MANDATORY: Respect user preference for reduced motion by selectively applying transitions. */
@media (prefers-reduced-motion: no-preference) {
  [popover].hovercard {
    transition:
      opacity,
      transform,
      display,
      overlay;
    transition-duration: 0.4s;
    transition-behavior: allow-discrete;
  }
}

4. İSTEĞE BAĞLI: Sonraki sayfaya sorunsuz geçiş

İsteğe bağlı olarak, bilgi kutucuğu ile hedef sayfa arasında sorunsuz bir "şekil değiştirme" animasyonu oluşturmak için Belgeler Arası Görünüm Geçişleri'ni kullanabilirsiniz. Uygulamayla ilgili yol gösterici bilgiler için Tutarlı Dokümanlar Arası Geçişler başlıklı makaleyi inceleyin.

Tarayıcı, bilgi kutucuğundaki öğelere ve sonraki sayfadaki karşılıklarına eşleşen view-transition-name değerleri atayarak bu öğeleri gezinme sırasında animasyonlu hale getirir. Karmaşık, çok öğeli bir şekil değiştirme efekti oluşturmak için birden fazla öğeyi (ör. başlıklar, resimler, yazar bilgileri) adlandırabilirsiniz. Yinelenen view-transition-name'ler oluşturmaktan veya bağlantıya özel view-transition-name'ler gerektirmekten kaçınmak için :popover-open kullanarak açık popover'daki öğelere view-transition-name atayın.

/* Opt-in to cross-document transitions on both pages */
@view-transition {
  navigation: auto;
}

/* Don't show transitions when loading this page */
::view-transition-group(*) {
  animation-duration: 0s;
}

/* Assign names ONLY when the popover is open to ensure only the correct elements are selected. */
[popover]:popover-open {
  view-transition-name: --hovercard;
  view-transition-class: morph;

  h2 {
    view-transition-name: --title;
    view-transition-class: morph;
  }

  img {
    view-transition-name: --image;
    view-transition-class: morph;
  }
}

ZORUNLU: Geçişin kararlı olması ve titrememesi için hedef sayfa, ilk kareyi oluşturmadan önce kritik içeriğin ayrıştırılmasını beklemek üzere blocking="render" ve <link rel="expect"> kullanmalıdır.

<!-- On the destination page: -->
<head>
  <!-- Block rendering until the hero image and title are parsed,
       ensuring the view transition snapshot is taken at the right time. -->
  <link rel="expect" href="#main-content" blocking="render">
</head>
<body>
  <main id="main-content">
    <h1>The buzz on hummingbirds</h1>
    <img src="bird.jpg">
  </main>
</body>
/* On the destination page: */
main {
  view-transition-name: --hovercard;
  view-transition-class: morph;
}
h1 {
  view-transition-name: --title;
  view-transition-class: morph;
}
img {
  view-transition-name: --image;
  view-transition-class: morph;
}

/* By default no transition */
::view-transition-group(*) {
  animation-duration: 0s;
}
/* Short transition for morphing elements */
::view-transition-group(.morph) {
  animation-duration: 0.4s;
}
/* Disable transition if no `old` view */
::view-transition-new(.morph):only-child {
  animation-duration: 0s;
}

Yedek stratejiler

Tetikleyici standart bir <a href="..."> bağlantısı olduğundan, bilgi kutucuğunu progresif geliştirme olarak değerlendirmeyi seçerseniz desteklenmeyen tarayıcılar tıklandığında gezinmeye devam edebilir. Tarayıcılar arası bilgi kutucuğu desteği gerektiğinde polyfill'leri gerektiği gibi koşullu olarak yükleyin.

Popover için yedekler ve tarayıcı desteği

Popover API çoğunlukla progresif geliştirme ile ilgilidir ancak tanımlayıcı davranışlarının (üst katman tanıtımı, hafif kapatma ve popovertarget çağrısı) yalnızca CSS'ye dayalı bir eşdeğeri yoktur. Eski tarayıcılar için polyfill veya polyfill kullanmak istemiyorsanız manuel yedek gerekir.

Polyfill: Eski tarayıcılarda popover özelliğini desteklemek için @oddbird/popover-polyfill öğesini koşullu olarak yükleyin. ZORUNLU: HTMLElement.prototype üzerinde popover özelliğini kontrol ederek özelliği tespit edin ve polyfill'i yalnızca yerel destek eksik olduğunda yükleyin. Koşulsuz olarak YÜKLEMEYİN.

Paketleyici veya içe aktarma eşlemesiyle:

// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
  import("@oddbird/popover-polyfill");
}

Paketleyici olmadan, <script type="module"> içindeki bir CDN'den içe aktarın:

<script type="module">
  if (!("popover" in HTMLElement.prototype)) {
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  }
</script>

Stil uyarısı: Polyfill, gerçek :popover-open sözde sınıfını tanımlayamadığı için bunun yerine .\:popover-open sınıfını uygular. ZORUNLU: İkisini :is() veya :where() ile birleştirin. Aksi takdirde, :popover-open içermeyen tarayıcılar kuralın tamamını siler:

[popover]:is(:popover-open, .\:popover-open) {
  display: block;
}

Alternatif olarak, polyfill içermeyen eski bir yedek için position: fixed kullanın ve koordinatları getBoundingClientRect() aracılığıyla manuel olarak hesaplayın veya kullanım alanına uygunsa inset: auto ile varsayılan konumlandırmayı kullanın.

İlgi alanı çağırıcıları için yedekler ve tarayıcı desteği

İlgi alanı çağırıcılar, NPM'deki interestfor polyfill paketi kullanılarak koşullu olarak polyfill edilmelidir. CDN kullanmak yerine polyfill'i paketlemeyi tercih edin.

ZORUNLU: HTMLButtonElement.prototype üzerinde interestForElement özelliğini kontrol ederek özellik algılama gerçekleştirin ve polyfill'i yalnızca yerel destek olmadığında yükleyin.

<script type="module">
  if (!HTMLButtonElement.prototype.hasOwnProperty("interestForElement")) {
    // CDN link only used for example, prefer bundling.
    await import("https://unpkg.com/interestfor@latest");
  }
</script>

CSS Polyfill ile İlgili Dikkat Edilmesi Gerekenler

Polyfill kullanılırken CSS API, yerel sözde sınıf ve özellik desteğinin eksikliğini gidermek için biraz değişir:

  • Sözde sınıflar: Polyfill, gerçek :interest-source ve :interest-target sözde sınıflarını tanımlayamadığından bunun yerine .interest-source ve .interest-target sınıflarını uygular. ZORUNLU: Hem yerel hem de polyfill durumlarını desteklemek için bunları :is() ile birleştirin.
/* Styles to apply when the effect is being previewed */
:is(:interest-source, .interest-source) { /* ... */ }
:is(:interest-target, .interest-target) { /* ... */ }
  • CSS özellikleri: interest-delay, interest-delay-start ve interest-delay-end için polyfill, özel özellikleri tüm tarayıcılarda doğrudan okuyamadığından CSS değişkenlerinin kullanılmasını gerektirir.
/* Adjust the start and end delay for interest invokers */
[interestfor] {
  --interest-delay-start: 0.2s;
  interest-delay-start: var(--interest-delay-start);
  --interest-delay-end: 0.1s;
  interest-delay-end: var(--interest-delay-end);
}