Block Links: Die Suche nach einer perfekten Lösung

Avatar of Vikas Parashar
Vikas Parashar am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ich habe diesen Artikel von Chris gelesen, in dem er über Block Links spricht – wissen Sie, wie man ein ganzes Karten-Element in einen Anker einbettet – als schlechte Idee. Es ist schlecht für die Barrierefreiheit, da es Bildschirmlesegeräte beeinträchtigt. Und es ist schlecht für die Benutzerfreundlichkeit, da es einfache Benutzeraufgaben wie das Auswählen von Text verhindert.

Aber vielleicht spielt etwas anderes eine Rolle. Vielleicht liegt das Problem weniger am Muster als an dessen Implementierung. Das hat mich zu der Überzeugung gebracht, dass jetzt der richtige Zeitpunkt ist, einen Folgeartikel zu schreiben, um zu sehen, ob wir einige der Probleme lösen können, auf die Chris hingewiesen hat.

In diesem Beitrag verwende ich den Begriff „Karte“, um eine Komponente zu beschreiben, die das Block-Link-Muster verwendet. Hier ist, was wir damit meinen.

Sehen wir uns an, wie unsere Karten-Komponenten funktionieren sollen

  1. Das Ganze sollte verlinkt und klickbar sein.
  2. Es sollte mehr als einen Link enthalten können.
  3. Der Inhalt sollte semantisch sein, damit assistive Technologien ihn verstehen können.
  4. Der Text sollte auswählbar sein, wie normale Links.
  5. Dinge wie Rechtsklick und Tastenkombinationen sollten damit funktionieren
  6. Seine Elemente sollten beim Tab-Wechsel fokussierbar sein.

Das ist eine lange Liste! Und da der Browser keine standardmäßige Karten-Widget bereitstellt, haben wir keine Standardrichtlinien für dessen Erstellung. 

Wie bei den meisten Dingen im Web gibt es mehr als eine Möglichkeit, eine Kartenkomponente zu erstellen. Ich habe jedoch noch nichts gefunden, das alle von uns gerade behandelten Anforderungen erfüllt. In diesem Artikel werden wir versuchen, alle zu erfüllen. Das werden wir jetzt tun!

Methode 1: Alles in einen <a> einbetten

Dies ist die gängigste und einfachste Methode, eine verlinkte Karte zu erstellen. Nehmen Sie den HTML-Code für die Karte und betten Sie das Ganze in ein Anker-Tag ein.

<a href="/">
  <!-- Card markup -->
</a>

Hier ist, was uns das bringt

  1. Sie ist klickbar.
  2. Sie funktioniert mit Rechtsklick und Tastenkombinationen.

Nun ja, nicht gut. Wir können immer noch nicht

  1. Einen weiteren Link in die Karte einfügen, da das Ganze ein einzelner Link ist
  2. Sie mit einem Bildschirmlesegerät verwenden – der Inhalt ist nicht semantisch, sodass assistive Technologien alles innerhalb der Karte ankündigen, beginnend mit dem Zeitstempel
  3. Text auswählen

Das ist genug 👎, dass wir es wahrscheinlich nicht benutzen sollten. Gehen wir zur nächsten Technik über.

Dies ist ein guter Kompromiss, der etwas Benutzerfreundlichkeit für verbesserte Barrierefreiheit opfert.

Mit diesem Muster erreichen wir die meisten unserer Ziele

  1. Wir können so viele Links einfügen, wie wir möchten. 
  2. Inhalt ist semantisch.
  3. Wir können den Text der Karte auswählen.
  4. Rechtsklick und Tastenkombinationen funktionieren.
  5. Der Fokus liegt beim Tabulatorwechsel in der richtigen Reihenfolge.

Aber es fehlt die Hauptfunktion, die wir uns von einer Karte wünschen: Das Ganze sollte klickbar sein! Sieht so aus, als müssten wir einen anderen Weg versuchen.

Methode 3: Das gute alte ::before Pseudo-Element

Bei dieser Methode fügen wir ein ::before oder ::after Element hinzu, platzieren es mit absoluter Positionierung über der Karte und dehnen es über die gesamte Breite und Höhe der Karte aus, damit es klickbar ist.

Aber jetzt

  1. Wir können immer noch nicht mehr als einen Link hinzufügen, da alles andere, was verlinkt ist, unter der Pseudo-Element-Ebene liegt. Wir können versuchen, den gesamten Text über das Pseudo-Element zu legen, aber der Kartenlink selbst funktioniert nicht, wenn man über den Text klickt.
  2. Wir können den Text immer noch nicht auswählen. Auch hier könnten wir die Ebenen tauschen, aber dann sind wir wieder beim Problem des klickbaren Links.

Versuchen wir, mit unserer letzten Technik wirklich alle Kriterien zu erfüllen.

Methode 4: Etwas JavaScript auf die zweite Methode streuen

Wir bauen auf der zweiten Methode auf. Erinnern Sie sich, das war die, bei der wir alles verlinken, was ein Link sein soll

<article class="card">
  <time datetime="2020-03-20">Mar 20, 2020</time>
  <h2><a href="https://css-tricks.de/a-complete-guide-to-calc-in-css/" class="main-link">A Complete Guide to calc() in CSS</a></h2>
  <p>
    In this guide, let’s cover just about everything there is to know about this very useful function.
  </p>
  <a class="author-name" href="https://css-tricks.de/author/chriscoyier/" target="_blank">Chris Coyier</a>
    <div class="tags">
      <a class="tag" href="https://css-tricks.de/tag/calc/" >calc</a>
    </div>
</article>

Wie machen wir also die *ganze* Karte klickbar? Wir könnten JavaScript als progressive Verbesserung dafür nutzen. Wir beginnen damit, einen click Event-Listener zur Karte hinzuzufügen und den Klick auf den Hauptlink auszulösen, wenn er ausgelöst wird.

const card = document.querySelector(".card")
const mainLink = document.querySelector('.main-link')


card.addEventListener("click", handleClick)


function handleClick(event) {
  mainLink.click();
}

Vorübergehend führt dies zu dem Problem, dass wir den Text nicht auswählen können, was wir die ganze Zeit versucht haben zu beheben. Hier ist der Trick: Wir verwenden die relativ unbekannte Web-API window.getSelection. Laut MDN

Die Methode Window.getSelection() gibt ein Selection-Objekt zurück, das den vom Benutzer ausgewählten Textbereich oder die aktuelle Position des Cursors darstellt.

Obwohl diese Methode ein Objekt zurückgibt, können wir es mit toString() in einen String konvertieren.

const isTextSelected = window.getSelection().toString()

Mit einer Zeile und ohne komplizierte Tricks mit Event-Listenern wissen wir, ob der Benutzer Text ausgewählt hat. Verwenden wir das in unserer handleClick Funktion.

const card = document.querySelector(".card")
const mainLink = document.querySelector('.main-link')


card.addEventListener("click", handleClick)


function handleClick(event) {
  const isTextSelected = window.getSelection().toString();
  if (!isTextSelected) {
    mainLink.click();
  }
}

Auf diese Weise kann der Hauptlink angeklickt werden, wenn kein Text ausgewählt ist, und das alles erforderte nur ein paar Zeilen JavaScript. Das erfüllt unsere Anforderungen

  1. Das Ganze ist verlinkt und klickbar.
  2. Es kann mehr als einen Link enthalten.
  3. Dieser Inhalt ist semantisch, damit assistive Technologien ihn verstehen können.
  4. Der Text sollte auswählbar sein, wie normale Links.
  5. Dinge wie Rechtsklick und Tastenkombinationen sollten damit funktionieren
  6. Seine Elemente sollten beim Tab-Wechsel fokussierbar sein.

Wir haben alle Anforderungen erfüllt, aber es gibt immer noch einige Haken, wie z. B. doppelte Event-Auslösung bei klickbaren Elementen wie Links und Schaltflächen in der Karte. Wir können dies beheben, indem wir auf allen von ihnen einen Klick-Event-Listener hinzufügen und die Weiterleitung des Events stoppen.

// You might want to add common class like 'clickable' on all elements and use that for the query selector.
const clickableElements = Array.from(card.querySelectorAll("a"));
clickableElements.forEach((ele) =>
  ele.addEventListener("click", (e) => e.stopPropagation())
);

Hier ist die finale Demo mit dem gesamten JavaScript-Code, den wir hinzugefügt haben

Ich glaube, wir haben es geschafft! Jetzt wissen Sie, wie man eine perfekte klickbare Kartenkomponente erstellt.

Was ist mit anderen Mustern? Was ist zum Beispiel, wenn die Karte den Auszug eines Blogbeitrags enthält, gefolgt von einem „Weiterlesen“-Link? Wo soll dieser hin? Wird das zum „Haupt“-Link? Was ist mit dem Bild?

Für diese und weitere Fragen gibt es hier weiterführende Lektüre zum Thema