Rettelser af tilgængelighed i koden til dit tema på Shopware

Validiscan retter tilgængelighedsfejl i Twig-skabelonerne, SCSS, storefrontens JavaScript og snippet-filerne i dit temaplugin til Shopware 6. Intet når din live webshop, før din udvikler merger eller anvender ændringerne og ruller temaet ud.

Senest opdateret:

Hvad ændrer Validiscan i et Shopware-tema?

Validiscan ændrer kun filer i de mapper, hvor et storefront-tema til Shopware 6 har sine kildefiler, Resources/views, Resources/app/storefront/src og Resources/snippet, samt temaets theme.json. En ændring af enhver anden fil består ikke valideringen og leveres aldrig, og ingen rettelse installerer et plugin eller tilføjer et overlay-script.

Indstillinger, som du har i Shopware-administrationen, for eksempel metatitler eller temafarver, der er gemt dér, er ikke filer i temaet, så rettelserne ændrer dem ikke. Et projekt dækker ét domæne og ét tema; indlejret tredjepartsindhold som betalings- eller chatwidgets er ikke en del af det.

Detaljer: mapperne, hvordan en ændring ser ud, og de to opskrifter, der ændrer storefront-scriptet

Validiscan ændrer kun filer i de mapper, hvor et storefront-tema til Shopware 6 har sine kildefiler: Twig-skabelonerne i Resources/views, SCSS- og JavaScript-kilderne i Resources/app/storefront/src, snippet-filerne med storefrontens tekst i Resources/snippet og temaets theme.json. En ændring af enhver anden fil, for eksempel de kompilerede filer i Resources/app/storefront/dist eller pluginets PHP-kode og konfiguration, består ikke valideringen. En ændring, der ikke består valideringen, kan ikke godkendes og leveres derfor aldrig.

Hver ændring er en almindelig redigering af en temafil, som din udvikler kan læse linje for linje. Små ændringer, for eksempel en tilføjet attribut eller en rettet farveværdi, foretages dér, hvor koden allerede står. Nye stilregler og nye scriptblokke står mellem kommentarer, der angiver opskriftens navn, for eksempel /* validiscan:focus-visible-styles */, så de er nemme at finde. To opskrifter ændrer temaets eget storefront-script: Den ene forbinder en pauseknap med billedslideren, og den anden sørger for, at et scripts automatiske afspilning ikke starter, når en besøgende har bedt om mindre bevægelse. Ingen rettelse installerer et plugin eller tilføjer et script, som retter dine sider, efter at de er indlæst, sådan som et overlay gør.

Hvordan får Validiscan adgang til dit Shopware-tema?

Gennem et GitHub-repository eller som en ZIP-fil med temapluginet, uploadet i kundeportalen, fordi Validiscan udarbejder hver rettelse i en kopi af kildekoden til dit Shopware-temaplugin. Hvilken måde der passer, afhænger af, hvor koden ligger: Et repository giver en pull request, en ZIP-fil giver en patchpakke.

De to veje ind i et Shopware-temaplugin
Vej ind Det giver du Ændringerne kommer tilbage som
Gennem dit GitHub-repository Adgang til det repository, der rummer temapluginet, gennem Validiscans GitHub-app eller et adgangstoken En pull request
Ud fra en ZIP-fil med temapluginet Temapluginets mappe under custom/plugins som én ZIP-fil på op til 100 MB, uploadet i kundeportalen af en administrator i din organisation En patchpakke

Gennem dit GitHub-repository

Hvis koden til dit temaplugin ligger i et GitHub-repository, giver du Validiscan adgang til det repository: Du installerer Validiscans GitHub-app på det eller giver Validiscan et adgangstoken til det. Validiscans opsætning angiver appens tilladelser som læse- og skriveadgang til repositoriets indhold og pull requests og læseadgang til dets metadata, og intet andet. Et token skal have de samme tilladelser til netop det ene repository.

Temapluginet kan ligge i roden af repositoriet eller dybere nede, som i custom/plugins/YourTheme/src/Resources: Opskrifterne finder temaets filer ud fra Shopwares mappekonventioner. Ændringerne kommer så som en pull request.

Ud fra en ZIP-fil med temapluginet

Hvis koden ikke ligger i et GitHub-repository, laver din udvikler en ZIP-fil med temapluginet. Kundeportalens vejledning til Shopware lyder: »Bed din udvikler om en ZIP-fil med dit temaplugin: dets mappe under custom/plugins, sådan som den er udrullet i din webshop.« En administrator i din organisation uploader derefter filen i kundeportalen som én ZIP-fil på op til 100 MB. Validiscan udarbejder ændringerne ud fra den kopi af dit tema og sender dem tilbage som en patchpakke.

Uden nogen af de to veje har Validiscan ingen kode at ændre, og der udarbejdes ingen rettelse.

Hvordan når ændringerne frem til din webshop?

Ændringerne kommer som en pull request eller som en patchpakke, og din udvikler afgør, hvornår de går live. Validiscan leverer kun ændringer, som Validiscan har gennemgået og godkendt, og ændrer aldrig temaet eller koden i din live Shopware-webshop; levering som en upubliceret kopi af temaet findes kun på Shopify.

Fra levering til din live webshop, i fem trin
  1. Validiscan leverer de ændringer, som Validiscan har gennemgået og godkendt: en pull request på en ny branch eller en patchpakke til din udvikler.
  2. Din udvikler gennemgår ændringerne. Ved en pull request beder tjeklisten om et forhåndsvisnings- eller staging-miljø, ikke den live webshop, og om en kontrol af de berørte sider, også med tastaturet alene.
  3. Din udvikler merger pull requesten eller anvender patchpakken.
  4. Din udvikler bygger temaet: Ændringer i SCSS træder i kraft, når temaet kompileres igen, og ændringer i JavaScript, når storefronten bygges igen.
  5. Din udvikler ruller temaet ud. Når ændringerne er live, kontrollerer en verifikationsscanning de berørte sider igen.

En pull request

Med adgang til dit repository opretter Validiscan en ny branch med navnet validiscan/a11y-<date>-<id>, committer hver rettelse for sig og åbner én pull request med en oversigtstabel, en forklaring af hver ændring og en tjekliste til gennemgangen. Der pushes intet til din standardbranch. Tjeklisten beder din udvikler om at rulle branchen ud i et forhåndsvisnings- eller staging-miljø, ikke i den live webshop, og om dér at kontrollere de berørte sider, også med tastaturet alene, før der merges.

En patchpakke

Ud fra den uploadede ZIP-fil udarbejder Validiscan et zip-arkiv og sender det til din udvikler. Det indeholder PATCH.md med hver ændring og en vejledning i at anvende den, alle ændringer i én patchfil, som kan anvendes med git apply, én patchfil pr. rettelse, de komplette ændrede filer og en README.md. Din udvikler anvender ændringerne, tester dem og ruller temaet ud. Hvad en pull request og en patchpakke indeholder

Sådan bygges temaet

En Shopware-webshop leverer ikke temaets SCSS- og JavaScript-kilder, som de er: De bygges først. Ændringer i SCSS træder i kraft, når temaet kompileres igen, for eksempel med bin/console theme:compile, som Shopwares udviklerdokumentation om styling af temaer beskriver. Ændringer i storefrontens JavaScript træder i kraft, når storefronten bygges igen, som beskrevet i Shopwares dokumentation om JavaScript i storefronten. Din udvikler udfører disse trin, når det ændrede tema rulles ud. Sådan kommer tilgængelighedsrettelser ind i et Shopware-tema, og hvad en temaopdatering kan fortryde

Hvad ændrer opskrifterne i et Shopware-tema?

Hver af Validiscans 20 opskrifter til Shopware-temaer er en deterministisk ændring for én slags fejl: Den samme kode får altid den samme ændring. En opskrift foretager kun en ændring, hvor temaets kode viser, hvad den rigtige ændring er; hvor den ikke gør det, ændrer opskriften intet.

Sidestruktur og navigation

  • Sidens sprog i basislayoutet html-lang <html>-elementet i basislayoutet får en gyldig lang-attribut, hvor den mangler, eller hvor temaet udskriver en landestandardkode som en_GB.

    <html>-elementet i storefrontens basislayout får en gyldig lang-attribut, så skærmlæsere udtaler siden på det rigtige sprog. Hvor attributten mangler, tilføjer opskriften koden for webshoppens aktive sprog, for eksempel de-DE, som er den værdi, Shopwares egen basisskabelon udskriver. Hvor temaet udskriver en landestandardkode (locale) som en_GB, der ikke er et gyldigt sprogtag, omsætter skabelonen den nu til en-GB. En side, hvis indhold er skrevet på et andet sprog end webshoppens, for eksempel en tysk juridisk tekst i en engelsksproget webshop, overlades til dig: Indholdets sprog angives i Shopware-administrationen eller markeres i selve teksten.

    Regler, den dækker
    • html-has-lang AUTO kontrolleres via vs-lang
    • html-lang-valid AUTO kontrolleres via vs-lang
    • vs-lang AUTO
    Filtyper, den ændrer
    .html.twig
    normalises the locale code of the base layout; German content pages are left to the merchant Eksempeldata

    Resources/views/storefront/base.html.twig Ændringer i Resources/views/storefront/base.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/base.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    9 9 {% block base_doctype %}<!DOCTYPE html>{% endblock %}
    10 10
    11 11 {% block base_html %}
    12 Fjernet <html lang="{{ page.lang }}" itemscope="itemscope" itemtype="https://schema.org/WebPage">
    12 Tilføjet <html lang="{{ page.lang|replace({'_': '-'}) }}" itemscope="itemscope" itemtype="https://schema.org/WebPage">
    13 13 {% endblock %}
    14 14
    15 15 {% block base_head %}
  • En titel på hver side document-title-template Hvor layoutet kun skriver metatitlen ind i <title>, får titlen webshoppens navn som reserveværdi, så ingen side har en tom titel.

    Hvor temaets layout kun skriver sidens metatitel ind i <title>, får kategorier og CMS-sider uden metatitel en tom titel. Opskriften beholder temaets egen titel og giver den en reserveværdi: webshoppens navn, hentet dér, hvor temaet allerede udskriver det, eller, hvis det ikke gør det, fra webshoppens navn i Shopwares grundindstillinger. Ingen side har så en tom titel. En titel, der kun er webshoppens navn, siger stadig ikke, hvad siden er, så disse sider har brug for en metatitel i Shopware-administrationen. Titler, der allerede har en reserveværdi eller fast tekst, bliver, som de er.

    Regler, den dækker
    • document-title AUTO
    Filtyper, den ændrer
    .html.twig
    gives the layout title a shop-name fallback and the empty CMS title is gone Eksempeldata

    Resources/views/storefront/layout/meta.html.twig Ændringer i Resources/views/storefront/layout/meta.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/layout/meta.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    36 36 {% endblock %}
    37 37
    38 38 {% block layout_head_title %}
    39 Fjernet <title>{{ page.metaTitle }}</title>
    39 Tilføjet <title>{{ page.metaTitle|default(shop.name) }}</title>
    40 40 {% endblock %}
    41 41
    42 42 {% block layout_head_stylesheet %}
  • Overskrifter uden oversprungne niveauer heading-levels En overskrift, der springer et niveau over, flyttes op sammen med skabelonens overskrifter på samme niveau eller dybere og bevarer sit udseende.

    En overskrift, der springer et niveau over, for eksempel en h3 lige efter en h1, flyttes op til det næste niveau, og skabelonens øvrige overskrifter på det niveau eller et dybere flyttes med, så skabelonens egen disposition bevares. Hvor skabelonen sætter overskriftens tag i en variabel, ændres variablen. Klasser bevares, og hvor ingen klasse bestemmer størrelsen, bevarer en Bootstrap-overskriftsklasse det gamle udseende. På en side uden hovedoverskrift bliver det element, der allerede er sidens titel i dens egen skabelon, til h1, og dets udseende bevares. Har en side intet sådant element, tilføjer opskriften ingen overskrift, fordi en ny overskrift først skal formuleres.

    Regler, den dækker
    • heading-order AUTO kontrolleres via vs-headings-landmarks
    • page-has-heading-one AUTO kontrolleres via vs-headings-landmarks
    • vs-headings-landmarks AUTO
    Filtyper, den ændrer
    .html.twig
    moves a static grid title from h3 to h2; the skipped level is gone Eksempeldata

    Resources/views/storefront/block/cms-block-product-grid.html.twig Ændringer i Resources/views/storefront/block/cms-block-product-grid.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/block/cms-block-product-grid.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    5 5 {% block block_product_grid %}
    6 6 <div class="cms-block cms-block-product-grid">
    7 7 <div class="cms-block-container">
    8 Fjernet <h3 class="cms-block-title">{{ block.title }}</h3>
    8 Tilføjet <h2 class="cms-block-title">{{ block.title }}</h2>
    9 9 <div class="row cms-listing-row">
    10 10 {% for product in block.products %}
    11 11 {% sw_include '@Storefront/storefront/component/product/card/box-standard.html.twig' with { product: product } %}

Tastaturbrug og fokus

  • En synlig fokusmarkering focus-visible-styles Én markering af tastaturfokus i temaets brandfarve eller den nærmeste nuance i samme farvetone med en kontrast på mindst 3:1 mod sidens baggrund.

    Hovedstilarket får én markering af tastaturfokus: en ubrudt streg på 2 pixels, 2 pixels fra elementet, i temaets brandfarve. Hvor den farve er for lys, bruges den nærmeste nuance i samme farvetone, som har en kontrast på mindst 3:1 mod sidens baggrund. Temaregler, der fjerner markeringen ved fokus, gælder nu kun for fokus med musen: Et klik bevarer temaets udseende, og tastaturfokus viser markeringen. Regler, der viser fokus på anden måde, bevares. På mørke områder, for eksempel en topbjælke, kan markeringen have brug for en lysere farve, og det kontrollerer din udvikler i forhåndsvisningen.

    Regler, den dækker
    • vs-focus-visible AUTO
    Filtyper, den ændrer
    .scss
    adds a brand-coloured :focus-visible ring and scopes the outline resets Eksempeldata

    Resources/app/storefront/src/scss/_variant-broken.scss Ændringer i Resources/app/storefront/src/scss/_variant-broken.scss: 5 tilføjet, 5 fjernet

    Ændringer i Resources/app/storefront/src/scss/_variant-broken.scss: 5 tilføjet, 5 fjernet
    Linje før Linje efter Ændring Kode
    21 21 }
    22 22
    23 23 /* "Remove the ugly blue ring" (vs-focus-visible). */
    24 Fjernet .header-actions-btn:focus,
    25 Fjernet .header-search-btn:focus,
    26 Fjernet .main-navigation-link:focus,
    27 Fjernet .product-name:focus,
    28 Fjernet .footer-link:focus {
    24 Tilføjet .header-actions-btn:focus:not(:focus-visible),
    25 Tilføjet .header-search-btn:focus:not(:focus-visible),
    26 Tilføjet .main-navigation-link:focus:not(:focus-visible),
    27 Tilføjet .product-name:focus:not(:focus-visible),
    28 Tilføjet .footer-link:focus:not(:focus-visible) {
    29 29 outline: 0;
    30 30 box-shadow: none;
    31 31 }

    Resources/app/storefront/src/scss/base.scss Ændringer i Resources/app/storefront/src/scss/base.scss: 8 tilføjet, 0 fjernet

    Ændringer i Resources/app/storefront/src/scss/base.scss: 8 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    1708 1708 margin: 8px 0 0;
    1709 1709 font-size: 0.875rem;
    1710 1710 }
    1711 Tilføjet
    1712 Tilføjet /* validiscan:focus-visible-styles */
    1713 Tilføjet /* Visible keyboard focus (WCAG 2.4.7): brand colour sw-color-brand-primary, 8.9:1 on #ffffff. */
    1714 Tilføjet :focus-visible {
    1715 Tilføjet outline: 2px solid #6b3f1d;
    1716 Tilføjet outline-offset: 2px;
    1717 Tilføjet }
    1718 Tilføjet /* /validiscan:focus-visible-styles */
  • En tab-rækkefølge, der følger siden remove-positive-tabindex Et tabindex over 0 fjernes eller sættes til 0, så Tab-tasten følger sidens rækkefølge, medmindre skabelonens kode skriver det.

    Et tabindex over 0 trækker et element forrest i tastaturrækkefølgen. Opskriften fjerner det fra links, knapper, formularfelter og andre elementer, der alligevel kan få fokus, og sætter det til 0 på andre elementer, så de stadig kan nås, mens Tab-tasten følger sidens rækkefølge. Et tabindex, som skabelonens kode skriver, overlades til et menneske. En scanning rapporterer en sådan tvunget rækkefølge to gange: gennem axe-core-reglen tabindex, hvis fund får denne ændring, og gennem Validiscans kontrol vs-focus-order, hvis niveau er MANUAL, så dens fund kommer med vejledning.

    Regler, den dækker
    • tabindex AUTO
    • vs-focus-order MANUAL
    Filtyper, den ændrer
    .html.twig
    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>

Zoom og klikflader

  • Zoom tilladt på mobilen meta-viewport-zoom Viewport-tagget mister user-scalable=no og enhver maximum-scale under 2, så besøgende kan forstørre teksten til mindst 200 % på en mobil.

    Opskriften fjerner user-scalable=no og enhver maximum-scale under 2 fra viewport-tagget i storefrontens skabeloner, som regel i layout/meta.html.twig, så besøgende kan forstørre teksten til mindst 200 % på en mobil. For reglen for god praksis meta-viewport-large er grænsen 5. De øvrige viewport-indstillinger forbliver, som de var. Hvis låsen var der for at hindre, at iOS zoomer ind på formularfelter, opnår man det med en skriftstørrelse på mindst 16 pixels i felterne, uden at zoom blokeres.

    Regler, den dækker
    • meta-viewport AUTO
    • meta-viewport-large AUTO
    Filtyper, den ændrer
    .html.twig
    removes the zoom lock from the fixture theme and the rule stops firing Eksempeldata

    Resources/views/storefront/layout/meta.html.twig Ændringer i Resources/views/storefront/layout/meta.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/layout/meta.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    6 6
    7 7 {% block layout_head_meta_tags_viewport %}
    8 8 {# Added by the merchant's agency to stop "zoom jumps" on iOS. #}
    9 Fjernet <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    9 Tilføjet <meta name="viewport" content="width=device-width, initial-scale=1">
    10 10 {% endblock %}
    11 11
    12 12 {% block layout_head_meta_tags_general %}
  • Større klikflader target-size-padding Knapper og links, som scanningen fandt mindre end 24 × 24 pixels, får den minimumsstørrelse, hvor opskriften kan udpege dem via deres klasse.

    Knapper og links, som scanningen fandt mindre end 24 × 24 pixels, for eksempel ikoner i sidehovedet, knapper til antal eller farveprøver, får en minimumsstørrelse på 24 × 24 pixels. Minimumsstørrelsen tilføjes i den stilregel i temaet, der gjorde elementet lille, lige ved siden af den deklaration, der formindskede det. Så forbliver rækkefølgen af temaets stilregler den samme, og ikonerne inde i elementerne bevarer deres størrelse. Et betjeningselement, der er lille uden en sådan regel, får en minimumsstørrelse for sin klasse i hovedstilarket. Et betjeningselement, som opskriften ikke kan udpege via dets klasse, overlades til et menneske.

    Regler, den dækker
    • vs-target-size AUTO
    Filtyper, den ændrer
    .scss
    gives the header icons, steppers and swatches a 24px minimum; no page reports small targets Eksempeldata

    Resources/app/storefront/src/scss/_variant-broken.scss Ændringer i Resources/app/storefront/src/scss/_variant-broken.scss: 6 tilføjet, 2 fjernet

    Ændringer i Resources/app/storefront/src/scss/_variant-broken.scss: 6 tilføjet, 2 fjernet
    Linje før Linje efter Ændring Kode
    10 10
    11 11 .header-actions-btn {
    12 12 width: 18px;
    13 Tilføjet min-width: 24px;
    13 14 height: 18px;
    14 Fjernet min-height: 0;
    15 Tilføjet min-height: 24px;
    15 16 padding: 0;
    16 17 }
    17 18
    96 97 /* 18 px colour swatches, 20 px quantity and remove buttons (vs-target-size). */
    97 98 .product-detail-configurator-option-input {
    98 99 width: 18px;
    100 Tilføjet min-width: 24px;
    99 101 height: 18px;
    102 Tilføjet min-height: 24px;
    100 103 margin-right: 4px;
    101 104 }
    102 105
    103 106 .quantity-selector-group .btn,
    104 107 .line-item-remove-button {
    105 108 width: 20px;
    109 Tilføjet min-width: 24px;
    106 110 height: 20px;
    107 Fjernet min-height: 0;
    111 Tilføjet min-height: 24px;
    108 112 padding: 0;
    109 113 }
    110 114

Bevægelse, slideshows og lyd

  • Mindre bevægelse, når en besøgende beder om det reduced-motion-guard Når en besøgendes enhed beder om reduceret bevægelse, slutter de animationer og overgange, som stilark definerer, med det samme, og blød scrolling slås fra.

    Når en besøgendes enhed er indstillet til at reducere bevægelse, får en blok i hovedstilarket animationer og overgange til at slutte med det samme og slår blød scrolling fra. Blokken gælder for hvert element på siden, så den også dækker animationer, som andre stilark definerer, herunder dem fra plugins. Hvor temaets storefront-script kun starter en timer, for eksempel et slideshows automatiske afspilning, når en autoplay-indstilling er sat, kontrollerer den betingelse nu også den besøgendes indstilling. Anden bevægelse, som et script starter, føres på listen til den, der gennemgår ændringen, og der gættes ikke.

    Regler, den dækker
    • vs-motion AUTO
    Filtyper, den ændrer
    .js.scss
    guards the pulsing badge and the slider autoplay; the animation stops under reduce Eksempeldata

    Resources/app/storefront/src/main.js Ændringer i Resources/app/storefront/src/main.js: 1 tilføjet, 1 fjernet

    Ændringer i Resources/app/storefront/src/main.js: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    139 139 });
    140 140 });
    141 141
    142 Fjernet if (options.autoplay === true) {
    142 Tilføjet if (options.autoplay === true && !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
    143 143 window.setInterval(
    144 144 function () {
    145 145 show(current + 1);

    Resources/app/storefront/src/scss/base.scss Ændringer i Resources/app/storefront/src/scss/base.scss: 14 tilføjet, 0 fjernet

    Ændringer i Resources/app/storefront/src/scss/base.scss: 14 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    1708 1708 margin: 8px 0 0;
    1709 1709 font-size: 0.875rem;
    1710 1710 }
    1711 Tilføjet
    1712 Tilføjet /* validiscan:reduced-motion-guard */
    1713 Tilføjet /* Honour the visitor's reduced-motion setting: animations and transitions end at once, no smooth scrolling. */
    1714 Tilføjet @media (prefers-reduced-motion: reduce) {
    1715 Tilføjet *,
    1716 Tilføjet *::before,
    1717 Tilføjet *::after {
    1718 Tilføjet animation-duration: 0.01ms !important;
    1719 Tilføjet animation-iteration-count: 1 !important;
    1720 Tilføjet transition-duration: 0.01ms !important;
    1721 Tilføjet scroll-behavior: auto !important;
    1722 Tilføjet }
    1723 Tilføjet }
    1724 Tilføjet /* /validiscan:reduced-motion-guard */
  • En pauseknap til slideshows i bevægelse slider-pause-control Shopwares basisslider, der ligger bag CMS’ets billedslider, får en synlig, oversat knap til pause og afspilning.

    Shopwares basisslider, den slider, der ligger bag CMS’ets billedslider, får ved siden af pilene til forrige og næste en synlig, oversat knap til pause og afspilning. En kodeblok i temaets storefront-script forbinder knappen med sliderens automatiske afspilning gennem Shopwares eget sliderplugin. Hvor temaet styrer den automatiske afspilning med sin egen timer, får timeren én linje, der springer et trin over, mens slideren er på pause. Knappen forbliver skjult, indtil scriptet har forbundet den, så den aldrig vises uden en automatisk afspilning, der kan sættes på pause. For besøgende, hvis enhed beder om reduceret bevægelse, starter slideren på pause. Slidere bygget med andre biblioteker overlades til et menneske.

    Regler, den dækker
    • vs-carousel AUTO
    Filtyper, den ændrer
    .html.twig.js.json
    adds a wired pause button to the hero slider; the carousel is no longer unstoppable Eksempeldata

    Resources/app/storefront/src/main.js Ændringer i Resources/app/storefront/src/main.js: 52 tilføjet, 0 fjernet

    Ændringer i Resources/app/storefront/src/main.js: 52 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    142 142 if (options.autoplay === true) {
    143 143 window.setInterval(
    144 144 function () {
    145 Tilføjet if (slider.getAttribute('data-autoplay-paused') === 'true') return;
    145 146 show(current + 1);
    146 147 },
    147 148 Number(options.autoplayTimeout) || 5000,
    453 454 initFilterRanges();
    454 455 initToggles();
    455 456 })();
    457 Tilføjet
    458 Tilføjet /* validiscan:slider-pause-control */
    459 Tilføjet /*
    460 Tilføjet * Pause / play button of auto-advancing sliders (WCAG 2.2.2): wired to the
    461 Tilføjet * slider's autoplay; sliders start paused when the visitor prefers reduced motion.
    462 Tilføjet */
    463 Tilføjet (function sliderPauseControl() {
    464 Tilføjet 'use strict';
    465 Tilføjet
    466 Tilføjet function tinySlider(slider) {
    467 Tilføjet const manager = window.PluginManager;
    468 Tilføjet if (!manager || typeof manager.getPluginInstanceFromElement !== 'function') return null;
    469 Tilføjet const plugin = manager.getPluginInstanceFromElement(slider, 'BaseSlider');
    470 Tilføjet return plugin && plugin._slider ? plugin._slider : null;
    471 Tilføjet }
    472 Tilføjet
    473 Tilføjet function autoplays(slider) {
    474 Tilføjet try {
    475 Tilføjet const options = JSON.parse(slider.getAttribute('data-base-slider-options') || '{}') || {};
    476 Tilføjet return Boolean(options.slider && options.slider.autoplay);
    477 Tilføjet } catch {
    478 Tilføjet return false;
    479 Tilføjet }
    480 Tilføjet }
    481 Tilføjet
    482 Tilføjet function init() {
    483 Tilføjet const reduceMotion =
    484 Tilføjet window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    485 Tilføjet document.querySelectorAll('[data-slider-pause]').forEach(function (button) {
    486 Tilføjet const slider = button.closest('[data-base-slider]');
    487 Tilføjet if (!slider || !autoplays(slider)) return;
    488 Tilføjet
    489 Tilføjet function setPaused(paused) {
    490 Tilføjet slider.setAttribute('data-autoplay-paused', paused ? 'true' : 'false');
    491 Tilføjet button.textContent = button.getAttribute(paused ? 'data-label-play' : 'data-label-pause');
    492 Tilføjet const instance = tinySlider(slider);
    493 Tilføjet if (instance) instance[paused ? 'pause' : 'play']();
    494 Tilføjet }
    495 Tilføjet
    496 Tilføjet button.hidden = false;
    497 Tilføjet button.addEventListener('click', function () {
    498 Tilføjet setPaused(slider.getAttribute('data-autoplay-paused') !== 'true');
    499 Tilføjet });
    500 Tilføjet if (reduceMotion) setPaused(true);
    501 Tilføjet });
    502 Tilføjet }
    503 Tilføjet
    504 Tilføjet if (document.readyState === 'complete') init();
    505 Tilføjet else window.addEventListener('load', init);
    506 Tilføjet })();
    507 Tilføjet /* /validiscan:slider-pause-control */

    Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 6 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 6 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "slider": {
    199 Tilføjet "pause": "Diashow anhalten",
    200 Tilføjet "play": "Diashow abspielen"
    201 Tilføjet }
    196 202 }
    197 203 }

    Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 6 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 6 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "slider": {
    199 Tilføjet "pause": "Pause slideshow",
    200 Tilføjet "play": "Play slideshow"
    201 Tilføjet }
    196 202 }
    197 203 }

    Resources/views/storefront/element/cms-element-image-slider.html.twig Ændringer i Resources/views/storefront/element/cms-element-image-slider.html.twig: 1 tilføjet, 0 fjernet

    Ændringer i Resources/views/storefront/element/cms-element-image-slider.html.twig: 1 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    57 57 <button type="button" class="base-slider-controls-next image-slider-controls-btn" data-slide-next>
    58 58 {% sw_icon 'arrow-head-right' %}
    59 59 </button>
    60 Tilføjet <button type="button" class="btn btn-light base-slider-pause" data-slider-pause="true" data-label-pause="{{ 'a11y.slider.pause'|trans|striptags }}" data-label-play="{{ 'a11y.slider.play'|trans|striptags }}" hidden>{{ 'a11y.slider.pause'|trans|sw_sanitize }}</button>
    60 61 </div>
    61 62 {% endblock %}
    62 63 </div>
  • Ingen lyd, der starter af sig selv mute-autoplay En video, der afspilles af sig selv, gøres lydløs, og lyd starter ikke længere af sig selv, undtagen automatisk afspilning fra skabelonkode eller et script og afspillere i indlejrede rammer; på Shopware bruges opskriften ikke til fund fra vs-media.

    En video, der afspilles af sig selv, får muted og playsinline, så den fortsætter med at spille lydløst, som en baggrundsvideo gør, og afspilles inde på siden i Safari på mobilen i stedet for at åbne afspilleren i fuld skærm. Lyd starter ikke længere af sig selv; de besøgende starter den selv. Automatisk afspilning, som skabelonkode eller et script sætter, og afspillere i indlejrede rammer overlades til et menneske. I en Validiscan-scanning rapporteres lyd, der starter af sig selv, af Validiscans mediekontrol vs-media, som erstatter axe-core-reglen no-autoplay-audio. vs-media, som også dækker undertekster og transskriptioner, har niveau MANUAL, så et sådant fund på Shopware kommer med vejledning i stedet for denne ændring.

    Regler, den dækker
    • no-autoplay-audio AUTO kontrolleres via vs-media
    • vs-media MANUAL
    Filtyper, den ændrer
    .html.twig
    mutes a seeded autoplaying background video; vs-media no longer reports autoplay Eksempeldata

    Resources/views/storefront/block/cms-block-video.html.twig Ændringer i Resources/views/storefront/block/cms-block-video.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/block/cms-block-video.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    9 9 <h2 class="cms-block-title">{{ block.title }}</h2>
    10 10 <p class="cms-video-text">{{ block.text }}</p>
    11 11 <div class="cms-element-video">
    12 Fjernet <video class="cms-video" autoplay loop preload="none" width="1280" height="720" poster="{{ block.posterUrl }}">
    12 Tilføjet <video class="cms-video" autoplay loop preload="none" width="1280" height="720" poster="{{ block.posterUrl }}" muted playsinline>
    13 13 <source src="{{ block.videoUrl }}" type="video/mp4">
    14 14 {% if block.captionsUrl %}
    15 15 <track kind="captions" src="{{ block.captionsUrl }}" srclang="en" label="{{ 'general.captionsEnglish'|trans }}" default>

Formularer, kurven og indlejret indhold

  • Etiketter knyttet til deres felter label-association Et felt, hvis etikettekst allerede står på siden lige før feltet, bliver knyttet til den tekst.

    Et formularfelt, hvis etikettekst allerede står på siden lige før feltet, bliver knyttet til den tekst. Et <label> uden for får en for-attribut, der peger på feltet. Et tekstelement, som temaet via sin klasse markerer som titel eller etiket, for eksempel navnet på en variantgruppe på en produktside, bliver feltets <label> og beholder sine klasser og sin egen linje. Skærmlæsere læser så etiketten op, når feltet får fokus. Et felt, der kun har en pladsholdertekst, overlades til et menneske, fordi det er en beslutning om indhold at skrive en etiket.

    Regler, den dækker
    • label AUTO kontrolleres via vs-forms-ecommerce
    • select-name ASSISTED
    • vs-forms-ecommerce AUTO
    Filtyper, den ændrer
    .html.twig
    turns the variant group titles into labels of their selects; select-name no longer fires Eksempeldata

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

    Ændringer i Resources/views/storefront/page/product-detail/configurator.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    13 13 {% for group in product.configurator %}
    14 14 {% if group.display == 'select' %}
    15 15 <div class="product-detail-configurator-group">
    16 Fjernet <div class="product-detail-configurator-group-title">{{ group.name }}</div>
    16 Tilføjet <label class="product-detail-configurator-group-title" for="configurator-{{ group.id }}">{{ group.name }}</label>
    17 17 <select class="form-select product-detail-configurator-select-input"
    18 18 id="configurator-{{ group.id }}"
    19 19 name="{{ group.id }}"{% if group.price|default(false) %}
  • Konto-, adresse- og kontaktfelter, som browsere kan udfylde autocomplete-tokens Felter, der spørger efter kundens egne oplysninger, for eksempel ved registrering, adresse og login, får den autocomplete-værdi, der svarer til det, de spørger efter, medmindre skabelonkode skriver den.

    Felter, der spørger efter kundens egne oplysninger, for eksempel i formularerne til registrering, adresse, login, kontakt og nyhedsbrev, får den autocomplete-værdi, der svarer til det, de spørger efter, for eksempel e-mail, for- og efternavn, postnummer, telefonnummer eller adgangskode. Værdien udledes af feltets type, navn, id, etiket og pladsholdertekst. Adgangskoder får new-password i registreringsformularer og current-password ellers. Felter til søgning, rabatkode, antal, captcha og beskeder bliver, som de er, og en værdi, som skabelonkode skriver, overlades til et menneske. Browsere kan så udfylde felterne, og hjælpemidler kan se, hvad hvert felt skal bruges til.

    Regler, den dækker
    • autocomplete-valid AUTO kontrolleres via vs-forms-ecommerce
    • vs-forms-ecommerce AUTO
    Filtyper, den ændrer
    .html.twig
    adds tokens to the register, address, login, contact and newsletter fields; no autocomplete hits remain Eksempeldata

    Resources/views/storefront/component/account/login.html.twig Ændringer i Resources/views/storefront/component/account/login.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/component/account/login.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    19 19 name="username"
    20 20 placeholder="{{ 'account.loginMailPlaceholder'|trans }}"
    21 21 required
    22 Fjernet autocomplete="off">
    22 Tilføjet autocomplete="email">
    23 23 </div>
    24 24
    25 25 <div class="form-group">

    Resources/views/storefront/component/account/register.html.twig Ændringer i Resources/views/storefront/component/account/register.html.twig: 8 tilføjet, 4 fjernet

    Ændringer i Resources/views/storefront/component/account/register.html.twig: 8 tilføjet, 4 fjernet
    Linje før Linje efter Ændring Kode
    33 33 id="{{ formId }}FirstName"
    34 34 name="firstName"
    35 35 placeholder="{{ 'account.firstNamePlaceholder'|trans }}"
    36 Fjernet required>
    36 Tilføjet required
    37 Tilføjet autocomplete="given-name">
    37 38 </div>
    38 39 <div class="form-group col-sm-6">
    39 40 <input type="text"
    41 42 id="{{ formId }}LastName"
    42 43 name="lastName"
    43 44 placeholder="{{ 'account.lastNamePlaceholder'|trans }}"
    44 Fjernet required>
    45 Tilføjet required
    46 Tilføjet autocomplete="family-name">
    45 47 </div>
    46 48 </div>
    47 49 <div class="row g-2">
    52 54 id="{{ formId }}Mail"
    53 55 name="email"
    54 56 placeholder="{{ 'account.emailPlaceholder'|trans }}"
    55 Fjernet required>
    57 Tilføjet required
    58 Tilføjet autocomplete="email">
    56 59 </div>
    57 60 <div class="form-group col-sm-6">
    58 61 <label class="form-label" for="{{ formId }}Password">{{ 'account.passwordLabel'|trans }}</label>
    62 65 name="password"
    63 66 minlength="8"
    64 67 aria-describedby="{{ formId }}PasswordHint"
    65 Fjernet required>
    68 Tilføjet required
    69 Tilføjet autocomplete="new-password">
    66 70 <small class="form-text" id="{{ formId }}PasswordHint">{{ 'account.passwordHint'|trans }}</small>
    67 71 </div>
    68 72 </div>

    Resources/views/storefront/component/address/address-form.html.twig Ændringer i Resources/views/storefront/component/address/address-form.html.twig: 8 tilføjet, 4 fjernet

    Ændringer i Resources/views/storefront/component/address/address-form.html.twig: 8 tilføjet, 4 fjernet
    Linje før Linje efter Ændring Kode
    14 14 id="{{ prefix }}AddressStreet"
    15 15 name="{{ prefix }}[street]"
    16 16 placeholder="{{ 'address.streetPlaceholder'|trans }}"
    17 Fjernet required>
    17 Tilføjet required
    18 Tilføjet autocomplete="address-line1">
    18 19 </div>
    19 20 {% endblock %}
    20 21
    26 27 name="{{ prefix }}[zipcode]"
    27 28 placeholder="{{ 'address.zipcodePlaceholder'|trans }}"
    28 29 inputmode="numeric"
    29 Fjernet required>
    30 Tilføjet required
    31 Tilføjet autocomplete="postal-code">
    30 32 </div>
    31 33 {% endblock %}
    32 34
    37 39 class="form-control"
    38 40 id="{{ prefix }}AddressCity"
    39 41 name="{{ prefix }}[city]"
    40 Fjernet required>
    42 Tilføjet required
    43 Tilføjet autocomplete="address-level2">
    41 44 </div>
    42 45 {% endblock %}
    43 46
    47 50 <select class="form-select"
    48 51 id="{{ prefix }}AddressCountry"
    49 52 name="{{ prefix }}[countryId]"
    50 Fjernet required>
    53 Tilføjet required
    54 Tilføjet autocomplete="country">
    51 55 {% for country in countries %}
    52 56 <option value="{{ country.id }}"{% if loop.first %} selected{% endif %}>{{ country.name }}</option>
    53 57 {% endfor %}

    Resources/views/storefront/element/cms-element-form.html.twig Ændringer i Resources/views/storefront/element/cms-element-form.html.twig: 4 tilføjet, 4 fjernet

    Ændringer i Resources/views/storefront/element/cms-element-form.html.twig: 4 tilføjet, 4 fjernet
    Linje før Linje efter Ændring Kode
    18 18 </select>
    19 19 </div>
    20 20 <div class="form-group col-md-4">
    21 Fjernet <input type="text" class="form-control" id="contactFormFirstName" name="firstName" placeholder="{{ 'account.firstNamePlaceholder'|trans }}" required>
    21 Tilføjet <input type="text" class="form-control" id="contactFormFirstName" name="firstName" placeholder="{{ 'account.firstNamePlaceholder'|trans }}" required autocomplete="given-name">
    22 22 </div>
    23 23 <div class="form-group col-md-4">
    24 Fjernet <input type="text" class="form-control" id="contactFormLastName" name="lastName" placeholder="{{ 'account.lastNamePlaceholder'|trans }}" required>
    24 Tilføjet <input type="text" class="form-control" id="contactFormLastName" name="lastName" placeholder="{{ 'account.lastNamePlaceholder'|trans }}" required autocomplete="family-name">
    25 25 </div>
    26 26 </div>
    27 27
    28 28 <div class="row g-2">
    29 29 <div class="form-group col-md-6">
    30 30 <label class="form-label" for="contactFormMail">{{ 'account.emailLabel'|trans }}</label>
    31 Fjernet <input type="email" class="form-control" id="contactFormMail" name="email" placeholder="{{ 'account.emailPlaceholder'|trans }}" required>
    31 Tilføjet <input type="email" class="form-control" id="contactFormMail" name="email" placeholder="{{ 'account.emailPlaceholder'|trans }}" required autocomplete="email">
    32 32 </div>
    33 33 <div class="form-group col-md-6">
    34 34 <label class="form-label" for="contactFormPhone">{{ 'contact.phoneLabel'|trans }}</label>
    35 Fjernet <input type="tel" class="form-control" id="contactFormPhone" name="phone">
    35 Tilføjet <input type="tel" class="form-control" id="contactFormPhone" name="phone" autocomplete="tel">
    36 36 </div>
    37 37 </div>
    38 38

    Resources/views/storefront/layout/footer/footer.html.twig Ændringer i Resources/views/storefront/layout/footer/footer.html.twig: 2 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/layout/footer/footer.html.twig: 2 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    62 62 id="footerNewsletterMail"
    63 63 class="form-control"
    64 64 placeholder="{{ 'footer.newsletterPlaceholder'|trans }}"
    65 Fjernet required>
    65 Tilføjet required
    66 Tilføjet autocomplete="email">
    66 67 <button type="submit" class="btn btn-primary newsletter-submit">{{ 'footer.newsletterSubmit'|trans }}</button>
    67 68 </div>
    68 69 <div class="form-check newsletter-privacy">
  • Ændringer i pris, lagerstatus og kurv bliver oplæst live-region-cart-variant Prisen, lagerstatussen eller kurvens samlede beløb, som storefront-scriptet opdaterer på stedet, bliver live-områder, som skærmlæsere læser op uden at afbryde, medmindre scriptet erstatter selve elementet.

    De dele af en side, som storefront-scriptet opdaterer på stedet, for eksempel prisen, når en kunde vælger en variant, lagerstatussen eller kurvens samlede beløb, bliver live-områder af typen »polite«. Skærmlæsere oplæser så den nye værdi én gang og i sin helhed uden at afbryde. Hvor et script erstatter selve elementet i stedet for dets indhold, ville et live-område ikke virke, så opskriften overlader det element til et menneske.

    Regler, den dækker
    • vs-live-updates AUTO
    Filtyper, den ændrer
    .html.twig
    makes the variant price and the cart totals polite live regions; the updates are announced Eksempeldata

    Resources/views/storefront/page/checkout/cart/index.html.twig Ændringer i Resources/views/storefront/page/checkout/cart/index.html.twig: 2 tilføjet, 2 fjernet

    Ændringer i Resources/views/storefront/page/checkout/cart/index.html.twig: 2 tilføjet, 2 fjernet
    Linje før Linje efter Ændring Kode
    59 59 <span class="line-item-unit-price-label">{{ 'checkout.cartHeaderUnitPrice'|trans }}:</span>
    60 60 <span class="line-item-unit-price-value">{{ item.unitPrice|currency }}*</span>
    61 61 </div>
    62 Fjernet <div class="line-item-total-price">
    62 Tilføjet <div class="line-item-total-price" aria-live="polite" aria-atomic="true">
    63 63 <span class="line-item-total-price-label">{{ 'checkout.cartHeaderTotalPrice'|trans }}:</span>
    64 64 <span class="line-item-total-price-value" data-line-total>{{ item.totalPrice|currency }}*</span>
    65 65 </div>
    88 88 <div class="col-lg-4 checkout-aside">
    89 89 <div class="checkout-aside-summary">
    90 90 <h2 class="checkout-aside-summary-header">{{ 'checkout.summaryHeader'|trans }}</h2>
    91 Fjernet <div class="checkout-aside-summary-totals" data-shipping-threshold="{{ shop.shippingThreshold }}" data-shipping-costs="{{ shop.shippingCosts }}">
    91 Tilføjet <div class="checkout-aside-summary-totals" data-shipping-threshold="{{ shop.shippingThreshold }}" data-shipping-costs="{{ shop.shippingCosts }}" aria-live="polite" aria-atomic="true">
    92 92 <dl class="checkout-aside-summary-list">
    93 93 <dt class="checkout-aside-summary-label">{{ 'checkout.summaryPositionPrice'|trans }}</dt>
    94 94 <dd class="checkout-aside-summary-value" data-cart-subtotal>{{ cart.subtotal|currency }}*</dd>

    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
    17 17 {% endblock %}
    18 18
    19 19 {% block buy_widget_price %}
    20 Fjernet <div class="product-detail-price-container">
    20 Tilføjet <div class="product-detail-price-container" aria-live="polite" aria-atomic="true">
    21 21 <meta itemprop="priceCurrency" content="{{ shop.currency.isoCode }}">
    22 22 <meta itemprop="price" content="{{ product.price }}">
    23 23 <p class="product-detail-price{% if product.listPrice %} with-list-price{% endif %}" data-price-display>{{ product.price|currency }}*</p>
  • Titler til indlejrede kort og videoer iframe-title En indlejret ramme uden titel får en oversat titel, der siger, hvad den viser, hvor koden afslører det.

    En indlejret ramme uden titel, for eksempel et kort eller en YouTube- eller Vimeo-video, får en oversat titel fra temaets snippet-filer, der siger, hvad den viser. Opskriften læser, hvad rammen viser, ud fra dens adresse, dens klasse og navn eller skabelonen omkring den. En ramme, hvis indhold koden ikke afslører, får ingen titel af opskriften, fordi en opfundet titel er værre end ingen.

    Regler, den dækker
    • frame-title AUTO
    Filtyper, den ændrer
    .html.twig.json
    titles the contact map frame through the snippets; frame-title no longer fires Eksempeldata

    Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 5 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 5 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "iframe": {
    199 Tilføjet "map": "Karte"
    200 Tilføjet }
    196 201 }
    197 202 }

    Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 5 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 5 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "iframe": {
    199 Tilføjet "map": "Map"
    200 Tilføjet }
    196 201 }
    197 202 }

    Resources/views/storefront/block/cms-block-map.html.twig Ændringer i Resources/views/storefront/block/cms-block-map.html.twig: 2 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/block/cms-block-map.html.twig: 2 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    11 11 <iframe class="cms-map-frame"
    12 12 src="{{ url('/widgets/cms/map') }}"
    13 13 width="1280"
    14 Fjernet height="360"></iframe>
    14 Tilføjet height="360"
    15 Tilføjet title="{{ 'a11y.iframe.map'|trans|striptags }}"></iframe>
    15 16 </div>
    16 17 <p class="cms-map-address">{{ shop.company.street }}, {{ shop.company.zip }} {{ shop.company.city }}</p>
    17 18 </div>

Kontrast, billeder og betjeningselementer, der kræver en vurdering

Tekstkontrast, tekstalternativer til billeder og navne til betjeningselementer uden navn kræver som regel en vurdering: hvilken farve der passer til dit brand, hvilke ord der beskriver et billede. De regler, der rapporterer dem, har niveau ASSISTED, som listerne herunder viser. For et fund på en ASSISTED-regel udarbejder AI kun et udkast til en ændring, hvis du har sagt ja til AI-udkast, og Validiscan gennemgår hver ændring, før den leveres.

De fire opskrifter herunder er ikke standardrettelsen for nogen regel. Hver af dem dækker kun de snævre tilfælde, hvor temaets kode alene beviser, hvad ændringen skal være. To af dem, button-semantics og icon-accessible-name, dækker også slideshow-kontrollen vs-carousel, som har niveau AUTO: I et projekt prøver rettelsesmotoren dem på dens fund, når opskriften med pauseknappen ovenfor ikke kan rette dem. De to andre dækker kun regler på niveau ASSISTED.

  • Tekstfarver med tilstrækkelig kontrast contrast-tokens En tekstfarve, der ikke består kontrastkontrollen og er defineret ét sted, ændres til den nærmeste nuance i samme farvetone med den krævede kontrast; anvendes ikke i et projekt.

    Når en tekst ikke består kontrastkontrollen, og dens farve er defineret ét sted i temaet, ændres det sted til den nærmeste nuance i samme farvetone, som opnår den krævede kontrast, så designet forbliver genkendeligt. Ét sted kan være et farvefelt i theme.json sammen med den SCSS-variabel, der gentager det, en SCSS-variabel eller en CSS-variabel, der kun bruges til tekst, eller en enkelt color-deklaration. En farve, der bruges flere steder eller også som baggrund eller kant, og Shopwares centrale farvefelter til brandet, kanter, baggrunde, statusmeddelelser og købsknappen overlades til et menneske. En farve, der er gemt i temaindstillingerne i Shopware-administrationen, tilsidesætter theme.json: Hvis den er ændret dér, skal den ændres dér også. Reglen color-contrast har niveau ASSISTED, så i et projekt følger et kontrastfund ASSISTED-forløbet, og denne opskrift anvendes ikke på det.

    Regler, den dækker
    • color-contrast ASSISTED
    Filtyper, den ændrer
    .scss
    darkens the unit price colour to 4.5:1 with the same hue; axe clears it on both pages Eksempeldata

    Resources/app/storefront/src/scss/_variant-broken.scss Ændringer i Resources/app/storefront/src/scss/_variant-broken.scss: 1 tilføjet, 1 fjernet

    Ændringer i Resources/app/storefront/src/scss/_variant-broken.scss: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    45 45 /* Light grey unit prices, 3.1:1 (color-contrast). */
    46 46 .product-price-unit,
    47 47 .product-detail-price-unit {
    48 Fjernet color: #929292;
    48 Tilføjet color: #757575;
    49 49 }
    50 50
    51 51 /* Fixed two-line product names (vs-text-spacing). */
  • Dekorative billeder skjult for skærmlæsere decorative-image-alt Kun billeder, som skabelonen beviser er dekorative, får et tomt alt eller aria-hidden; anvendes ikke i et projekt.

    Et billede markeres kun som dekorativt, når skabelonen beviser, at det ikke tilføjer noget: Det sidder i et link eller en knap, der har navn på anden måde, det er et ikon ved siden af sin egen tekstetiket, eller det er en afstandsholder eller en skillelinje. Et <img> får et tomt alt, et billede, der udskrives med Shopwares sw_thumbnails-tag, får et tomt alt i sine attributter, og SVG-ikoner får aria-hidden="true", så skærmlæsere springer dem over i stedet for at læse et filnavn op. Ethvert andet billede er indhold, for eksempel betalingslogoerne i en sidefod, og dets tekstalternativ kræver ord, som et menneske vælger. De regler, denne opskrift dækker, har niveau ASSISTED, så i et projekt følger deres fund ASSISTED-forløbet, og denne opskrift anvendes ikke på dem.

    Regler, den dækker
    • image-alt ASSISTED
    • role-img-alt ASSISTED
    • svg-img-alt ASSISTED
    Filtyper, den ændrer
    .html.twig
    marks a seeded phone icon inside the hotline link decorative; image-alt stops firing there Eksempeldata

    Resources/views/storefront/layout/footer/footer.html.twig Ændringer i Resources/views/storefront/layout/footer/footer.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/layout/footer/footer.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    9 9 <div class="footer-column-content">
    10 10 <p class="footer-contact-hotline">
    11 11 {{ 'footer.serviceHotlineText'|trans }}
    12 Fjernet <a class="footer-contact-hotline-link" href="tel:+49405550192"><img src="{{ asset('bundles/storefront/assets/icon/default/headset.svg') }}" class="footer-contact-hotline-icon" width="16" height="16"> {{ shop.company.phone }}</a>
    12 Tilføjet <a class="footer-contact-hotline-link" href="tel:+49405550192"><img src="{{ asset('bundles/storefront/assets/icon/default/headset.svg') }}" class="footer-contact-hotline-icon" width="16" height="16" alt=""> {{ shop.company.phone }}</a>
    13 13 </p>
    14 14 <p class="footer-contact-hours">{{ 'footer.serviceHours'|trans }}</p>
    15 15 <p class="footer-contact-form">
  • Betjeningselementer, der kun virker med mus, bliver til knapper button-semantics Betjeningselementer i slidere og cookiebannere, der kun reagerer på en mus, bliver til rigtige knapper og beholder klasser, data-attributter og id’er; i et projekt prøves opskriften på slideshowfund fra vs-carousel.

    Klikbare <div>-, <span>-, <i>- og <li>-elementer i slidere og cookiebannere og links uden adresse, som kun reagerer på en mus, bliver til rigtige knapper. Klasser, data-attributter og id’er bevares, så temaets script finder dem som før, og Enter og mellemrumstasten gør nu det samme som et klik. Et listeelement beholder sin plads i listen og får knappen inde i sig. Et betjeningselement uden tekst får et oversat navn ud fra sit formål, for eksempel »Show slide 2«, og en lille nulstilling af stilen bevarer dets udseende. Et betjeningselement uden tekst, hvis formål er uklart, eller hvis styling afhænger af dets tag eller dets placering, overlades til et menneske. I et projekt prøves denne opskrift på slideshowfund fra vs-carousel; fund fra cookiebanner-kontrollen vs-cookie-banner har niveau ASSISTED og følger ASSISTED-forløbet.

    Regler, den dækker
    • vs-carousel AUTO
    • vs-cookie-banner ASSISTED
    Filtyper, den ændrer
    .html.twig.json.scss
    turns the mouse-only slider dots into named buttons in their list items; vs-carousel stops reporting them Eksempeldata

    Resources/app/storefront/src/scss/base.scss Ændringer i Resources/app/storefront/src/scss/base.scss: 17 tilføjet, 0 fjernet

    Ændringer i Resources/app/storefront/src/scss/base.scss: 17 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    1708 1708 margin: 8px 0 0;
    1709 1709 font-size: 0.875rem;
    1710 1710 }
    1711 Tilføjet
    1712 Tilføjet /* validiscan:button-semantics */
    1713 Tilføjet /* Former <div>/<span>/<li> controls, now <button>: drop the browser button styles, keep the theme's (no specificity). */
    1714 Tilføjet :where(button.base-slider-dot) {
    1715 Tilføjet display: block;
    1716 Tilføjet margin: 0;
    1717 Tilføjet padding: 0;
    1718 Tilføjet border: 0;
    1719 Tilføjet background: none;
    1720 Tilføjet color: inherit;
    1721 Tilføjet font: inherit;
    1722 Tilføjet line-height: inherit;
    1723 Tilføjet text-align: inherit;
    1724 Tilføjet cursor: pointer;
    1725 Tilføjet appearance: none;
    1726 Tilføjet }
    1727 Tilføjet /* /validiscan:button-semantics */

    Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 5 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 5 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "control": {
    199 Tilføjet "showSlide": "Folie %index% anzeigen"
    200 Tilføjet }
    196 201 }
    197 202 }

    Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 5 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 5 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "control": {
    199 Tilføjet "showSlide": "Show slide %index%"
    200 Tilføjet }
    196 201 }
    197 202 }

    Resources/views/storefront/element/cms-element-image-slider.html.twig Ændringer i Resources/views/storefront/element/cms-element-image-slider.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/element/cms-element-image-slider.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    51 51 </button>
    52 52 <ol class="base-slider-dots">
    53 53 {% for slide in slides %}
    54 Fjernet <li class="base-slider-dot{% if loop.first %} is-active{% endif %}" data-slide-to="{{ loop.index0 }}"></li>
    54 Tilføjet <li><button class="base-slider-dot{% if loop.first %} is-active{% endif %}" data-slide-to="{{ loop.index0 }}" type="button" aria-label="{{ 'a11y.control.showSlide'|trans({'%index%': loop.index})|striptags }}"></button></li>
    55 55 {% endfor %}
    56 56 </ol>
    57 57 <button type="button" class="base-slider-controls-next image-slider-controls-btn" data-slide-next>
  • Navne til knapper og links, der kun består af et ikon icon-accessible-name Knapper og links, der kun viser et ikon, får et oversat navn, der siger, hvad de gør, hvor koden afslører deres formål; i et projekt prøves opskriften på de slideshowkontroller, som vs-carousel rapporterer.

    Knapper og links, der kun viser et ikon, for eksempel søgning, kurv, konto, logolinket, pile i slidere, knapper til antal og cookievalg, får en oversat aria-label, der siger, hvad de gør. Formålet udledes af betjeningselementets klasser, dets linkmål, ikonet inde i det og den komponent, der omgiver det. Et betjeningselement, hvis formål koden ikke afslører, for eksempel et link til et socialt medie, hvis netværk er gemt som data, overlades til et menneske, fordi et opfundet navn er værre end intet. I et projekt prøves denne opskrift på de slideshowkontroller, som vs-carousel rapporterer; andre betjeningselementer, der kun består af et ikon, rapporteres af regler på niveau ASSISTED og følger ASSISTED-forløbet.

    Regler, den dækker
    • button-name ASSISTED
    • link-name ASSISTED
    • vs-carousel AUTO
    • vs-cookie-banner ASSISTED
    Filtyper, den ændrer
    .html.twig.json
    names every icon-only button of the home, product and cart pages; button-name no longer fires Eksempeldata

    Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 12 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 12 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "control": {
    199 Tilføjet "search": "Suchen",
    200 Tilføjet "previousSlide": "Vorherige Folie",
    201 Tilføjet "nextSlide": "Nächste Folie",
    202 Tilføjet "cookieSettings": "Cookie-Einstellungen",
    203 Tilføjet "acceptCookies": "Alle Cookies akzeptieren",
    204 Tilføjet "decreaseQuantity": "Menge verringern",
    205 Tilføjet "increaseQuantity": "Menge erhöhen",
    206 Tilføjet "removeFromCart": "Aus dem Warenkorb entfernen"
    207 Tilføjet }
    196 208 }
    197 209 }

    Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 12 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 12 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "control": {
    199 Tilføjet "search": "Search",
    200 Tilføjet "previousSlide": "Previous slide",
    201 Tilføjet "nextSlide": "Next slide",
    202 Tilføjet "cookieSettings": "Cookie settings",
    203 Tilføjet "acceptCookies": "Accept all cookies",
    204 Tilføjet "decreaseQuantity": "Decrease quantity",
    205 Tilføjet "increaseQuantity": "Increase quantity",
    206 Tilføjet "removeFromCart": "Remove from cart"
    207 Tilføjet }
    196 208 }
    197 209 }

    Resources/views/storefront/element/cms-element-image-gallery.html.twig Ændringer i Resources/views/storefront/element/cms-element-image-gallery.html.twig: 2 tilføjet, 2 fjernet

    Ændringer i Resources/views/storefront/element/cms-element-image-gallery.html.twig: 2 tilføjet, 2 fjernet
    Linje før Linje efter Ændring Kode
    31 31
    32 32 {% if media|length > 1 %}
    33 33 <div class="gallery-slider-controls">
    34 Fjernet <button type="button" class="base-slider-controls-prev gallery-slider-controls-prev" data-gallery-prev>
    34 Tilføjet <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 Fjernet <button type="button" class="base-slider-controls-next gallery-slider-controls-next" data-gallery-next>
    37 Tilføjet <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 Ændringer i Resources/views/storefront/element/cms-element-image-slider.html.twig: 2 tilføjet, 2 fjernet

    Ændringer i Resources/views/storefront/element/cms-element-image-slider.html.twig: 2 tilføjet, 2 fjernet
    Linje før Linje efter Ændring Kode
    46 46
    47 47 {% block element_image_slider_controls %}
    48 48 <div class="image-slider-controls-container">
    49 Fjernet <button type="button" class="base-slider-controls-prev image-slider-controls-btn" data-slide-prev>
    49 Tilføjet <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 Fjernet <button type="button" class="base-slider-controls-next image-slider-controls-btn" data-slide-next>
    57 Tilføjet <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 Ændringer i Resources/views/storefront/layout/cookie/cookie-permission.html.twig: 2 tilføjet, 2 fjernet

    Ændringer i Resources/views/storefront/layout/cookie/cookie-permission.html.twig: 2 tilføjet, 2 fjernet
    Linje før Linje efter Ændring Kode
    22 22 </p>
    23 23 </div>
    24 24 <div class="col-auto cookie-permission-actions">
    25 Fjernet <button type="button" class="btn cookie-permission-icon-btn js-cookie-configuration-toggle">{% sw_icon 'settings' %}</button>
    26 Fjernet <button type="button" class="btn btn-primary cookie-permission-icon-btn js-cookie-accept-all-button">{% sw_icon 'checkmark' %}</button>
    25 Tilføjet <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 Tilføjet <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 Ændringer i Resources/views/storefront/layout/header/search.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/layout/header/search.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    13 13 autocomplete="off"
    14 14 autocapitalize="off"
    15 15 placeholder="{{ 'header.searchPlaceholder'|trans }}" value="{{ page.searchTerm }}">
    16 Fjernet <button type="submit" class="btn header-search-btn">
    16 Tilføjet <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 Ændringer i Resources/views/storefront/page/checkout/cart/index.html.twig: 3 tilføjet, 3 fjernet

    Ændringer i Resources/views/storefront/page/checkout/cart/index.html.twig: 3 tilføjet, 3 fjernet
    Linje før Linje efter Ændring Kode
    39 39 </div>
    40 40 <div class="line-item-quantity">
    41 41 <div class="input-group quantity-selector-group" data-quantity-selector="true">
    42 Fjernet <button type="button" class="btn btn-outline-light btn-minus js-btn-minus">
    42 Tilføjet <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 Fjernet <button type="button" class="btn btn-outline-light btn-plus js-btn-plus">
    53 Tilføjet <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 Fjernet <button type="button" class="btn btn-light btn-sm line-item-remove-button">
    67 Tilføjet <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 Ændringer i Resources/views/storefront/page/product-detail/buy-widget.html.twig: 2 tilføjet, 2 fjernet

    Ændringer i Resources/views/storefront/page/product-detail/buy-widget.html.twig: 2 tilføjet, 2 fjernet
    Linje før Linje efter Ændring Kode
    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 Fjernet <button type="button" class="btn btn-outline-light btn-minus js-btn-minus">
    67 Tilføjet <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 Fjernet <button type="button" class="btn btn-outline-light btn-plus js-btn-plus">
    78 Tilføjet <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>
    names the logo and account links; social links whose network is data are left for review Eksempeldata

    Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 6 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/de_DE/kaffeekontor-nord.de-DE.json: 6 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "control": {
    199 Tilføjet "home": "Zur Startseite",
    200 Tilføjet "account": "Ihr Konto"
    201 Tilføjet }
    196 202 }
    197 203 }

    Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 6 tilføjet, 0 fjernet

    Ændringer i Resources/snippet/en_GB/kaffeekontor-nord.en-GB.json: 6 tilføjet, 0 fjernet
    Linje før Linje efter Ændring Kode
    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 Tilføjet },
    197 Tilføjet "a11y": {
    198 Tilføjet "control": {
    199 Tilføjet "home": "Go to the homepage",
    200 Tilføjet "account": "Your account"
    201 Tilføjet }
    196 202 }
    197 203 }

    Resources/views/storefront/layout/header/actions.html.twig Ændringer i Resources/views/storefront/layout/header/actions.html.twig: 2 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/layout/header/actions.html.twig: 2 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    3 3 {% block layout_header_actions_account %}
    4 4 <div class="header-account">
    5 5 <a href="{{ url('/account/login') }}"
    6 Fjernet class="btn account-menu-btn header-actions-btn">
    6 Tilføjet class="btn account-menu-btn header-actions-btn"
    7 Tilføjet 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 Ændringer i Resources/views/storefront/layout/header/logo.html.twig: 1 tilføjet, 1 fjernet

    Ændringer i Resources/views/storefront/layout/header/logo.html.twig: 1 tilføjet, 1 fjernet
    Linje før Linje efter Ændring Kode
    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 Fjernet <a class="header-logo-main-link" href="{{ url('/') }}">
    5 Tilføjet <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') }}"
Detaljer: niveauerne, testtemaet, kontrollen af hver ændring og tekst på din webshops sprog

En opskrift er en deterministisk ændring for én slags fejl: Den samme kode får altid den samme ændring. Validiscan har 20 opskrifter til Shopware-temaer. Hver af dem foretager kun en ændring, hvor temaets kode viser, hvad den rigtige ændring er. Hvor den ikke gør det, ændrer opskriften intet. Den gætter ikke.

Under hver opskrift finder du de regler, den dækker, med hver regels niveau i Validiscans regelkatalog for Shopware. AUTO betyder, at en opskrift er reglens standardrettelse. ASSISTED betyder, at rettelsen kræver en vurdering, så en ændring udarbejdes som udkast og gennemgås derefter. MANUAL betyder, at reglen kræver en persons beslutning og kommer med vejledning, ikke med en kodeændring. I et projekt anvendes opskrifter på fund af regler på niveau AUTO. Hvor en opskrift også angiver en regel på niveau ASSISTED eller MANUAL, følger et fund af den regel i stedet ASSISTED- eller MANUAL-forløbet. En regel, der kontrolleres via en anden kontrol, køres ikke selvstændigt i en scanning; den anden kontrol rapporterer den samme fejl.

Filtyperne og før-og-efter-visningen for hver opskrift stammer fra Validiscans egne tests. De kører på Validiscans Shopware-testtema, et temaplugin bygget på standard-storefronten i Shopware 6, hvor der med vilje er lagt tilgængelighedsfejl ind. Hver test gengiver temaets skabeloner som sider før og efter ændringen og kører den samme regel på begge: Fejlen skal rapporteres før og ikke længere efter, og ændringen må ikke give en ny fejl for den regel. Siderne gengives af en testrenderer, ikke af en fuld Shopware-installation, og dit temas filer ser anderledes ud.

Før Validiscan gennemgår en ændring, kontrolleres hver ændret fil. Twig-skabeloner læses af en parser, der kender Shopwares egne tags, for eksempel sw_extends og sw_include; de kompileres eller køres aldrig. Stilark får en strukturkontrol, snippet-filer og theme.json læses som JSON, og JavaScript får en syntakskontrol.

Når en opskrift tilføjer synlig tekst eller et navn, for eksempel ordene i et spring over-link eller navnet på en ikonknap, bruger den en snippet i skabelonen. Teksten lægges i temaets engelske snippet-fil, som opskriften opretter, hvis temaet ikke har en, og i dets tyske snippet-fil, hvor temaet har en. Snippets, der allerede findes, beholder deres tekst. Tekst på webshoppens andre sprog tilføjes ikke.

Hvad forbliver på niveau MANUAL på Shopware?

Fejl, der kræver en beslutning om indhold eller adfærd, som en fast kodeændring ikke kan træffe, for eksempel undertekster og transskriptioner til dine videoer og din lyd, forbliver på niveau MANUAL på Shopware. For et fund på en MANUAL-regel giver Validiscan vejledning i, hvordan det rettes, ikke en ændring af din kode.

Reglerne herunder køres i scanninger og har niveau MANUAL på Shopware.

  • meta-refresh Forsinket genindlæsning under 20 timer må ikke bruges
  • nested-interactive Interaktive betjeningselementer må ikke være indlejret i hinanden
  • scrollable-region-focusable Scrollbare områder skal kunne nås med tastaturet
  • server-side-image-map Serverside-billedkort må ikke bruges
  • vs-keyboard-trap Tastaturfokus må aldrig sidde fast
  • vs-focus-order Fokusrækkefølgen skal følge den visuelle rækkefølge
  • vs-dragging Elementer, der kun kan betjenes ved at trække, skal have et alternativ med et enkelt klik eller tryk
  • vs-media Video skal have undertekster, lyd skal have en transskription, og intet må afspille lyd automatisk
  • vs-documents Linkede dokumenter skal gennemgås manuelt for tilgængelighed
Detaljer: hvad et fund på niveau MANUAL får, og hvad et projekt ikke omfatter

For et fund på en MANUAL-regel giver Validiscan vejledning i, hvordan det rettes, ikke en ændring af din kode. Disse fejl kræver en beslutning om indhold eller adfærd, som en fast kodeændring ikke kan træffe, for eksempel undertekster og transskriptioner til dine videoer og din lyd, en vej ud af en widget, hvor tastaturfokus sidder fast, eller en anden måde at bruge et betjeningselement på, som kun virker ved at trække.

Arbejdet med fund på niveau MANUAL, der kræver dine egne beslutninger om indhold, er ikke en del af et projekt, og det samme gælder PDF-filer. Hvad scanningen tester automatisk, og hvad der kontrolleres ved manuel gennemgang

Hvad stiller du til rådighed?

Du sørger for tilladelse til en fuld scanning, én vej ind i dit temaplugin, dit svar om AI-udkast til ASSISTED-rettelser, en udvikler, der gennemgår ændringerne, bygger og ruller temaet ud, nogle indstillinger i Shopware-administrationen, ny tekst på andre sprog end engelsk og tysk og dine beslutninger om det, der forbliver MANUAL.

  1. Din tilladelse til en fuld scanning af din webshop, som Validiscan registrerer før scanningen. En fuld scanning lægger et produkt i kurven og åbner det første trin i kassen uden at gennemføre et køb eller indtaste betalingsoplysninger.
  2. Én vej ind i dit tema: adgang til det GitHub-repository, der rummer temapluginet, eller en ZIP-fil med pluginets mappe under custom/plugins, uploadet i kundeportalen.
  3. Dit svar på, om AI må udarbejde rettelser på niveau ASSISTED. AI-udkast er slået fra, indtil du siger ja.
  4. En udvikler, der gennemgår ændringerne, merger pull requesten eller anvender patchpakken, bygger temaet og ruller det ud.
  5. De indstillinger i Shopware-administrationen, som rettelserne ikke ændrer: metatitler til sider, der ingen har, sproget for indhold, der er skrevet på et andet sprog end din webshops, og en farve, der er gemt i temaindstillingerne, når en kontrastrettelse ændrer den farve.
  6. Tekst på webshoppens andre sprog end engelsk og tysk, hvor en rettelse tilføjer ny tekst.
  7. Dine beslutninger om det, der forbliver MANUAL, for eksempel undertekster til dine videoer.
Detaljer: når ændringerne er live, og hvad et projekt dækker

Når ændringerne er live, kontrollerer en verifikationsscanning de berørte sider igen, og Remediation Evidence Package registrerer resultatet. Sådan forløber et projekt, trin for trin

Et projekt dækker én webshop: ét domæne og ét tema. Det gælder en storefront bygget på et tema; en headless storefront fås på forespørgsel.

Kilder

2 kilder, alle kontrolleret til denne side den 6. oktober 2026.

Shopwares udvikler­dokumentation 2
  1. Add SCSS Styling and JavaScript to a Theme · Shopware · kontrolleret
  2. Add custom JavaScript · Shopware · kontrolleret

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