Kombinacje selektorów i reguł @

Funkcje internetowe: Zapytania o styl kontenera

Problem

Często musimy łączyć kryteria filtrowania różnych typów, np. selektory i zapytania o multimedia, zapytania o multimedia i zapytania o kontenery itd.

Możesz na przykład połączyć (prefers-color-scheme: dark) z selektorem, który jest kierowany na zastąpienia schematu kolorów (np. :root:has(> head > meta[name="color-scheme"][content="dark"]) lub :root.dark), aby zastosować określone style w trybie jasnym lub trybie ciemnym niezależnie od tego, jak ustawiono schemat kolorów.

Naiwne podejście prowadzi do powielania kodu:

/* Light mode styles */
.card.featured {
  font-weight: 400;
}

#logo-dark {
  display: none;
}

@media (prefers-color-scheme: dark) {
  /* Dark mode styles */
  :root:not(.light) {
    .card.featured {
      font-weight: 300;
    }

    #logo-dark {
      display: inline;
    }

    #logo {
      display: none;
    }
  }
}

/* Dark mode styles, again */
:root.dark {
  .card.featured {
    font-weight: 300;
  }

  #logo-dark {
    display: inline;
  }

  #logo {
    display: none;
  }
}

Co należy zrobić

Zapisz wynik połączonego filtra we właściwości niestandardowej, a następnie użyj zapytań dotyczących stylu kontenera, aby ustawić reguły na podstawie tej właściwości.

WAŻNE: ze względu na sposób działania zapytań o kontener ta technika działa tylko wtedy, gdy możemy ustawić właściwość niestandardową w elemencie nadrzędnym wszystkich reguł, które muszą zostać dopasowane.

1. Oddzielenie logiki wyboru od stosowanych reguł

:root {
  --color-scheme: light;

  @media (prefers-color-scheme: dark) {
    --color-scheme: dark;
  }

  &:has(> head > meta[name="color-scheme"][content="dark"]) {
    --color-scheme: dark;
  }

  &:has(> head > meta[name="color-scheme"][content="light"]) {
    --color-scheme: light;
  }
}

2. Klucz we właściwości niestandardowej dla zastosowanych reguł

@container not style(--color-scheme: dark) {
  .card.featured {
    font-weight: 400;
  }

  #logo-dark {
    display: none;
  }
}

@container style(--color-scheme: dark) {
  .card.featured {
    font-weight: 300;
  }

  #logo {
    display: none;
  }
}

3. OPCJONALNE: klasy narzędziowe do przełączania widoczności

Bardzo częstym przypadkiem jest przełączanie widoczności na podstawie tego, czy kryteria są spełnione. Klasy narzędziowe muszą mieć pierwszeństwo przed dowolnymi stylami komponentów (stąd !important), a ich wyświetlany display jest nieznany, więc nie mogą używać zastąpień – ogranicz je za pomocą not style(...):

@container not style(--color-scheme: dark) {
  .if-dark {
    display: none !important;
  }
}

@container not style(--color-scheme: light) {
  .if-light {
    display: none !important;
  }
}

Wartości zastępcze

Istnieją 2 rodzaje kreacji zastępczych, w zależności od tego, jak krytyczne jest rozgałęzienie i co stanowi akceptowalną kreację zastępczą.

  1. W przypadku krytycznego rozgałęzienia, w którym wszystkie stany muszą działać prawidłowo, nawet jeśli zapytania o style nie są obsługiwane, nie można używać zapytań o style. Zamiast tego użyj powyższego prostego podejścia, powielając reguły dla każdego stanu. Można nadal używać klas narzędziowych, o ile są one zdefiniowane w ten sposób.
  2. W przypadku niekrytycznego rozgałęziania, gdy stan domyślny jest akceptowalny, możesz zdefiniować style podstawowe poza regułą @container i używać zapytań o style tylko jako zastąpień. Pozwala to zachować większość zalet tego podejścia, a główną wadą jest sprzężenie wartości, które wprowadzają zastąpienia.
#logo-dark {
  display: none;
}

@container style(--color-scheme: dark) {
  #logo-dark {
    display: inline; /* override */
  }

  #logo {
    display: none;
  }
}