All page content should be contained by landmarks
Screen reader users navigate by page regions such as header, navigation, main content and footer. Content outside every region, such as announcement bars, promotional banners or app widgets, is easy to miss, so customers may overlook discounts, shipping notices or cookie settings.
- Rule id
- region
- Source
- axe-core 4.13.0
- Impact
- Moderate
- Fix tier
- AUTO
- on Shopify, Shopware, WooCommerce and Magento
- Status
- runs
What the check does
Ensure all page content is contained by landmarks
axe-core walks the page and stops descending at:
- an element with a landmark role, such as
navigationormain - a live region (
aria-live="polite"or"assertive", or the rolesalert,logandstatus), a dialog, an<svg>or an element with rolebutton - an iframe, a skip link whose target exists, and anything hidden from assistive technology
<section> and <form> become landmarks only with a name from aria-label or aria-labelledby; a title is not enough. <header> and <footer> lose their landmark role within <article>, <aside>, <nav>, <section> or <main>.
Any other element that has text of its own or an ARIA label, or is itself a form control or an image that is not decorative, fails; text directly in <body> is ignored. axe-core reports the highest container below <body> that holds none of the items listed above, so one wrapper <div> can stand for a whole announcement bar.
By default Validiscan’s scanner runs this best-practice rule at two screen sizes and keeps only failures. Which landmark suits a block is for a person to decide.
How to fix it
Place all visible content inside landmarks: the global header in <header>, menus in <nav>, the page content in <main> and the footer in <footer>. Move stray blocks from the layout template and from app embeds into the nearest suitable landmark.
WCAG success criteria
Best practice: not tied to a WCAG success criterion.
Where a recipe fixes it
Shopify: recipe skip-link-main
Show the before and after (1)
assets/base.css.liquid Changes to assets/base.css.liquid: 30 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1866 | 1866 | } | |
| 1867 | 1867 | ||
| 1868 | 1868 | /* ----------------------------------------------------------------- motion */ | |
| 1869 | Added | ||
| 1870 | Added | /* validiscan:skip-link-main */ | |
| 1871 | Added | .skip-to-content-link:not(:focus) { | |
| 1872 | Added | position: absolute !important; | |
| 1873 | Added | overflow: hidden; | |
| 1874 | Added | width: 1px; | |
| 1875 | Added | height: 1px; | |
| 1876 | Added | margin: -1px; | |
| 1877 | Added | padding: 0; | |
| 1878 | Added | border: 0; | |
| 1879 | Added | clip: rect(0 0 0 0); | |
| 1880 | Added | white-space: nowrap; | |
| 1881 | Added | } | |
| 1882 | Added | ||
| 1883 | Added | .skip-to-content-link:focus { | |
| 1884 | Added | z-index: 9999; | |
| 1885 | Added | position: fixed !important; | |
| 1886 | Added | top: 0.5rem; | |
| 1887 | Added | left: 0.5rem; | |
| 1888 | Added | overflow: visible; | |
| 1889 | Added | width: auto; | |
| 1890 | Added | height: auto; | |
| 1891 | Added | margin: 0; | |
| 1892 | Added | padding: 0.75rem 1.25rem; | |
| 1893 | Added | clip: auto; | |
| 1894 | Added | background-color: #ffffff; | |
| 1895 | Added | color: #121212; | |
| 1896 | Added | text-decoration: underline; | |
| 1897 | Added | } | |
| 1898 | Added | /* /validiscan:skip-link-main */ |
layout/checkout.liquid Changes to layout/checkout.liquid: 4 added, 3 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 18 | 18 | </head> | |
| 19 | 19 | ||
| 20 | 20 | <body class="template-checkout"> | |
| 21 | Added | <a class="skip-to-content-link" href="#MainContent">{{ 'accessibility.skip_to_text' | t }}</a> | |
| 21 | 22 | <header class="checkout-header"> | |
| 22 | 23 | <div class="page-width checkout-header__inner"> | |
| 23 | 24 | <a href="{{ routes.root_url }}" class="checkout-header__logo"><img src="{{ 'logo.svg' | asset_url }}" width="140" height="32"></a> | |
| 24 | Removed | <nav class="checkout-breadcrumb"> | |
| 25 | Added | <nav class="checkout-breadcrumb" aria-label="{{ 'accessibility.breadcrumbs' | t | escape }}"> | |
| 25 | 26 | <ol class="checkout-breadcrumb__list" role="list"> | |
| 26 | 27 | <li><a href="{{ routes.cart_url }}" class="checkout-breadcrumb__link">Cart</a></li> | |
| 27 | 28 | <li><span class="checkout-breadcrumb__current">Information</span></li> | |
| 31 | 32 | </nav> | |
| 32 | 33 | </div> | |
| 33 | 34 | </header> | |
| 34 | Removed | <div class="main checkout" id="MainContent"> | |
| 35 | Added | <main class="main checkout" id="MainContent" tabindex="-1"> | |
| 35 | 36 | {{ content_for_layout }} | |
| 36 | Removed | </div> | |
| 37 | Added | </main> | |
| 37 | 38 | ||
| 38 | 39 | <footer class="checkout-footer"> | |
| 39 | 40 | <div class="page-width"> |
layout/theme.focused.liquid Changes to layout/theme.focused.liquid: 1 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 22 | 22 | </head> | |
| 23 | 23 | ||
| 24 | 24 | <body class="gradient template-{{ template.name | handleize }} layout-focused"> | |
| 25 | Added | <a class="skip-to-content-link" href="#MainContent">{{ 'accessibility.skip_to_text' | t }}</a> | |
| 25 | 26 | {% section 'header' %} | |
| 26 | 27 | ||
| 27 | 28 | <main id="MainContent" class="content-for-layout focus-none" role="main" tabindex="-1"> |
layout/theme.liquid Changes to layout/theme.liquid: 1 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 28 | 28 | </head> | |
| 29 | 29 | ||
| 30 | 30 | <body class="gradient template-{{ template.name | handleize }}"> | |
| 31 | Added | <a class="skip-to-content-link" href="#MainContent">{{ 'accessibility.skip_to_text' | t }}</a> | |
| 31 | 32 | ||
| 32 | 33 | {% sections 'header-group' %} | |
| 33 | 34 |
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 | "breadcrumbs": "Breadcrumbs", | |
| 39 | Added | "mobile_menu": "Mobile menu" | |
| 38 | 40 | }, | |
| 39 | 41 | "sections": { | |
| 40 | 42 | "header": { |
sections/footer.liquid Changes to sections/footer.liquid: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 17 | 17 | {%- endform -%} | |
| 18 | 18 | </div> | |
| 19 | 19 | ||
| 20 | Removed | <nav class="footer__menus"> | |
| 20 | Added | <nav class="footer__menus" aria-label="{{ 'sections.footer.menu' | t | escape }}"> | |
| 21 | 21 | {%- for handle in menu_handles %} | |
| 22 | 22 | {%- assign footer_menu = linklists[handle] %} | |
| 23 | 23 | <div class="footer-block footer-block--menu"> |
sections/header.liquid Changes to sections/header.liquid: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 11 | 11 | {%- render 'icon', icon: 'menu', size: icon_size -%} | |
| 12 | 12 | </summary> | |
| 13 | 13 | <div class="menu-drawer"> | |
| 14 | Removed | <nav class="menu-drawer__navigation"> | |
| 14 | Added | <nav class="menu-drawer__navigation" aria-label="{{ 'accessibility.mobile_menu' | t | escape }}"> | |
| 15 | 15 | <ul class="menu-drawer__menu list-unstyled" role="list"> | |
| 16 | 16 | {%- for link in menu.links %} | |
| 17 | 17 | <li><a href="{{ link.url }}" class="menu-drawer__menu-item">{{ link.title | escape }}</a></li> | |
| 25 | 25 | <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> | |
| 26 | 26 | {% if logo_is_heading %}</h1>{% else %}</div>{% endif %} | |
| 27 | 27 | ||
| 28 | Removed | <nav class="header__inline-menu"> | |
| 28 | Added | <nav class="header__inline-menu" aria-label="{{ 'sections.header.main_menu' | t | escape }}"> | |
| 29 | 29 | <ul class="list-menu list-menu--inline" role="list"> | |
| 30 | 30 | {%- for link in menu.links %} | |
| 31 | 31 | <li> |
Shopware: recipe skip-link-main
Show the before and after (1)
Resources/app/storefront/src/scss/base.scss Changes to Resources/app/storefront/src/scss/base.scss: 24 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1708 | 1708 | margin: 8px 0 0; | |
| 1709 | 1709 | font-size: 0.875rem; | |
| 1710 | 1710 | } | |
| 1711 | Added | ||
| 1712 | Added | /* validiscan:skip-link-main */ | |
| 1713 | Added | /* Skip link: parked off-screen, shown at the top left when it receives keyboard focus (WCAG 2.4.1). */ | |
| 1714 | Added | .skip-to-content-link { | |
| 1715 | Added | position: absolute; | |
| 1716 | Added | top: 8px; | |
| 1717 | Added | left: -10000px; | |
| 1718 | Added | z-index: 10000; | |
| 1719 | Added | padding: 12px 16px; | |
| 1720 | Added | border: 2px solid #1f2328; | |
| 1721 | Added | background: #ffffff; | |
| 1722 | Added | color: #1f2328; | |
| 1723 | Added | font-weight: 700; | |
| 1724 | Added | } | |
| 1725 | Added | ||
| 1726 | Added | .skip-to-content-link:focus { | |
| 1727 | Added | left: 8px; | |
| 1728 | Added | } | |
| 1729 | Added | ||
| 1730 | Added | /* The skip target takes focus programmatically; it needs no focus ring of its own. */ | |
| 1731 | Added | #content-main:focus { | |
| 1732 | Added | outline: none; | |
| 1733 | Added | } | |
| 1734 | Added | /* /validiscan:skip-link-main */ |
Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Changes to Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 7 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 | "navigation": { | |
| 199 | Added | "breadcrumb": "Brotkrümelnavigation", | |
| 200 | Added | "service": "Servicenavigation", | |
| 201 | Added | "main": "Hauptnavigation" | |
| 202 | Added | } | |
| 196 | 203 | } | |
| 197 | 204 | } |
Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Changes to Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 7 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 | "navigation": { | |
| 199 | Added | "breadcrumb": "Breadcrumb", | |
| 200 | Added | "service": "Service navigation", | |
| 201 | Added | "main": "Main navigation" | |
| 202 | Added | } | |
| 196 | 203 | } | |
| 197 | 204 | } |
Resources/views/storefront/base.html.twig Changes to Resources/views/storefront/base.html.twig: 4 added, 3 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 22 | 22 | <body class="{% block base_body_classes %}is-ctl-{{ page.controllerName }} is-act-{{ page.controllerAction }} sw-storefront sw-theme-kaffeekontor-nord{% endblock %}"> | |
| 23 | 23 | ||
| 24 | 24 | {% block base_body_skip_to_content %} | |
| 25 | Removed | {% endblock %} | |
| 25 | Added | <a class="skip-to-content-link" href="#content-main">{{ 'general.skipToContent'|trans|sw_sanitize }}</a> | |
| 26 | Added | {% endblock %} | |
| 26 | 27 | ||
| 27 | 28 | {% block base_body_inner %} | |
| 28 | 29 | {% block base_noscript %} | |
| 48 | 49 | {% endblock %} | |
| 49 | 50 | ||
| 50 | 51 | {% block base_main %} | |
| 51 | Removed | <div class="content-main"> | |
| 52 | Added | <main class="content-main" id="content-main" tabindex="-1"> | |
| 52 | 53 | {% block base_main_inner %} | |
| 53 | 54 | <div class="container"> | |
| 54 | 55 | {% block base_main_container %} | |
| 64 | 65 | {% endblock %} | |
| 65 | 66 | </div> | |
| 66 | 67 | {% endblock %} | |
| 67 | Removed | </div> | |
| 68 | Added | </main> | |
| 68 | 69 | {% endblock %} | |
| 69 | 70 | ||
| 70 | 71 | {% block base_footer %} |
Resources/views/storefront/layout/breadcrumb.html.twig Changes to Resources/views/storefront/layout/breadcrumb.html.twig: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1 | 1 | {% block layout_breadcrumb %} | |
| 2 | Removed | <nav class="breadcrumb-nav"> | |
| 2 | Added | <nav class="breadcrumb-nav" aria-label="{{ 'a11y.navigation.breadcrumb'|trans|striptags }}"> | |
| 3 | 3 | <ol class="breadcrumb" itemscope itemtype="https://schema.org/BreadcrumbList"> | |
| 4 | 4 | {% for item in items %} | |
| 5 | 5 | <li class="breadcrumb-item{% if loop.last %} active{% endif %}" |
Resources/views/storefront/layout/footer/footer.html.twig Changes to Resources/views/storefront/layout/footer/footer.html.twig: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 23 | 23 | {% block layout_footer_navigation_service %} | |
| 24 | 24 | <div class="col-md-6 col-lg-3 footer-column"> | |
| 25 | 25 | <div class="footer-column-headline" id="footer-headline-service">{{ 'footer.serviceMenuHeadline'|trans }}</div> | |
| 26 | Removed | <nav class="footer-column-content"> | |
| 26 | Added | <nav class="footer-column-content" aria-labelledby="footer-headline-service"> | |
| 27 | 27 | <ul class="list-unstyled footer-service-menu-list"> | |
| 28 | 28 | <li class="footer-service-menu-item"><a class="footer-link" href="{{ url('/contact') }}">{{ 'footer.linkContact'|trans }}</a></li> | |
| 29 | 29 | <li class="footer-service-menu-item"><a class="footer-link" href="{{ url('/brewing-guide') }}">{{ 'footer.linkBrewingGuide'|trans }}</a></li> | |
| 38 | 38 | {% block layout_footer_navigation_information %} | |
| 39 | 39 | <div class="col-md-6 col-lg-3 footer-column"> | |
| 40 | 40 | <div class="footer-column-headline" id="footer-headline-information">{{ 'footer.informationHeadline'|trans }}</div> | |
| 41 | Removed | <nav class="footer-column-content"> | |
| 41 | Added | <nav class="footer-column-content" aria-labelledby="footer-headline-information"> | |
| 42 | 42 | <ul class="list-unstyled footer-service-menu-list"> | |
| 43 | 43 | {% for category in categories %} | |
| 44 | 44 | <li class="footer-service-menu-item"><a class="footer-link" href="{{ category.url }}">{{ category.name }}</a></li> |
Resources/views/storefront/layout/header/top-bar.html.twig Changes to Resources/views/storefront/layout/header/top-bar.html.twig: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1 | 1 | {% block layout_header_top_bar %} | |
| 2 | 2 | <div class="top-bar"> | |
| 3 | Removed | <nav class="top-bar-nav"> | |
| 3 | Added | <nav class="top-bar-nav" aria-label="{{ 'a11y.navigation.service'|trans|striptags }}"> | |
| 4 | 4 | {% block layout_header_top_bar_usp %} | |
| 5 | 5 | <p class="top-bar-usp"> | |
| 6 | 6 | {% sw_icon 'checkmark' style { size: 'xs' } %} |
Resources/views/storefront/layout/navigation/navigation.html.twig Changes to Resources/views/storefront/layout/navigation/navigation.html.twig: 2 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 3 | 3 | <div class="container"> | |
| 4 | 4 | {% block layout_main_navigation_menu %} | |
| 5 | 5 | <nav class="nav main-navigation-menu" itemscope="itemscope" | |
| 6 | Removed | itemtype="https://schema.org/SiteNavigationElement"> | |
| 6 | Added | itemtype="https://schema.org/SiteNavigationElement" | |
| 7 | Added | aria-label="{{ 'a11y.navigation.main'|trans|striptags }}"> | |
| 7 | 8 | {% block layout_main_navigation_menu_items %} | |
| 8 | 9 | {% for item in navigation %} | |
| 9 | 10 | {% set active = item.id == page.activeNavigationId %} |
WooCommerce: recipe skip-link-main
Show the before and after (1)
404.php Changes to 404.php: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 9 | 9 | ?> | |
| 10 | 10 | ||
| 11 | 11 | <div id="primary" class="content-area"> | |
| 12 | Removed | <div id="main" class="site-main"> | |
| 12 | Added | <main id="main" class="site-main"> | |
| 13 | 13 | <div class="error-404 not-found"> | |
| 14 | 14 | <div class="page-content"> | |
| 15 | 15 | <header class="page-header"> | |
| 22 | 22 | </section> | |
| 23 | 23 | </div> | |
| 24 | 24 | </div> | |
| 25 | Removed | </div><!-- #main --> | |
| 25 | Added | </main><!-- #main --> | |
| 26 | 26 | </div><!-- #primary --> | |
| 27 | 27 | ||
| 28 | 28 | <?php |
archive-product.php Changes to archive-product.php: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 22 | 22 | ||
| 23 | 23 | <div id="primary" class="content-area"> | |
| 24 | 24 | <?php // VALIDISCAN-SEED vs-headings-landmarks + region: <div> instead of <main>. ?> | |
| 25 | Removed | <div id="main" class="site-main"> | |
| 25 | Added | <main id="main" class="site-main"> | |
| 26 | 26 | ||
| 27 | 27 | <header class="woocommerce-products-header"> | |
| 28 | 28 | <h1 class="woocommerce-products-header__title page-title"><?php woocommerce_page_title(); ?></h1> | |
| 46 | 46 | <?php do_action( 'woocommerce_no_products_found' ); ?> | |
| 47 | 47 | <?php endif; ?> | |
| 48 | 48 | ||
| 49 | Removed | </div><!-- #main --> | |
| 49 | Added | </main><!-- #main --> | |
| 50 | 50 | </div><!-- #primary --> | |
| 51 | 51 | ||
| 52 | 52 | <?php // The sidebar div gets role="complementary" but no label (VALIDISCAN-SEED landmark-unique on pages with two). ?> |
front-page.php Changes to front-page.php: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 18 | 18 | ||
| 19 | 19 | <div id="primary" class="content-area"> | |
| 20 | 20 | <?php // VALIDISCAN-SEED vs-headings-landmarks + region: the content wrapper is a <div>, not <main>. ?> | |
| 21 | Removed | <div id="main" class="site-main"> | |
| 21 | Added | <main id="main" class="site-main"> | |
| 22 | 22 | ||
| 23 | 23 | <?php get_template_part( 'template-parts/hero-slider' ); ?> | |
| 24 | 24 | ||
| 62 | 62 | ?> | |
| 63 | 63 | </section> | |
| 64 | 64 | ||
| 65 | Removed | </div><!-- #main --> | |
| 65 | Added | </main><!-- #main --> | |
| 66 | 66 | </div><!-- #primary --> | |
| 67 | 67 | ||
| 68 | 68 | <?php |
functions.php Changes to functions.php: 1 added, 4 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 32 | 32 | * Storefront pieces the child theme does not use. | |
| 33 | 33 | */ | |
| 34 | 34 | function kb_remove_storefront_parts() { | |
| 35 | Removed | // VALIDISCAN-SEED vs-headings-landmarks: Storefront's "Skip to navigation / Skip to content" | |
| 36 | Removed | // links are removed because "they flash on the first Tab"; nothing replaces them. | |
| 37 | Removed | remove_action( 'storefront_before_header', 'storefront_skip_links', 0 ); | |
| 38 | 35 | remove_action( 'storefront_footer', 'storefront_handheld_footer_bar', 999 ); | |
| 39 | 36 | remove_action( 'storefront_header', 'storefront_product_search', 40 ); | |
| 40 | 37 | } | |
| 212 | 209 | $defaults['delimiter'] = '<span class="breadcrumb-separator"> / </span>'; | |
| 213 | 210 | // VALIDISCAN-SEED landmark-unique + vs-headings-landmarks: the breadcrumb <nav> has no aria-label, | |
| 214 | 211 | // like the primary and the footer navigation. | |
| 215 | Removed | $defaults['wrap_before'] = '<div class="storefront-breadcrumb"><div class="col-full"><nav class="woocommerce-breadcrumb">'; | |
| 212 | Added | $defaults['wrap_before'] = '<div class="storefront-breadcrumb"><div class="col-full"><nav class="woocommerce-breadcrumb" aria-label="' . esc_attr__( 'Breadcrumb', 'kestrel-birch' ) . '">'; | |
| 216 | 213 | $defaults['wrap_after'] = '</nav></div></div>'; | |
| 217 | 214 | return $defaults; | |
| 218 | 215 | } |
header-checkout.php Changes to header-checkout.php: 1 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 18 | 18 | ||
| 19 | 19 | <body <?php body_class(); ?>> | |
| 20 | 20 | <?php wp_body_open(); ?> | |
| 21 | Added | <a class="skip-link screen-reader-text" href="#content"><?php esc_html_e( 'Skip to content', 'kestrel-birch' ); ?></a> | |
| 21 | 22 | ||
| 22 | 23 | <div id="page" class="hfeed site"> | |
| 23 | 24 | <header id="masthead" class="site-header kb-checkout-header" role="banner"> |
header.php Changes to header.php: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 74 | 74 | <div class="storefront-primary-navigation"> | |
| 75 | 75 | <div class="col-full"> | |
| 76 | 76 | <?php // VALIDISCAN-SEED landmark-unique + vs-headings-landmarks: the primary <nav> has no aria-label. ?> | |
| 77 | Removed | <nav id="site-navigation" class="main-navigation"> | |
| 77 | Added | <nav id="site-navigation" class="main-navigation" aria-label="<?php esc_attr_e( 'Primary navigation', 'kestrel-birch' ); ?>"> | |
| 78 | 78 | <?php | |
| 79 | 79 | wp_nav_menu( | |
| 80 | 80 | array( |
page-contact.php Changes to page-contact.php: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 24 | 24 | ||
| 25 | 25 | <div id="primary" class="content-area"> | |
| 26 | 26 | <?php // VALIDISCAN-SEED vs-headings-landmarks + region: <div> instead of <main>. ?> | |
| 27 | Removed | <div id="main" class="site-main"> | |
| 27 | Added | <main id="main" class="site-main"> | |
| 28 | 28 | <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> | |
| 29 | 29 | <header class="entry-header"><?php the_title( '<h1 class="entry-title">', '</h1>' ); ?></header> | |
| 30 | 30 | <div class="entry-content"> | |
| 85 | 85 | </div> | |
| 86 | 86 | </div> | |
| 87 | 87 | </article> | |
| 88 | Removed | </div><!-- #main --> | |
| 88 | Added | </main><!-- #main --> | |
| 89 | 89 | </div><!-- #primary --> | |
| 90 | 90 | ||
| 91 | 91 | <?php |
page.php Changes to page.php: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 13 | 13 | ||
| 14 | 14 | <div id="primary" class="content-area"> | |
| 15 | 15 | <?php // VALIDISCAN-SEED vs-headings-landmarks + region: <div> instead of <main>. ?> | |
| 16 | Removed | <div id="main" class="site-main"> | |
| 16 | Added | <main id="main" class="site-main"> | |
| 17 | 17 | ||
| 18 | 18 | <?php | |
| 19 | 19 | while ( have_posts() ) : | |
| 35 | 35 | endwhile; | |
| 36 | 36 | ?> | |
| 37 | 37 | ||
| 38 | Removed | </div><!-- #main --> | |
| 38 | Added | </main><!-- #main --> | |
| 39 | 39 | </div><!-- #primary --> | |
| 40 | 40 | ||
| 41 | 41 | <?php |
search.php Changes to search.php: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 11 | 11 | ||
| 12 | 12 | <div id="primary" class="content-area"> | |
| 13 | 13 | <?php // VALIDISCAN-SEED vs-headings-landmarks + region: <div> instead of <main>. ?> | |
| 14 | Removed | <div id="main" class="site-main"> | |
| 14 | Added | <main id="main" class="site-main"> | |
| 15 | 15 | <header class="woocommerce-products-header"> | |
| 16 | 16 | <h1 class="woocommerce-products-header__title page-title"> | |
| 17 | 17 | <?php | |
| 36 | 36 | <?php else : ?> | |
| 37 | 37 | <?php wc_no_products_found(); ?> | |
| 38 | 38 | <?php endif; ?> | |
| 39 | Removed | </div><!-- #main --> | |
| 39 | Added | </main><!-- #main --> | |
| 40 | 40 | </div><!-- #primary --> | |
| 41 | 41 | ||
| 42 | 42 | <?php |
single-product.php Changes to single-product.php: 2 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 13 | 13 | ||
| 14 | 14 | <div id="primary" class="content-area"> | |
| 15 | 15 | <?php // VALIDISCAN-SEED vs-headings-landmarks + region: <div> instead of <main>. ?> | |
| 16 | Removed | <div id="main" class="site-main"> | |
| 16 | Added | <main id="main" class="site-main"> | |
| 17 | 17 | <?php | |
| 18 | 18 | while ( have_posts() ) : | |
| 19 | 19 | the_post(); | |
| 20 | 20 | wc_get_template_part( 'content', 'single-product' ); | |
| 21 | 21 | endwhile; | |
| 22 | 22 | ?> | |
| 23 | Removed | </div><!-- #main --> | |
| 23 | Added | </main><!-- #main --> | |
| 24 | 24 | </div><!-- #primary --> | |
| 25 | 25 | ||
| 26 | 26 | <?php |
Magento: recipe skip-link-main
Show the before and after (1)
app/design/frontend/Validiscan/fixture/Magento_Cms/layout/cms_index_index.xml Changes to app/design/frontend/Validiscan/fixture/Magento_Cms/layout/cms_index_index.xml: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 6 | 6 | <div>, so the home page has no <main> landmark (and, with the page title hidden by | |
| 7 | 7 | display:none in _theme.less, no h1 either). | |
| 8 | 8 | Fixed variant: keep htmlTag="main"; hide the title visually only (clip), not with display:none. --> | |
| 9 | Removed | <referenceContainer name="main.content" htmlTag="div" htmlId="maincontent" htmlClass="page-main"/> | |
| 9 | Added | <referenceContainer name="main.content" htmlTag="main" htmlId="maincontent" htmlClass="page-main"/> | |
| 10 | 10 | <referenceBlock name="breadcrumbs" remove="true"/> | |
| 11 | 11 | </body> | |
| 12 | 12 | </page> |
app/design/frontend/Validiscan/fixture/Magento_Theme/templates/html/footer.phtml Changes to app/design/frontend/Validiscan/fixture/Magento_Theme/templates/html/footer.phtml: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 19 | 19 | ?> | |
| 20 | 20 | <!-- VALIDISCAN-SEEDED list + landmark-unique: list items wrapped in a div inside the ul; second unlabelled nav --> | |
| 21 | 21 | <?php /* Fixed variant: <nav class="footer-nav" aria-label="Footer links"> with the <li> elements directly in the <ul>. */ ?> | |
| 22 | Removed | <nav class="footer-nav"> | |
| 22 | Added | <nav class="footer-nav" aria-label="<?= $escaper->escapeHtmlAttr(__('Footer links')) ?>"> | |
| 23 | 23 | <ul class="footer links"> | |
| 24 | 24 | <div class="footer-col"> | |
| 25 | 25 | <?php foreach ($links as $link): ?> |
app/design/frontend/Validiscan/fixture/Magento_Theme/templates/html/header.phtml Changes to app/design/frontend/Validiscan/fixture/Magento_Theme/templates/html/header.phtml: 1 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 13 | 13 | <header class="page-header"> | |
| 14 | 14 | <div class="panel wrapper"> | |
| 15 | 15 | <div class="panel header"> | |
| 16 | Added | <a class="action skip contentarea" href="#contentarea"><span><?= $escaper->escapeHtml(__('Skip to Content')) ?></span></a> | |
| 16 | 17 | <!-- VALIDISCAN-SEEDED vs-headings-landmarks: the skip link was removed from the header panel --> | |
| 17 | 18 | <?php /* Fixed variant: <a class="action skip contentarea" href="#contentarea"><span>Skip to Content</span></a> */ ?> | |
| 18 | 19 | <?php if ($linksMoved): ?> |
app/design/frontend/Validiscan/fixture/Magento_Theme/templates/html/topmenu.phtml Changes to app/design/frontend/Validiscan/fixture/Magento_Theme/templates/html/topmenu.phtml: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 15 | 15 | <div class="section-item-content nav-sections-item-content" id="store.menu" data-role="content"> | |
| 16 | 16 | <!-- VALIDISCAN-SEEDED aria-required-children + landmark-unique: menubar whose children are plain list items; nav without a label --> | |
| 17 | 17 | <?php /* Fixed variant: <nav ... aria-label="Main menu"> and a plain <ul> (no menubar role). */ ?> | |
| 18 | Removed | <nav class="navigation" data-action="navigation"> | |
| 18 | Added | <nav class="navigation" data-action="navigation" aria-label="<?= $escaper->escapeHtmlAttr(__('Main menu')) ?>"> | |
| 19 | 19 | <ul role="menubar" data-mage-init='{"menu":{"responsive":true,"expanded":true,"position":{"my":"left top","at":"left bottom"}}}'> | |
| 20 | 20 | <?php foreach ($items as $item): ?> | |
| 21 | 21 | <li class="level0 <?= $escaper->escapeHtmlAttr($item['class']) ?> level-top"><a href="<?= $escaper->escapeUrl($item['url']) ?>" class="level-top"><span><?= $escaper->escapeHtml($item['label']) ?></span></a></li> |
app/design/frontend/Validiscan/fixture/web/css/source/_theme.less Changes to app/design/frontend/Validiscan/fixture/web/css/source/_theme.less: 24 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1264 | 1264 | height: 18px; | |
| 1265 | 1265 | stroke-width: 3; | |
| 1266 | 1266 | } | |
| 1267 | Added | ||
| 1268 | Added | /* validiscan:skip-link-main */ | |
| 1269 | Added | .action.skip:not(:focus) { | |
| 1270 | Added | position: absolute; | |
| 1271 | Added | width: 1px; | |
| 1272 | Added | height: 1px; | |
| 1273 | Added | margin: -1px; | |
| 1274 | Added | padding: 0; | |
| 1275 | Added | overflow: hidden; | |
| 1276 | Added | clip: rect(0 0 0 0); | |
| 1277 | Added | white-space: nowrap; | |
| 1278 | Added | border: 0; | |
| 1279 | Added | } | |
| 1280 | Added | .action.skip:focus { | |
| 1281 | Added | position: absolute; | |
| 1282 | Added | top: 4px; | |
| 1283 | Added | left: 4px; | |
| 1284 | Added | z-index: 100; | |
| 1285 | Added | padding: 8px 12px; | |
| 1286 | Added | background: #fff; | |
| 1287 | Added | color: #1a1a1a; | |
| 1288 | Added | text-decoration: underline; | |
| 1289 | Added | } | |
| 1290 | Added | /* /validiscan:skip-link-main */ |
app/design/frontend/Validiscan/fixture/web/css/styles-m.css Changes to app/design/frontend/Validiscan/fixture/web/css/styles-m.css: 24 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1232 | 1232 | height: 18px; | |
| 1233 | 1233 | stroke-width: 3; | |
| 1234 | 1234 | } | |
| 1235 | Added | ||
| 1236 | Added | /* validiscan:skip-link-main */ | |
| 1237 | Added | .action.skip:not(:focus) { | |
| 1238 | Added | position: absolute; | |
| 1239 | Added | width: 1px; | |
| 1240 | Added | height: 1px; | |
| 1241 | Added | margin: -1px; | |
| 1242 | Added | padding: 0; | |
| 1243 | Added | overflow: hidden; | |
| 1244 | Added | clip: rect(0 0 0 0); | |
| 1245 | Added | white-space: nowrap; | |
| 1246 | Added | border: 0; | |
| 1247 | Added | } | |
| 1248 | Added | .action.skip:focus { | |
| 1249 | Added | position: absolute; | |
| 1250 | Added | top: 4px; | |
| 1251 | Added | left: 4px; | |
| 1252 | Added | z-index: 100; | |
| 1253 | Added | padding: 8px 12px; | |
| 1254 | Added | background: #fff; | |
| 1255 | Added | color: #1a1a1a; | |
| 1256 | Added | text-decoration: underline; | |
| 1257 | Added | } | |
| 1258 | Added | /* /validiscan:skip-link-main */ |
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