İçeriğe Dayalı Stil Oluşturma

Web özellikleri: :has() :not()

Geçmişte, bir bileşene içeriğine göre farklı düzenler uygulamak için HTML şablon oluşturma dilinizde JavaScript veya koşullu mantık kullanarak değiştirici sınıflar (.card--has-image veya .card--text-only gibi) eklemeniz gerekiyordu.

:has() sözde sınıfı, üst seçici olarak hareket ederek bu ihtiyacı ortadan kaldırır. Bu sözde sınıf, belirli alt öğelerin varlığına veya yokluğuna bağlı olarak bir kapsayıcı öğeyi koşullu olarak biçimlendirmenize olanak tanır.

:has() kullanarak, bir bileşenin gerçek DOM içeriğine göre tamamen CSS'de farklı düzen varyasyonlarını kolayca tanımlayabilirsiniz. Varsayılan düzenleri tanımlamak için içeriğin yokluğunu açıkça hedeflemek üzere isteğe bağlı olarak :not() ile birleştirebilirsiniz.

İçeriğe dayalı kapsayıcı stilini uygulama

ZORUNLU: Belirli alt içeriklerin varlığını tespit etmek için kapsayıcı öğede :has() seçicisini kullanmanız gerekir.

Düzenini içeriğine göre değiştiren bir bileşen oluşturmak için:

  1. Varsayılan stili tanımlama: Temel düzen stillerini kapsayıcı öğeye (ör. basit bir tek sütunlu yığın) uygulayın.
  2. İçeriğe dayalı geçersiz kılma işlemleri uygulama: Kapsayıcıyı :has([child-selector]) ile hedefleyin ve bu içerik mevcut olduğunda yeni düzen stillerini (ör. çok sütunlu tablo) uygulayın.

Örnek: Resim varsa yan yana düzene geçen bir kart bileşeni.

/* 1. Define the default state on the component container */
/* This applies when there is NO image */
.article-card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.5rem;
  border: 1px solid #ccc;
  border-radius: 8px;
}

/* 2. Apply styles when a specific child element is present */
/* MANDATORY: Target the container and use :has() to check for the descendant */
.article-card:has(img) {
  /* Change the layout to a row if an image exists */
  flex-direction: row;
  align-items: center;
}

/* Optional: Style the image itself (no :has() needed here) */
.article-card img {
  width: 150px;
  height: auto;
  border-radius: 4px;
}

/* You can also combine :has() and :not() to explicitly target the ABSENCE of content */
/* This selects a card that DOES NOT have an image */
.article-card:not(:has(img)) {
  /* E.g., apply a different background color for text-only cards */
  background-color: #f9f9f9;
}
<!-- Assume an <h1> precedes these components in the document layout -->
<!-- A card WITH an image (will use row layout) -->
<article class="article-card">
  <img src="thumbnail.jpg" alt="Article thumbnail" />
  <div class="content">
    <h2>Card With Image</h2>
    <p>This card lays out its content horizontally.</p>
  </div>
</article>

<!-- A card WITHOUT an image (will use default column layout) -->
<article class="article-card">
  <div class="content">
    <h2>Text-Only Card</h2>
    <p>This card lays out its content vertically, and gets its background color from the :not(:has()) rule.</p>
  </div>
</article>

Performans ipucu: :has() kullanırken seçiciyi mümkün olan en spesifik bileşen kapsayıcısına (ör. .article-card) göre ayarlayın. Stil değişiklikleri yüksek düzeyde yerelleştirilmişse seçiciyi body:has(img) gibi çok üst düzey öğelere sabitlemekten kaçının. Geniş :has() sorguları, daha fazla düzen yeniden hesaplamasını tetikleyebilir.

Yedek stratejiler

İçeriğe dayalı düzen stili, kullanıcı deneyimi veya sayfa tasarımı açısından kritik öneme sahipse :has() seçiciyi desteklemeyen tarayıcılar için bir yedek sağlamanız gerekir. Yalnızca dekoratif efektler için :has(), yedek olmadan progresif geliştirme olarak kullanılabilir.

ZORUNLU: Kritik düzenler için yedek uygularken geleneksel sınıf tabanlı bir yedek (ör. .has-image) tanımlamak için CSS'nizde @supports not selector(:has(*)) kullanmanız gerekir.

Etkileşimli duruma dayalı stil oluşturmanın aksine, içerik varlığı genellikle oluşturma sırasında bilinir. En sağlam yedek, sunucu tarafı şablon oluşturma motorunuzun (veya statik site oluşturucunuzun), verilerde alt öğe (resim gibi) varsa kapsayıcıya .has-image gibi bir sınıf eklemesidir.

Sunucu tarafı oluşturma bir seçenek değilse içeriği algılamak ve yükleme sırasında veya dinamik içerik ekleme işleminden sonra sınıfı eklemek için CSS.supports() ile küçük bir komut dosyası kullanmanız gerekir.

/* Fallback CSS for older browsers */
/* We check if the browser DOES NOT support the :has() selector */
@supports not selector(:has(*)) {
  /* Define a traditional modifier class that applies the exact same layout overrides */
  .article-card.has-image {
    flex-direction: row;
    align-items: center;
  }
  
  .article-card:not(.has-image) {
    background-color: #f9f9f9;
  }
}
/* Fallback JavaScript for older browsers (if not using SSR to add the class) */
/* Check for support before running the script to avoid unnecessary work in modern browsers */
if (!CSS.supports('selector(:has(*))')) {
  // Find all components that need checking
  const cards = document.querySelectorAll('.article-card');
  
  cards.forEach(card => {
    // If the critical content exists, manually add the fallback class
    if (card.querySelector('img')) {
      card.classList.add('has-image');
    }
  });
}