Ihr bewährter Begleiter.
Viele Nutzer schätzen die vertraute Umgebung des Classic-Editors, die eine einfache und schnelle Bearbeitung ermöglicht.
Mehr Funktionen, mehr Möglichkeiten.
Der Advanced Editor erweitert den Funktionsumfang des Classic-Editors und ermöglicht es, Inhalte noch effektiver zu bearbeiten.
Der Classic-Editor für alle.
Der Classic-Editor zeichnet sich durch Stabilität und Zuverlässigkeit aus, was für professionellen Anwender von Bedeutung ist.
Der Advanced Editor für kreative Köpfe.
Mit dem Advanced Editor können Designer und
Content Creatoren kreative Ideen umsetzten.
In diesem Beitrag erläutern wir, wie die Tastaturnavigation oder Keyboard Navigation (englisch, in technischen Kontexten oft direkt übernommen) auf einer Webseite durch JavaScript-Lösungen optimiert werden kann. Der Beitrag beginnt mit einem Überblick über die Grundlagen der Tastaturnavigation und deren Bedeutung. Anschließend wird detailliert beschrieben, wie ein speziell entwickeltes Script die Fokussierung und Interaktion im Inhalt verbessert und gleichzeitig die Benutzerfreundlichkeit für Tastaturbenutzer gewährleistet. Es handelt sich hierbei überwiegend um nachgebaute Browserfunktionalitäten, die nicht den umfassenden Anspruch an Barrierefreiheit im heutigen Sinne erheben.
Der Beitrag bietet sowohl eine theoretische Grundlage als auch praktische Anwendungsbeispiele. Die Betonung liegt auf 'Anwendungsbeispiele', denn eine so komplexe Konfiguration sollte ohnehin maßgeschneidert für jede Website erstellt werden. Sie funktioniert nicht einfach per Copy und Paste.
Beitrag Zwei
Die Tastaturnavigation spielt eine große Rolle für die Nutzererfahrung von Webseiten. Wir haben die 'Custom Inline Embeds' entwickelt, da wir bei der Optimierung der Navigation ... weiterlesen
Beitrag Drei
Die Lösung 'SafariEmbedToBlockquote' wurde speziell für WP-Embeds in Safari entwickelt. Sie adressiert die besonderen Herausforderungen der Fokussierbarkeit, die in Safari bei der Darstellung von WP-Embeds ... weiterlesen
Inhaltsverzeichnis
Einleitung: Überblick über Tastaturnavigation
In den folgenden Abschnitten werden wir die Grundlagen der Tastaturnavigation kennenlernen, ihre praktische Anwendung untersuchen und die Herausforderungen beleuchten, die dabei auftreten können.
Was ist die Tastaturnavigation?
Das Thema Tastaturnavigation ist in der Webentwicklung und Usability ein sehr wichtiger Aspekt, und es gibt einige Überlegungen, die berücksichtigt werden sollten:
1. Maus vs. Tastatur
Es stimmt, dass viele Menschen sowohl Maus als auch Tastatur verwenden können, aber es gibt auch Nutzer, die auf Tastatur oder andere Eingabegeräte angewiesen sind. Die Idee ist nicht unbedingt, die Maus als weniger wichtig zu betrachten, sondern sicherzustellen, dass alle Nutzer eine gleichwertige Erfahrung haben können.
2. Ergonomie und Komfort
- Ergonomie: Für einige Menschen ist die Tastatur ergonomischer als die Maus, insbesondere bei langen Nutzungszeiten.
- Multitasking: Tastaturnavigation kann schneller sein, wenn Nutzer zwischen verschiedenen Elementen und Funktionen auf der Webseite hin und her wechseln.
Es ist sowohl die Maus- als auch die Tastaturbedienung zu unterstützen, um eine möglichst breite Nutzerbasis zu erreichen. Tastaturnavigation sollte nicht nur als zusätzliche Funktion betrachtet werden, sondern als integraler Bestandteil einer benutzerfreundlichen Webgestaltung.
Grundprinzipien der Tastaturnavigation
In diesem Abschnitt werden die grundlegenden Prinzipien der Tastaturnavigation vorgestellt. Es wird erläutert, wie Nutzer durch Tastenkombinationen und Navigationselemente effizient durch eine Webseite navigieren können. Anschließend wird ein praktisches Beispiel gegeben, um die Anwendung der Tastaturnavigation zu verdeutlichen.
- Tabulatortaste (Tab): Mit der Tabulatortaste kann durch die interaktiven Elemente einer Seite navigiert werden, wie z.B. Links, Formulareingabefelder, Buttons und andere steuerbare Elemente. Jedes Mal, wenn die Tabulatortaste gedrückt wird, wird der Fokus auf das nächste interaktive Element verschoben.
- Shift + Tab: Dies verschiebt den Fokus zurück zum vorherigen interaktiven Element. Diese Kombination wird verwendet, um rückwärts durch die Elemente zu navigieren.
- Pfeiltasten: Die Pfeiltasten (nach oben und unten) können verwendet werden, um innerhalb eines längeren Textes oder eines geöffneten
details
– odersummary
-Elements zu scrollen oder um durch eine Liste von Optionen in einem Menü oder Dropdown zu navigieren. - Leertaste: In der Headerleiste kann die Leertaste verwendet werden, um Buttons zu aktivieren, ähnlich wie die Enter-Taste. Im Content-Bereich dient die Leertaste hauptsächlich dem abschnittsweisen Scrollen durch das Dokument, indem sie den Fokus auf den nächsten Abschnitt verschiebt.
- Enter-Taste: Die Enter-Taste wird verwendet, um das aktuell fokussierte Element zu aktivieren. Dies kann das Öffnen eines Links, das Betätigen eines Buttons oder das Öffnen bzw. Schließen eines Summary-Elements umfassen. Im Inhaltsbereich erfüllt die erste Betätigung der Enter-Taste die Fokussierung des Elements, während die zweite Betätigung die Aktivierung des fokussierten Elements vornimmt. Diese Funktion ist besonders wichtig für die Navigation und Interaktion auf einer Webseite.
- Escape-Taste (Esc): Die Escape-Taste dient dazu, eine Aktion oder einen Vorgang abzubrechen. In unerem Fall ist das von Nutzen, um etwa in der Headerzeile eine Fokussierung abzubrechen.
1. Anwendung der Tastaturnavigation
- Navigation durch die Seite: Drücke die Tabulatortaste, um durch die verschiedenen interaktiven Elemente auf einer Webseite zu wechseln. Die fokussierten Elemente können anhand von visuellem Feedback wie einem Rahmen oder einer Hervorhebung erkannt werden.
- Interaktion mit Elementen: Wenn sich der Fokus auf einem Element wie einem Button, einem Link oder einem
summary
-Element befindet, kann dieses durch Drücken der Enter-Taste aktiviert werden. Bei Formularfeldern können Eingaben vorgenommen werden, indem direkt getippt wird. - Scrollen mit Pfeiltasten: Bei längeren Seiten oder innerhalb von geöffneten
details
– odersummary
-Elementen können die Pfeiltasten verwendet werden, um durch den Inhalt zu scrollen. - Suchfeld aufrufen: Das Suchfled wird mit der Taste '7' geöffnet und mit der Escape-Taste geschlossen.
- Fokussierungen: Mit der Esc-Taste können Fokussierungen von Links, Elementen aufgehoben und Dialoge geschlossen werden.
- Verwendung der Leertaste: Nutze die Leertaste in der Headerleiste, um Buttons zu aktivieren. Im Content-Bereich hilft sie beim abschnittsweisen Scrollen durch das Dokument.
2. Beispiel für Tastaturnavigation
- Webseite besuchen: Beim Öffnen einer Webseite beginnt der Fokus beim ersten fokussierbaren Element.
- Durch die Seite navigieren: Drücke die Tabulatortaste, um zum nächsten Button oder Eingabefeld zu gelangen. Drücke Shift+Tab, um zum vorherigen Element zurückzukehren.
- Elemente aktivieren: Wenn der Fokus auf einem Button, Link oder
summary
-Element liegt, drücke die Enter-Taste, um die Aktion auszuführen oder das Element zu öffnen. Im Inhaltsbereich erfüllt die erste Betätigung der Enter-Taste die Fokussierung des Elements, und die zweite Betätigung aktiviert es. - Scrollen innerhalb von Elementen: Verwende die Pfeiltasten, um innerhalb eines fokussierten
details
– odersummary
-Elements zu scrollen, nachdem es mit der Leertaste oder Enter-Taste geöffnet wurde. - Suchfeld steuern und Aktionen abbrechen: Verwende die Escape-Taste, um das Suchfeld zu schließen oder eine nicht gewünschte Fokussierung aufzuheben.
- Verwendung der Leertaste: In der Headerleiste aktiviert die Leertaste Buttons, während sie im Content-Bereich für das abschnittsweise Scrollen verantwortlich ist. Verwende Shift + Leertaste zum abschnittsweisen Scoll nach oben.
Erlebe die Freiheit der Tastaturnavigation –
Einfach, präzise, und so effizient wie nie zuvor.
Herausforderungen der Tastaturnavigation
Die Tastaturnavigation ist eine essentielle Komponente der Web-Benutzererfahrung, besonders für Nutzer, die auf alternative Eingabemethoden angewiesen sind. Doch selbst für viele, die die Maus als primäres Eingabegerät nutzen, bietet die Tastaturnavigation eine schnellere und oft effizientere Möglichkeit, durch Webseiten zu navigieren. Trotz dieser Bedeutung gibt es bei der Umsetzung von Tastaturnavigation einige Herausforderungen, die häufig übersehen werden:
1. Unklare Fokusreihenfolge
Eine der häufigsten Herausforderungen bei der Tastaturnavigation ist die unklare oder unlogische Reihenfolge, in der interaktive Elemente den Tastaturfokus erhalten. Standardmäßig folgt die Fokussierung der Reihenfolge, in der die Elemente im HTML-Dokument erscheinen. Dies kann jedoch zu einer Navigation führen, die für den Benutzer verwirrend oder ineffizient ist – besonders auf komplexen Seiten mit vielen interaktiven Elementen wie Formularen, Menüs und Widgets.
2. Fehlende visuelle Hinweise
Ein weiteres häufiges Problem ist das Fehlen klarer visueller Hinweise, die anzeigen, welches Element aktuell den Fokus hat. Ohne eine sichtbare Hervorhebung des fokussierten Elements können Benutzer schnell die Orientierung verlieren. Dies ist besonders problematisch, wenn Elemente wie Links oder Schaltflächen lediglich durch CSS-Stile hervorgehoben werden, die im Fokuszustand nicht angepasst wurden.
3. Schwierigkeiten bei der Navigation durch dynamische Inhalte
Moderne Webseiten enthalten oft dynamische Inhalte, wie z. B. Dropdown-Menüs, Modal-Fenster oder sich automatisch aktualisierende Inhalte. Diese können die Tastaturnavigation erheblich erschweren, wenn sie nicht sorgfältig implementiert werden. Ohne angemessene Tastatursteuerung und Fokusmanagement kann es für den Benutzer unmöglich werden, auf diese Inhalte zuzugreifen oder sie zu schließen.
4. Nicht standardisierte Tastenkombinationen
Während einige Tastenkombinationen für die Navigation auf Webseiten weit verbreitet sind (z. B. Tabulator für den Fokuswechsel, Enter zum Aktivieren), können nicht standardisierte oder schlecht dokumentierte Tastenkombinationen Benutzer verwirren und frustrieren. Zudem ist es für viele Nutzer schwierig, individuelle Tastenkombinationen zu erlernen und effektiv zu nutzen, wenn sie nicht intuitiv gestaltet sind.
Hier im Startleitfaden für WordPress kannst du die Tastaturnavigation testen, um zu sehen, wie sie auf der Website funktioniert. Dort findest du mehrere Links, Embeds, Bilder und sogar ein Tabmenü.
Letzteres ist etwas gewöhnungsbedürftig: Mit Enter lässt sich, wie bei den Links, auch das Inhaltsverzeichnis fokussieren und auswählen. Das Inhaltsverzeichnis kann mit Tab durchlaufen werden. Die Tabs selbst können nach dem Drücken von Enter und deren direkter Fokussierung (sofern sie das oberste Element im Viewport sind) mit den Pfeiltasten bedient werden. Die Fokussierung des Tabs erfolgt immer dem ersten Tab auch wenn ein anderer Tab geöffnet ist.
🧡 Vorstellung des Scripts: Tastaturnavigation und Fokusverwaltung
Die Entwicklung der Tastaturnavigation war nicht einfach, aber in Zusammenarbeit mit ChatGPT haben wir es erneut geschafft, die Tastatursteuerung erfolgreich zu optimieren!
- Hinweis: Unser Script mit Erweiterungen folgt unter ➡︎ Tastaturnavigation auf der Website.
Überblick über das JavaScript
Das vorgestellte Script wurde entwickelt, um die Tastaturnavigation auf Webseiten zu optimieren und die Benutzerfreundlichkeit zu erhöhen, insbesondere im "Above the Fold"-Bereich einer Webseite. Das Script überwacht die Interaktionen der Nutzer und passt die Navigation entsprechend an. Es erkennt, ob der Benutzer sich noch im sichtbaren oberen Bereich der Webseite ("Above the Fold") befindet, und ändert die Navigationslogik, sobald dieser Bereich verlassen wird. Dies stellt sicher, dass die Fokussierung und die Interaktion der Elemente effizient und intuitiv gestaltet sind.
Folgend sind drei JavaScript-Abschnitte aufgeführt, die sich mit folgenden Themen befassen:
- Tastaturnavigation für die Headerzeile
- Allgemeine Navigation und Fokusverwaltung
- Fokussierung und Markierung von EMBEDs
Finden und Fokussieren – Mit der Tastatur sicher ans Ziel!
1. Tastaturnavigation für die Headerzeile
Der erste Teil des Codes widmet sich der Verwaltung der Tastaturnavigation in der Headerzeile der Webseite. Dieser Abschnitt prüft, ob der Benutzer die Tab
-Taste oder eine Maustaste verwendet, um den Fokus auf bestimmte Elemente zu setzen.
- Tastaturnavigation: Ermöglicht die Navigation per Tastatur (Tab, Enter, Leertaste) und setzt den Fokus auf relevante Elemente.
- Fokusmanagement: Setzt den Fokus bei Bedarf auf spezifische Elemente im Admin-Frontend, insbesondere beim Scrollen.
- MutationObserver: Überwacht DOM-Änderungen, um den Fokus bei Bedarf anzupassen.
Der Code ist optimiert für Tastaturnavigation und Fokusmanagement auch für WordPress-Admin-Frontends.
Hinweis: Das Script ist möglicherweise nicht für die direkte Verwendung durch Copy und Paste geeignet.
/* === HEADERBEREICH Tastaturnavigation & Fokusverwaltung === */
document.addEventListener('DOMContentLoaded', function() {
const body = document.body;
// Erstmalige Tab-Taste-Überprüfung
function handleFirstTab(event) {
if (event.key === 'Tab') {
body.classList.add('keyboard-focused');
window.removeEventListener('keydown', handleFirstTab);
window.addEventListener('mousedown', handleMouseDown);
}
}
// Mausklick-Überprüfung nach der Tab-Taste
function handleMouseDown() {
body.classList.remove('keyboard-focused');
window.removeEventListener('mousedown', handleMouseDown);
window.addEventListener('keydown', handleFirstTab);
}
window.addEventListener('keydown', handleFirstTab);
// Tastaturnavigation für fokussierbare Elemente
document.querySelectorAll('.focusable').forEach(button => {
button.addEventListener('keydown', function(event) {
// Prüfen, ob das fokussierte Element kein Eingabefeld ist
if (event.key === 'Enter' || event.key === ' ') {
const tagName = event.target.tagName.toLowerCase();
if (tagName !== 'input' && tagName !== 'textarea') {
event.preventDefault();
button.click();
}
}
});
});
// Für Admin-Frontend: Fokus auf spezifisches Element setzen, wenn nach oben gescrollt wird
function focusOnSpecificElement() {
const firstFocusableElement = document.querySelector('.main-content .focusable');
if (firstFocusableElement) {
firstFocusableElement.focus();
}
}
// Für Admin-Frontend: Fokus auf die Admin-Leiste entfernen
function removeFocusFromAdminBar() {
const adminBar = document.getElementById('wpadminbar');
if (adminBar && document.activeElement.closest('#wpadminbar')) {
document.activeElement.blur();
}
}
// Für Admin-Frontend: Überwachung des Scroll-Events mit Verzögerung
window.addEventListener('scroll', function() {
if (window.scrollY === 0) {
setTimeout(() => {
removeFocusFromAdminBar();
focusOnSpecificElement();
}, 100); // Verzögerung anpassen, falls nötig
}
});
// Für Admin-Frontend: MutationObserver zur Überwachung von DOM-Änderungen
const observer = new MutationObserver(function() {
if (window.scrollY === 0) {
removeFocusFromAdminBar();
focusOnSpecificElement();
}
});
observer.observe(document.body, { childList: true, subtree: true });
// Für Admin-Frontend: Initiales Setup
document.addEventListener('DOMContentLoaded', function() {
removeFocusFromAdminBar();
focusOnSpecificElement();
});
});
/* = Ende HEADERBEREICH Tastaturnavigation & Fokusverwaltung === */
2. Allgemeine Navigation und Fokusverwaltung
Dieser Abschnitt des Codes konzentriert sich auf die allgemeine Navigation und Fokusverwaltung auf der Webseite. Die Implementierung beinhaltet Mechanismen zur Überwachung von Scroll- und Klickereignissen, um den Fokus auf relevante Elemente zu setzen und eine reibungslose Benutzererfahrung sicherzustellen.
- Tastaturnavigation und Fokusverwaltung
- Tastaturnavigation steuern: Das Script überwacht die Tastatureingaben und reagiert speziell auf die
Enter
-Taste, um das aktive Element im sichtbaren Bereich zu fokussieren oder zu aktivieren. Falls kein passendes Element gefunden wird, wird das erste relevante Element im Inhaltsbereich (#content
) fokussiert. - Verhinderung von Standardaktionen: Standardaktionen, wie die des
Enter
-Schlüssels, werden in bestimmten Fällen unterdrückt, um eine benutzerdefinierte Navigation zu ermöglichen.
- Tastaturnavigation steuern: Das Script überwacht die Tastatureingaben und reagiert speziell auf die
- Scroll-Überwachung mit "Above the Fold"-Logik
- Erkennen des "Above the Fold"-Status: Das Script überwacht die Scrollposition der Seite, um festzustellen, ob sich der Benutzer im "Above the Fold"-Bereich befindet (der sichtbare obere Bereich der Webseite, ohne Scrollen).
- Tabindex zurücksetzen: Sobald der Benutzer wieder in den "Above the Fold"-Bereich zurückkehrt, wird der Tabindex auf das erste relevante Element gesetzt, um die Navigation zu erleichtern.
- Fokusverwaltung
- Fokusverlust bei Verlassen des Viewports: Wenn ein fokussiertes Element aus dem sichtbaren Bereich (
Viewport
) gescrollt wird, entfernt das Script den Fokus von diesem Element. - Fokus auf den Headerbereich: Falls der Benutzer auf den Header klickt oder der Fokus dorthin wechselt, wird die Tastaturnavigation pausiert, um unerwünschte Navigation zu verhindern.
- Fokusverlust bei Verlassen des Viewports: Wenn ein fokussiertes Element aus dem sichtbaren Bereich (
- Tabindex-Verwaltung
- Zurücksetzen des Tabindex: Das Script stellt sicher, dass der Tabindex auf das erste relevante Element gesetzt wird, um eine logische und zugängliche Navigation zu gewährleisten.
- Escape-Taste Funktionalität
- Schließen von Suchfeldern: Bei Drücken der
Escape
-Taste wird das Suchfeld geschlossen, falls es aktiv ist. - Entfernen des Fokus: Falls ein Element fokussiert ist, wird der Fokus durch Drücken der
Escape
-Taste entfernt.
- Schließen von Suchfeldern: Bei Drücken der
- Öffnen der Suche mit der 7-Taste
- Suche aktivieren: Durch Drücken der
7
-Taste wird die Suche geöffnet, indem ein unsichtbares Such-Toggle-Element aktiviert wird.
- Suche aktivieren: Durch Drücken der
- Viewport-Prüfung
- Überprüfung, ob ein Element im Viewport ist: Das Script enthält eine Funktion zur Prüfung, ob ein Element sich innerhalb des sichtbaren Bereichs (
Viewport
) des Browsers befindet, um zu entscheiden, ob es aktiviert oder fokussiert werden kann.
- Überprüfung, ob ein Element im Viewport ist: Das Script enthält eine Funktion zur Prüfung, ob ein Element sich innerhalb des sichtbaren Bereichs (
Ziel des Scripts: Das Script ist darauf ausgelegt, die Benutzererfahrung für Tastaturnutzer zu verbessern, indem es sicherstellt, dass relevante Elemente fokussiert und aktiviert werden, und unnötige oder unerwartete Navigationsereignisse vermieden werden. Es sorgt dafür, dass der Fokus der Tastaturnavigation logisch und benutzerfreundlich bleibt, besonders in komplexen Webseitenstrukturen.
Hinweis: Das Script ist möglicherweise nicht für die direkte Verwendung durch Copy und Paste geeignet.
/* === ALLGEMEINE Tastaturnavigation & Fokusverwaltung === */
// Event-Handler für die Enter-Taste zur Verwaltung der Navigation und des Fokus im Dokument.
document.addEventListener('keydown', function(event) {
const tagName = event.target.tagName.toLowerCase();
if (event.key === 'Enter' && tagName !== 'input' && tagName !== 'textarea') {
event.preventDefault(); // Verhindert das Standardverhalten der Enter-Taste
focusNextElementIfAboveOffset(50);
}
});
// Funktion, um sicherzustellen, dass Elemente oberhalb einer bestimmten Schwelle (z.B. 50px) nicht fokussiert werden.
function focusNextElementIfAboveOffset(offset) {
const activeElement = document.activeElement;
if (activeElement && activeElement !== document.body) {
const elementRect = activeElement.getBoundingClientRect();
if (elementRect.top < offset) {
focusNextRelevantElementBelowOffset(offset);
} else {
activateElement(activeElement);
}
} else {
focusFirstRelevantElementBelowOffset(offset);
}
}
// Funktion, um das nächste relevante Element unterhalb der Offset-Schwelle zu fokussieren.
function focusNextRelevantElementBelowOffset(offset) {
const allFocusableElements = Array.from(document.querySelectorAll('#content summary, #content pre, #content a[href], #content button, #content input, #content textarea')); // Entfernt .overflow-scroll-gradient__scroller
for (const element of allFocusableElements) {
const elementRect = element.getBoundingClientRect();
if (elementRect.top >= offset && isElementInViewport(element)) {
element.focus({ preventScroll: true });
return;
}
}
}
// Funktion, um das erste relevante Element unterhalb der Offset-Schwelle zu fokussieren.
function focusFirstRelevantElementBelowOffset(offset) {
const allFocusableElements = Array.from(document.querySelectorAll('#content summary, #content pre, #content a[href], #content button, #content input, #content textarea'));
for (const element of allFocusableElements) {
const elementRect = element.getBoundingClientRect();
if (elementRect.top >= offset && isElementInViewport(element)) {
element.focus({ preventScroll: true });
return;
}
}
}
// Funktion, um zu überprüfen, ob ein Element im sichtbaren Bereich des Viewports ist.
function isElementInViewport(element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
// Funktion zum Aktivieren eines Elements.
function activateElement(element) {
element.focus({ preventScroll: true });
}
// Überwachung des Scrollens mit Debouncing und "Above the Fold"-Logik
let aboveTheFold = true;
let navigationPaused = false;
let lastScrollY = 0;
let scrollTimeout;
const headerHeight = 50;
// Überwachung des Scrollens
window.addEventListener('scroll', function() {
const currentScrollY = window.scrollY;
if (Math.abs(currentScrollY - lastScrollY) < 10) return;
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function() {
const foldBoundary = window.innerHeight * 0.5;
const activeElement = document.activeElement;
if (window.scrollY > foldBoundary) {
aboveTheFold = false;
} else {
if (!aboveTheFold) {
resetTabindex();
}
aboveTheFold = true;
}
if (activeElement && !isElementInViewport(activeElement)) {
activeElement.blur();
}
if (activeElement) {
const rect = activeElement.getBoundingClientRect();
const viewportThreshold = 100;
if (rect.top < headerHeight || rect.top < viewportThreshold) {
activeElement.blur();
}
}
lastScrollY = currentScrollY;
}, 100);
});
// Überwachung des Fokus-Wechsels außerhalb des Headerbereichs
document.addEventListener('focusout', function(event) {
const headerElement = document.querySelector('#masthead') || document.querySelector('.header-main');
if (headerElement && headerElement.contains(event.target)) {
navigationPaused = false;
}
});
// Funktion zum Zurücksetzen des Tabindex: Das Scrollverhalten wird gezielt überprüft und der Fokus nur dann setzt, wenn der Benutzer bereits ganz oben auf der Seite ist
function resetTabindex() {
const firstFocusableElement = document.querySelector('a, button, input, textarea, select, embed, [tabindex]:not([tabindex="-1"])');
if (firstFocusableElement) {
// Überprüfen, ob der Benutzer ganz oben auf der Seite ist
if (window.scrollY === 0) {
firstFocusableElement.focus();
}
}
}
/* = Ende ALLGEMEINE Tastaturnavigation & Fokusverwaltung = */
Bereit für Anpassungen? Profis wissen:
Vor dem Erfolg gilt es, auf alle Aspekte vorbereitet zu sein!
Browser Safari: Navigation und Fokusverwaltung
Zusätzliche Logik, um den Fokus in Safari zu korrigieren:
/* Browser Safari
* Zusätzliche Logik, um den Fokus in Safari zu korrigieren
*/
function handleSafariTabNavigation(event) {
const activeElement = document.activeElement;
// Überprüfen, ob die Taste "Tab" gedrückt wurde
if (event.key === 'Tab') {
// Definiere fokussierbare Tags
const focusableTags = ['a', 'audio', 'iframe', 'button', 'embed'];
// Überprüfen, ob das aktive Element fokussierbar ist
const isFocusableElement = activeElement &&
focusableTags.includes(activeElement.tagName.toLowerCase()) &&
activeElement.closest('#content');
if (isFocusableElement) {
event.preventDefault(); // Verhindert das Standard-TAB-Verhalten
// Alle relevanten fokussierbaren Elemente im Content-Bereich auswählen
const focusableSelectors = [
'#content a[href]',
'#audioPlayer audio',
'#content iframe',
'#content embed',
'#content summary',
'#content pre',
'#content button',
'#content input',
'#content textarea',
'.overflow-scroll-gradient__scroller',
'#content [tabindex]:not([tabindex="-1"])'
].join(', ');
const allFocusableElements = Array.from(document.querySelectorAll(focusableSelectors));
const currentIndex = allFocusableElements.indexOf(activeElement);
if (currentIndex !== -1) {
if (event.shiftKey) {
// Rückwärtsnavigation mit Shift+Tab
if (currentIndex > 0) {
allFocusableElements[currentIndex - 1].focus();
} else {
// Falls der erste Link erreicht ist, den letzten fokussieren
allFocusableElements[allFocusableElements.length - 1].focus();
}
} else {
// Vorwärtsnavigation mit Tab
if (currentIndex < allFocusableElements.length - 1) {
allFocusableElements[currentIndex + 1].focus();
} else {
// Falls der letzte Link erreicht ist, zum ersten zurückspringen
allFocusableElements[0].focus();
}
}
}
}
}
// Überprüfen, ob die Enter-Taste gedrückt wurde
if (event.key === 'Enter') {
// Falls das aktive Element ein Audio-Element ist
if (activeElement.tagName.toLowerCase() === 'audio') {
const audio = activeElement;
if (audio.paused) {
audio.play().catch((error) => {
console.log('Audio konnte nicht abgespielt werden:', error);
});
} else {
audio.pause();
}
event.preventDefault(); // Verhindert die Standardaktion der Enter-Taste
}
}
}
// Nur in Safari aktivieren
if (navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome')) {
document.addEventListener('keydown', handleSafariTabNavigation);
}
/* - Ende Browser Safari: Zusätzliche Logik, um den Fokus in Safari zu korrigieren - */
3. Fokussierung und Markierung von EMBEDs
Im Folgenden sprechen wir über die WordPress-Embeds, die durch das Einfügen eines Links in eine separate Zeile automatisch visuell dargestellt werden. Grundsätzlich handelt es sich dabei um 'iframes', die jedoch nicht mit herkömmlichen 'iframes' zu verwechseln sind.
Um die Benutzerfreundlichkeit zu verbessern, haben wir ein Skript entwickelt, das iframes so behandelt, als wären sie anklickbare Links. Dies ermöglicht eine einfache Navigation und Fokusverwaltung über die Tastatur.
Funktionsweise
Unser Skript "EMBED Iframe-Link-Navigation & Fokusverwaltung" transformiert eingebettete Inhalte (iframes) in fokussierbare und anklickbare Links. Dies geschieht, indem jedem iframe eine HTML-Verlinkung hinzugefügt und ein tabIndex
gesetzt wird. Diese einfache, aber wirkungsvolle Lösung stellt sicher, dass Nutzer eingebettete Inhalte direkt mit der Tastatur erreichen können, ohne auf die Maus angewiesen zu sein.
Darüber hinaus wird über CSS eine optische Rückmeldung eingebaut, die signalisiert, dass der iframe über die Tab-Taste fokussiert werden kann. Diese auch Benachrichtigung sorgt für eine klare visuelle Rückmeldung und verbessert das Benutzererlebnis.
Technische Details
Das Skript verwendet einfaches JavaScript, um alle iframe
-Elemente mit der Klasse .wp-embedded-content
auszuwählen und in anklickbare Links zu verwandeln. Es wird jedem iframe ein Wrapper (a
-Tag) hinzugefügt, der die URL des iframes als Ziel hat. Der tabIndex
wird gesetzt, um die Tastaturnavigation zu aktivieren.
Folgend ist der Code des Skripts, das für die Tastaturnavigation und Fokusverwaltung sorgt, darunter ist ein CSS-Vorschlag und dann unser CSS-Beispiel.
Hinweis: Das Script ist möglicherweise nicht für die direkte Verwendung durch Copy und Paste geeignet.
/**
* -----------------------------------------------------------------------------
* Scriptname: Iframe-Embed-Link-Navigation & Fokusverwaltung
* Version: 1.0
* Datum: 2024-09-14
* Autor: [Team WP Wegerl.at]
* -----------------------------------------------------------------------------
*
* Beschreibung:
* Dieses Skript behandelt eingebettete Inhalte (iframes/Embed) so, als wären sie
* anklickbare Links. Es ermöglicht die Tastaturnavigation und Fokusverwaltung
* für Embeds, indem ein tabIndex hinzugefügt wird.
* Das Styling, das dem Nutzer zeigt, dass die Inhalte mit der Tab-Taste
* fokussiert werden können, wird durch CSS gesteuert und angepasst.
*
* Funktionen:
* - Wandelt iframes in anklickbare Links um, sodass sie per Tastatur fokussierbar sind.
* - Fügt Tastaturnavigation und Fokusverwaltung hinzu.
* - CSS-basierte Benachrichtigung für den Nutzer über die Tab-Taste zur Fokussierung.
* - Unterstützung durch tabIndex und visuelles Feedback.
*
* -----------------------------------------------------------------------------
*/
/* === EMBED Iframe-Link-Navigation & Fokusverwaltung === */
// Funktion, um iframes wie Links zu behandeln
function makeIframesFocusable() {
const iframes = document.querySelectorAll('iframe.wp-embedded-content'); // Selektiert alle iframes mit der Klasse wp-embedded-content
iframes.forEach(iframe => {
// Erstelle einen Wrapper-Link um das iframe
const link = document.createElement('a');
link.tabIndex = 0; // Macht den Link fokussierbar
link.className = 'iframe-link'; // Füge eine Klasse für weiteres Styling hinzu
// Füge den Link vor dem iframe ein und verschiebe das iframe in den Link
iframe.parentNode.insertBefore(link, iframe);
link.appendChild(iframe);
// Optional: Event Listener für die Enter-Taste, um den Link zu aktivieren
link.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
window.location.href = link.href; // Weiterleitung bei Enter
}
});
});
}
// Funktion aufrufen, um iframes wie Links zu behandeln
makeIframesFocusable();
/* = Ende EMBED Iframe-Link-Navigation & Fokusverwaltung = */
Diese Scripts verbessern die Zugänglichkeit und Benutzerfreundlichkeit von Webseiten erheblich, indem sie sicherstellen, dass die Navigation und die Aktivierung von Elementen sowohl für Maus- als auch für Tastaturnutzer nahtlos funktionieren.
CSS-Vorschlag
Ein weiteres Feature ist die Einbindung einer CSS-Nachricht, die durch ein ::after
Pseudo-Element dargestellt wird. Diese Nachricht erscheint beim Fokus und informiert den Nutzer, dass er mit der Tab-Taste den eingebetteten Inhalt ansteuern kann.
/* --- Voschlag 1: EMBEDS Link-Navigation-Focus. Der Hinweis "Fokussiere mit Tab" steht oben --- */
.iframe-link {
display: inline-block;
position: relative;
}
.iframe-link:focus {
outline: 3px solid #007acc !important;
}
.iframe-link:focus::after {
content: "Fokussiere mit Tab";
color: #007acc;
font-weight: bold;
position: absolute;
left: 10%;
top: -23px;
background-color: #f0f0f0;
padding: 5px;
z-index: 1;
}
.wp-embedded-content {
margin-bottom: -10px;
}
/* - Ende Vorschlag 1: EMBEDS Link-Navigation-Focus. Der Hinweis "Fokussiere mit Tab" steht oben - */
/* --- Vorschlag 2: EMBEDS Link-Navigation-Focus. Der Hinweis "Fokussiere mit Tab" steht unten --- */
.iframe-link {
/*display: inline-block;*/
position: relative;
}
.iframe-link:focus {
outline: 3px solid #007acc !important;
}
.iframe-link:focus::after {
content: "Fokussiere mit Tab";
color: #007acc;
font-weight: bold;
position: absolute;
left: 10%;
top: 10px;
background-color: #f0f0f0;
padding: 5px;
z-index: 1;
}
.wp-embedded-content {
margin-bottom: -10px;
}
/* - Ende Vorschlag 2: EMBEDS Link-Navigation-Focus. Der Hinweis "Fokussiere mit Tab" steht unten - */
- Hinweis: Durch die Verwendung von
display: inline-block;
kann gesteuert werden, ob der Hinweis "Fokussiere mit Tab" oben oder unten angezeigt wird. In diesem Zusammenhang ist das Styling mit::before
wirkungslos.
Das folgende Embed als Beispiel: Die Enter-Taste betätigen, um das Embed zu fokussieren. Durch weiteres Drücken der Tab-Taste werden die Links im Embed nacheinander fokussiert. Letzteres geschieht automatisch im Embed. Zunächst geht es darum, die erste Fokussierung zu sehen, um sicherzustellen, dass das Embed fokussiert werden kann.
- Hinweis: Es gibt bekannte Einschränkungen bei der Fokussierbarkeit von
iframe
-Elementen, insbesondere wenn sie nur teilweise im Viewport sichtbar sind. Technische Versuche,iframes
durch Scrollen oder Overlays fokussierbar zu machen, waren nicht erfolgreich oder scheitern an browserseitigen Sicherheitsmechanismen. Dasiframe
ist jedoch immer fokussierbar, wenn der untere Teil vollständig im Viewport sichtbar ist, auch wenn der obere Teil außerhalb des sichtbaren Bereichs liegt.
Fortsetzung, unser CSS ist ein weiteres Beispiel:
/* --- EMBEDS Link-Navigation-Focus --- */
.iframe-link {
/* display: inline-block; */
margin-left: 15px !important;
position: relative;
}
.iframe-link:focus {
outline: 3px solid #fd8826 !important;
}
.iframe-link:focus::after {
content: "Fokussiere mit Tab";
color: #fd8826;
font-weight: bold;
position: absolute;
left: 10%;
top: 15px;
background-color: white;
padding: 5px;
z-index: 1;
}
.wp-embedded-content {
margin-bottom: -15px;
}
@media all and (min-width: 700px) {
.readermode .iframe-link {
margin-left: 14.6% !important;
position: relative;
}
}
/* - Ende EMBEDS Link-Navigation-Focus - */
Ein häufiges Problem, das wir festgestellt haben, betrifft die Fokussierbarkeit von WP Embeds in Safari. Darum habe wir hier eine Lösung entwickelt:
Die Tastaturnavigation spielt eine große Rolle für die Nutzererfahrung von Webseiten. Wir haben die 'Custom Inline Embeds' entwickelt, da wir bei der Optimierung der Navigation ... weiterlesen
➡︎ Tastaturnavigation auf der Website
Diese JavaScript-Lösungen sind Erweiterungen der vorherigen Vorschläge. Es ist nicht anders, nur einige Teile des Scripts bieten möglicherweise mehr Funktionen, als normalerweise benötigt werden, und können bei Bedarf problemlos entfernt werden – mit gewissen Einschränkungen. ChatGPT kann dabei jederzeit unterstützen, und das grundlegende Script ist bereits vorhanden.
HEADER und ALLGEMEINE Tastaturnavigation und Fokusverwaltung
Dieses Script erweitert die Tastaturnavigation auf unserer Website. Es enthält unter anderem Anpassungen, wie die Möglichkeit, die Inhalte von Boxzilla-Pop-up zu fokussieren. Auch grundlegende Funktionen, die in Verbindung mit Night Eye stehen und anders sind integriert.
Hinweis: Das Script ist möglicherweise nicht für die direkte Verwendung durch Copy und Paste geeignet.
tastaturnavigation-fokusverwaltung_v3.1.js
/**
* -----------------------------------------------------------------------------
* Scriptname: Tastaturnavigation und Fokusverwaltung
* Version: 3.0
* Datum: 2024-09-12
* Autor: [Team WP Wegerl]
* -----------------------------------------------------------------------------
*
* Beschreibung:
* Dieses Script bietet umfassende Tastaturnavigation und Fokusverwaltung für die gesamte Seite, einschließlich der Headerzeile, Seitenleisten und Fußleisten.
* Es enthält erweiterte Funktionen für die Navigation und Interaktion mittels Tastatur, sowie Anpassungen für spezielle Bereiche wie den Nachtmodus und die Sidebar.
*
* Hauptfunktionen im Überblick:
*
* - **Tastaturnavigation für Headerzeile:**
* - Ermöglicht das Fokussieren und Navigieren durch Header-Elemente mit der Tastatur.
* - Verhindert das Entfernen der Tastaturfokus-Klasse bei Nutzung der Maus.
* - Unterstützt das Fokussieren und Aktivieren von spezifischen Header-Elementen.
*
* - **Tastaturnavigation für Seitenleisten und Fußleisten:**
* - Erweiterte Navigation für die Bereiche '#secondary', '#content-sidebar', '#footer-sidebar' und '#colophon'.
* - Aktiviert fokussierte Elemente in diesen Bereichen durch die Enter-Taste.
*
* - **Toggle-Button für NightEye:**
* - Konfiguriert den Toggle-Button für den Nachtmodus, um ihn per Tastatursteuerung (Enter-Taste) zu bedienen.
* - Öffnet das Dialogfeld für NightEye bei Klick und ermöglicht die Tastaturbedienung.
*
* - **Scroll- und Fokusmanagement:**
* - Setzt den Fokus auf ein spezifisches Element, wenn der Benutzer nach oben scrollt.
* - Entfernt den Fokus von der Admin-Leiste, wenn der Fokus dorthin verschoben wird.
* - Verhindert das Fokussieren auf Elemente außerhalb des Sichtbereichs.
*
* - **Allgemeine Navigation und Interaktionen:**
* - Ermöglicht die Steuerung der Sichtbarkeit und Aktivierung von Elementen über die Tastatur (Enter- oder Space-Taste).
* - Verwaltet Popup-Fenster und die Sichtbarkeit der TOC (Table of Contents) durch Tasteneingaben.
* - Schließt Dialoge und Suchfelder bei Escape-Taste und verwaltet den Fokus.
*
* - **Erweiterte Navigation für Seitenleisten:**
* - Berücksichtigt spezifische Bereiche wie '#secondary', '#content-sidebar', '#footer-sidebar' und '#colophon' für Tastaturnavigation.
* - Aktiviert fokussierte Elemente in diesen Bereichen mit der Enter-Taste.
*
* - **MutationObserver:**
* - Überwacht DOM-Änderungen und passt die Sichtbarkeit und den Fokus von Elementen entsprechend an.
*
* - **Event-Handling für Tastatureingaben:**
* - Verarbeitet spezifische Tastatureingaben für Navigation und Interaktionen innerhalb der Seite.
*
* - **Touch- und Mausinteraktionen:**
* - Verarbeitet spezifische Maus- und Touch-Ereignisse zur Verbesserung der Benutzererfahrung.
*/
/* === HEADERBEREICH Tastaturnavigation & Fokusverwaltung === */
document.addEventListener('DOMContentLoaded', function() {
const body = document.body;
let toggleButtonSetupDone = false;
// Erstmalige Tab-Taste-Überprüfung
function handleFirstTab(event) {
if (event.key === 'Tab') {
body.classList.add('keyboard-focused');
window.removeEventListener('keydown', handleFirstTab);
window.addEventListener('mousedown', handleMouseDown);
}
}
// Mausklick-Überprüfung nach der Tab-Taste
function handleMouseDown() {
body.classList.remove('keyboard-focused');
window.removeEventListener('mousedown', handleMouseDown);
window.addEventListener('keydown', handleFirstTab);
}
window.addEventListener('keydown', handleFirstTab);
// Tastaturnavigation für fokussierbare Elemente
document.querySelectorAll('.focusable').forEach(button => {
button.addEventListener('keydown', function(event) {
// Prüfen, ob das fokussierte Element kein Eingabefeld ist
if (event.key === 'Enter' || event.key === ' ') {
const tagName = event.target.tagName.toLowerCase();
if (tagName !== 'input' && tagName !== 'textarea') {
event.preventDefault();
button.click();
}
}
});
});
// Setup für den NightEye-Toggle-Button
function setupToggleButton() {
if (toggleButtonSetupDone) return;
toggleButtonSetupDone = true;
const toggleCheckbox = document.querySelector('.NightEyeToggleButton input[type="checkbox"]');
if (toggleCheckbox) {
toggleCheckbox.setAttribute('tabindex', '0');
toggleCheckbox.focus();
toggleCheckbox.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
event.preventDefault();
event.stopPropagation();
toggleCheckbox.checked = !toggleCheckbox.checked;
toggleCheckbox.dispatchEvent(new Event('change', { bubbles: true }));
}
});
}
}
// Listener für das Öffnen des NightEye-Dialogs
function addDialogOpenListener() {
const nightEyeWidget = document.querySelector('.NightEyeWidget');
if (nightEyeWidget) {
nightEyeWidget.addEventListener('click', function() {
setupToggleButton();
});
}
}
addDialogOpenListener();
// Hier fügen wir den Code für die overflow-scroll-gradient__scroller-Elemente hinzu
const scrollers = document.querySelectorAll('.overflow-scroll-gradient__scroller');
scrollers.forEach(scroller => {
scroller.setAttribute('tabindex', '0');
});
// Für Admin-Frontend: Fokus auf spezifisches Element setzen, wenn nach oben gescrollt wird
function focusOnSpecificElement() {
const firstFocusableElement = document.querySelector('.main-content .focusable');
if (firstFocusableElement) {
firstFocusableElement.focus();
}
}
// Für Admin-Frontend: Fokus auf die Admin-Leiste entfernen
function removeFocusFromAdminBar() {
const adminBar = document.getElementById('wpadminbar');
if (adminBar && document.activeElement.closest('#wpadminbar')) {
document.activeElement.blur();
}
}
// Für Admin-Frontend: Überwachung des Scroll-Events mit Verzögerung
window.addEventListener('scroll', function() {
if (window.scrollY === 0) {
setTimeout(() => {
removeFocusFromAdminBar();
focusOnSpecificElement();
}, 100); // Verzögerung anpassen, falls nötig
}
});
// Für Admin-Frontend: MutationObserver zur Überwachung von DOM-Änderungen
const observer = new MutationObserver(function() {
if (window.scrollY === 0) {
removeFocusFromAdminBar();
focusOnSpecificElement();
}
});
observer.observe(document.body, { childList: true, subtree: true });
// Für Admin-Frontend: Initiales Setup
document.addEventListener('DOMContentLoaded', function() {
removeFocusFromAdminBar();
focusOnSpecificElement();
});
});
/* = Ende HEADERBEREICH Tastaturnavigation & Fokusverwaltung === */
/* === ALLGEMEINE Tastaturnavigation & Fokusverwaltung === */
// Event-Handler für die Enter-Taste zur Verwaltung der Navigation und des Fokus im Dokument.
document.addEventListener('keydown', function(event) {
// Überprüfen, ob der Fokus sich nicht auf einem Eingabe- oder Textbereichsfeld befindet
const tagName = event.target.tagName.toLowerCase();
const isGoBackButton = event.target.classList.contains('go-back'); // Überprüfen, ob das fokussierte Element ein .go-back-Button ist
// Wenn die Enter-Taste gedrückt wird und der Fokus nicht auf einem Eingabe- oder Textbereichsfeld liegt und es kein .go-back-Button ist
if (event.key === 'Enter' && tagName !== 'input' && tagName !== 'textarea' && !isGoBackButton) {
event.preventDefault(); // Verhindert das Standardverhalten der Enter-Taste
// Fokussiere das nächste Element, wenn das aktuelle fokussierte Element oberhalb von 50px im Sichtbereich liegt
focusNextElementIfAboveOffset(50);
}
});
// Funktion, um sicherzustellen, dass Elemente oberhalb einer bestimmten Schwelle (z.B. 50px) nicht fokussiert werden.
function focusNextElementIfAboveOffset(offset) {
const activeElement = document.activeElement;
if (activeElement && activeElement !== document.body) {
const elementRect = activeElement.getBoundingClientRect();
// Überprüfen, ob das aktive Element zu nah am oberen Rand ist (oberhalb von 50px)
if (elementRect.top < offset) {
// Fokus auf das nächste relevante Element unterhalb der Offset-Schwelle
focusNextRelevantElementBelowOffset(offset);
} else {
// Wenn das Element unterhalb des Offsets ist, bleibt der Fokus auf dem aktuellen Element
activateElement(activeElement);
}
} else {
// Falls kein aktives Element vorhanden ist, setze den Fokus auf das erste Element im sichtbaren Bereich
focusFirstRelevantElementBelowOffset(offset);
}
}
// Funktion, um das nächste relevante Element unterhalb der Offset-Schwelle zu fokussieren.
function focusNextRelevantElementBelowOffset(offset) {
const allFocusableElements = Array.from(document.querySelectorAll('#content summary, #content pre, #content a[href], #content button, #content input, #content textarea, .overflow-scroll-gradient__scroller, #content [tabindex]:not([tabindex="-1"])')); // Erweitere hier die Selektoren nach Bedarf
for (const element of allFocusableElements) {
const elementRect = element.getBoundingClientRect();
// Fokus auf das erste Element, das sich unterhalb des Offsets (50px) befindet und im sichtbaren Bereich ist
if (elementRect.top >= offset && isElementInViewport(element)) {
element.focus({ preventScroll: true });
return;
}
}
}
//Funktion, um das erste relevante Element unterhalb der Offset-Schwelle zu fokussieren.
function focusFirstRelevantElementBelowOffset(offset) {
const allFocusableElements = Array.from(document.querySelectorAll('#content summary, #content pre, #content a[href], #content button, #content input, #content textarea, .overflow-scroll-gradient__scroller, #content [tabindex]:not([tabindex="-1"])')); // Erweitere hier die Selektoren nach Bedarf
for (const element of allFocusableElements) {
const elementRect = element.getBoundingClientRect();
// Fokus auf das erste Element, das sich unterhalb des Offsets (50px) befindet und im sichtbaren Bereich ist
if (elementRect.top >= offset && isElementInViewport(element)) {
element.focus({ preventScroll: true });
return;
}
}
}
// Funktion, um zu überprüfen, ob ein Element im sichtbaren Bereich des Viewports ist.
function isElementInViewport(element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
// Funktion zum Aktivieren eines Elements.
function activateElement(element) {
element.focus({ preventScroll: true });
}
// Überwachung des Scrollens mit Debouncing und "Above the Fold"-Logik
let aboveTheFold = true; // Zustand, ob wir uns im "Above the Fold"-Bereich befinden
let navigationPaused = false; // Zustand, ob die Navigation pausiert ist
let lastScrollY = 0; // Variable für die letzte Scroll-Position
let scrollTimeout;
const headerHeight = 50; // Höhe der Headerleiste in Pixeln
// Überwachung des Scrollens
window.addEventListener('scroll', function() {
const currentScrollY = window.scrollY;
if (Math.abs(currentScrollY - lastScrollY) < 10) return; // Wenn die Scroll-Änderung zu klein ist, überspringe
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function() {
const foldBoundary = window.innerHeight * 0.5; // Definition von "Above the Fold"
const activeElement = document.activeElement;
if (window.scrollY > foldBoundary) {
aboveTheFold = false; // Benutzer hat den "Above the Fold"-Bereich verlassen
} else {
if (!aboveTheFold) { // Nur zurücksetzen, wenn wir gerade erst in den "Above the Fold"-Bereich gescrollt haben
resetTabindex(); // Setzt den Tabindex zurück
}
aboveTheFold = true; // Benutzer ist wieder im "Above the Fold"-Bereich
}
// Entferne den Fokus, wenn das aktive Element nicht mehr im Viewport ist
if (activeElement && !isElementInViewport(activeElement)) {
activeElement.blur();
}
// NEUE LOGIK: Fokus entfernen, wenn das aktive Element hinter der Headerleiste liegt
if (activeElement) {
const rect = activeElement.getBoundingClientRect();
const viewportThreshold = 100; // Optionaler Abstand in Pixeln vom oberen Rand
// Wenn das Element hinter der Headerleiste liegt oder sich dem oberen Rand nähert
if (rect.top < headerHeight || rect.top < viewportThreshold) {
activeElement.blur(); // Fokussierung entfernen
}
}
lastScrollY = currentScrollY; // Update lastScrollY after processing
}, 100); // Timeout nach 100ms Inaktivität
});
// Überwachung des Klicks auf die Headerzeile
const headerElement = document.querySelector('#masthead') || document.querySelector('.header-main');
if (headerElement) {
headerElement.addEventListener('click', function() {
navigationPaused = true; // Pausiert die Tastaturnavigation
});
}
// Überwachung des Fokus-Wechsels im Headerbereich
document.addEventListener('focusin', function(event) {
if (headerElement && headerElement.contains(event.target)) {
navigationPaused = true; // Pausiert die Tastaturnavigation, wenn der Fokus im Headerbereich liegt
}
});
// Überwachung des Fokus-Wechsels außerhalb des Headerbereichs
document.addEventListener('focusout', function(event) {
if (headerElement && headerElement.contains(event.target)) {
navigationPaused = false; // Reaktiviert die Tastaturnavigation, wenn der Fokus den Headerbereich verlässt
}
});
// Funktion zum Zurücksetzen des Tabindex: Das Scrollverhalten wird gezielt überprüft und der Fokus nur dann setzt, wenn der Benutzer bereits ganz oben auf der Seite ist
function resetTabindex() {
const firstFocusableElement = document.querySelector('a, button, input, textarea, select, embed, [tabindex]:not([tabindex="-1"])');
if (firstFocusableElement) {
// Überprüfen, ob der Benutzer ganz oben auf der Seite ist
if (window.scrollY === 0) {
firstFocusableElement.focus();
}
}
}
// Variable zum Verfolgen des aktuell fokussierten Pop-ups
let lastFocusedPopup = null;
// Funktion zum Fokussieren des neuesten sichtbaren Boxzilla-Pop-ups
function focusBoxzillaPopups() {
// Alle sichtbaren Boxzilla-Pop-ups auswählen
const popups = document.querySelectorAll('.boxzilla:not([style*="display: none"])');
// Fokus nur auf das neueste Pop-up setzen
let focusedAnyPopup = false;
popups.forEach(popup => {
const focusableElements = popup.querySelectorAll('a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])');
if (focusableElements.length > 0) {
if (popup !== lastFocusedPopup) {
// Setzt den Fokus auf das erste fokussierbare Element
const firstFocusableElement = focusableElements[0];
firstFocusableElement.focus();
// Scrollen, um sicherzustellen, dass das Pop-up sichtbar ist
if (popup.scrollIntoViewIfNeeded) {
popup.scrollIntoViewIfNeeded(true);
} else {
popup.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// Setze lastFocusedPopup auf das aktuelle Pop-up
lastFocusedPopup = popup;
focusedAnyPopup = true;
}
}
});
return focusedAnyPopup; // Gibt zurück, ob mindestens ein Pop-up fokussiert wurde
}
// Funktion zur Überwachung von Pop-up-Änderungen
function setupPopupMonitoring() {
const observer = new MutationObserver(() => {
// Verzögerung hinzufügen, um sicherzustellen, dass das Pop-up vollständig gerendert ist
setTimeout(() => {
focusBoxzillaPopups();
}, 100); // Verzögerung anpassen, falls nötig
});
// Beobachte Änderungen im DOM
observer.observe(document.body, { childList: true, subtree: true });
// Initiales Fokussieren beim Laden der Seite
setTimeout(() => {
focusBoxzillaPopups();
}, 100); // Verzögerung anpassen, falls nötig
}
// Starte die Überwachung der Pop-ups
setupPopupMonitoring();
// Funktion zum Fokussieren des ersten relevanten Elements im Inhaltsbereich
function focusFirstRelevantElement() {
const focusableElements = '#content summary, #content pre, #content iframe, #content embed, #content a[href], #content button, #content input, #content textarea, #content select, .overflow-scroll-gradient__scroller, #content [tabindex]:not([tabindex="-1"])';
const elements = Array.from(document.querySelectorAll(focusableElements));
// Priorisiere das Fokussieren von EMBED- und IFRAME-Elementen, wenn sie sichtbar sind
const firstRelevantElement = elements.find(el =>
isElementInViewport(el) &&
(['IFRAME', 'EMBED'].includes(el.tagName) || !isBlockedByEmbed(el))
);
if (firstRelevantElement) {
// Eventuelle Besonderheiten für Firefox beim Fokussieren von `iframe` oder `embed`
if (firstRelevantElement.tagName === 'IFRAME' || firstRelevantElement.tagName === 'EMBED') {
// Fallback-Logik für Firefox
setTimeout(() => firstRelevantElement.focus(), 100);
} else {
firstRelevantElement.focus();
}
}
}
// Funktion zum Aktivieren eines Elements
function activateElement(element) {
if (typeof element.click === 'function') {
element.click();
}
}
// Funktion zum Überprüfen, ob ein Element im Viewport ist
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.bottom > 0 &&
rect.top < window.innerHeight &&
rect.right > 0 &&
rect.left < window.innerWidth
);
}
// Funktion zum Überprüfen, ob ein Element von einem Embed oder Iframe verdeckt wird
function isBlockedByEmbed(el) {
const embeds = document.querySelectorAll('iframe, embed');
return Array.from(embeds).some(embed => {
const rect = embed.getBoundingClientRect();
const elRect = el.getBoundingClientRect();
return !(rect.right < elRect.left ||
rect.left > elRect.right ||
rect.bottom < elRect.top ||
rect.top > elRect.bottom);
});
}
// Schlüsselereignis-Listener für die Escape-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
// Schließe das NightEyeDialog-Element
const backgroundElement = document.querySelector('.NightEyeDialogBackground');
if (backgroundElement) {
backgroundElement.click();
}
// Schließe das Suchfeld, falls aktiv
const activeToggle = document.querySelector('.search-toggle.active');
if (activeToggle) {
activeToggle.click();
}
// Entferne den Fokus vom aktiven Element
if (document.activeElement) {
document.activeElement.blur();
}
}
// Öffnen der Suche mit der 7-Taste
if (event.key === '7') {
// Finde das inaktive Such-Toggle-Element
const inactiveToggle = document.querySelector('.search-toggle:not(.active)');
if (inactiveToggle) {
// Simuliere einen Klick auf das inaktive Toggle-Element, um die Suche zu öffnen
inactiveToggle.click();
}
// Verhindern, dass die 7 in ein Eingabefeld eingegeben wird
event.preventDefault();
}
// Funktion für Enter- oder Space-Taste
if (event.key === 'Enter' || event.key === ' ') {
const focusedElement = document.activeElement;
// Überprüfe, ob das fokussierte Element der Tag-Nachtmodus-Schalter ist
if (focusedElement && focusedElement.matches('[aria-label="Tag- Nachtmodus"]')) {
// Simuliere einen Klick auf das fokussierte Element, um den NightEyeDialog aufzurufen
focusedElement.click();
event.preventDefault();
}
// Optional: Weitere Logik für andere Enter/Space-Aktionen kann hier hinzugefügt werden
}
});
document.addEventListener('keydown', function(event) {
// Prüft, ob die Taste 'T' gedrückt wurde
if (event.key === 't' || event.key === 'T') {
// Überprüft, ob das aktive Element ein Eingabefeld oder ein Textbereich ist
if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') {
// Falls das aktive Element ein Eingabefeld oder Textbereich ist, ignoriere den Tastendruck
return;
}
// Sucht nach dem .ez-toc-sticky-fixed-Element
const tocElement = document.querySelector('.ez-toc-sticky-fixed');
if (tocElement) {
// Überprüft, ob das Element die Klasse 'show' hat
if (tocElement.classList.contains('show')) {
// Entfernt die Klasse 'show' und fügt 'hide' hinzu, um das Element zu schließen
tocElement.classList.remove('show');
tocElement.classList.add('hide');
} else if (tocElement.classList.contains('hide')) {
// Entfernt die Klasse 'hide' und fügt 'show' hinzu, um das Element zu öffnen
tocElement.classList.remove('hide');
tocElement.classList.add('show');
} else {
// Falls weder 'show' noch 'hide' gesetzt ist, wird standardmäßig geöffnet
tocElement.classList.add('show');
}
}
}
});
// Details-Element/Summary nach öffnen durch Leertaste: Leertaste ist wieder zum Scrollen geeignet
document.addEventListener('keydown', function(event) {
// Überprüfe, ob die Leertaste gedrückt wurde
if (event.code === 'Space') {
const focusedElement = document.activeElement;
// Überprüfe, ob das fokussierte Element ein <summary> ist
if (focusedElement.tagName.toLowerCase() === 'summary') {
// Verhindere das normale Scrollen durch die Leertaste
event.preventDefault();
// Öffne oder schließe das <details>-Element
const detailsElement = focusedElement.parentElement;
if (detailsElement.hasAttribute('open')) {
detailsElement.removeAttribute('open');
} else {
detailsElement.setAttribute('open', true);
}
// Entferne die Fokussierung vom <summary>-Element
focusedElement.blur();
}
}
});
/* = Ende ALLGEMEINE Tastaturnavigation & Fokusverwaltung = */
CSS-Beispiel für Fokus Styles
/* === Fokus Styles === */
/* Standardfokus Bilder unsichtbar machen */
.entry-content a:focus img {
outline: none;
}
/* Fokus-Stil für Links */
.entry-content a:focus-visible {
padding: 3px 0;
outline: 1.5px solid #FD8826;
}
/* Fokus-Stil für das Inhaltsverzeichnis */
a.ez-toc-link:focus {
padding: 0 !important;
}
a.ez-toc-link:focus-visible {
margin: 5px;
}
/* Fokus-Stil für Bilder in der Galerie, die zur Lightbox gehören */
.gallery-item a[data-featherlight]:focus-visible img {
border-radius: 3px;
box-shadow: 0 0 8px 8px rgba(33, 117, 155, 0.8);
outline: thin dotted rgba(33, 117, 155, 0.8);
transform: scale(1.1);
z-index: 10;
transition: transform 0.3s ease, box-shadow 0.3s ease;
overflow: visible;
}
/* Fokus-Stil nur für Bilder, die in der Lightbox geöffnet werden */
a[data-featherlight]:focus-visible img {
transform: scale(1.03);
transition: transform 0.3s ease;
box-shadow: 0 0 3px 3px rgba(33, 117, 155, 0.8);
border-radius: 5px;
box-shadow: 4px 4px #e6e6e6, -4px -4px #ccc;
}
[nighteyeplgn="active"] a[data-featherlight]:focus-visible img {
transform: scale(1.03);
transition: transform 0.3s ease;
outline: 4px solid #FD8826 !important;
}
/* Bilder mit Link sollten mit der Klasse 'ent' ausgezeichnet sein */
a.ent {
position: relative;
}
/* Fokussieren und Hervorheben des Bildes im Link */
a.ent:focus-visible img {
outline: 2px solid #FD8826 !important;
outline-offset: 4px;
}
/* Zusatztext für fokussierte Links mit Bildern und Klasse 'ent' */
a.ent:focus-visible::before {
content: 'Enter den Link';
color: #FD8826;
font-weight: bold;
position: absolute;
left: 0;
background-color: white;
padding: 5px;
z-index: 1;
}
/* Scrollbare Elemente fokussieren */
.overflow-scroll-gradient__scroller:focus-visible {
outline: 2px solid #FD8826;
outline-offset: 4px;
}
/* Fokus-Stile für den Span-Tag im Zurück-Button */
span.go-back.button:focus-visible {
outline: -webkit-focus-ring-color auto 1px;
}
/* = Ende Fokus Styles = */
Tastaturbedienung
- Tabulatortaste (Tab): Navigiert durch interaktive Elemente wie Links und Buttons.
- Shift + Tab: Verschiebt den Fokus zurück zum vorherigen Element.
- Enter-Taste: Aktiviert das aktuell fokussierte Element. Im Inhaltsbereich bewirkt die erste Betätigung die Fokussierung, während die zweite Betätigung das Element aktiviert.
- Pfeiltasten: Scrollen innerhalb von Texten oder Menüs.
- Leertaste: Aktiviert Buttons in der Headerleiste ähnlich wie die Enter-Taste und wird im Content zum abschnittsweisen Scrollen verwendet.
- Shift + Leertaste: Abschnittweies Scrollen nach oben.
- 7-Taste: Tippe '7', um die Suche zu aktivieren und 'Esc', um sie abzubrechen.
- Escape-Taste (Esc): Bricht alle Fokussierungen ab und schließt Dialoge.
- T-Taste: Das Sticky-Toc (Inhaltsverzeichnis) aus- einblenden.
- Ctrl + Alt: Den internen Link in einem neuen Tab öffnen.
Entwicklungsteil
Bei der kompakten Darstellung der Skripte als Entwicklungsteil trat ein Problem auf, das sich gut als Beispiel eignet, um darauf aufmerksam zu machen.
Das hier im Details-Element ist ein Beispiel dafür, wie sich ein geschlossenes details
–Element, oder ein Element in einem Scroller verhält, wenn es den <pre>
-Tag enthält: Die nächsten Links und Elemente unter dem aufklappbaren Element wird mit 'Enter' nicht fokussiert, wenn das details
-Element eingeklappt ist.
Unsichtbare, aber technisch noch im DOM vorhandene Inhalte können dann die Navigation beeinträchtigen. Dies tritt im details
–Element immer auf, jedoch nicht im Scroller bei normalen Inhalten, also ohne <pre>
-Tag und entsprechenden Inhalten.
Das Problem tritt also auf, nach einem <details>
-Element oder in einem Scrollcontainer (z.B. mit overflow: auto
oder scroll
) wenn ein <pre>
-Tag enthalten ist – unabhängig davon, ob der <pre>
-Tag eine festgelegte Höhe hat oder nicht. Es liegt an der Art und Weise, wie der <pre>
-Tag als Block-Element innerhalb dieser Container funktioniert.
Im Browser Safari ist das hier beschriebene Problem nicht aufgetreten.
Warum tritt das Problem auf?
- Block-Level-Verhalten des
<pre>
-Tags:- Der
<pre>
-Tag ist ein Block-Element, das von Haus aus eine spezielle Formatierung für den Inhalt übernimmt (Zeilenumbrüche und Leerzeichen werden beibehalten). Als Block-Element nimmt es in der Layout-Struktur eine signifikante Position ein. - In Verbindung mit Containern wie
<details>
oder scrollbaren Bereichen kann der Browser Schwierigkeiten haben, den Inhalt richtig zu verwalten, insbesondere was die Fokussierung von Elementen betrifft.
- Der
- Verhalten im
<details>
-Element:- Wenn das
<details>
-Element geschlossen ist, bleibt der Inhalt technisch im DOM (Document Object Model) erhalten, ist aber nicht sichtbar. Dies führt dazu, dass der Browser die Existenz des Inhalts weiterhin berücksichtigt, auch wenn es nicht gerendert wird. - Problem: Da der Inhalt als "blockierender" Inhalt im DOM vorhanden bleibt, kann dies die Navigation stören, besonders wenn versucht wird, nachfolgende Links oder interaktive Elemente zu fokussieren. Der Browser „verliert“ manchmal den Kontext oder blockiert die Navigation, da er weiterhin den blockbasierten Inhalt berücksichtigt, obwohl er visuell nicht verfügbar ist.
- Wenn das
- Verhalten im Scrollcontainer:
- Ähnlich verhält es sich bei
<pre>
-Tags in einem Scrollcontainer. Da das<pre>
-Tag als Block-Element oft größere Textblöcke enthält und für formatierten Text gedacht ist, kann es sein, dass der Scrollcontainer Schwierigkeiten hat, den Fokus auf nachfolgende Elemente zu verschieben, wenn das<pre>
-Tag sichtbar ist. - Problem: Wenn ein großes
<pre>
-Element in einem scrollbaren Bereich ist, und der sichtbare Bereich des Scrollcontainers endet, kann der Browser den Fokus schwer über das<pre>
-Tag hinaus bewegen. Der Inhalt des<pre>
-Tags blockiert effektiv die Fokussierung auf nachfolgende interaktive Elemente, da der Browser das Block-Level-Verhalten des<pre>
-Tags priorisiert.
- Ähnlich verhält es sich bei
Das passiert nicht, wenn man allein die Tab-Taste drückt.
Details Problem
/ Käse ist ein Genuss, aber nicht immer.
Vorherige Ausgaben HEADER und ALLGEMEINE Tastaturnavigation & Fokusverwaltung:
Tastaturnavigation-und-Fokusverwaltung_v2.js
Tastaturnavigation und Fokusverwaltung.js (_v1)
Entwicklungsbeispiel "Tastaturnavigation Headerzeile" und die "Allgemeine Navigation und Fokusverwaltung":
/* === Tastaturnavigation Headerzeile === */
document.addEventListener('DOMContentLoaded', function() {
// Finde alle Elemente mit der angegebenen Klasse
const scrollers = document.querySelectorAll('.overflow-scroll-gradient__scroller');
// Füge jedem Element tabindex="0" hinzu
scrollers.forEach(scroller => {
scroller.setAttribute('tabindex', '0');
});
const body = document.body;
let toggleButtonSetupDone = false;
// Erstmalige Tab-Taste-Überprüfung
function handleFirstTab(event) {
console.log('Tab event detected');
if (event.key === 'Tab') {
body.classList.add('keyboard-focused');
window.removeEventListener('keydown', handleFirstTab);
window.addEventListener('mousedown', handleMouseDown);
}
}
// Mausklick-Überprüfung nach der Tab-Taste
function handleMouseDown() {
console.log('Mouse down detected');
body.classList.remove('keyboard-focused');
window.removeEventListener('mousedown', handleMouseDown);
window.addEventListener('keydown', handleFirstTab);
}
window.addEventListener('keydown', handleFirstTab);
// Tastaturnavigation für fokussierbare Elemente
document.querySelectorAll('.focusable').forEach(button => {
button.addEventListener('keydown', function(event) {
console.log('Focusable keydown event detected:', event.key);
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
button.click();
}
});
});
// Setup für den NightEye-Toggle-Button
function setupToggleButton() {
if (toggleButtonSetupDone) return;
toggleButtonSetupDone = true;
const toggleCheckbox = document.querySelector('.NightEyeToggleButton input[type="checkbox"]');
if (toggleCheckbox) {
console.log('Setting up toggle button');
toggleCheckbox.setAttribute('tabindex', '0');
toggleCheckbox.focus();
toggleCheckbox.addEventListener('keydown', function(event) {
console.log('Toggle button keydown event detected:', event.key);
if (event.key === 'Enter') {
event.preventDefault();
event.stopPropagation();
toggleCheckbox.checked = !toggleCheckbox.checked;
toggleCheckbox.dispatchEvent(new Event('change', { bubbles: true }));
}
});
}
}
// Listener für das Öffnen des NightEye-Dialogs
function addDialogOpenListener() {
const nightEyeWidget = document.querySelector('.NightEyeWidget');
if (nightEyeWidget) {
nightEyeWidget.addEventListener('click', function() {
console.log('NightEyeWidget clicked');
setupToggleButton();
});
}
}
addDialogOpenListener();
});
/* = Ende Tastaturnavigation Headerzeile === */
/* === Anpassung für die allgemeine Navigation und Fokusverwaltung === */
// Schlüsselereignis-Listener für die Enter-Taste
document.addEventListener('keydown', function(event) {
if (!aboveTheFold && !navigationPaused && event.key === 'Enter') {
event.preventDefault(); // Verhindere das Standardverhalten der Enter-Taste
// Überprüfe, ob Boxzilla-Pop-ups geöffnet sind und setze den Fokus darauf
if (focusBoxzillaPopups()) {
return; // Beende die Funktion, wenn Pop-ups fokussiert wurden
}
const activeElement = document.activeElement;
if (!activeElement || activeElement === document.body || !isElementInViewport(activeElement) || !activeElement.closest('#content')) {
// Setze den Fokus auf das erste relevante sichtbare Element im #content
focusFirstRelevantElement();
} else {
// Wenn das fokussierte Element im sichtbaren Bereich und im Inhalt ist, aktiviere es
activateElement(activeElement);
}
}
});
// Überwachung des Scrollens mit Debouncing und "Above the Fold"-Logik
let aboveTheFold = true; // Zustand, ob wir uns im "Above the Fold"-Bereich befinden
let navigationPaused = false; // Zustand, ob die Navigation pausiert ist
let lastScrollY = 0; // Variable für die letzte Scroll-Position
let scrollTimeout;
// Überwachung des Scrollens
window.addEventListener('scroll', function() {
const currentScrollY = window.scrollY;
if (Math.abs(currentScrollY - lastScrollY) < 10) return; // Wenn die Scroll-Änderung zu klein ist, überspringe
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function() {
const foldBoundary = window.innerHeight * 0.5; // Definition von "Above the Fold"
const activeElement = document.activeElement;
if (window.scrollY > foldBoundary) {
aboveTheFold = false; // Benutzer hat den "Above the Fold"-Bereich verlassen
} else {
if (!aboveTheFold) { // Nur zurücksetzen, wenn wir gerade erst in den "Above the Fold"-Bereich gescrollt haben
resetTabindex(); // Setzt den Tabindex zurück
}
aboveTheFold = true; // Benutzer ist wieder im "Above the Fold"-Bereich
}
// Entferne den Fokus, wenn das aktive Element nicht mehr im Viewport ist
if (activeElement && !isElementInViewport(activeElement)) {
activeElement.blur();
console.log('Element out of viewport, focus removed:', activeElement);
}
lastScrollY = currentScrollY; // Update lastScrollY after processing
}, 100); // Timeout nach 100ms Inaktivität
});
// Überwachung des Klicks auf die Headerzeile
const headerElement = document.querySelector('#masthead') || document.querySelector('.header-main');
if (headerElement) {
headerElement.addEventListener('click', function() {
navigationPaused = true; // Pausiert die Tastaturnavigation
console.log('Navigation paused due to header interaction');
});
}
// Überwachung des Fokus-Wechsels im Headerbereich
document.addEventListener('focusin', function(event) {
if (headerElement && headerElement.contains(event.target)) {
navigationPaused = true; // Pausiert die Tastaturnavigation, wenn der Fokus im Headerbereich liegt
console.log('Navigation paused due to header focus');
}
});
// Überwachung des Fokus-Wechsels außerhalb des Headerbereichs
document.addEventListener('focusout', function(event) {
if (headerElement && headerElement.contains(event.target)) {
navigationPaused = false; // Reaktiviert die Tastaturnavigation, wenn der Fokus den Headerbereich verlässt
console.log('Navigation resumed after leaving header');
}
});
// Funktion zum Zurücksetzen des Tabindex
function resetTabindex() {
const firstFocusableElement = document.querySelector('a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])');
if (firstFocusableElement) {
firstFocusableElement.focus();
console.log('Tabindex reset and focus set on:', firstFocusableElement);
} else {
console.log('No focusable element found to reset tabindex');
}
}
// Funktion zum Fokussieren von Boxzilla-Pop-ups
/*function focusBoxzillaPopups() {
const popups = document.querySelectorAll('.boxzilla:not([style*="display: none"])'); // Selektor für sichtbare Boxzilla-Pop-ups
let focusedAnyPopup = false;
// Durchlaufe alle sichtbaren Boxzilla-Pop-ups
popups.forEach(popup => {
const focusableElements = popup.querySelectorAll('a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])');
if (focusableElements.length > 0) {
focusableElements[0].focus(); // Setzt den Fokus auf das erste fokussierbare Element
focusedAnyPopup = true;
console.log('Focus set on Boxzilla popup:', popup);
}
});
return focusedAnyPopup; // Gibt zurück, ob mindestens ein Pop-up fokussiert wurde
}*/
// Variable zum Verfolgen des aktuell fokussierten Pop-ups
let lastFocusedPopup = null;
// Funktion zum Fokussieren des ersten sichtbaren Boxzilla-Pop-ups
function focusBoxzillaPopups() {
// Alle sichtbaren Boxzilla-Pop-ups auswählen
const popups = document.querySelectorAll('.boxzilla:not([style*="display: none"])');
// Fokus nur auf das neueste Pop-up setzen
let focusedAnyPopup = false;
popups.forEach(popup => {
const focusableElements = popup.querySelectorAll('a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])');
if (focusableElements.length > 0) {
if (popup !== lastFocusedPopup) {
// Setzt den Fokus auf das erste fokussierbare Element
const firstFocusableElement = focusableElements[0];
firstFocusableElement.focus();
// Scrollen, um sicherzustellen, dass das Pop-up sichtbar ist
if (popup.scrollIntoViewIfNeeded) {
popup.scrollIntoViewIfNeeded(true);
} else {
popup.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// Setze lastFocusedPopup auf das aktuelle Pop-up
lastFocusedPopup = popup;
focusedAnyPopup = true;
console.log('Focus set on Boxzilla popup:', popup);
}
}
});
return focusedAnyPopup; // Gibt zurück, ob mindestens ein Pop-up fokussiert wurde
}
// Funktion zur Überwachung von Pop-up-Änderungen
function setupPopupMonitoring() {
const observer = new MutationObserver(() => {
// Verzögerung hinzufügen, um sicherzustellen, dass das Pop-up vollständig gerendert ist
setTimeout(() => {
focusBoxzillaPopups();
}, 100); // Verzögerung anpassen, falls nötig
});
// Beobachte Änderungen im DOM
observer.observe(document.body, { childList: true, subtree: true });
// Initiales Fokussieren beim Laden der Seite
setTimeout(() => {
focusBoxzillaPopups();
}, 100); // Verzögerung anpassen, falls nötig
}
// Starte die Überwachung der Pop-ups
setupPopupMonitoring();
// Funktion zum Fokussieren des ersten relevanten Elements im Inhaltsbereich
function focusFirstRelevantElement() {
const focusableElements = '#content iframe, #content embed, #content a[href], #content button, #content input, #content textarea, #content select, #content [tabindex]:not([tabindex="-1"])';
const elements = Array.from(document.querySelectorAll(focusableElements));
// Priorisiere das Fokussieren von EMBED- und IFRAME-Elementen, wenn sie sichtbar sind
const firstRelevantElement = elements.find(el =>
isElementInViewport(el) &&
(['IFRAME', 'EMBED'].includes(el.tagName) || !isBlockedByEmbed(el))
);
if (firstRelevantElement) {
// Eventuelle Besonderheiten für Firefox beim Fokussieren von `iframe` oder `embed`
if (firstRelevantElement.tagName === 'IFRAME' || firstRelevantElement.tagName === 'EMBED') {
// Fallback-Logik für Firefox
setTimeout(() => firstRelevantElement.focus(), 100);
} else {
firstRelevantElement.focus();
}
console.log('Focus set on first relevant element:', firstRelevantElement);
} else {
console.log('No relevant focusable element found in #content');
}
}
// Funktion zum Aktivieren eines Elements
function activateElement(element) {
if (typeof element.click === 'function') {
element.click();
console.log('Element activated:', element);
} else {
console.log('Element cannot be activated:', element);
}
}
// Funktion zum Überprüfen, ob ein Element im Viewport ist
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.bottom > 0 &&
rect.top < window.innerHeight &&
rect.right > 0 &&
rect.left < window.innerWidth
);
}
// Funktion zum Überprüfen, ob ein Element von einem Embed oder Iframe verdeckt wird
function isBlockedByEmbed(el) {
const embeds = document.querySelectorAll('iframe, embed');
return Array.from(embeds).some(embed => {
const rect = embed.getBoundingClientRect();
const elRect = el.getBoundingClientRect();
return !(rect.right < elRect.left ||
rect.left > elRect.right ||
rect.bottom < elRect.top ||
rect.top > elRect.bottom);
});
}
// Schlüsselereignis-Listener für die Escape-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
console.log('Escape-Taste wurde gedrückt');
// Schließe das NightEyeDialog-Element
const backgroundElement = document.querySelector('.NightEyeDialogBackground');
if (backgroundElement) {
backgroundElement.click();
console.log('NightEyeDialog geschlossen');
}
// Schließe das Suchfeld, falls aktiv
const activeToggle = document.querySelector('.search-toggle.active');
if (activeToggle) {
activeToggle.click();
console.log('Suchfeld geschlossen durch Klicken auf das aktive Toggle-Element');
}
// Entferne den Fokus vom aktiven Element
if (document.activeElement) {
document.activeElement.blur();
console.log('Fokus entfernt');
}
}
// Öffnen der Suche mit der 7-Taste
if (event.key === '7') {
console.log('7-Taste wurde gedrückt');
// Finde das inaktive Such-Toggle-Element
const inactiveToggle = document.querySelector('.search-toggle:not(.active)');
if (inactiveToggle) {
// Simuliere einen Klick auf das inaktive Toggle-Element, um die Suche zu öffnen
inactiveToggle.click();
console.log('Suchfeld geöffnet durch Klicken auf das inaktive Toggle-Element');
}
// Verhindern, dass die / in ein Eingabefeld eingegeben wird
event.preventDefault();
}
// Funktion für Enter- oder Space-Taste
if (event.key === 'Enter' || event.key === ' ') {
const focusedElement = document.activeElement;
// Überprüfe, ob das fokussierte Element der Tag-Nachtmodus-Schalter ist
if (focusedElement && focusedElement.matches('[aria-label="Tag- Nachtmodus"]')) {
console.log('Tag-Nachtmodus-Schalter wurde aktiviert');
// Simuliere einen Klick auf das fokussierte Element, um den NightEyeDialog aufzurufen
focusedElement.click();
event.preventDefault();
}
// Optional: Weitere Logik für andere Enter/Space-Aktionen kann hier hinzugefügt werden
}
});
/* = Ende Anpassung für die allgemeine Navigation und Fokusverwaltung === */
Das oben gezeigte JavaScript zeigt möglicherweise keine Fokussierung von Embeds bei der Verwendung der Enter-Taste.
/ Käse ist ein Genuss, aber nicht immer.
Vorherige Ausgaben Fokussierung und Markierung von EMBEDs:
Die Fokussierung der WP-Embeds wurden im Skript von "3. Fokussierung und Markierung von EMBEDs" vollständig neu überarbeitet und sind daher deutlich performanter. Das Folgende ist eine Dokumentation der veralteten Herangehensweise.
Die Links in einem Embed werden zwar durch die Tab-Taste nacheinander aktiviert, doch mit der Enter-Taste ließ sich die Fokussierung bislang nicht richtig umsetzen. Da Embeds generell schwerer zu fokussieren sind und das Aktivieren mit Enter nicht dieselbe visuelle Rückmeldung wie bei Links bietet, war das ein Problem. Das Embed wird zwar durch Enter Fokussiert, aber diese Fokussierung wird nicht visuell deutlich. Der erste Link in einem Embed wird erst mit einem weiteren Druck auf die Tab-Taste fokussiert. Im Folgenden geht es um die primäre Fokussierung.
Mit einem JavaScript konnten wir das Problem so lösen, dass das gesamte Embed markiert wird, wenn es direkt mit der Enter-Taste aktiviert wird. Diese Markierung erfolgt jedoch nur, wenn Enter verwendet wird, nicht bei einer Fokussierung durch Tab, da die Links im Embed ohnehin durch Tab optisch hervorgehoben werden.
- CSS-Anwendung bei
Enter
-Taste: Das Skript fügt ein benutzerdefiniertes CSS hinzu, um ein Embed-Element hervorzuheben, wenn es durch Drücken derEnter
-Taste im Viewport fokussiert wird. - Keine CSS-Anwendung bei Links vor Embeds: Wenn ein Link direkt vor einem Embed fokussiert wird, wird das CSS nicht angewendet, um unnötige Hervorhebungen zu vermeiden.
- CSS-Entfernung bei
Tab
-Navigation: Wenn durch dieTab
-Taste ein anderes Element als das Embed fokussiert wird, wird das benutzerdefinierte CSS entfernt. - Scroll-Überwachung: Beim Scrollen wird das CSS automatisch entfernt, wenn das Embed den Viewport verlässt.
- Fokus-Überwachung: Das Skript überwacht den Fokuswechsel und passt das CSS entsprechend an, je nachdem, ob das Embed im Viewport sichtbar ist und fokussiert wird.
- Hilfsfunktion zur Sichtbarkeitsprüfung: Eine Funktion prüft, ob das Embed tatsächlich im sichtbaren Bereich des Viewports liegt, bevor das CSS angewendet oder entfernt wird.
Dieses JavaScript-Skript bietet eine Lösung zur Verwaltung der Fokussierung und visuellen Markierung von Embed-Elementen auf unserer Webseite. Es sorgt dafür, dass EMBEDs beim Fokus oder Klick hervorgehoben werden und bietet eine verbesserte Benutzererfahrung, indem es visuelle Hinweise gibt und die Fokussierung gezielt steuert. Das Skript behandelt verschiedene Interaktionen wie Klicks, Tastatureingaben und Scrollen, um sicherzustellen, dass die Sichtbarkeit und Interaktivität von Embeds optimal gehandhabt werden.
Die Hauptfunktionen umfassen:
- Automatische Markierung und Entfernen der Markierung bei Fokuswechsel
- Visuelle Hervorhebung durch benutzerdefiniertes CSS
- Intelligente Verwaltung der Fokussierung, um Konflikte zwischen Links und Embeds zu vermeiden.
iframe-embed-focus-control-plus-nachricht_v1.js
iframe-embed-focus-control_v2.js
iframe-embed-focus-control_v1.js
Entwicklungsbeispiel "Embed Fokussieren":
Ziel war es, dass Embeds durch Enter fokussiert werden können, ähnlich wie es normalerweise mit der Tab-Taste geschieht. Allerdings blieb das folgende CSS wirkungslos:
/* Versuch: Embed Link durch Enter fokussieren */
.wp-embedded-content:focus,
iframe.wp-embedded-content:focus {
outline: 1px solid gray;
}
Auch der Ansatz, das gesamte Embed durch Einfügen einer CSS-Klasse (focused
) im JavaScript zu fokussieren und visuell hervorzuheben, scheiterte. In diesem Fall verhinderten Sicherheitsmechanismen wie Same-Origin-Policies oder strenge Content Security Policies (CSP), dass die Classe per JavaScript hinzugefügt und über CSS visualisiert werden konnte.
.wp-embedded-content.focused,
iframe.wp-embedded-content.focused {
outline: 1px solid gray;
}
Diese Ansätze waren also erfolglos.
Die nächste Idee war, das Embed durch Enter zu visualisieren, indem es dauerhaft hervorgehoben wird. Hierfür sollte ein einfaches CSS-Styling verwendet werden:
.wp-embedded-content {
outline: 1px solid gray;
}
Logischerweise sollte das CSS nur wirksam werden, wenn das Embed im Viewport ist und erst durch Drücken der Enter-Taste aktiviert wird. Zudem sollte die Markierung wieder entfernt werden, wenn das Embed den Viewport verlässt oder der Fokus per Tab auf das nächste Element wechselt. Diese Funktionalität konnte erfolgreich umgesetzt werden.
Ein Problem bleibt jedoch bestehen: Wenn sich ein Link oberhalb des Embeds befindet und dieser durch Enter fokussiert wurde, wird das Embed nach dem Drücken der Tab-Taste wie gewohnt fokussiert, während der Fokus vom Link entfernt wird. Das funktioniert soweit gut. Interessanterweise wird bei einem Embed ohne vorhergehenden Link oder Element im Viewport durch Drücken der Enter-Taste keine Markierung angezeigt, da sich das Embed nur durch die Tab-Taste fokussieren lässt.
Das folgende JavaScript integriert diese Funktionalität. Es stellt sicher, dass das CSS nur dann aktiv wird, wenn das Embed im Viewport ist und kein Link oder Element zuvor fokussiert wurde, Entwicklung:
/* --- Embed als gesamtens mit Enter markieren --- */
// Funktion, um das CSS für das spezifische Element hinzuzufügen
function addCustomCSS(embedElement) {
if (!embedElement.querySelector('.wp-embedded-content-css')) {
const style = document.createElement('style');
style.className = 'wp-embedded-content-css'; // Füge eine Klasse hinzu
style.type = 'text/css';
const css = `
.wp-embedded-content {
outline: 1px solid gray;
}
`;
style.appendChild(document.createTextNode(css));
embedElement.appendChild(style);
}
}
// Funktion, um das CSS von einem spezifischen Element zu entfernen
function removeCustomCSS(embedElement) {
const style = embedElement.querySelector('.wp-embedded-content-css');
if (style) {
style.remove(); // Entferne das CSS-Element
}
}
// Funktion zum Überprüfen, ob ein Embed im Viewport sichtbar ist
function getEmbedInViewport() {
const embeds = document.querySelectorAll('iframe, embed');
return Array.from(embeds).find(embed => isElementInViewport(embed));
}
// Funktion zum Überprüfen, ob ein Link vor einem Embed fokussiert wird
function getLinkBeforeEmbed() {
const links = document.querySelectorAll('#content a');
return Array.from(links).find(link => {
const linkRect = link.getBoundingClientRect();
const embed = getEmbedInViewport();
if (embed) {
const embedRect = embed.getBoundingClientRect();
return linkRect.bottom < embedRect.top && isElementInViewport(link);
}
return false;
});
}
// Überwachung der Enter-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
const activeElement = document.activeElement;
const embedElement = getEmbedInViewport();
const linkBeforeEmbed = getLinkBeforeEmbed();
if (linkBeforeEmbed && linkBeforeEmbed === activeElement) {
// Kein CSS anwenden, wenn der Link vor dem Embed fokussiert ist
return;
}
if (embedElement && isElementInViewport(embedElement)) {
event.preventDefault(); // Verhindere Standardverhalten für Enter
addCustomCSS(embedElement);
console.log('Custom CSS applied to the embed in the viewport.');
}
}
});
// Überwachung der Tab-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Tab') {
const embedElement = getEmbedInViewport();
const activeElement = document.activeElement;
if (embedElement && isElementInViewport(embedElement)) {
if (activeElement === embedElement) {
addCustomCSS(embedElement);
} else {
removeCustomCSS(embedElement);
}
}
}
});
// Überwachung des Scrollens, um das CSS zurückzusetzen, wenn das Embed den Viewport verlässt
window.addEventListener('scroll', function() {
const embeds = document.querySelectorAll('iframe, embed');
embeds.forEach(embed => {
if (!isElementInViewport(embed)) {
removeCustomCSS(embed); // Entferne das CSS von nicht sichtbaren Embeds
}
});
});
// Überwachung des Fokus-Wechsels (Tab- und Enter-Navigation)
document.addEventListener('focusin', function() {
const embedElement = getEmbedInViewport();
const activeElement = document.activeElement;
if (embedElement && isElementInViewport(embedElement)) {
if (activeElement === embedElement) {
addCustomCSS(embedElement);
} else {
removeCustomCSS(embedElement);
}
}
});
// Hilfsfunktion zum Überprüfen, ob ein Element im Viewport sichtbar ist
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.bottom > 0 &&
rect.top < window.innerHeight &&
rect.right > 0 &&
rect.left < window.innerWidth
);
}
/* - Ende Embed als gesamtes mit Enter markieren - */
Folgende beide Codes sind relativ ähnlich und erfüllen ihre Funktion. Es gibt jedoch einige Unterschiede, die die Stabilität und allgemeine Handhabung beeinflussen können. Ich werde die Vor- und Nachteile beider Ansätze zusammenfassen und eine Empfehlung aussprechen.
Erster Code
- Vorteile:
- Nutzt die Funktion
getLinkBeforeEmbed
, um sicherzustellen, dass ein vor dem Embed fokussierter Link erkannt wird, bevor das CSS angewendet wird. - Die Logik zur Überprüfung des Links vor dem Embed ist detailliert und spezifisch.
- Nutzt die Funktion
- Nachteile:
- Der Code ist etwas länger und komplexer durch die Verwendung der zusätzlichen
getLinkBeforeEmbed
-Funktion. - Da die Logik für das Entfernen des CSS auf dem
focusin
-Event basiert, könnte es in bestimmten Fällen zu Timing-Problemen kommen, wenn der Fokus schnell gewechselt wird.
- Der Code ist etwas länger und komplexer durch die Verwendung der zusätzlichen
Zweiter Code
- Vorteile:
- Der Code ist stabil und einfach zu warten.
- Die Verwendung des
focusout
-Events zum Entfernen des CSS ist robuster und stellt sicher, dass das CSS zuverlässig entfernt wird, wenn das Embed den Fokus verliert. - Die Funktion
isLinkBeforeEmbedInViewport
ist einfacher, was potenziell weniger Fehlerquellen bietet.
- Nachteile:
- Ein kleiner Nachteil könnte sein, dass das Entfernen des CSS nicht auf eine spezielle Bedingung wie im ersten Code basiert, sondern auf einem simpleren Ansatz. Das könnte unter bestimmten Bedingungen zu einem unerwarteten Verhalten führen.
Erster Code:
/* --- Embed als gesamtens mit Enter markieren, Optimierung 1 --- */
// Funktion, um das CSS für das spezifische Element hinzuzufügen
function addCustomCSS(embedElement) {
if (!embedElement.querySelector('.wp-embedded-content-css')) {
const style = document.createElement('style');
style.className = 'wp-embedded-content-css'; // Füge eine Klasse hinzu
style.type = 'text/css';
style.textContent = `
.wp-embedded-content {
outline: 1px solid gray;
}
`;
embedElement.appendChild(style);
}
}
// Funktion, um das CSS von einem spezifischen Element zu entfernen
function removeCustomCSS(embedElement) {
const style = embedElement.querySelector('.wp-embedded-content-css');
if (style) {
style.remove(); // Entferne das CSS-Element
}
}
// Funktion zum Überprüfen, ob ein Embed im Viewport sichtbar ist
function getEmbedInViewport() {
const embeds = document.querySelectorAll('iframe, embed');
return Array.from(embeds).find(isElementInViewport);
}
// Funktion zum Überprüfen, ob ein Link vor einem Embed fokussiert wird
function getLinkBeforeEmbed() {
const links = document.querySelectorAll('#content a');
const embed = getEmbedInViewport();
if (!embed) return null;
return Array.from(links).find(link => {
const linkRect = link.getBoundingClientRect();
const embedRect = embed.getBoundingClientRect();
return linkRect.bottom < embedRect.top && isElementInViewport(link);
});
}
// Überwachung der Enter-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
const activeElement = document.activeElement;
const embedElement = getEmbedInViewport();
const linkBeforeEmbed = getLinkBeforeEmbed();
if (linkBeforeEmbed && linkBeforeEmbed === activeElement) {
// Kein CSS anwenden, wenn der Link vor dem Embed fokussiert ist
return;
}
if (embedElement && isElementInViewport(embedElement)) {
event.preventDefault(); // Verhindere Standardverhalten für Enter
addCustomCSS(embedElement);
console.log('Custom CSS applied to the embed in the viewport.');
}
}
});
// Überwachung der Tab-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Tab') {
const embedElement = getEmbedInViewport();
const activeElement = document.activeElement;
if (embedElement && isElementInViewport(embedElement)) {
if (activeElement === embedElement) {
addCustomCSS(embedElement);
} else {
removeCustomCSS(embedElement);
}
}
}
});
// Überwachung des Scrollens, um das CSS zurückzusetzen, wenn das Embed den Viewport verlässt
window.addEventListener('scroll', function() {
const embeds = document.querySelectorAll('iframe, embed');
embeds.forEach(embed => {
if (!isElementInViewport(embed)) {
removeCustomCSS(embed); // Entferne das CSS von nicht sichtbaren Embeds
}
});
});
// Überwachung des Fokus-Wechsels (Tab- und Enter-Navigation)
document.addEventListener('focusin', function() {
const embedElement = getEmbedInViewport();
const activeElement = document.activeElement;
if (embedElement && isElementInViewport(embedElement)) {
if (activeElement === embedElement) {
addCustomCSS(embedElement);
} else {
removeCustomCSS(embedElement);
}
}
});
// Hilfsfunktion zum Überprüfen, ob ein Element im Viewport sichtbar ist
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.bottom > 0 &&
rect.top < window.innerHeight &&
rect.right > 0 &&
rect.left < window.innerWidth
);
}
/* - Ende Embed als gesamtens mit Enter markieren, Optimierung 1 - */
Zweiter Code:
/* --- Embed als gesamtens mit Enter markieren, Optimierung 2 --- */
// Funktion, um das CSS für das spezifische Element hinzuzufügen
function addCustomCSS(embedElement) {
if (!embedElement.querySelector('.wp-embedded-content-css')) {
const style = document.createElement('style');
style.className = 'wp-embedded-content-css';
style.type = 'text/css';
style.textContent = `
.wp-embedded-content {
outline: 1px solid gray;
}
`;
embedElement.appendChild(style);
}
}
// Funktion, um das CSS von einem spezifischen Element zu entfernen
function removeCustomCSS(embedElement) {
const style = embedElement.querySelector('.wp-embedded-content-css');
if (style) {
style.remove();
}
}
// Funktion zum Überprüfen, ob ein Embed im Viewport sichtbar ist
function getEmbedInViewport() {
const embeds = document.querySelectorAll('iframe, embed');
return Array.from(embeds).find(isElementInViewport);
}
// Funktion zum Überprüfen, ob vor dem Embed ein Link im Viewport sichtbar ist
function isLinkBeforeEmbedInViewport() {
const embed = getEmbedInViewport();
if (!embed) return false;
const links = document.querySelectorAll('#content a');
return Array.from(links).some(link => {
const linkRect = link.getBoundingClientRect();
const embedRect = embed.getBoundingClientRect();
return linkRect.bottom < embedRect.top && isElementInViewport(link);
});
}
// Überwachung der Enter-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
const embedElement = getEmbedInViewport();
if (embedElement && isElementInViewport(embedElement) && !isLinkBeforeEmbedInViewport()) {
event.preventDefault(); // Verhindere Standardverhalten für Enter
addCustomCSS(embedElement);
console.log('Custom CSS applied to the embed in the viewport.');
}
}
});
// Überwachung der Tab-Taste
document.addEventListener('keydown', function(event) {
if (event.key === 'Tab') {
const embedElement = getEmbedInViewport();
const activeElement = document.activeElement;
if (embedElement && isElementInViewport(embedElement)) {
if (activeElement === embedElement) {
addCustomCSS(embedElement);
} else {
removeCustomCSS(embedElement);
}
}
}
});
// Überwachung des Fokus-Wechsels (Tab- und Enter-Navigation)
document.addEventListener('focusin', function(event) {
const embedElement = getEmbedInViewport();
const activeElement = document.activeElement;
if (embedElement && isElementInViewport(embedElement)) {
if (activeElement === embedElement) {
addCustomCSS(embedElement);
} else {
removeCustomCSS(embedElement);
}
}
});
// Überwachung des Fokus-Verlassens (wenn Tab verwendet wird)
document.addEventListener('focusout', function(event) {
const embedElement = event.target;
if (embedElement && embedElement.tagName.toLowerCase() === 'iframe' || embedElement.tagName.toLowerCase() === 'embed') {
removeCustomCSS(embedElement);
}
});
// Überwachung des Scrollens, um das CSS zurückzusetzen, wenn das Embed den Viewport verlässt
window.addEventListener('scroll', function() {
const embeds = document.querySelectorAll('iframe, embed');
embeds.forEach(embed => {
if (!isElementInViewport(embed)) {
removeCustomCSS(embed); // Entferne das CSS von nicht sichtbaren Embeds
}
});
});
// Hilfsfunktion zum Überprüfen, ob ein Element im Viewport sichtbar ist
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.bottom > 0 &&
rect.top < window.innerHeight &&
rect.right > 0 &&
rect.left < window.innerWidth
);
}
/* - Ende Embed als gesamtens mit Enter markieren, Optimierung 2 - */
Empfehlung
ChatGPT empfahl den zweiten Code aufgrund seiner Einfachheit und der Nutzung von focusout
, um das CSS zu entfernen. Der Code ist stabiler, weil er den Fokusverlust effizienter überwacht und somit das Risiko von Timing-Problemen minimiert. Er ist zudem einfacher zu verstehen und zu warten, was in der Regel für langfristige Stabilität und Zuverlässigkeit von Vorteil ist.
Wenn in der Praxis feststellt wird, dass bestimmte Fälle nicht ausreichend abgedeckt sind, kann der zweite Code immer noch anpasst werden. In den meisten Anwendungsfällen sollte dieser jedoch zuverlässig funktionieren.
Testlink, der sich bei geschlossenem details
-Element oder einem Scrollbereich mit Inhalten im <pre>
-Tag nicht per 'Enter' fokussieren lässt: Scrolle zum Entwicklungsteil. Links weiter unterhalb sind nicht betroffen.
Zusatzinformationen
Ankerlinks sollten nicht im <a>-
Tag sein?
Update: durch die Änderung von #content a
zu #content a[href]
ist folgendes nicht mehr relevant:
Vermeidung unnötiger Fokussierung: Ankerlinks (die durch das <a>
-Tag definiert werden) können dazu führen, dass unerwünschte Fokussierung auf sie gesetzt wird, was oft zu einer leeren Fokussierung führt. Wenn die Fokussierung auf einem Ankerlink nicht erforderlich ist, sollte dieser nicht fokussierbar sein. Eine mögliche Lösung besteht darin, den Anker durch ein <div>
oder <span>
mit einer ID zu ersetzen, wenn keine Fokussierung gewünscht ist.
Hinweis: Ankerlinks, die von <a id="Anker"></a>
zu <span id="Anker"></span>
geändert wurden, sind im Editor visuell nicht mehr sichtbar gekennzeichnet.
Weitere Anpassungen
Im Zusammenhang mit der Tabnavigation gibt es hier der Website folgende Artikel:
Hauptartikel:
- Custom Inline Embeds – ideale Lösung für interne Inhalte
- SafariEmbedToBlockquote: WP-Embeds und Safari
Nebenartikel:
- Tastaturnavigation Night Eye Plug-in und das der Headerzeile
- Flexible Schrift mit Tipps zur Tastaturnavigation
- Tab-Menü: Tastaturnavigation
- WP-Polls und die Tastaturnavigation
- Tastatursteuerung für Abspiel-Buttons WP Featerlight
- Relevanssi-Live: Tastatursteuerung ohne Seitenscrollen in den Suchergebnissen.
Nachlese zur Barrierefreiheit
- Tastatur-Bedienung und Barrierefreiheit (netz-barrierefrei.de)
- WordPress für alle: Ein Leitfaden zur Barrierefreiheit (pachnerweb.at)
- Barrierefreie WordPress Webseiten erstellen (gehirngerecht.digita)
Plug-ins
Es gibt eine Vielzahl von Plug-ins, die bestimmte Funktionen zur Barrierefreiheit abdecken. Während sie für einfache und schnelle Implementierungen hilfreich sein können, können sie in speziellen Anwendungsfällen manchmal nicht die erwartete Flexibilität oder Leistung bieten. Auch wenn einige Plug-ins zusätzliche Features wie einen Dunkelmodus bereitstellen, entsprechen diese möglicherweise nicht immer den individuellen Vorstellungen oder Anforderungen.
Für Entwickler und Webseitenbetreiber, die eine besonders präzise Anpassung wünschen, ist es oft sinnvoll, eigene Lösungen zu implementieren. Dennoch bieten Plug-ins eine solide Basis, insbesondere für diejenigen, die auf eine schnelle Umsetzung und Standardfunktionen Wert legen.
Es ist folgend zu beobachten, dass die Teile des Details-Elements, welche innerhalb eines Pre-Tags, wenn sie eingeklappt sind, nicht fokussierbar sind. Daher ist bei der Integration darauf zu achten, wie diese Darstellungen umgesetzt werden. Das Beispiel: Die folgenden Elemente sind nicht mit der Enter-Taste fokussierbar, wenn das Details-Element eingeklappt ist – außer in Safari, wo die Fokussierung auch im eingeklappten Zustand funktioniert. Siehe oben: ↑ Warum tritt das Problem auf?
- Top 9 Plugins für optimale User Experience (freelancer-florian.de)
Anhang: Barrierefreiheit
Ein Tool zum Testen, das uns sehr ausführlich erscheint und eigentlich keine Wünsche offenlässt, ist https://wave.webaim.org/.
Auch wenn auf der Website nicht alles in Bezug auf die Kontrastprüfung perfekt ist, eignet sich das Tool hervorragend, um andere Ungereimtheiten leicht zu finden und zu beheben.
Hinweise zum <noscript>-Elements
Anmerkung zum Test und Hinweise zum <noscript>
-Elements in der Webseite, das im WAVE-Tool als Problem markiert wird. Hier eine kurze Erklärung:
Das <noscript>
-Element wird verwendet, um Inhalte für Benutzer bereitzustellen, die JavaScript in ihrem Browser deaktiviert haben. Es wird aber auch von Crawlern und Barrierefreiheits-Tools erkannt. Obwohl es kein direktes Barrierefreiheitsproblem darstellt, kann es von Prüftools als Hinweis darauf aufgenommen werden, dass der Inhalt möglicherweise anders gerendert wird, wenn JavaScript deaktiviert ist.
Warum wird es angezeigt?
Das <noscript>
-Element wird von Autoptimize eingefügt. Autoptimize ist ein beliebtes Plugin zur Optimierung von Websites, und es sorgt unter anderem dafür, dass Bilder und andere Medien lazy-loaded (also nur dann geladen) werden, wenn sie im sichtbaren Bereich erscheinen.
Dabei kann Autoptimize das <noscript>
-Element als Fallback verwenden, um sicherzustellen, dass Inhalte auch dann angezeigt werden, wenn JavaScript deaktiviert ist oder Lazy Loading aus irgendeinem Grund nicht funktioniert. Das <noscript>
-Element enthält dann meist das Bild oder den Inhalt in normaler Form, damit es auch ohne JavaScript geladen wird.
Und der https://validator.w3.org/ kann auch immer mal gut sein 😛
Der Beitrag wurde mit fachlicher Unterstützung erstellt.
Aktualisiert im Jahr 2024 September