Wie man Links deaktiviert

Avatar of Gerard Cohen
Gerard Cohen am

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

Das Thema der Deaktivierung von Links kam neulich bei der Arbeit auf. Irgendwie wurde letztes Jahr ein "deaktivierter" Ankerstil zu unseren Typografie-Stilen hinzugefügt, als ich nicht hinsah. Es gibt jedoch ein Problem: Es gibt keine wirkliche Möglichkeit, einen <a>-Link (mit einem gültigen href-Attribut) in HTML zu deaktivieren. Ganz zu schweigen davon, warum man das überhaupt wollen würde? Links sind die Grundlage des Webs.

Irgendwann sah es so aus, als ob meine Kollegen diese Tatsache nicht akzeptieren würden, also begann ich darüber nachzudenken, wie dies erreicht werden könnte. Da ich wusste, dass es viel Aufwand bedeuten würde, wollte ich beweisen, dass es die Mühe und den Code nicht wert war, eine solch unkonventionelle Interaktion zu unterstützen, aber ich befürchtete, dass sie bei der Demonstration, dass es möglich ist, all meine Warnungen ignorieren und mein Beispiel als Beweis dafür verwenden würden, dass es in Ordnung ist. Das hat sich für mich noch nicht ganz ergeben, aber ich dachte, wir könnten meine Recherche durchgehen.

Zuerst das Wichtigste

Mach es einfach nicht.

Ein deaktivierter Link ist kein Link, er ist nur Text. Sie müssen Ihr Design überdenken, wenn es die Deaktivierung eines Links erfordert.

Bootstrap hat Beispiele für die Anwendung der Klasse .disabled auf Anker-Tags, und ich hasse sie dafür. Zumindest erwähnen sie, dass die Klasse nur einen deaktivierten *Stil* bietet, aber das ist irreführend. Sie müssen mehr tun, als nur einen Link deaktiviert *aussehen* zu lassen, wenn Sie ihn wirklich deaktivieren wollen.

Sicherer Weg: Entfernen Sie das href

Wenn Sie sich entschieden haben, meine Warnung zu ignorieren und mit der Deaktivierung eines Links fortzufahren, dann ist das Entfernen des href-Attributs der beste Weg, den ich kenne.

Direkt aus der offiziellen Hyperlink-Spezifikation

Das href-Attribut auf a- und area-Elementen ist nicht erforderlich; wenn diese Elemente keine href-Attribute haben, erstellen sie keine Hyperlinks.

Eine leichter verständliche Definition von MDN

Dieses Attribut kann weggelassen werden (ab HTML5), um einen Platzhalter-Link zu erstellen. Ein Platzhalter-Link ähnelt einem herkömmlichen Hyperlink, führt aber nirgendwohin.

Hier ist einfacher JavaScript-Code zum Setzen und Entfernen des href-Attributs

/* 
 * Use your preferred method of targeting a link
 *
 * document.getElementById('MyLink');
 * document.querySelector('.link-class');
 * document.querySelector('[href="https://unfetteredthoughts.net"]');
 */
// "Disable" link by removing the href property
link.href = '';
// Enable link by setting the href property
link.href = 'https://unfetteredthoughts.net';

Das Styling über CSS ist ebenfalls ziemlich unkompliziert

a {
  /* Disabled link styles */
}
a:link, a:visited { /* or a[href] */
  /* Enabled link styles */
}

Das ist alles, was Sie tun müssen!

Das ist nicht genug, ich will etwas Komplexeres, damit ich schlauer aussehe!

Wenn Sie unbedingt eine extrem komplexe Lösung überkonstruieren müssen, hier sind einige Dinge zu beachten. Hoffentlich werden Sie darauf hören und erkennen, dass das, was ich Ihnen zeigen werde, die Mühe nicht wert ist.

Zuerst müssen wir unseren Link so gestalten, dass er deaktiviert aussieht.

.isDisabled {
  color: currentColor;
  cursor: not-allowed;
  opacity: 0.5;
  text-decoration: none;
}
<a class="isDisabled" href="https://unfetteredthoughts.net">Disabled Link</a>

Das Setzen von color auf currentColor sollte die Schriftfarbe auf Ihre normale, nicht-Link-Textfarbe zurücksetzen. Ich setze auch den Mauszeiger auf not-allowed, um einen schönen Hinweis beim Überfahren mit der Maus anzuzeigen, dass die normale Aktion nicht erlaubt ist. Bereits haben wir Nicht-Maus-Benutzer ausgelassen, die nicht überfahren können, hauptsächlich Touch und Tastatur, sodass sie diese Anzeige nicht erhalten. Als nächstes wird die Deckkraft halbiert. Laut WCAG müssen deaktivierte Elemente die Richtlinien für den Farbkontrast nicht erfüllen. Ich halte das für sehr riskant, da es sich im Grunde nur um normalen Text handelt, und eine Halbierung der Deckkraft würde es für Benutzer mit eingeschränkter Sehkraft sehr schwer lesbar machen, ein weiterer Grund, warum ich das hasse. Zuletzt wird die Textdekoration Unterstrich entfernt, da dies normalerweise das beste Anzeichen dafür ist, dass etwas ein Link ist. Jetzt *sieht* es wie ein deaktivierter Link aus!

Aber er ist nicht wirklich deaktiviert! Ein Benutzer kann diesen Link immer noch anklicken/tippen. Ich höre Sie wegen pointer-events schreien.

.isDisabled {
  ...
  pointer-events: none;
}

Ok, wir sind fertig! Deaktivierter Link erreicht! Außer, er ist nur *wirklich* für Mausbenutzer beim Klicken und Touch-Benutzer beim Tippen deaktiviert. Was ist mit Browsern, die pointer-events nicht unterstützen? Laut caniuse wird dies für Opera Mini und IE<11 nicht unterstützt. IE11 und Edge unterstützen tatsächlich pointer-events nicht, es sei denn, display ist auf block oder inline-block gesetzt. Außerdem überschreibt das Setzen von pointer-events auf none unseren schönen not-allowed-Cursor, sodass Mausbenutzer jetzt nicht mehr diese zusätzliche visuelle Anzeige erhalten, dass der Link deaktiviert ist. Das beginnt schon zu zerfallen. Jetzt müssen wir unser Markup und CSS ändern...

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.isDisabled > a {
  color: currentColor;
  display: inline-block;  /* For IE11/ MS Edge bug */
  pointer-events: none;
  text-decoration: none;
}
<span class="isDisabled"><a href="https://unfetteredthoughts.net">Disabled Link</a></span>

Das Umwickeln des Links in einem <span> und das Hinzufügen der Klasse isDisabled gibt uns die Hälfte unseres deaktivierten visuellen Stils. Ein netter Nebeneffekt ist hier, dass die Klasse disabled jetzt generisch ist und auf andere Elemente wie Buttons und Formularelemente angewendet werden kann. Der eigentliche Anker-Tag hat nun pointer-events und text-decoration auf none gesetzt.

Was ist mit Tastaturnutzern? Tastaturnutzer verwenden die ENTER-Taste, um Links zu aktivieren. pointer-events sind nur für Zeiger, es gibt keine Keyboard-Events. Wir müssen auch die Aktivierung für ältere Browser verhindern, die pointer-events nicht unterstützen. Jetzt müssen wir etwas JavaScript einführen.

Holen Sie sich das JavaScript

// After using preferred method to target link
link.addEventListener('click', function (event) {
  if (this.parentElement.classList.contains('isDisabled')) {
    event.preventDefault();
  }
});

Jetzt sieht unser Link deaktiviert *aus* und reagiert nicht auf Aktivierung durch Klicks, Taps und die ENTER-Taste. Aber wir sind immer noch nicht fertig! Screenreader-Benutzer haben keine Möglichkeit zu wissen, dass dieser Link deaktiviert ist. Wir müssen diesen Link als deaktiviert beschreiben. Das disabled-Attribut ist für Links nicht gültig, aber wir können aria-disabled="true" verwenden.

<span class="isDisabled"><a href="https://unfetteredthoughts.net" aria-disabled="true">Disabled Link</a></span>

Nun werde ich diese Gelegenheit nutzen, um den Link basierend auf dem aria-disabled-Attribut zu gestalten. Ich verwende gerne ARIA-Attribute als Hooks für CSS, denn schlecht gestaltete Elemente sind ein Indikator dafür, dass wichtige Barrierefreiheit fehlt.

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
a[aria-disabled="true"] {
  color: currentColor;
  display: inline-block;  /* For IE11/ MS Edge bug */
  pointer-events: none;
  text-decoration: none;
}

Jetzt *sehen* unsere Links deaktiviert aus, *verhalten* sich deaktiviert und sind als deaktiviert *beschrieben*.

Leider wird dieser Link, obwohl er als deaktiviert beschrieben wird, von einigen Screenreadern (JAWS) immer noch als klickbar angekündigt. Das tut er für jedes Element, das einen Klick-Listener hat. Dies liegt an der Tendenz der Entwickler, nicht-interaktive Elemente wie div und span mit einem einfachen Listener zu Pseudo-interaktiven Elementen zu machen. Nichts, was wir hier tun können. Alles, was wir getan haben, um jede Andeutung zu entfernen, dass dies ein Link ist, wird durch die assistive Technologie, die wir zu täuschen versucht haben, vereitelt, ironischerweise, weil wir versucht haben, sie zuvor zu täuschen.

Aber was ist, wenn wir den Listener zum Body verschieben?

document.body.addEventListener('click', function (event) {
  // filter out clicks on any other elements
  if (event.target.nodeName == 'A' && event.target.getAttribute('aria-disabled') == 'true') {
    event.preventDefault();
  }
});

Sind wir fertig? Nun, nicht wirklich. Irgendwann müssen wir diese Links wieder aktivieren, also müssen wir zusätzlichen Code hinzufügen, der diesen Zustand/dieses Verhalten umschaltet.

function disableLink(link) {
// 1. Add isDisabled class to parent span
  link.parentElement.classList.add('isDisabled');
// 2. Store href so we can add it later
  link.setAttribute('data-href', link.href);
// 3. Remove href
  link.href = '';
// 4. Set aria-disabled to 'true'
  link.setAttribute('aria-disabled', 'true');
}
function enableLink(link) {
// 1. Remove 'isDisabled' class from parent span
  link.parentElement.classList.remove('isDisabled');
// 2. Set href
  link.href = link.getAttribute('data-href');
// 3. Remove 'aria-disabled', better than setting to false
  link.removeAttribute('aria-disabled');
}

Das ist alles. Wir haben jetzt einen deaktivierten Link, der für alle Benutzer visuell, funktional und semantisch deaktiviert ist. Es brauchte nur 10 Zeilen CSS, 15 Zeilen JavaScript (einschließlich eines Listeners am Body) und 2 HTML-Elemente.

Im Ernst Leute, macht es einfach nicht.