Wyszukiwanie ukrytych treści

Interfejsy internetowe często ukrywają treści, aby poprawić wrażenia użytkowników, zaoszczędzić miejsce na ekranie lub zwiększyć wydajność strony. Tradycyjne metody, takie jak display: none lub visibility: hidden, ukrywają treści wizualnie, ale sprawiają też, że są one całkowicie niedostępne dla czytników ekranu i funkcji przeglądarki, takich jak „Znajdź na stronie”.

Aby ukryć treści wizualnie, ale nadal umożliwiać użytkownikom ich wyszukiwanie i tworzenie do nich precyzyjnych linków za pomocą fragmentów adresów URL i linków „Przewiń do fragmentu tekstu”, możesz użyć elementu HTML <details> lub atrybutu hidden="until-found". Zalecamy używanie elementu <details>, ponieważ jest on prostszy we wdrożeniu i utrzymaniu, ale w niektórych bardziej złożonych przypadkach element <details> nie wystarcza i wymagany jest element hidden="until-found".

Na przykład:

  • Jeśli chcesz mieć pełną kontrolę nad stylem mechanizmu wyświetlania/ukrywania.
  • Jeśli elementy sterujące interfejsu do wyświetlania/ukrywania treści znajdują się w innej części modelu DOM.
  • Jeśli nie chcesz obsługiwać ukrywania treści po ich wyświetleniu.

Jak to zrobić?

Element <details> domyślnie zawiera tekst, który można wyszukiwać i który jest dostępny, więc nie wymaga specjalnej implementacji. Jeśli to możliwe, używaj <details> zamiast hidden="until-found".

Jeśli musisz użyć hidden="until-found", wykonaj te czynności:

  1. Zastosuj atrybut: dodaj atrybut HTML hidden="until-found" bezpośrednio do elementów zawierających treści, które mają być ukryte.
  2. Zsynchronizuj stan interfejsu: jeśli interfejs ma powiązane stany, które zależą od widoczności treści (np. aktualizowanie atrybutów ARIA, przełączanie otwartych/zamkniętych klas CSS lub obracanie ikon akordeonu):
    • MUSISZ dodać detektor zdarzeń dla zdarzenia beforematch.
    • Zarejestruj detektor zdarzeń beforematch bezpośrednio w elemencie zawierającym atrybut hidden="until-found". Zdarzenie jest przekazywane w górę, więc możesz też użyć delegowania zdarzeń, rejestrując pojedynczy detektor w elemencie nadrzędnym (np. kontenerze kart), aby zarządzać wieloma ukrytymi sekcjami naraz.
    • W detektorze zdarzeń wykonaj logikę, aby zsynchronizować powiązane elementy interfejsu (np. zamknąć inne otwarte karty lub zmienić stan przycisku przełączania).

Przykładowy kod

Cel: wyrenderowanie ukrytego kontenera, w którym treść pozostaje niewidoczna dla użytkownika, dopóki nie wyszuka on słowa w tej sekcji.

Używanie elementu <details>

<details>
  <summary>Click to expand</summary>
  <p>This content is visually hidden.</p>
</details>

Wykluczające się oświadczenia

W przypadku wzajemnie wykluczających się regionów treści, takich jak wyłączny akordeon, użyj natywnego elementu HTML <details> z udostępnionym atrybutem name.

<div class="accordion-group">
  <!-- The name attribute creates an exclusive disclosure group -->
  <details class="disclosure" name="my-accordion">
    <summary>Section 1</summary>
    <p>Section 1 content</p>
  </details>

  <details class="disclosure" name="my-accordion" open>
    <summary>Section 2</summary>
    <p>Section 2 content</p>
  </details>

  <details class="disclosure" name="my-accordion">
    <summary>Section 3</summary>
    <p>Section 3 content</p>
  </details>
</div>

Używanie atrybutu hidden="until-found"

<!-- The browser automatically removes hidden="until-found" upon a search match -->
<div class="hidden-container" hidden="until-found">
  <p>This content is visually hidden.</p>
</div>

Niestandardowe oświadczenia wykluczające się wzajemnie

Podczas obsługi niestandardowych, wzajemnie wykluczających się regionów kontrolowanych przez przyciski zewnętrzne upewnij się, że widoczny jest tylko dopasowany panel. W module obsługi zdarzeń beforematch MUSISZ zsynchronizować powiązane stany ARIA, np. ustawić aria-expanded="true" na przycisku sterującym.

<div class="custom-accordion">
  <div class="controls">
    <button aria-expanded="true" aria-controls="panel-1" id="btn-1">Section 1</button>
    <button aria-expanded="false" aria-controls="panel-2" id="btn-2">Section 2</button>
  </div>

  <div id="panel-1" class="panel">
    <p>Section 1 content (visible)</p>
  </div>

  <div id="panel-2" class="panel" hidden="until-found">
    <p>Section 2 content (hidden)</p>
  </div>
</div>
const accordion = document.querySelector('.custom-accordion');

accordion.addEventListener('beforematch', (e) => {
  // Hide all panels and synchronize button states before the browser reveals the matched panel
  accordion.querySelectorAll('.panel').forEach((panel) => {
    if (panel !== e.target) {
      panel.hidden = 'until-found';
    }
  });
  accordion.querySelectorAll('button').forEach((btn) => {
    const controls = btn.getAttribute('aria-controls');
    btn.setAttribute('aria-expanded', controls === e.target.id ? 'true' : 'false');
  });
});

hidden="until-found" – sprawdzone metody

  • ZASTOSUJ obramowania, dopełnienia i tła do zagnieżdżonych elementów podrzędnych, a nie bezpośrednio do elementu z atrybutem hidden="until-found". Zapobiega to niezamierzonym przesunięciom układu lub pozostawieniu elementów wizualnych, gdy element jest ukryty.
  • NIE stosuj właściwości CSS display: none, visibility: hidden ani żadnych powiązanych właściwości display lub visibility bezpośrednio do elementów z atrybutem hidden="until-found". Powoduje to uszkodzenie natywnej funkcji i trwałe ukrycie treści w indeksie wyszukiwarki.
  • NIE używaj hidden="until-found" do przechowywania informacji poufnych, tokenów danych wewnętrznych ani nieistotnych danych, które nie powinny być widoczne w wynikach wyszukiwania.
  • NIE używaj hidden="until-found" jako zamiennika tekstu „tylko dla czytnika ekranu” (.sr-only).

Obsługa przeglądarek i strategie zastępcze

NIE unikaj elementu hidden="until-found" z powodu braku obsługi przez przeglądarkę, ponieważ korzyści związane z ułatwieniami dostępu znacznie przewyższają koszty wdrożenia kreacji zastępczej.

hidden="until-found" – kreacja zastępcza

W przypadku standardowych elementów interfejsu, takich jak akordeony czy sekcje „Czytaj więcej”, użyj JavaScriptu, aby wykryć funkcję i wyświetlić całą treść, jeśli funkcja nie jest obsługiwana.

if (!('onbeforematch' in HTMLElement.prototype)) {
  // Expand all hidden content for unsupported browsers
  document.querySelectorAll('[hidden="until-found"]').forEach((el) => {
    el.removeAttribute('hidden');
    // MANDATORY: also update any aria references to this element.
  });
}

W przypadku wzorców interfejsu, które wzajemnie się wykluczają (np. niestandardowych paneli, w których treści współdzielą ten sam obszar wizualny), kreacja zastępcza powinna wyodrębniać i wyświetlać wszystkie treści liniowo pod głównym obszarem interaktywnym, używając fragmentów kotwicy adresu URL, aby umożliwić użytkownikom przechodzenie bezpośrednio do odpowiednich sekcji.