Fokusrækkefølgen skal følge den visuelle rækkefølge

Når Tab-tasten springer fra headeren til footeren og tilbage til et produkt, mister kunder, der bruger tastatur eller skærmlæser, orienteringen, overser valgmuligheder og har svært ved at udfylde formularer i den rigtige rækkefølge.

Regel-id
vs-focus-order
Kilde
Validiscan-kontrol
Alvorlighed
Moderat
Rettelsesniveau
MANUAL
på Shopify, Shopware, WooCommerce og Magento
Status
køres

Hvad kontrollen gør

Sammenligner Tab-rækkefølgen med det visuelle layout og markerer spring, hvor fokus bevæger sig i en rækkefølge, der ikke passer til skærmen, for eksempel på grund af positive tabindex-værdier eller indhold, der er flyttet med CSS (2.4.3).

Kontrollen samler op til 300 synlige elementer, der kan nås med tastaturet, og deres placering på siden. Den udleder tab-rækkefølgen ud fra opmærkningen i stedet for at trykke på Tab: først positive tabindex-værdier i stigende orden, derefter dokumentrækkefølgen. Den kører i hver scannet viewport, som standard 1440 og 390 px i bredden.

Hvert element med et positivt tabindex er et fund. For trin mellem elementer uden et sådant sammenligner kontrollen hvert element med det foregående i tab-rækkefølgen. Ligger dets underkant mere end 100 px over det foregående elements overkant, springer fokus tilbage op ad siden, og trinnet får resultatet »kræver gennemgang«, højst 25 pr. side. CSS, der ændrer rækkefølgen af indhold, for eksempel order i flexbox, placering i et grid eller absolut positionering, kan give et sådant spring, og et menneske må afgøre, om rækkefølgen stadig giver mening. Scanneren laver i dag ingen fund af resultater, der kræver gennemgang, så kun positive tabindex-værdier giver fund. Spring sidelæns eller ned ad siden måles ikke.

Sådan retter du det

Få rækkefølgen i skabelonernes kildekode til at svare til den visuelle rækkefølge, fjern positive tabindex-værdier, og undgå at ændre rækkefølgen af indhold med CSS order, flex-direction eller absolut positionering, hvor det ændrer læse- og tab-rækkefølgen.

WCAG-succeskriterier

Afsnit i EN 301 549

Afsnittet i EN 301 549 for hvert kriterium, fordelt på versioner af standarden
WCAG-kriterium Version 3.2.1 Version 4.1.1
2.4.3 9.2.4.3 9.2.4.3

Opskrifter, der angiver denne regel

Reglen har niveau MANUAL. I et projekt følger et fund af reglen MANUAL-forløbet, og disse opskrifter anvendes ikke på 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