Etykietki z informacją o pozycji

Podczas tworzenia etykietek lub wyskakujących okienek za pomocą pozycjonowania zakotwiczonego CSS przeglądarka może automatycznie „odwrócić” element do pozycji zastępczej, jeśli w przeciwnym razie przekroczyłby on widoczny obszar. W takich przypadkach możesz dostosować styl pozycjonowanej treści, np. zmienić położenie strzałki, która wskazuje od pozycjonowanej treści do kotwicy.

Zapytania o zakotwiczone kontenery rozwiązują ten problem, umożliwiając wysyłanie zapytań o aktywny stan pozycjonowania elementu i odpowiednie stosowanie stylów. Ogólne informacje o pozycjonowaniu zakotwiczonych menu i menu wysuwanych z odwracaniem kolizji widocznego obszaru (bez zmiany stylu strzałki kierunkowej) znajdziesz w artykule Menu uwzględniające widoczny obszar.

Problem

Wyobraź sobie etykietkę, która domyślnie pojawia się nad kotwicą. Na dole znajduje się strzałka w dół. Jeśli użytkownik przewinie stronę i etykietka pojawi się poniżej kotwicy, strzałka będzie wskazywać niewłaściwy kierunek i będzie znajdować się po niewłaściwej stronie etykietki.

Rozwiązanie: zapytania dotyczące kontenerów zakotwiczonych

Ustawiając container-type: anchored na elemencie pozycjonowanym, zmieniasz go w kontener zapytania, który zna swój stan pozycjonowania zakotwiczonego. Następnie możesz użyć zapytania @container anchored(), aby zaktualizować elementy podrzędne lub pseudoelementy.

1. Tworzenie etykietki i aktywatora

Użyj interfejsu Popover API, aby utworzyć etykietkę. Wywołanie elementu popover za pomocą popovertarget automatycznie ustanawia niejawne połączenie zakotwiczone z przyciskiem aktywującym, więc nie jest wymagane jawne użycie anchor-name ani position-anchor.

<button popovertarget="tooltip" id="anchor" aria-describedby="tooltip">anchor</button>
<div id="tooltip" popover role="tooltip"></div>

Resetowanie stylów wstawki i marginesu wyskakującego okienka do użycia z pozycjonowaniem zakotwiczonym, ale tylko wtedy, gdy pozycjonowanie zakotwiczone jest obsługiwane.

@supports (anchor-name: --my-anchor) {
  [popover] {
    inset: auto;
    margin: unset;
  }
}

2. Konfigurowanie kontenera

Zastosuj container-type: anchored do elementu, który ma zostać umieszczony. Aby włączyć odwracanie, ten element musi mieć też zdefiniowany atrybut position-try-fallbacks.

#tooltip {
  position: fixed;
  position-area: block-start;
  position-try-fallbacks: flip-block;

  /* Enable anchored container queries */
  container-type: anchored;
}

3. Styl oparty na kreacji zastępczej

Użyj @container anchored(fallback: <value>), aby zastosować style, gdy aktywna jest określona kreacja zastępcza.

Podobnie jak w przypadku wszystkich zapytań o kontener, @container może stylizować tylko elementy podrzędne kontenera. Częstą strategią tworzenia strzałek jest użycie pseudoelementów ::before i ::after, które są traktowane jako elementy podrzędne i mogą być stylizowane bezpośrednio. Aby jednak nadać styl samej etykiecie (jak w kroku 4), dodamy do niej element podrzędny i utworzymy strzałkę w jego pseudoelemencie ::before.

<div id="tooltip" popover role="tooltip">
  <div class="tooltip-content">Tooltip</div>
</div>
.tooltip-content::before {
  /* Default "down" arrow for the 'top' position */
  content: "▼";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 1rem;
}

/* Update to an "up" arrow when the 'flip-block' fallback (bottom) is active */
@container anchored(fallback: flip-block) {
  .tooltip-content::before {
    content: "▲";
    inset-block-start: 0;
    inset-block-end: auto;
  }
}

4. Stylizowanie samego kontenera

Jeśli chcesz zmienić właściwości samego kontenera (np. margin lub background-color) podczas jego odwracania, użyj wewnętrznego elementu opakowującego.

  1. Zastosuj container-type: anchored do zewnętrznego elementu pozycjonowanego.
  2. Ustaw element wewnętrzny w bloku @container jako element docelowy.
@container anchored(fallback: flip-block) {
  .tooltip-content {
    border-radius: 0 0 .5rem .5rem;
    margin-block-start: 0.25rem;
  }
}

Sprawdzone metody

  • Preferuj logiczne wartości zastępcze: używaj słów kluczowych takich jak flip-block i flip-inline w position-try-fallbacks, aby uprościć zapytania, które automatycznie obsługują języki zapisywane od prawej do lewej i różne tryby pisania.
  • Używaj pseudoelementów do strzałek: strzałki etykietek mają charakter czysto dekoracyjny i doskonale nadają się do użycia z ::before lub ::after, które można stylizować za pomocą zapytań o zakotwiczony kontener bez dodatkowego modelu DOM.

Strategie zastępcze

Pozycjonowanie strzałki na podstawie zastosowanego elementu zastępczego to progresywne ulepszanie i nie ma innego sposobu reagowania na pozycję elementu zastępczego. Aby ukryć strzałkę w przeglądarkach, które nie obsługują zapytań o kontener pozycji zakotwiczenia, przetestuj obsługę CSS za pomocą @supports (container-type: anchored).

@supports (container-type: anchored) {
  .tooltip-content::before {
    content: "▼";
  }
}

Kreacje zastępcze i obsługa wyskakujących okienek w przeglądarkach

Interfejs Popover API to głównie progresywne ulepszanie, ale jego definiujące zachowania – promowanie warstwy górnej, lekkie odrzucanie i wywoływanie popovertarget – nie mają odpowiednika tylko w CSS. Starsze przeglądarki wymagają polyfilla lub ręcznego rozwiązania zastępczego, jeśli nie chcesz go dostarczać.

Polyfill: aby obsługiwać atrybut popover w starszych przeglądarkach, warunkowo wczytuj @oddbird/popover-polyfill. OBOWIĄZKOWO: wykryj funkcję, sprawdzając właściwość popover w HTMLElement.prototype, i wczytaj polyfill tylko wtedy, gdy brakuje obsługi natywnej – NIE wczytuj go bezwarunkowo.

Za pomocą bundlera lub mapy importu:

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

Bez bundlera, importuj z sieci CDN w tagu <script type="module">:

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

Uwaga dotycząca stylów: polyfill nie może zdefiniować rzeczywistej pseudoklasy :popover-open, więc zamiast tego stosuje klasę .\:popover-open. OBOWIĄZKOWO: połącz te 2 właściwości za pomocą :is() lub :where(), w przeciwnym razie przeglądarki, które nie obsługują :popover-open, odrzucą całą regułę:

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

Możesz też użyć position: fixed i ręcznie obliczyć współrzędne za pomocą getBoundingClientRect() lub polegać na domyślnym pozycjonowaniu za pomocą inset: auto, jeśli jest to akceptowalne w danym przypadku użycia.

Przeglądarki, które nie obsługują interfejsu Popover API, nie obsługują też pozycjonowania kotwicy, więc etykietka pojawi się na środku ekranu.