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 aufa- undarea-Elementen ist nicht erforderlich; wenn diese Elemente keinehref-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.
Ja, es scheint mir, dass, wenn es einen Bedarf dafür gibt, es wahrscheinlich einen besseren Ansatz für das gibt, was erreicht werden soll.
Zustimmung. Ich bin mir nicht sicher, warum jemand Links im Internet deaktivieren möchte. Das ist, als würde man alle Fahrgeschäfte in Disneyland schließen.
Ähäm. Natürlich macht es Sinn. Links können vorübergehend oder unter bestimmten Bedingungen oder Zeitrahmen nicht verfügbar sein. Darauf zu bestehen, dass es ein Link sein muss, klingt seltsam. Ein deaktivierter Button würde den Trick ohne all den Aufwand machen. Gestalten Sie ihn einfach als Inline-Link! *Lässt das Mikro fallen
(Hebt das Mikro auf) Samuel, die Verwendung eines Buttons wäre ein falscher semantischer Gebrauch. Links sind für Navigation/Kontextwechsel gedacht, entweder zu einer völlig anderen URL oder zu einer anderen Stelle auf der Seite, während Buttons dazu gedacht sind, dynamische Änderungen auf der Seite vorzunehmen. Beide haben ihre richtigen Verwendungszwecke und sollten nicht vermischt werden, sonst verwirren Sie Benutzer, die sich auf diese Semantik verlassen, um zu verstehen, wie sie mit der Interaktion umgehen sollen und was das Ergebnis dieser Interaktion ist. Schauen Sie sich diese Links vs Buttons Präsentation von Marcy Sutton an, um mehr Informationen zu erhalten.
Ich verstehe – nicht tun, aber warum nicht einfach den JS-Handler nehmen, das zusätzliche Markup fallen lassen und den CSS-Selektor
.disabledoder[aria-disabled]ohne diepointer-events-Eigenschaft haben? Scheint effektiv genug.Hallo Stephen! Ich habe nicht versucht, es einfach zu machen, aber ich wollte auf jeden Fall gründlich sein und so inklusiv wie möglich, um allen die gleiche Erfahrung zu bieten. Ich kämpfe damit, eine Lösung anzubieten, wie erwähnt, aber ich hoffe, alle werden erkennen, wie albern es ist und es einfach nicht tun.
Eigentlich ist dies nur ein Versuch, die Leute zum Nachdenken anzuregen und vielleicht ein paar Dinge über HTML, CSS und ARIA zu lernen, die sie vorher nicht kannten.
Seien wir ehrlich, das zu tun ist einfach verrückt. Ich mache seit dem Bestehen des Webs Websites, auch für Unternehmenskunden. Ich hatte noch nie ein Bedürfnis dafür und kann mir keinen tatsächlichen realen Anwendungsfall dafür vorstellen. Kinder heutzutage...
Zustimmung. Traurigerweise kommt es ziemlich oft vor. Vor allem in OSS-Bibliotheken/Frameworks. Hoffentlich werden die Kinder heute darauf hören und es nicht tun. Es ist nicht nur ein Entwicklerproblem, sondern auch ein Designproblem.
Ich habe einen Anwendungsfall.
Auf der Kursplattform, die mein Team nutzt, werden Lektionen angezeigt, auf die man keinen Zugriff haben sollte, bis eine vorherige Lektion abgeschlossen ist.
Wenn man auf diese Lektionen klickt, gelangt man zu einer Seite, auf der steht: "Sie haben keinen Zugriff".
Es ist kein gutes Design, im Wesentlichen auf eine Fehlerseite weitergeleitet zu werden. Deshalb habe ich ihren Code überschrieben, um den Link zu deaktivieren.
Hallo Rocky, ich glaube wirklich, dass das Entfernen des href und das Erstellen eines Platzhalter-Links in Ihrem Fall eine wirklich gute Lösung für Ihr Problem ist. Letztendlich müssen das keine Links sein, sie sind wirklich nur statischer Text. Für manche Benutzer erwarten sie eine bestimmte Nutzung des Links, und Ihre zusätzliche JS verhindert ihre erwartete Interaktion, ohne zu erklären, warum.
Haben Sie darüber nachgedacht, eine React-Komponente mit etwas schickem ES7-Syntax zu erstellen, sodass Sie unbedingt webpack+babel benötigen, um diese lästigen Links zu deaktivieren?
/s
Dominic, das ist lustig. Ich habe buchstäblich gelacht.
Wenn Sie das HREF entfernen, wie Sie es am Anfang des Artikels beschreiben, dann ist der Anker nicht mehr tastaturfokussierbar und daher würden Screenreader ihn nicht "sehen"...
...oder irre ich mich?
Hallo Basher, ja, das Entfernen des HREF würde im Wesentlichen einen Platzhalter-Link erstellen. Da er nicht bedienbar ist, sollte er nicht fokussierbar sein. Screenreader hätten immer noch Zugriff darauf, er ist nicht versteckt. Er ist nicht mehr bedienbar. Daher ein "deaktivierter" Link.
iOS VoiceOver überspringt ungültige Links komplett (oder tat es zumindest früher), daher wäre die Verwendung von
href="#"oder etwas Ähnlichem eine bessere Lösung als das Entfernen deshref.James, ich glaube, das ist eher ein Fehler des User-Agents, auf den ich mich nicht verlassen würde, es ist ein bisschen ein Hack. Letztendlich zielen Sie nur auf eine sehr kleine Gruppe von Benutzern ab und lassen viele andere Benutzer aus.
Ich stimme zu, es nicht zu tun. Aber was ist mit dem Setzen von
tabindex="-1"anstelle der Verwendung eines Click-Handlers zumpreventDefault()? Auf diese Weise ist der Link nicht klickbar oder tastaturfokussierbar, und dann sollte der Screenreader ihn nicht ankündigen.Hey Corey, das Hinzufügen von
tabindex="-1"würde das Standardverhalten oder die Semantik nicht entfernen, sodass er immer noch bedienbar (klickbar) wäre. Er ist vielleicht nicht per Tab tastaturfokussierbar, aber er wäre immer noch auffindbar und bedienbar für assistive Technologien mit speziellen Tastenkombinationen oder in Listen von Elementen nach Typ.Richtig, ich habe nicht gesagt, dass es das Standardverhalten oder die Semantik entfernt, ich habe nur auf diesen Abschnitt geantwortet
Also *anstatt* JavaScript zu verwenden, um
preventDefault()aufzurufen, könnten Sie tabindex="-1" verwenden. Assistive Technologien sollten nichts vorlesen oder dieses Element als interaktiv darstellen.Hallo Corey,
tabindex="-1"macht noch andere Dinge mit assistiven Technologien, die Sie vielleicht nicht erwarten, und würde wahrscheinlich andere Probleme verursachen. Solange das Element noch Link-Semantik hat, wird es für Screenreader-Benutzer bedienbar und auffindbar sein. Das Hinzufügen vontabindex="-1"würde daran nichts ändern.Nur eine Anmerkung zum Styling von "aktivierten" Links in Ihrem Beispiel
Ich würde empfehlen,
aina:link, a:visitedzu entfernen.Es erhöht die Spezifität auf 11, während
:link, :visitedeine Spezifität von 10 hätten.Eine Spezifität von 11 würde bedeuten, dass sie nicht durch eine klassische
.button-Klasse überschrieben würde, die eine Spezifität von 10 hat.Außerdem sollte
:link, :visitedgegenüber[href]bevorzugt werden, da[href]auch dann gültig wäre, wenn er leer ist.Hallo Johan, danke für den Kommentar. Letztendlich müssen Sie die Selektoren verwenden, die mit Ihrer Implementierung funktionieren, dies dient nur dazu, den Punkt zu verdeutlichen.
Nicht tun. Verstanden.
Nehmen wir also an, es gäbe eine hypothetische Legacy-Webanwendung, die diese Taktik anwendet, bevor jemand, der Blog-Posts wie diesen liest und es besser weiß, daran zu arbeiten begann, um das Verbrechen zu verhindern...
Empfehlungen für geeignete Alternativen, die zumindest grob ähnlich aussehen? Szenario ist, dass Geschäftsregeln der aktuellen Seite die Links einschränken, bis Bedingungen erfüllt sind, sie aber trotzdem anzeigen sollten. Minimale JS und HTML, die den "Link" selbst betreffen, offensichtlich, aber zumindest eine Zeile JS, um den Zustand umzuschalten (sagen wir, eine CSS-Klasse umschalten)... Gleiche Barrierefreiheitsaspekte.
Gedanken?
Verwenden Sie das Platzhalter-
<a>-Element ohnehref, wenn Sie ein Element haben, das manchmal ein Link ist, aber derzeit nicht.Sie könnten ein
data-*-Attribut verwenden, um die URL zu speichern, die verwendet wird, wenn der Link aktiv ist. Eine Codezeile für jede Richtungsänderung.Verwenden Sie nach Bedarf Stile, um zwischen
:linkund:not(:link)-Elementen zu unterscheiden.Wenn Sie etwas erstellen, bei dem Sie nach dem Laden eine Pause einlegen möchten, damit der Betrachter gezwungen ist zu lesen, bevor er klickt. Ich weiß nicht, ich sehe mehrere Anwendungen dafür, wenn es um komplexere Dashboard-Designs oder Intros geht.
Ich bin neugierig... was ist der eigentliche Anwendungsfall dafür? Ich kann mir keine Situation vorstellen, in der ich möchte, dass etwas wie ein Link aussieht, aber eigentlich kein Link ist.
Es ist nicht so, dass man will, dass etwas wie ein Link aussieht...
Es ist eher für etwas, das ein Link war, aber Sie müssen es mit Code nicht mehr zu einem Link machen.
Zwei Anwendungsfälle, die in den Kommentaren genannt wurden, waren
1) (Mein Kommentar) Wenn ein Programm eines anderen Benutzers einen Link erstellte, der – abhängig vom Status des Benutzers – entweder zu einer Fehlerseite oder zur richtigen Seite führte. Ich habe den Link deaktiviert, bis der Status korrekt war.
2) Für Intros/Tutorials, bei denen Sie einen Link deaktivieren, bis der Benutzer etwas "abschließt".
Hallo Gérard. Um Coreys Kommentar zu ergänzen, würde ich zusätzlich zu tabindex="-1" das Attribut aria-hidden="false" hinzufügen. Das versteckt sogar normale, gute alte Links. Dann kann der umgebende SPAN-Tag ein aria-hidden-Attribut haben, das vorliest, wie auch immer Sie es klingen lassen möchten. Zum Beispiel "Blah blah blah. Deaktivierter Link".
Es macht so viel Spaß, nutzlose Dinge zu tun, nur um zu beweisen, dass wir es können LOL.
... Aber Leute, versucht das nicht im Büro. Versucht es stattdessen zu Hause. LOL.
Der einzige mögliche Grund, den ich für einen deaktivierten Link-Stil sehe, ist zu zeigen, dass der Link jetzt defekt ist... In diesem Fall möchten Sie immer noch, dass er wie ein Link aussieht (nur mit einer leichten Änderung, um anzuzeigen, dass er defekt ist), und es ist nicht wirklich wichtig, ob der Benutzer ihn anklicken kann.
Warum nicht
touch-action: nonefür Mobilgeräte verwenden? Unabhängig davon haben Sie Recht, das ist seltsam.Sie haben sich nicht einmal mit dem (archaischen)
<a name="..." >-Tag beschäftigt, das früher die empfohlene Verwendung für Link-Ziele war. (Der Teil, der nach#in einer URL kommt.) Diese wären jetzt als deaktivierte Links markiert, obwohl sie überhaupt keine Links sind.Auch wenn heutzutage eher
ids für Link-Ziele verwendet werden, kenne ich viele CMS, die immer noch<a name>einfügen.Hier ist ein möglicher Anwendungsfall...
Ich betreibe eine Website, die Links zu den Portfolios aller meiner Studenten enthält. Aus verschiedenen Gründen gehen ihre Websites manchmal kaputt (Domains laufen aus, Hosting läuft aus, sie löschen versehentlich ihre Website usw.).
Wir ermutigen die Industrie und potenzielle Arbeitgeber, die Website zu besuchen. Ich möchte nicht, dass diese Leute eine defekte Website besuchen. In diesem Fall würde ich den Namen des Studenten in der Liste als Teil des Abschlussjahrgangs belassen, aber seine Website entlinken, bis sie behoben ist. Ich habe ein WordPress-Plugin, das defekte Links einmal alle 24 Stunden scannt und Aktionen ausführen kann, wie z. B. eine Klasse auf die defekten Links anzuwenden.
Alan Nugent erwähnte schriftlich, dass man tabindex="-1" zu den Links als Teil der Strategie hinzufügen könnte, da der Link nicht mehr funktionsfähig ist, ist es vielleicht nicht nützlich, überhaupt in den Fokus zu geraten.