Elementer bør ikke have et tabindex større end nul

Et tabindex større end nul tvinger et element frem forrest i tastaturrækkefølgen. Tastatur- og skærmlæserbrugere hopper så rundt på siden i en uventet rækkefølge, for eksempel fra headeren direkte til et felt til nyhedsbrevet, og kan fare vild på vejen til kurven eller kassen.

Regel-id
tabindex
Kilde
axe-core 4.13.0
Alvorlighed
Alvorlig
Rettelsesniveau
AUTO
på Shopify, Shopware, WooCommerce og Magento
Status
køres

Hvad kontrollen gør

Sørg for, at tabindex-værdier ikke er større end 0

Reglen tester hvert element med en tabindex-attribut, uanset elementtype, medmindre det er skjult for hjælpemidler. Den læser attributtens værdi, ikke DOM-egenskaben. axe-core fjerner blanktegn omkring værdien og tager det indledende hele tal med et eventuelt fortegn, så tabindex="2.5" tæller som 2 og tabindex="+1" som 1. En værdi uden et indledende tal består, og det gør 0 og negative værdier også.

axe-core mærker reglen som god praksis, og den er ikke knyttet til noget WCAG-succeskriterium. Validiscans scanner kører den som standard i et særskilt gennemløb for god praksis, der kun beholder fejlene. Fundet gemmes som god praksis og holdes ude af overensstemmelsestabellerne og tallet for fremskridt i udbedringen. En positiv tabindex på et synligt element, der kan få fokus, kan også blive rapporteret af vs-focus-order under succeskriterium 2.4.3.

Reglen vurderer ikke, om den tab-rækkefølge, der opstår, giver mening, eller om tabindex="0" og tabindex="-1" sidder på de rigtige elementer; det tjekker et menneske med tastaturet.

Sådan retter du det

Fjern positive tabindex-værdier, eller lav dem om til tabindex="0", og tilpas rækkefølgen i skabelonens kildekode, så den naturlige tab-rækkefølge følger det visuelle layout.

WCAG-succeskriterier

God praksis: ikke knyttet til et succeskriterium i WCAG.

Hvor en opskrift retter det

Shopify: opskrift remove-positive-tabindex

Vis før og efter (1)
Før og efter Eksempeldata

sections/header.liquid Ændringer i sections/header.liquid: 1 tilføjet, 1 fjernet

Ændringer i sections/header.liquid: 1 tilføjet, 1 fjernet
Linje før Linje efter Ændring Kode
37 37
38 38 <div class="header__search">
39 39 <form action="{{ routes.search_url }}" method="get" role="search" class="search">
40 Fjernet <input class="search__input field__input" type="search" name="q" value="" placeholder="{{ 'general.search.placeholder' | t }}" tabindex="1">
40 Tilføjet <input class="search__input field__input" type="search" name="q" value="" placeholder="{{ 'general.search.placeholder' | t }}">
41 41 <button type="submit" class="search__button">
42 42 {%- render 'icon', icon: 'search', size: 20 -%}
43 43 </button>

Shopware: opskrift remove-positive-tabindex

Vis før og efter (1)
removes tabindex="1" from the buy button; vs-focus-order and axe tabindex stop firing Eksempeldata

Resources/views/storefront/page/product-detail/buy-widget.html.twig Ændringer i Resources/views/storefront/page/product-detail/buy-widget.html.twig: 1 tilføjet, 1 fjernet

Ændringer i Resources/views/storefront/page/product-detail/buy-widget.html.twig: 1 tilføjet, 1 fjernet
Linje før Linje efter Ændring Kode
82 82 </div>
83 83 <div class="buy-widget-submit">
84 84 <button class="btn btn-primary btn-buy"
85 Fjernet title="{{ 'detail.addProduct'|trans }}" tabindex="1">
85 Tilføjet title="{{ 'detail.addProduct'|trans }}">
86 86 {{ 'detail.addProduct'|trans }}
87 87 </button>
88 88 </div>

WooCommerce: opskrift remove-positive-tabindex

Vis før og efter (1)
removes tabindex="1" from the header search field of the fixture theme Eksempeldata

header.php Ændringer i header.php: 1 tilføjet, 1 fjernet

Ændringer i header.php: 1 tilføjet, 1 fjernet
Linje før Linje efter Ændring Kode
49 49 <form role="search" method="get" class="woocommerce-product-search" action="<?php echo esc_url( home_url( '/search' ) ); ?>">
50 50 <label class="screen-reader-text" for="woocommerce-product-search-field-0"><?php esc_html_e( 'Search for:', 'woocommerce' ); ?></label>
51 51 <?php // VALIDISCAN-SEED vs-focus-order + tabindex: tabindex="1" "so the search is always the first stop". ?>
52 Fjernet <input type="search" id="woocommerce-product-search-field-0" class="search-field" placeholder="<?php echo esc_attr__( 'Search products&hellip;', 'woocommerce' ); ?>" value="<?php echo get_search_query(); ?>" name="s" tabindex="1">
52 Tilføjet <input type="search" id="woocommerce-product-search-field-0" class="search-field" placeholder="<?php echo esc_attr__( 'Search products&hellip;', 'woocommerce' ); ?>" value="<?php echo get_search_query(); ?>" name="s">
53 53 <?php // VALIDISCAN-SEED button-name: icon-only submit button without text. ?>
54 54 <button type="submit" value="<?php echo esc_attr_x( 'Search', 'submit button', 'woocommerce' ); ?>" class="kb-search-submit"><?php kb_icon( 'search' ); ?></button>
55 55 <input type="hidden" name="post_type" value="product">

Magento: opskrift remove-positive-tabindex

Vis før og efter (1)
removes tabindex 1-4 from the login form and the CAPTCHA and validates Eksempeldata

app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/captcha-math.phtml Ændringer i app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/captcha-math.phtml: 1 tilføjet, 1 fjernet

Ændringer i app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/captcha-math.phtml: 1 tilføjet, 1 fjernet
Linje før Linje efter Ændring Kode
14 14 <div class="field captcha required" role="group" aria-labelledby="captcha-question" data-captcha-type="math">
15 15 <label for="captcha_user_login" class="label" id="captcha-question"><span><?= $escaper->escapeHtml(__('Security question: what is %1 + %2?', $a, $b)) ?></span></label>
16 16 <div class="control captcha">
17 Fjernet <input name="captcha[user_login]" type="text" class="input-text required-entry" id="captcha_user_login" autocomplete="off" inputmode="numeric" tabindex="3" data-captcha-answer-hash="<?= $escaper->escapeHtmlAttr(md5((string) ($a + $b))) ?>">
17 Tilføjet <input name="captcha[user_login]" type="text" class="input-text required-entry" id="captcha_user_login" autocomplete="off" inputmode="numeric" data-captcha-answer-hash="<?= $escaper->escapeHtmlAttr(md5((string) ($a + $b))) ?>">
18 18 </div>
19 19 </div>

app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/login.phtml Ændringer i app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/login.phtml: 3 tilføjet, 3 fjernet

Ændringer i app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/login.phtml: 3 tilføjet, 3 fjernet
Linje før Linje efter Ændring Kode
27 27 <div class="field email required">
28 28 <label class="label" for="email"><span><?= $escaper->escapeHtml(__('Email')) ?></span></label>
29 29 <div class="control">
30 Fjernet <input name="login[username]" value="<?= $escaper->escapeHtmlAttr($username) ?>" autocomplete="off" id="email" type="email" class="input-text mage-error" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" aria-invalid="true" tabindex="1" onpaste="return false;" data-mage-init='{"mage/trim-input":{}}'>
30 Tilføjet <input name="login[username]" value="<?= $escaper->escapeHtmlAttr($username) ?>" autocomplete="off" id="email" type="email" class="input-text mage-error" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" aria-invalid="true" onpaste="return false;" data-mage-init='{"mage/trim-input":{}}'>
31 31 <div for="email" generated="true" class="mage-error" id="email-error"><?= $escaper->escapeHtml(__('Please enter a valid email address (Ex: johndoe@domain.com).')) ?></div>
32 32 </div>
33 33 </div>
35 35 <div class="field password required">
36 36 <label for="pass" class="label"><span><?= $escaper->escapeHtml(__('Password')) ?></span></label>
37 37 <div class="control">
38 Fjernet <input name="login[password]" type="password" autocomplete="off" class="input-text" id="pass" title="<?= $escaper->escapeHtmlAttr(__('Password')) ?>" tabindex="2" onpaste="return false;" oncopy="return false;">
38 Tilføjet <input name="login[password]" type="password" autocomplete="off" class="input-text" id="pass" title="<?= $escaper->escapeHtmlAttr(__('Password')) ?>" onpaste="return false;" oncopy="return false;">
39 39 </div>
40 40 </div>
41 41 <!-- VALIDISCAN-SEEDED vs-accessible-auth: arithmetic CAPTCHA with no alternative -->
42 42 <?= $block->getChildHtml('form_additional_info') /* math CAPTCHA module: div.field.captcha, input#captcha_user_login tabindex="3" */ ?>
43 43 <div class="actions-toolbar">
44 Fjernet <div class="primary"><button type="submit" class="action login primary" name="send" id="send2" tabindex="4"><span><?= $escaper->escapeHtml(__('Sign In')) ?></span></button></div>
44 Tilføjet <div class="primary"><button type="submit" class="action login primary" name="send" id="send2"><span><?= $escaper->escapeHtml(__('Sign In')) ?></span></button></div>
45 45 <div class="secondary"><a class="action remind" href="<?= $escaper->escapeUrl($block->getUrl('contact')) ?>"><span><?= $escaper->escapeHtml(__('Forgot Your Password? Contact us')) ?></span></a></div>
46 46 </div>
47 47 </fieldset>

Begynd med et gratis tjek af din webshop.

Send din webshops adresse. Validiscan scanner den og svarer med hver fejl, scanningen kan påvise, med siden og koden.

Bestil et gratis tjek

Eller skriv til info@validiscan.com.

Hvad det gratis tjek omfatter, og hvad det udelader
Du sender
din webshops adresse
Sider, der scannes
op til 15
Du får
hver fejl, scanningen kan påvise, med siden og koden
På din webshop
kun offentlige sider; intet login, intet købt, ingen formularer sendt
Hvad det ikke er
et fuldt audit

Skriv til Validiscan

Til et gratis tjek skal du skrive din webshops adresse og platform.

Validiscan bruger det, du sender, til at svare dig. Privatlivspolitik