Registernavigation für das Web veröffentlicht in 2015
Tabpanel mit FIELDSET
und LEGEND
Links
Sie können das Beispiel mit der Linkliste als .zip herunterladen. Erläuterungen zu barrierefreien Registernavigationen finden Sie im einleitenden Beitrag: Registernavigation für das Web.
Weitere Beispiele mit einem alternativen Aufbau im HTML stehen zur Verfügung:
Einschränkungen bei der Tastaturbedienung
Innerhalb von Registerseiten gibt es folgende Einschränkungen für die Tastaturbedienung:
- Die Tastenkombinationen funktionieren nur dann, wenn ein Inhalt der Registerseite fokussiert ist.
- In Screenreadern sind die empfohlenen Tastenkombinationen teilweise bereits belegt und müssen deshalb mit der dafür vorgesehenen Tastenbefehl an den Browser durchgereicht werden. Der Sprung zum aktivierten Reiter wurde per
accesskey="5"
berücksichtigt. - Die Tastenkombinationen sind zwar vom W3C empfohlen, aber es kann Konflikte mit einzelnen Browsern geben (z.B. wird in Firefox mit Strg+SeiteAuf der Browser-Tab gewechselt).
Hinweise zum CSS
Zwei Angaben im CSS dürfen nicht vernachlässigt werden:
- Der Tastaturfokus muss sichtbar sein, was auch für den Kontrastmodus gilt. Für den Kontrastmodus wurde ein
border-bottom
für die Visualisierung in der Reiterleiste gewählt. - Es gibt eine CSS-Eigenschaft, die in jedem Fall übernommen werden sollte:
.registerseite[aria-hidden=true] {display:none;}
.
Feinheiten mit ARIA
Einzelne Reiter sollten mit ihren zugehörigen Registerseiten verknüpft werden. Die ARIA-Spezifikation gibt 2 alternative Möglichkeiten vor, die beide berücksichtigt wurden:
- Wenn ein Reiter ein
aria-controls
-Attribut mit dem ID-Wert der zugehörigen Registerseite erhält, sollten Screenreadernutzer erfahren, mit welcher Tastenkombination sie direkt zur zugehörigen Registerseite wechseln können. Eine nennenswerte Unterstützung dieses Attributs kann derzeit allerdings nicht festgestellt werden. Das JavaScript für dieses Widget verwendet jedoch dieses Attribut; deswegen darf es nicht entfernt werden. - Die Registerseite sollte mit dem
aria-labelledby
-Attribut beschriftet werden. Die Beschriftung referenziert dabei den zugehörigen Reiter.
HTML
<div class="register">
<div class="registerleiste">
</div>
<fieldset id="id1" class="registerseite">
<legend id="beschriftung-id1" class="reiter">Beschriftung 1</legend>
<p>Inhalt für Registerseite 1.</p>
</fieldset>
<fieldset id="id2" class="registerseite">
<legend id="beschriftung-id2" class="reiter">Beschriftung 2</legend>
<p>Inhalt für Registerseite 2.</p>
</fieldset>
<fieldset id="id3" class="registerseite">
<legend id="beschriftung-id3" class="reiter">Beschriftung 3</legend>
<p>Inhalt für Registerseite 3.</p>
</fieldset>
</div>
JavaScript (jQuery)
function tabpanelInitialisieren( containerClass, tablistClass, tabClass, tabpanelClass, tabpanelLabelPrefix ) {
tabNavigationErstellen( containerClass, tablistClass, tabClass, tabpanelClass, tabpanelLabelPrefix );
$( '.' + tablistClass ) .children( '[role="tab"]' ) .each( function() {
var reiterID = $( this ) .attr( 'id' );
reiterEvents( reiterID );
registerseiteEvents( reiterID, tabpanelLabelPrefix );
});
var hash = window.location.hash;
if ( $( hash ) .is( $( '.' + tabClass ) ) ) {
reiterAktualisierung( hash .replace('#', '') );
}
else {
reiterAktualisierung( $( '.' + tablistClass ) .children( '[role="tab"]' ) .first() .attr( 'id' ) );
}
}
function tabNavigationErstellen( containerClass, tablistClass, tabClass, tabpanelClass, tabpanelLabelPrefix ) {
$( '.' + containerClass ) .each( function() {
$( this ) .prepend( ' <div class="' + tablistClass + '" role="tablist"></div>' );
var $registerleiste = $( this ) .children( '.' + tablistClass ), $registerseiten = $( this ) .children( '.' + tabpanelClass );
$registerseiten .each( function() {
var $seite = $( this ), reiterID = tabpanelLabelPrefix + $seite .attr( 'id' );
$seite .attr({
'role': 'tabpanel',
'aria-labelledby': reiterID
})
.children( '.' + tabClass ) .appendTo( $registerleiste );
});
$registerleiste .attr( 'role', 'tablist' )
.children( '.' + tabClass ) .each( function() {
var $reiter = $( this ), reiterID = $reiter .attr( 'id' ), seitenID = reiterID .replace( tabpanelLabelPrefix, '' );
$reiter .attr({
'role': 'tab',
'aria-controls': seitenID
})
});
})
}
function reiterAktualisierung( reiterID ) {
var $reiter = $( '#' + reiterID ), $alleReiter = $reiter .closest( '[role="tablist"]' ) .children( '[role="tab"]' );
$alleReiter .attr({
'aria-selected': 'false',
'tabindex': -1
})
.removeAttr( 'accesskey' );
$reiter .attr({
'aria-selected': 'true',
'tabindex': 0,
'accesskey': 5
});
$alleReiter .each(function() {
var seitenID = $( this ) .attr( 'aria-controls' );
if ( $( this ) .attr( 'aria-selected' ) == 'true' ) {
$( '#' + seitenID ) .attr( 'aria-hidden', 'false' );
}
else {
$( '#' + seitenID ) .attr( 'aria-hidden', 'true' );
}
})
}
function reiterEvents( reiterID ) {
$( '#' + reiterID ) .click( function( event ) {
reiterAktualisierung( reiterID );
})
.keydown( function( event ) {
var rueckgabe = true, $aktuellerReiter = $( '#' + reiterID ), $alleReiter = $aktuellerReiter .closest( '[role="tablist"]' ) .children( '[role="tab"]' );
if (event.keyCode == 13 || event.keyCode == 32 ) {
$aktuellerReiter .click() .focus();
rueckgabe = false;
}
else if ( event.keyCode == 35 ) {
$alleReiter .last() .focus();
rueckgabe = false;
}
else if ( event.keyCode == 36 ) {
$alleReiter .first() .focus();
rueckgabe = false;
}
else if (event.keyCode == 37 || event.keyCode == 38 ) {
if ( $aktuellerReiter .is ( $alleReiter .first() ) ) {
$alleReiter .last() .focus();
}
else {
$aktuellerReiter .prev() .focus();
}
rueckgabe = false;
}
else if (event.keyCode == 39 || event.keyCode == 40 ) {
if ( $aktuellerReiter .is ( $alleReiter .last() ) ) {
$alleReiter .first() .focus();
}
else {
$aktuellerReiter .next() .focus();
}
rueckgabe = false;
}
return rueckgabe;
})
}
function registerseiteEvents( reiterID, tabpanelLabelPrefix ) {
var registerseiteID = reiterID .replace( tabpanelLabelPrefix, '' ), $registerseite = $( '#' + registerseiteID ), $aktuellerReiter = $( '#' + reiterID ), $alleReiter = $aktuellerReiter .closest( '[role="tablist"]' ) .children( '[role="tab"]' );
$registerseite .keydown( function( event ) {
if ((event.ctrlKey) && ((event.keyCode == 37 || event.keyCode == 38))) {
event .preventDefault();
event .stopPropagation();
alert('tada');
$aktuellerReiter .focus();
}
else if (event.ctrlKey && event.keyCode == 33) {
event .preventDefault();
if ( $aktuellerReiter .is( $alleReiter .first() ) ) {
$alleReiter .last() .click() .focus();
}
else {
$aktuellerReiter .prev() .click() .focus();
}
}
else if (event.ctrlKey && event.keyCode == 34) {
event .preventDefault();
if ( $aktuellerReiter .is( $alleReiter .last() ) ) {
$alleReiter .first() .click() .focus();
}
else {
$aktuellerReiter .next() .click() .focus();
}
}
})
}
tabpanelInitialisieren( 'register', 'registerleiste', 'reiter', 'registerseite', 'beschriftung-' );
CSS
.register {
width: 100%;
background: #fff;
}
.register [role=tablist] {
display: block;
width: 100%;
}
.register [role=tab] {
border-color: #6fbed6;
border-style: solid;
border-width: 1px 1px 0;
border-top-right-radius: 3px;
border-top-left-radius: 3px;
margin-right: .4em;
display:block;
float:left;
width:30%;
color: #fff;
background: #005f87;
text-align:center;
cursor: pointer;
padding: 10px 2px;
font-weight: bold;
font-size: .9em;
}
.register [role=tab]:focus {
outline: 2px dotted #000;
}
.register [role=tab]:hover,
.register [role=tab]:focus {
padding-bottom: 8px;
border-bottom: 2px dotted #005f87;
}
.register [role=tab][aria-selected=true] {
background: #ddf0fa;
color:#000;
cursor: default;
padding-bottom: 7px;
border-bottom: 3px solid #ddf0fa;
font-size: 1em;
}
.register [role=tab][aria-selected=true]:hover {
text-decoration:none;
}
.register [role=tabpanel] {
clear:left;
padding: 0;
border-top-right-radius: 3px;
border-width: 0 1px 1px;
border-color: #005f87;
background: #ddf0fa;
color: #000;
}
.register [role=tabpanel][aria-hidden=true] {
display: none;
}
.registerseite .anweisung {
display:block;
font-size:.9em;
}
Der Beitrag Registernavigation für das Web besteht aus folgenden einzelnen Webseiten:
- Klassischer Tabpanel mit einer Linkliste
Demo eines klassischen Tabpanels mit Beschreibung der Anforderungen der Barrierefreiheit.
- Tabpanel mit
FIELDSET
undLEGEND
(Aktuelle Seite)
- Tabpanel mit einer Definitionsliste
Demo eines vertikal angeordneten Tabpanels mit barrierefreier Bedienung.