Buttons must have discernible text
Buttons without a name are announced only as "button" by screen readers. Blind customers cannot tell which button adds to cart, opens the menu, closes a pop-up or goes to checkout, so they may be unable to complete a purchase.
- Rule id
- button-name
- Source
- axe-core 4.13.0
- Impact
- Critical
- Fix tier
- ASSISTED
- on Shopify, Shopware, WooCommerce and Magento
- Status
- runs
What the check does
Ensure buttons have discernible text
The rule looks only at real <button> elements; role="button" controls and <input> buttons have their own rules, aria-command-name and input-button-name. A <button> is left out when it is hidden from assistive technology, or when an explicit role other than none or presentation swaps its button role for one that needs no name and the element cannot take focus.
A button passes when it has one of seven things: the text content, aria-label, aria-labelledby, title, a wrapping <label>, a <label for> matching its id, or a presentational role. A value of only whitespace counts as missing. Text content leaves out children hidden from screen readers, so an icon-only cart or close button whose icon is marked aria-hidden="true" needs one of the other sources. Visually hidden text, for example clipped, still counts. role="none" does not rescue an enabled button: axe-core ignores a presentational role on focusable elements.
Only the presence of a name is tested. A button named “x” passes; the rule does not judge whether the name says what the button does.
How to fix it
Give every button an accessible name: visible text, aria-labelledby or aria-label. Icon-only buttons (cart, search, close, quantity plus and minus) need a label that describes the action, such as aria-label="Close" or visually hidden text.
WCAG success criteria
- 4.1.2 Name, Role, Value, level A
EN 301 549 clauses
| WCAG criterion | Version 3.2.1 | Version 4.1.1 |
|---|---|---|
| 4.1.2 | 9.4.1.2 | 9.4.1.2 |
Recipes that list this rule
This rule has the tier ASSISTED. In a project, a finding of it takes the ASSISTED way, and these recipes are not applied to it.
Shopify: recipe icon-accessible-name
Show the before and after (2)
locales/en.default.json Changes to locales/en.default.json: 3 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 34 | 34 | "total_reviews": "{{ count }} reviews", | |
| 35 | 35 | "link_messages": { | |
| 36 | 36 | "new_window": "Opens in a new window." | |
| 37 | Removed | } | |
| 37 | Added | }, | |
| 38 | Added | "accept_cookies": "Accept cookies", | |
| 39 | Added | "reject_cookies": "Reject cookies" | |
| 38 | 40 | }, | |
| 39 | 41 | "sections": { | |
| 40 | 42 | "header": { |
sections/header.liquid Changes to sections/header.liquid: 1 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 40 | 40 | <input class="search__input field__input" type="search" name="q" value="" placeholder="{{ 'general.search.placeholder' | t }}" tabindex="1"> | |
| 41 | 41 | <button type="submit" class="search__button"> | |
| 42 | 42 | {%- render 'icon', icon: 'search', size: 20 -%} | |
| 43 | Added | <span class="visually-hidden">{{ 'general.search.search' | t }}</span> | |
| 43 | 44 | </button> | |
| 44 | 45 | </form> | |
| 45 | 46 | </div> |
sections/main-product.liquid Changes to sections/main-product.liquid: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 88 | 88 | <p class="form__label">{{ option.name | escape }}</p> | |
| 89 | 89 | <div class="swatch-list swatch-list--compact"> | |
| 90 | 90 | {%- for swatch in option.swatches %} | |
| 91 | Removed | <button type="button" class="swatch swatch--button{% if swatch.selected %} swatch--active{% endif %}" style="--swatch-color: {{ swatch.color }};" data-option-index="{{ option_index }}" data-value="{{ swatch.value | escape }}"></button> | |
| 91 | Added | <button type="button" class="swatch swatch--button{% if swatch.selected %} swatch--active{% endif %}" style="--swatch-color: {{ swatch.color }};" data-option-index="{{ option_index }}" data-value="{{ swatch.value | escape }}"><span class="visually-hidden">{{ swatch.value | escape }}</span></button> | |
| 92 | 92 | {%- endfor %} | |
| 93 | 93 | </div> | |
| 94 | 94 | </div> |
sections/slideshow.liquid Changes to sections/slideshow.liquid: 2 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 59 | 59 | <div class="slideshow__controls"> | |
| 60 | 60 | <button type="button" class="slider-button slider-button--prev" name="previous" data-slide-prev> | |
| 61 | 61 | {%- render 'icon', icon: 'chevron-left', size: 20 -%} | |
| 62 | Added | <span class="visually-hidden">{{ 'accessibility.previous_slide' | t }}</span> | |
| 62 | 63 | </button> | |
| 63 | 64 | <div class="slider-counter"> | |
| 64 | 65 | {%- for block in section.blocks %} | |
| 67 | 68 | </div> | |
| 68 | 69 | <button type="button" class="slider-button slider-button--next" name="next" data-slide-next> | |
| 69 | 70 | {%- render 'icon', icon: 'chevron-right', size: 20 -%} | |
| 71 | Added | <span class="visually-hidden">{{ 'accessibility.next_slide' | t }}</span> | |
| 70 | 72 | </button> | |
| 71 | 73 | </div> | |
| 72 | 74 | </slideshow-component> |
snippets/cookie-banner.liquid Changes to snippets/cookie-banner.liquid: 2 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 23 | 23 | <div class="cookie-banner__actions"> | |
| 24 | 24 | <button type="button" class="cookie-banner__icon-button cookie-banner__icon-button--accept" data-cookie-accept> | |
| 25 | 25 | {%- render 'icon', icon: 'check', size: 20 -%} | |
| 26 | Added | <span class="visually-hidden">{{ 'accessibility.accept_cookies' | t }}</span> | |
| 26 | 27 | </button> | |
| 27 | 28 | <button type="button" class="cookie-banner__icon-button" data-cookie-reject> | |
| 28 | 29 | {%- render 'icon', icon: 'close', size: 20 -%} | |
| 30 | Added | <span class="visually-hidden">{{ 'accessibility.reject_cookies' | t }}</span> | |
| 29 | 31 | </button> | |
| 30 | 32 | </div> | |
| 31 | 33 | </div> |
snippets/quantity-input.liquid Changes to snippets/quantity-input.liquid: 2 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 9 | 9 | {%- endcomment -%} | |
| 10 | 10 | <div class="quantity quantity--compact" data-quantity{% if line %} data-line="{{ line }}"{% endif %}><button class="quantity__button" name="minus" type="button" data-quantity-minus> | |
| 11 | 11 | {%- render 'icon', icon: 'minus', size: 12 -%} | |
| 12 | Added | <span class="visually-hidden">{{ 'products.product.quantity.decrease' | t: product: product_title }}</span> | |
| 12 | 13 | </button> | |
| 13 | 14 | <input class="quantity__input" type="number" name="{{ input_name }}" id="{{ input_id }}" value="{{ value | default: 1 }}" min="{% if line %}0{% else %}1{% endif %}" data-quantity-input> | |
| 14 | 15 | <button class="quantity__button" name="plus" type="button" data-quantity-plus> | |
| 15 | 16 | {%- render 'icon', icon: 'plus', size: 12 -%} | |
| 17 | Added | <span class="visually-hidden">{{ 'products.product.quantity.increase' | t: product: product_title }}</span> | |
| 16 | 18 | </button></div> |
sections/footer.liquid Changes to sections/footer.liquid: 1 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 37 | 37 | {%- for social in shop.social %} | |
| 38 | 38 | <a href="{{ social.url }}" class="list-social__link link"> | |
| 39 | 39 | {%- render 'icon', icon: social.icon, size: 20 -%} | |
| 40 | Added | <span class="visually-hidden">{{ 'general.social.links.' | append: social.icon | t }}</span> | |
| 40 | 41 | </a> | |
| 41 | 42 | {%- endfor %} | |
| 42 | 43 | </ul> |
sections/header.liquid Changes to sections/header.liquid: 3 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 22 | 22 | </details> | |
| 23 | 23 | ||
| 24 | 24 | {% if logo_is_heading %}<h1 class="header__heading">{% else %}<div class="header__heading">{% endif %} | |
| 25 | Removed | <a href="{{ routes.root_url }}" class="header__heading-link"><img src="{{ 'logo.svg' | asset_url }}" width="{{ settings.logo_width }}" height="32" class="header__heading-logo"></a> | |
| 25 | Added | <a href="{{ routes.root_url }}" class="header__heading-link"><img src="{{ 'logo.svg' | asset_url }}" width="{{ settings.logo_width }}" height="32" class="header__heading-logo" alt="{{ shop.name | escape }}"></a> | |
| 26 | 26 | {% if logo_is_heading %}</h1>{% else %}</div>{% endif %} | |
| 27 | 27 | ||
| 28 | 28 | <nav class="header__inline-menu"> | |
| 50 | 50 | {%- endif %} | |
| 51 | 51 | <a href="{{ routes.account_login_url }}" class="header__icon header__icon--account link"> | |
| 52 | 52 | {%- render 'icon', icon: 'account', size: icon_size -%} | |
| 53 | Added | <span class="visually-hidden">{{ 'sections.header.account' | t }}</span> | |
| 53 | 54 | </a> | |
| 54 | 55 | <a href="{{ routes.cart_url }}" class="header__icon header__icon--cart link" id="cart-icon-bubble"> | |
| 55 | 56 | {%- render 'icon', icon: 'cart', size: icon_size -%} | |
| 57 | 58 | <span class="cart-count-bubble" aria-hidden="true"><span data-cart-count>{{ cart.item_count }}</span></span> | |
| 58 | 59 | {%- endif -%} | |
| 59 | 60 | ||
| 61 | Added | <span class="visually-hidden">{{ 'sections.header.cart' | t }}</span> | |
| 60 | 62 | </a> | |
| 61 | 63 | </div> | |
| 62 | 64 | </header> |
sections/main-cart.liquid Changes to sections/main-cart.liquid: 1 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 26 | 26 | {% render 'quantity-input', input_id: qty_id, input_name: 'updates[]', value: item.quantity, product_title: item.product.title, line: line %} | |
| 27 | 27 | <a href="{{ routes.cart_change_url }}?line={{ line }}&quantity=0" class="cart-item__remove cart-item__remove--compact" data-cart-remove> | |
| 28 | 28 | {%- render 'icon', icon: 'trash', size: 16 -%} | |
| 29 | Added | <span class="visually-hidden">{{ 'sections.cart.remove' | t: title: item.product.title }}</span> | |
| 29 | 30 | </a> | |
| 30 | 31 | </div> | |
| 31 | 32 | <div class="cart-item__totals"> |
Shopware: recipe icon-accessible-name
Show the before and after (2)
Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Changes to Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 12 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 193 | 193 | "notFoundText": "Die gesuchte Seite existiert nicht oder wurde verschoben.", | |
| 194 | 194 | "backToHome": "Zurück zur Startseite", | |
| 195 | 195 | "searchInstead": "Unsere Kaffees durchsuchen" | |
| 196 | Added | }, | |
| 197 | Added | "a11y": { | |
| 198 | Added | "control": { | |
| 199 | Added | "search": "Suchen", | |
| 200 | Added | "previousSlide": "Vorherige Folie", | |
| 201 | Added | "nextSlide": "Nächste Folie", | |
| 202 | Added | "cookieSettings": "Cookie-Einstellungen", | |
| 203 | Added | "acceptCookies": "Alle Cookies akzeptieren", | |
| 204 | Added | "decreaseQuantity": "Menge verringern", | |
| 205 | Added | "increaseQuantity": "Menge erhöhen", | |
| 206 | Added | "removeFromCart": "Aus dem Warenkorb entfernen" | |
| 207 | Added | } | |
| 196 | 208 | } | |
| 197 | 209 | } |
Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Changes to Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 12 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 193 | 193 | "notFoundText": "The page you are looking for does not exist or has moved.", | |
| 194 | 194 | "backToHome": "Back to the homepage", | |
| 195 | 195 | "searchInstead": "Search our coffees" | |
| 196 | Added | }, | |
| 197 | Added | "a11y": { | |
| 198 | Added | "control": { | |
| 199 | Added | "search": "Search", | |
| 200 | Added | "previousSlide": "Previous slide", | |
| 201 | Added | "nextSlide": "Next slide", | |
| 202 | Added | "cookieSettings": "Cookie settings", | |
| 203 | Added | "acceptCookies": "Accept all cookies", | |
| 204 | Added | "decreaseQuantity": "Decrease quantity", | |
| 205 | Added | "increaseQuantity": "Increase quantity", | |
| 206 | Added | "removeFromCart": "Remove from cart" | |
| 207 | Added | } | |
| 196 | 208 | } | |
| 197 | 209 | } |
Resources/views/storefront/element/cms-element-image-gallery.html.twig Changes to Resources/views/storefront/element/cms-element-image-gallery.html.twig: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 31 | 31 | ||
| 32 | 32 | {% if media|length > 1 %} | |
| 33 | 33 | <div class="gallery-slider-controls"> | |
| 34 | Removed | <button type="button" class="base-slider-controls-prev gallery-slider-controls-prev" data-gallery-prev> | |
| 34 | Added | <button type="button" class="base-slider-controls-prev gallery-slider-controls-prev" data-gallery-prev aria-label="{{ 'a11y.control.previousSlide'|trans|striptags }}"> | |
| 35 | 35 | {% sw_icon 'arrow-head-left' %} | |
| 36 | 36 | </button> | |
| 37 | Removed | <button type="button" class="base-slider-controls-next gallery-slider-controls-next" data-gallery-next> | |
| 37 | Added | <button type="button" class="base-slider-controls-next gallery-slider-controls-next" data-gallery-next aria-label="{{ 'a11y.control.nextSlide'|trans|striptags }}"> | |
| 38 | 38 | {% sw_icon 'arrow-head-right' %} | |
| 39 | 39 | </button> | |
| 40 | 40 | </div> |
Resources/views/storefront/element/cms-element-image-slider.html.twig Changes to Resources/views/storefront/element/cms-element-image-slider.html.twig: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 46 | 46 | ||
| 47 | 47 | {% block element_image_slider_controls %} | |
| 48 | 48 | <div class="image-slider-controls-container"> | |
| 49 | Removed | <button type="button" class="base-slider-controls-prev image-slider-controls-btn" data-slide-prev> | |
| 49 | Added | <button type="button" class="base-slider-controls-prev image-slider-controls-btn" data-slide-prev aria-label="{{ 'a11y.control.previousSlide'|trans|striptags }}"> | |
| 50 | 50 | {% sw_icon 'arrow-head-left' %} | |
| 51 | 51 | </button> | |
| 52 | 52 | <ol class="base-slider-dots"> | |
| 54 | 54 | <li class="base-slider-dot{% if loop.first %} is-active{% endif %}" data-slide-to="{{ loop.index0 }}"></li> | |
| 55 | 55 | {% endfor %} | |
| 56 | 56 | </ol> | |
| 57 | Removed | <button type="button" class="base-slider-controls-next image-slider-controls-btn" data-slide-next> | |
| 57 | Added | <button type="button" class="base-slider-controls-next image-slider-controls-btn" data-slide-next aria-label="{{ 'a11y.control.nextSlide'|trans|striptags }}"> | |
| 58 | 58 | {% sw_icon 'arrow-head-right' %} | |
| 59 | 59 | </button> | |
| 60 | 60 | </div> |
Resources/views/storefront/layout/cookie/cookie-permission.html.twig Changes to Resources/views/storefront/layout/cookie/cookie-permission.html.twig: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 22 | 22 | </p> | |
| 23 | 23 | </div> | |
| 24 | 24 | <div class="col-auto cookie-permission-actions"> | |
| 25 | Removed | <button type="button" class="btn cookie-permission-icon-btn js-cookie-configuration-toggle">{% sw_icon 'settings' %}</button> | |
| 26 | Removed | <button type="button" class="btn btn-primary cookie-permission-icon-btn js-cookie-accept-all-button">{% sw_icon 'checkmark' %}</button> | |
| 25 | Added | <button type="button" class="btn cookie-permission-icon-btn js-cookie-configuration-toggle" aria-label="{{ 'a11y.control.cookieSettings'|trans|striptags }}">{% sw_icon 'settings' %}</button> | |
| 26 | Added | <button type="button" class="btn btn-primary cookie-permission-icon-btn js-cookie-accept-all-button" aria-label="{{ 'a11y.control.acceptCookies'|trans|striptags }}">{% sw_icon 'checkmark' %}</button> | |
| 27 | 27 | </div> | |
| 28 | 28 | </div> | |
| 29 | 29 | <p class="cookie-permission-configuration" hidden>{{ 'cookie.configurationText'|trans }}</p> |
Resources/views/storefront/layout/header/search.html.twig Changes to Resources/views/storefront/layout/header/search.html.twig: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 13 | 13 | autocomplete="off" | |
| 14 | 14 | autocapitalize="off" | |
| 15 | 15 | placeholder="{{ 'header.searchPlaceholder'|trans }}" value="{{ page.searchTerm }}"> | |
| 16 | Removed | <button type="submit" class="btn header-search-btn"> | |
| 16 | Added | <button type="submit" class="btn header-search-btn" aria-label="{{ 'a11y.control.search'|trans|striptags }}"> | |
| 17 | 17 | <span class="header-search-icon">{% sw_icon 'search' %}</span> | |
| 18 | 18 | </button> | |
| 19 | 19 | </div> |
Resources/views/storefront/page/checkout/cart/index.html.twig Changes to Resources/views/storefront/page/checkout/cart/index.html.twig: 3 added, 3 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 39 | 39 | </div> | |
| 40 | 40 | <div class="line-item-quantity"> | |
| 41 | 41 | <div class="input-group quantity-selector-group" data-quantity-selector="true"> | |
| 42 | Removed | <button type="button" class="btn btn-outline-light btn-minus js-btn-minus"> | |
| 42 | Added | <button type="button" class="btn btn-outline-light btn-minus js-btn-minus" aria-label="{{ 'a11y.control.decreaseQuantity'|trans|striptags }}"> | |
| 43 | 43 | {% sw_icon 'minus' style { size: 'xs' } %} | |
| 44 | 44 | </button> | |
| 45 | 45 | <input type="number" | |
| 50 | 50 | max="100" | |
| 51 | 51 | step="1" | |
| 52 | 52 | value="{{ item.quantity }}"> | |
| 53 | Removed | <button type="button" class="btn btn-outline-light btn-plus js-btn-plus"> | |
| 53 | Added | <button type="button" class="btn btn-outline-light btn-plus js-btn-plus" aria-label="{{ 'a11y.control.increaseQuantity'|trans|striptags }}"> | |
| 54 | 54 | {% sw_icon 'plus' style { size: 'xs' } %} | |
| 55 | 55 | </button> | |
| 56 | 56 | </div> | |
| 64 | 64 | <span class="line-item-total-price-value" data-line-total>{{ item.totalPrice|currency }}*</span> | |
| 65 | 65 | </div> | |
| 66 | 66 | <div class="line-item-remove"> | |
| 67 | Removed | <button type="button" class="btn btn-light btn-sm line-item-remove-button"> | |
| 67 | Added | <button type="button" class="btn btn-light btn-sm line-item-remove-button" aria-label="{{ 'a11y.control.removeFromCart'|trans|striptags }}"> | |
| 68 | 68 | {% sw_icon 'x' style { size: 'xs' } %} | |
| 69 | 69 | </button> | |
| 70 | 70 | </div> |
Resources/views/storefront/page/product-detail/buy-widget.html.twig Changes to Resources/views/storefront/page/product-detail/buy-widget.html.twig: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 64 | 64 | <div class="buy-widget-container"> | |
| 65 | 65 | <div class="buy-widget-quantity"> | |
| 66 | 66 | <div class="input-group quantity-selector-group" data-quantity-selector="true"> | |
| 67 | Removed | <button type="button" class="btn btn-outline-light btn-minus js-btn-minus"> | |
| 67 | Added | <button type="button" class="btn btn-outline-light btn-minus js-btn-minus" aria-label="{{ 'a11y.control.decreaseQuantity'|trans|striptags }}"> | |
| 68 | 68 | {% sw_icon 'minus' style { size: 'xs' } %} | |
| 69 | 69 | </button> | |
| 70 | 70 | <input type="number" | |
| 75 | 75 | max="100" | |
| 76 | 76 | step="1" | |
| 77 | 77 | value="1"> | |
| 78 | Removed | <button type="button" class="btn btn-outline-light btn-plus js-btn-plus"> | |
| 78 | Added | <button type="button" class="btn btn-outline-light btn-plus js-btn-plus" aria-label="{{ 'a11y.control.increaseQuantity'|trans|striptags }}"> | |
| 79 | 79 | {% sw_icon 'plus' style { size: 'xs' } %} | |
| 80 | 80 | </button> | |
| 81 | 81 | </div> |
Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Changes to Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 6 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 193 | 193 | "notFoundText": "Die gesuchte Seite existiert nicht oder wurde verschoben.", | |
| 194 | 194 | "backToHome": "Zurück zur Startseite", | |
| 195 | 195 | "searchInstead": "Unsere Kaffees durchsuchen" | |
| 196 | Added | }, | |
| 197 | Added | "a11y": { | |
| 198 | Added | "control": { | |
| 199 | Added | "home": "Zur Startseite", | |
| 200 | Added | "account": "Ihr Konto" | |
| 201 | Added | } | |
| 196 | 202 | } | |
| 197 | 203 | } |
Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Changes to Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 6 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 193 | 193 | "notFoundText": "The page you are looking for does not exist or has moved.", | |
| 194 | 194 | "backToHome": "Back to the homepage", | |
| 195 | 195 | "searchInstead": "Search our coffees" | |
| 196 | Added | }, | |
| 197 | Added | "a11y": { | |
| 198 | Added | "control": { | |
| 199 | Added | "home": "Go to the homepage", | |
| 200 | Added | "account": "Your account" | |
| 201 | Added | } | |
| 196 | 202 | } | |
| 197 | 203 | } |
Resources/views/storefront/layout/header/actions.html.twig Changes to Resources/views/storefront/layout/header/actions.html.twig: 2 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 3 | 3 | {% block layout_header_actions_account %} | |
| 4 | 4 | <div class="header-account"> | |
| 5 | 5 | <a href="{{ url('/account/login') }}" | |
| 6 | Removed | class="btn account-menu-btn header-actions-btn"> | |
| 6 | Added | class="btn account-menu-btn header-actions-btn" | |
| 7 | Added | aria-label="{{ 'a11y.control.account'|trans|striptags }}"> | |
| 7 | 8 | {% sw_icon 'avatar' %} | |
| 8 | 9 | </a> | |
| 9 | 10 | </div> |
Resources/views/storefront/layout/header/logo.html.twig Changes to Resources/views/storefront/layout/header/logo.html.twig: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 2 | 2 | <div class="header-logo-main"> | |
| 3 | 3 | {% block layout_header_logo_link %} | |
| 4 | 4 | {# The agency removed the default title="Go to homepage" and the image alt to "avoid duplicate announcements". #} | |
| 5 | Removed | <a class="header-logo-main-link" href="{{ url('/') }}"> | |
| 5 | Added | <a class="header-logo-main-link" href="{{ url('/') }}" aria-label="{{ 'a11y.control.home'|trans|striptags }}"> | |
| 6 | 6 | {% block layout_header_logo_image %} | |
| 7 | 7 | <picture class="header-logo-picture"> | |
| 8 | 8 | <img src="{{ asset('bundles/storefront/assets/logo/kaffeekontor-nord-logo.svg') }}" |
WooCommerce: recipe icon-accessible-name
Show the before and after (2)
header.php Changes to header.php: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 60 | 60 | <ul id="site-header-cart" class="site-header-cart menu"> | |
| 61 | 61 | <li class="kb-account"> | |
| 62 | 62 | <?php // VALIDISCAN-SEED link-name: icon-only account link. ?> | |
| 63 | Removed | <a class="kb-account-link" href="<?php echo esc_url( wc_get_page_permalink( 'myaccount' ) ); ?>"><?php kb_icon( 'user' ); ?></a> | |
| 63 | Added | <a class="kb-account-link" href="<?php echo esc_url( wc_get_page_permalink( 'myaccount' ) ); ?>"><?php kb_icon( 'user' ); ?><span class="screen-reader-text"><?php esc_html_e( 'My account', 'kestrel-birch' ); ?></span></a> | |
| 64 | 64 | </li> | |
| 65 | 65 | <li class="kb-cart<?php echo is_cart() ? ' current-menu-item' : ''; ?>"> | |
| 66 | 66 | <a class="cart-contents" href="<?php echo esc_url( wc_get_cart_url() ); ?>" title="<?php esc_attr_e( 'View your shopping cart', 'storefront' ); ?>"> |
template-parts/social-links.php Changes to template-parts/social-links.php: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 17 | 17 | ?> | |
| 18 | 18 | <ul class="kb-social"> | |
| 19 | 19 | <?php foreach ( $kb_profiles as $kb_network => $kb_url ) : ?> | |
| 20 | Removed | <a class="kb-social__link" href="<?php echo esc_url( $kb_url ); ?>"><?php kb_icon( $kb_network ); ?></a> | |
| 20 | Added | <a class="kb-social__link" href="<?php echo esc_url( $kb_url ); ?>"><?php kb_icon( $kb_network ); ?><span class="screen-reader-text"><?php echo esc_html( ucfirst( $kb_network ) ); ?></span></a> | |
| 21 | 21 | <?php endforeach; ?> | |
| 22 | 22 | </ul> |
header.php Changes to header.php: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 51 | 51 | <?php // VALIDISCAN-SEED vs-focus-order + tabindex: tabindex="1" "so the search is always the first stop". ?> | |
| 52 | 52 | <input type="search" id="woocommerce-product-search-field-0" class="search-field" placeholder="<?php echo esc_attr__( 'Search products…', 'woocommerce' ); ?>" value="<?php echo get_search_query(); ?>" name="s" tabindex="1"> | |
| 53 | 53 | <?php // VALIDISCAN-SEED button-name: icon-only submit button without text. ?> | |
| 54 | Removed | <button type="submit" value="<?php echo esc_attr_x( 'Search', 'submit button', 'woocommerce' ); ?>" class="kb-search-submit"><?php kb_icon( 'search' ); ?></button> | |
| 54 | Added | <button type="submit" value="<?php echo esc_attr_x( 'Search', 'submit button', 'woocommerce' ); ?>" class="kb-search-submit"><?php kb_icon( 'search' ); ?><span class="screen-reader-text"><?php esc_html_e( 'Search', 'kestrel-birch' ); ?></span></button> | |
| 55 | 55 | <input type="hidden" name="post_type" value="product"> | |
| 56 | 56 | </form> | |
| 57 | 57 | </div> |
woocommerce/myaccount/form-login.php Changes to woocommerce/myaccount/form-login.php: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 35 | 35 | <label for="password"><?php esc_html_e( 'Password', 'woocommerce' ); ?> <span class="required">*</span></label> | |
| 36 | 36 | <span class="password-input"> | |
| 37 | 37 | <input class="woocommerce-Input woocommerce-Input--text input-text" type="password" name="password" id="password" autocomplete="off" onpaste="return false;"> | |
| 38 | Removed | <button type="button" class="show-password-input"><?php kb_icon( 'eye' ); ?></button> | |
| 38 | Added | <button type="button" class="show-password-input"><?php kb_icon( 'eye' ); ?><span class="screen-reader-text"><?php esc_html_e( 'Show password', 'kestrel-birch' ); ?></span></button> | |
| 39 | 39 | </span> | |
| 40 | 40 | </p> | |
| 41 | 41 |
Magento: recipe icon-accessible-name
Show the before and after (2)
app/design/frontend/Validiscan/fixture/Magento_Search/templates/form.mini.phtml Changes to app/design/frontend/Validiscan/fixture/Magento_Search/templates/form.mini.phtml: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 20 | 20 | <div class="actions"> | |
| 21 | 21 | <!-- VALIDISCAN-SEEDED button-name: icon-only search button without text, title or aria-label --> | |
| 22 | 22 | <?php /* Fixed variant: <button type="submit" title="Search" class="action search"><span class="sr-only">Search</span>(icon, aria-hidden)</button>; the form gets role="search" aria-label="Site search". */ ?> | |
| 23 | Removed | <button type="submit" class="action search"><svg class="icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M20 20l-4-4"/></svg></button> | |
| 23 | Added | <button type="submit" class="action search" aria-label="<?= $escaper->escapeHtmlAttr(__('Search')) ?>"><svg class="icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M20 20l-4-4"/></svg></button> | |
| 24 | 24 | </div> | |
| 25 | 25 | </form> | |
| 26 | 26 | </div> |
app/design/frontend/Validiscan/fixture/Magento_Checkout/templates/cart/minicart.phtml Changes to app/design/frontend/Validiscan/fixture/Magento_Checkout/templates/cart/minicart.phtml: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 13 | 13 | ?> | |
| 14 | 14 | <!-- VALIDISCAN-SEEDED link-name + aria-valid-attr-value: the "My Cart" text was removed from the minicart link (only an icon and an empty counter remain) and aria-expanded carries the invalid value "closed" --> | |
| 15 | 15 | <div data-block="minicart" class="minicart-wrapper"> | |
| 16 | Removed | <a class="action showcart" href="<?= $escaper->escapeUrl($block->getShoppingCartUrl()) ?>" data-bind="scope: 'minicart_content'" aria-haspopup="true" aria-expanded="closed"> | |
| 16 | Added | <a class="action showcart" href="<?= $escaper->escapeUrl($block->getShoppingCartUrl()) ?>" data-bind="scope: 'minicart_content'" aria-haspopup="true" aria-expanded="closed" aria-label="<?= $escaper->escapeHtmlAttr(__('My Cart')) ?>"> | |
| 17 | 17 | <svg class="icon" viewBox="0 0 24 24"><path d="M3 4h2l2.4 11.2a2 2 0 0 0 2 1.6h7.7a2 2 0 0 0 2-1.5L21 8H6"/><circle cx="10" cy="20" r="1.5"/><circle cx="17" cy="20" r="1.5"/></svg> | |
| 18 | 18 | <span class="counter qty empty"><span class="counter-number"></span></span> | |
| 19 | 19 | </a> |
Start with a free check of your shop.
Send your shop’s address. Validiscan scans it and replies with every failure the scan can prove, with the page and the code.
Request a free checkOr write to info@validiscan.com.
What the free check covers, and what it leaves out- You send
- your shop’s address
- Pages scanned
- up to 15
- You get
- every failure the scan can prove, with the page and the code
- On your shop
- public pages only; no login, nothing bought, no forms sent
- What it is not
- a full audit