Korrekturen zur Barrierefreiheit im Code Ihres Themes für Shopify

Validiscan behebt Fehler der Barrierefreiheit in den Liquid-Templates, Stylesheets, Skripten und Sprachdateien Ihres Shopify-Themes. Die Änderungen kommen als unveröffentlichte Kopie Ihres Themes, als Pull Request oder als Patch-Paket, und nichts gelangt in Ihr Live-Theme, bevor Sie oder Ihr Entwicklungsteam sie veröffentlichen, zusammenführen oder einspielen.

Zuletzt aktualisiert:

Welche Dateien in einem Shopify-Theme ändert Validiscan?

Validiscan ändert die eigenen Dateien Ihres Themes und sonst nichts: die Liquid-Dateien in layout, templates, sections, snippets und blocks, die Stylesheets und Skripte in assets, die Texte der Storefront in locales und die Einstellungen in config. Eine Änderung an einer anderen Datei wird abgelehnt, bevor Validiscan sie prüft.

Der Checkout von Shopify gehört nicht zum Code Ihres Themes

Ein vollständiger Scan öffnet den ersten Schritt im Checkout, aber für die Schritte Informationen, Versand und Zahlung unterstützt Shopify checkout.liquid nicht mehr, die Layoutdatei des Themes für den Checkout. Ein Fehler, den ein Scan in diesen Schritten findet, lässt sich deshalb nicht durch eine Änderung an den Dateien Ihres Themes beheben.

Details: was eine Änderung hinzufügen darf und was außerhalb dieser Arbeit liegt

Jede Änderung ist eine gewöhnliche Bearbeitung einer Theme-Datei, die Sie oder Ihr Entwicklungsteam Zeile für Zeile lesen können. Einige Korrekturen fügen dem eigenen Skript des Themes ein paar Zeilen hinzu, zum Beispiel um eine Pause-Schaltfläche mit einer Slideshow zu verbinden. Keine Korrektur fügt eine App oder ein Overlay hinzu, und es wird nichts eingeschleust, das Ihre Seiten im Browser der Besucherinnen und Besucher korrigiert. Code, der nicht zu den Dateien Ihres Themes gehört, liegt außerhalb dieser Arbeit, und eingebundene Dienste von Drittanbietern wie Zahlungs- oder Chat-Widgets sind in einem Projekt nicht enthalten.

Wie erhält Validiscan Zugriff auf Ihr Shopify-Theme?

Validiscan erreicht Ihr Shopify-Theme auf einem von drei Wegen: über Ihr GitHub-Repository, mit einem Theme-Access-Passwort oder aus einer Theme-Datei, die Sie selbst herunterladen. Welcher Weg passt, hängt davon ab, wo der Code Ihres Themes liegt; er bestimmt auch, wie die Änderungen zu Ihnen zurückkommen.

Die drei Wege in ein Shopify-Theme
Weg Was Sie geben Die Änderungen kommen zurück als
Über Ihr GitHub-Repository Zugriff auf das Repository, über die GitHub App von Validiscan oder ein Zugriffstoken Ein Pull Request
Mit einem Theme-Access-Passwort Ein Theme-Access-Passwort und die myshopify.com-Adresse Ihres Shops Eine unveröffentlichte Kopie Ihres Themes
Aus einer Theme-Datei, die Sie herunterladen Die ZIP-Datei Ihres Themes, bis zu 100 MB, im Kundenportal hochgeladen von einem Admin Ihrer Organisation Ein Patch-Paket

Über Ihr GitHub-Repository

Liegt der Code Ihres Themes in einem GitHub-Repository, zum Beispiel über die GitHub-Integration von Shopify, geben Sie Validiscan Zugriff auf dieses Repository. Sie installieren die GitHub App von Validiscan darauf oder geben Validiscan ein Zugriffstoken. Die App verlangt Lese- und Schreibzugriff auf die Inhalte und die Pull Requests des Repositorys sowie Lesezugriff auf seine Metadaten. Die Ordner des Themes, etwa layout, sections und snippets, müssen auf der obersten Ebene des Repositorys liegen, weil Änderungen an anderen Pfaden abgelehnt werden. Die Änderungen kommen dann als Pull Request.

Mit einem Theme-Access-Passwort

Die kostenlose App Theme Access von Shopify erstellt Passwörter, mit denen Entwicklerinnen und Entwickler über die Shopify CLI an den Themes eines Shops arbeiten können. Als Inhaberin oder Inhaber des Shops oder als Mitarbeiterin oder Mitarbeiter mit der Berechtigung für Themes installieren Sie die App und erstellen ein Passwort für Validiscan; Shopify sendet Validiscan per E-Mail einen Link zum Passwort, das sich nur einmal anzeigen lässt. Außerdem geben Sie Validiscan die myshopify.com-Adresse Ihres Shops. Validiscan speichert das Passwort verschlüsselt und verwendet es mit der Shopify CLI, um Ihr Live-Theme herunterzuladen und eine neue, unveröffentlichte Kopie davon hochzuladen. Ein Theme-Access-Passwort erlaubt Änderungen an den Themes des Shops. Deshalb lehnt der Auslieferungscode von Validiscan jeden Befehl ab, der in das Live-Theme schreiben oder ein Theme veröffentlichen würde. Sie beenden den Zugriff, indem Sie das Passwort in der App Theme Access löschen; laut Shopifys Dokumentation (Stand: 6. Oktober 2026) widerruft das Löschen eines Passworts den Zugriff. Validiscan verwendet das Passwort nach einer Auslieferung erneut, um zu prüfen, ob die Kopie veröffentlicht wurde. Löschen Sie es deshalb, wenn das Projekt abgeschlossen ist, und erstellen Sie für eine spätere Auslieferung ein neues.

Aus einer Theme-Datei, die Sie herunterladen

Passt keiner der beiden Wege, laden Sie Ihr Theme selbst herunter. Das Kundenportal nennt dafür diese Schritte:

  1. Öffnen Sie in Ihrem Shopify-Adminbereich „Onlineshop“ und dann „Themes“.
  2. Wählen Sie im Menü des Themes, das Sie verwenden, „Theme-Datei herunterladen“.
  3. Shopify sendet Ihnen die ZIP-Datei per E-Mail.

Shopifys eigene Anleitung steht im Hilfeartikel zum Herunterladen von Themes, auf Englisch. Ein Admin Ihrer Organisation im Kundenportal, zum Beispiel Ihre Entwicklerin oder Ihr Entwickler, lädt die Datei dort anschließend hoch, als eine einzige ZIP-Datei von bis zu 100 MB. Validiscan bereitet die Änderungen auf dieser Kopie Ihres Themes vor und schickt sie als Patch-Paket zurück.

Wie gelangen die Änderungen in Ihren Shop?

Validiscan liefert die Änderungen auf einem von drei Wegen aus: als unveröffentlichte Kopie Ihres Shopify-Themes, als Pull Request oder als Patch-Paket. Ausgeliefert werden nur Änderungen, die Validiscan geprüft und freigegeben hat, und keiner der drei Wege berührt Ihr Live-Theme.

Die Theme-Kopie veröffentlichen, in fünf Schritten

Mit einem Theme-Access-Passwort lädt Validiscan Ihr Live-Theme herunter, wendet die freigegebenen Änderungen an und lädt das Ergebnis als neues, unveröffentlichtes Theme mit dem Namen Validiscan A11y <date> hoch, zum Beispiel Validiscan A11y 2026-09-24. Sie erhalten eine E-Mail, sobald es bereit ist. Dann:

  1. Öffnen Sie im Shopify-Adminbereich „Onlineshop“ und dann „Themes“, und suchen Sie unter Ihren Theme-Entwürfen das unveröffentlichte Theme Validiscan A11y <date>.
  2. Sehen Sie es sich in der Vorschau an. Ihre Besucherinnen und Besucher sehen währenddessen weiter das Live-Theme.
  3. Prüfen Sie die betroffenen Seiten in der Vorschau, auch allein mit der Tastatur.
  4. Wenn Sie zufrieden sind, wählen Sie „Veröffentlichen“. Shopify beschreibt diesen Schritt in seinem Hilfeartikel zum Veröffentlichen von Themes, auf Englisch.
  5. Behalten Sie Ihr bisheriges Theme, bis Sie sicher sind. Sie können zu ihm zurückkehren.

Eine unveröffentlichte Kopie Ihres Themes

Die Kopie entspricht Ihrem Live-Theme an dem Tag, an dem Validiscan es heruntergeladen hat. Ändern Sie das Live-Theme nach diesem Tag, ob Inhalte, Einstellungen oder Code, übernehmen Sie dieselbe Änderung auch in die Kopie, bevor Sie sie veröffentlichen; sonst geht die Änderung verloren. Das Kundenportal zeigt, ob die Kopie auf die Veröffentlichung wartet, veröffentlicht wurde oder ohne Veröffentlichung gelöscht wurde. Laut dem englischsprachigen Hilfeartikel von Shopify zum Aktualisieren von Themes gibt es Updates nur für Themes, die aus dem Shopify Theme Store installiert wurden, und für hochgeladene Themes werden automatische Updates nicht unterstützt. Die Kopie wird mit der Shopify CLI hochgeladen. Prüfen Sie deshalb vor dem Veröffentlichen unter „Onlineshop“ und dann „Themes“, ob Shopify für die Kopie noch Updates anbietet. Wohin Korrekturen in einem Shopify-Theme gehören und was ein Theme-Update rückgängig machen kann

Ein Pull Request

Mit Zugriff auf Ihr Repository legt Validiscan einen neuen Branch mit dem Namen validiscan/a11y-<date>-<id> an, committet jede Korrektur einzeln und öffnet einen Pull Request mit einer Übersichtstabelle, einer Erklärung jeder Änderung und einer Checkliste für die Prüfung. In Ihren Standard-Branch wird nichts übertragen. Mit der GitHub-Integration von Shopify folgt ein Theme dem Branch, mit dem es verbunden ist: Ihr Entwicklungsteam kann den Branch des Pull Requests mit einem unveröffentlichten Theme verbinden, um ihn in der Vorschau anzusehen, und das Zusammenführen in den Branch, dem Ihr Live-Theme folgt, ändert das Live-Theme.

Ein Patch-Paket

Aus einer hochgeladenen Theme-Datei bereitet Validiscan ein ZIP-Archiv für Ihr Entwicklungsteam vor. Es enthält die PATCH.md mit jeder Änderung und der Anleitung, wie sie eingespielt wird, alle Änderungen in einer Patch-Datei, eine Patch-Datei je Korrektur, die vollständigen geänderten Dateien und eine README.md. Ihr Entwicklungsteam spielt die Änderungen ein, testet sie und veröffentlicht das Theme. Was ein Pull Request und ein Patch-Paket enthalten

Was ändern die Rezepte in einem Shopify-Theme?

Jedes der 20 Rezepte von Validiscan für Shopify-Themes ist eine deterministische Änderung für eine Art von Fehler: Derselbe Code erhält immer dieselbe Änderung. Ein Rezept ändert nur dort etwas, wo der Code des Themes zeigt, welche Änderung die richtige ist; sonst bleibt der Befund einem Menschen überlassen.

Seitenstruktur und Navigation

  • Seitensprache aus der Sprache Ihres Shops html-lang Ein Layout, dessen <html>-Element kein, ein leeres oder ein ungültiges lang-Attribut hat, erhält die Sprache, in der Ihr Shop gerade angezeigt wird.

    Ein Layout, dessen <html>-Element kein lang-Attribut, ein leeres oder ein ungültiges hat, erhält die Sprache, in der Ihr Shop gerade angezeigt wird, sodass Screenreader die Seite in der richtigen Sprache vorlesen. Wo das Theme die eigene Sprache einer Seite bereits in einem Metafeld ablegt, zum Beispiel bei deutschen Rechtstexten in einem englischen Shop, verwendet das Layout dieses Metafeld, wenn es gesetzt ist. Ohne ein solches Feld rät das Rezept die Sprache einer Seite nicht.

    Abgedeckte Regeln
    • html-has-lang AUTO geprüft durch vs-lang
    • html-lang-valid AUTO geprüft durch vs-lang
    • vs-lang AUTO
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    layout/checkout.liquid Änderungen an layout/checkout.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an layout/checkout.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    3 3 Checkout layout (the Shopify Plus `checkout.liquid` era). Only the first step
    4 4 (contact, delivery, billing) is modelled; nothing is ever submitted.
    5 5 {% endcomment %}
    6 Entfernt <html class="no-js">
    6 Hinzugefügt <html class="no-js" lang="{{ request.locale.iso_code }}">
    7 7 <head>
    8 8 <meta charset="utf-8">
    9 9 <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

    layout/theme.liquid Änderungen an layout/theme.liquid: 3 hinzugefügt, 0 entfernt

    Änderungen an layout/theme.liquid: 3 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    6 6 {% endcomment %}
    7 7 {%- liquid
    8 8 assign page_lang = request.locale.iso_code
    9 Hinzugefügt if page.metafields.custom.content_language != blank
    10 Hinzugefügt assign page_lang = page.metafields.custom.content_language
    11 Hinzugefügt endif
    9 12 -%}
    10 13 <html class="no-js" lang="{{ page_lang }}">
    11 14 <head>
  • Ein Titel auf jeder Seite document-title-template Layouts, deren <title> fehlt, leer ist oder auf jeder Seite derselbe feste Text ist, erhalten einen Titel aus den Variablen von Shopify.

    Jedes Layout, dessen <title> fehlt, leer ist oder auf jeder Seite derselbe feste Text ist, erhält einen Titel, der aus den Variablen von Shopify aufgebaut wird. Hat Ihr Haupt-Layout bereits einen Titel, der die Seite benennt, erhalten die anderen Layouts denselben. Andernfalls enthält der Titel den Seitentitel, die Seitennummer einer mehrseitigen Liste und den Namen des Shops, wobei das Wort für „Seite“ über die Sprachdateien des Themes übersetzt wird.

    Abgedeckte Regeln
    • document-title AUTO
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    layout/theme.focused.liquid Änderungen an layout/theme.focused.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an layout/theme.focused.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    11 11 <meta charset="utf-8">
    12 12 <meta http-equiv="X-UA-Compatible" content="IE=edge">
    13 13 <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    14 Entfernt <title></title>
    14 Hinzugefügt <title>{{ page_title }}{% unless page_title contains shop.name %} &ndash; {{ shop.name }}{% endunless %}</title>
    15 15 <link rel="canonical" href="{{ canonical_url }}">
    16 16 <!-- Theme assets: //cdn.shopify.com/s/files/1/0712/3456/7890/t/12/assets/ (served locally by the fixture server) -->
    17 17 {% render 'meta-tags' %}
  • Überschriften ohne übersprungene Ebenen heading-levels Eine Überschrift, die eine Ebene überspringt, erhält die nächste Ebene unterhalb der vorangehenden Überschrift; eine verborgene Überschrift fügt das Rezept nicht hinzu.

    Eine Überschrift, die eine Ebene überspringt, etwa ein h4 direkt nach einem h2, erhält in der Section-Datei, in der sie steht, die nächste Ebene unterhalb der vorangehenden Überschrift. Wo das Theme Überschriften nach ihrer Ebene gestaltet, bewahrt eine kleine Style-Regel das bisherige Aussehen der Überschrift. Auf einer Seite ohne Hauptüberschrift wird das Element, das schon wie ihr Titel aussieht, zum h1 gemacht; auf der Startseite ist das die eigene Option des Themes, das Logo als h1 anzuzeigen. Hat eine Seite kein solches Element, fügt das Rezept keine verborgene Überschrift hinzu, weil das eine Inhaltsentscheidung ist.

    Abgedeckte Regeln
    • heading-order AUTO geprüft durch vs-headings-landmarks
    • page-has-heading-one AUTO geprüft durch vs-headings-landmarks
    • vs-headings-landmarks AUTO
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    sections/featured-collection.liquid Änderungen an sections/featured-collection.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/featured-collection.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    1 1 {%- liquid
    2 2 assign featured = section.settings.collection
    3 Entfernt assign card_heading = 'h4'
    3 Hinzugefügt assign card_heading = 'h3'
    4 4 -%}
    5 5 <div class="featured-collection page-width section-spacing">
    6 6 <div class="title-wrapper">

    sections/header.liquid Änderungen an sections/header.liquid: 3 hinzugefügt, 0 entfernt

    Änderungen an sections/header.liquid: 3 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    3 3 assign menu = linklists[section.settings.menu]
    4 4 assign icon_size = 18
    5 5 assign logo_is_heading = false
    6 Hinzugefügt if request.page_type == 'index'
    7 Hinzugefügt assign logo_is_heading = true
    8 Hinzugefügt endif
    6 9 -%}
    7 10 <div class="header-wrapper">
    8 11 <header class="header page-width"{% if header_lang != '' %} lang="{{ header_lang }}"{% endif %}>

    sections/main-collection.liquid Änderungen an sections/main-collection.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/main-collection.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    6 6 wishlist heart nested inside the product image link.
    7 7 {%- endcomment -%}
    8 8 {%- liquid
    9 Entfernt assign card_heading = 'h4'
    9 Hinzugefügt assign card_heading = 'h3'
    10 10 assign price_max = collection.price_max_rounded
    11 11 assign in_stock_count = collection.products | where: 'available', true | size
    12 12 assign out_of_stock_count = collection.products_count | minus: in_stock_count

    sections/main-product.liquid Änderungen an sections/main-product.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/main-product.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    13 13 assign featured = product.featured_image
    14 14 assign form_id = 'product-form-' | append: section.id
    15 15 assign qty_id = 'Quantity-' | append: section.id
    16 Entfernt assign sub_heading = 'h4'
    16 Hinzugefügt assign sub_heading = 'h2'
    17 17 assign size_option = nil
    18 18 for option in product.options_with_values
    19 19 if option.name == 'Size'

    sections/main-search.liquid Änderungen an sections/main-search.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/main-search.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    1 1 {%- liquid
    2 Entfernt assign card_heading = 'h4'
    2 Hinzugefügt assign card_heading = 'h3'
    3 3 -%}
    4 4 <div class="template-search page-width">
    5 5 <h1 class="template-search__title">{{ 'templates.search.title' | t }}</h1>

Tastaturbedienung und Fokus

  • Ein sichtbarer Fokusrahmen focus-visible-styles Ein Fokusrahmen für die Tastaturbedienung in der Akzentfarbe Ihres Themes oder einer Ersatzfarbe, mit einem Kontrast von mindestens 3:1 gegenüber dem Seitenhintergrund.

    Das Haupt-Stylesheet erhält einen Fokusrahmen für die Tastaturbedienung: 2 Pixel breit, durchgezogen und 2 Pixel vom Element entfernt, in der Akzentfarbe Ihres Themes (oder in seiner Textfarbe oder in Schwarz oder Weiß, wo das Theme keine Akzentfarbe hat), im selben Farbton so weit aufgehellt oder abgedunkelt, bis er gegenüber dem Seitenhintergrund einen Kontrast von mindestens 3:1 hat. Regeln des Themes, die den Fokusrahmen sonst weiterhin ausblenden würden, verlieren ihr outline: none, außer sie zeigen den Fokus auf andere Weise, etwa durch einen Rand oder einen Schatten. Der Fokusrahmen hat eine einzige Farbe für das ganze Theme. Auf Abschnitten mit dunklem Farbschema braucht er deshalb unter Umständen eine hellere Farbe; das prüft Ihr Entwicklungsteam in der Vorschau.

    Abgedeckte Regeln
    • vs-focus-visible AUTO
    Geänderte Dateitypen
    .css.liquid
    Vorher und nachher Beispieldaten

    assets/base.css.liquid Änderungen an assets/base.css.liquid: 7 hinzugefügt, 0 entfernt

    Änderungen an assets/base.css.liquid: 7 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    1866 1866 }
    1867 1867
    1868 1868 /* ----------------------------------------------------------------- motion */
    1869 Hinzugefügt
    1870 Hinzugefügt /* validiscan:focus-visible-styles */
    1871 Hinzugefügt :focus-visible {
    1872 Hinzugefügt outline: 2px solid #1f4d3a;
    1873 Hinzugefügt outline-offset: 2px;
    1874 Hinzugefügt }
    1875 Hinzugefügt /* /validiscan:focus-visible-styles */
  • Eine Tab-Reihenfolge, die der Seite folgt remove-positive-tabindex Ein tabindex größer als 0 wird entfernt oder auf 0 gesetzt, sodass die Tab-Taste der Reihenfolge der Seite folgt, außer der Template-Code des Themes schreibt ihn.

    Ein tabindex größer als 0 zieht ein Element an den Anfang der Tastaturreihenfolge. Das Rezept entfernt ihn bei Links, Schaltflächen, Formularfeldern und anderen Elementen, die ohnehin den Fokus erhalten können, und setzt ihn bei anderen Elementen auf 0, sodass sie erreichbar bleiben, während die Tab-Taste der Reihenfolge der Seite folgt. Ein tabindex, den der Template-Code des Themes schreibt, bleibt einem Menschen überlassen. Das Rezept behandelt außerdem die Befunde der Prüfung der Fokusreihenfolge vs-focus-order, die einen tabindex größer als 0 betreffen; der Rest dieser Prüfung bleibt MANUAL.

    Abgedeckte Regeln
    • tabindex AUTO
    • vs-focus-order MANUAL
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    sections/header.liquid Änderungen an sections/header.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/header.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    37 37
    38 38 <div class="header__search">
    39 39 <form action="{{ routes.search_url }}" method="get" role="search" class="search">
    40 Entfernt <input class="search__input field__input" type="search" name="q" value="" placeholder="{{ 'general.search.placeholder' | t }}" tabindex="1">
    40 Hinzugefügt <input class="search__input field__input" type="search" name="q" value="" placeholder="{{ 'general.search.placeholder' | t }}">
    41 41 <button type="submit" class="search__button">
    42 42 {%- render 'icon', icon: 'search', size: 20 -%}
    43 43 </button>
  • Bedienelemente nur für die Maus werden zu Schaltflächen button-semantics Bedienelemente aus <div> oder <span>, die nur mit der Maus funktionieren, auf die ein Skript reagiert und deren Zweck klar ist, werden zu echten Schaltflächen.

    Anklickbare Elemente, die nur mit der Maus funktionieren, etwa die Punkte einer Slideshow oder die Auswahlmöglichkeiten in einem Cookie-Banner, die aus <div>- oder <span>-Elementen gebaut sind, werden zu echten <button>-Elementen. Jede Klasse und jedes Attribut bleibt erhalten, sodass das Skript des Themes weiter funktioniert, und die Eingabetaste und die Leertaste bewirken nun, was ein Klick bewirkt. Eine Schaltfläche ohne Namen erhält einen aus ihrem Zweck, zum Beispiel „Load slide 2 of 3“, und ein kleines Style-Reset bewahrt ihr Aussehen. Ein Element, auf das kein Skript reagiert oder dessen Zweck unklar ist, bleibt unverändert.

    Abgedeckte Regeln
    • vs-carousel AUTO
    • vs-cookie-banner ASSISTED
    Geänderte Dateitypen
    .css.liquid.liquid
    Vorher und nachher Beispieldaten

    assets/base.css.liquid Änderungen an assets/base.css.liquid: 14 hinzugefügt, 0 entfernt

    Änderungen an assets/base.css.liquid: 14 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    1866 1866 }
    1867 1867
    1868 1868 /* ----------------------------------------------------------------- motion */
    1869 Hinzugefügt
    1870 Hinzugefügt /* validiscan:button-semantics */
    1871 Hinzugefügt :where(button.slider-counter__link) {
    1872 Hinzugefügt appearance: none;
    1873 Hinzugefügt margin: 0;
    1874 Hinzugefügt padding: 0;
    1875 Hinzugefügt border: 0;
    1876 Hinzugefügt background: none;
    1877 Hinzugefügt color: inherit;
    1878 Hinzugefügt font: inherit;
    1879 Hinzugefügt text-align: inherit;
    1880 Hinzugefügt cursor: pointer;
    1881 Hinzugefügt }
    1882 Hinzugefügt /* /validiscan:button-semantics */

    sections/slideshow.liquid Änderungen an sections/slideshow.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/slideshow.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    62 62 </button>
    63 63 <div class="slider-counter">
    64 64 {%- for block in section.blocks %}
    65 Entfernt <span class="slider-counter__link" data-slide-to="{{ forloop.index0 }}"><span class="dot"></span></span>
    65 Hinzugefügt <button class="slider-counter__link" data-slide-to="{{ forloop.index0 }}" type="button"><span class="dot"></span><span class="visually-hidden">{{ 'accessibility.load_slide' | t: index: forloop.index, count: forloop.length }}</span></button>
    66 66 {%- endfor %}
    67 67 </div>
    68 68 <button type="button" class="slider-button slider-button--next" name="next" data-slide-next>

Zoom, Touch-Ziele und Kontrast

  • Zoomen auf dem Smartphone erlaubt meta-viewport-zoom user-scalable=no und jedes maximum-scale unter 5 werden aus den Viewport-Tags entfernt, sodass Besucherinnen und Besucher bis auf 500 % vergrößern können, außer der Template-Code des Themes setzt die Begrenzung.

    Das Rezept entfernt user-scalable=no und jedes maximum-scale unter 5 aus den Viewport-Tags in den Liquid-Dateien des Themes, sodass Besucherinnen und Besucher Ihren Shop mit zwei Fingern bis auf 500 % vergrößern können. Die übrigen Viewport-Einstellungen bleiben genau so, wie sie waren. Eine Zoombegrenzung, die der Template-Code des Themes setzt, bleibt einem Menschen überlassen.

    Abgedeckte Regeln
    • meta-viewport AUTO
    • meta-viewport-large AUTO
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    layout/checkout.liquid Änderungen an layout/checkout.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an layout/checkout.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    6 6 <html class="no-js">
    7 7 <head>
    8 8 <meta charset="utf-8">
    9 Entfernt <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    9 Hinzugefügt <meta name="viewport" content="width=device-width,initial-scale=1">
    10 10 <meta name="robots" content="noindex">
    11 11 <link rel="canonical" href="{{ canonical_url }}">
    12 12 <!-- Checkout assets: //cdn.shopify.com/s/files/1/0712/3456/7890/t/12/assets/ (served locally by the fixture server) -->

    layout/theme.focused.liquid Änderungen an layout/theme.focused.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an layout/theme.focused.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    10 10 <head>
    11 11 <meta charset="utf-8">
    12 12 <meta http-equiv="X-UA-Compatible" content="IE=edge">
    13 Entfernt <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    13 Hinzugefügt <meta name="viewport" content="width=device-width,initial-scale=1">
    14 14 <title></title>
    15 15 <link rel="canonical" href="{{ canonical_url }}">
    16 16 <!-- Theme assets: //cdn.shopify.com/s/files/1/0712/3456/7890/t/12/assets/ (served locally by the fixture server) -->

    layout/theme.liquid Änderungen an layout/theme.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an layout/theme.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    11 11 <head>
    12 12 <meta charset="utf-8">
    13 13 <meta http-equiv="X-UA-Compatible" content="IE=edge">
    14 Entfernt <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    14 Hinzugefügt <meta name="viewport" content="width=device-width,initial-scale=1">
    15 15 <meta name="theme-color" content="{{ settings.color_background }}">
    16 16 <link rel="canonical" href="{{ canonical_url }}">
    17 17 {%- comment -%} On the live store theme assets load from //cdn.shopify.com/s/files/1/0712/3456/7890/t/12/assets/; the fixture serves them from {{ routes.root_url }}assets/. {%- endcomment %}
  • Größere Touch-Ziele target-size-padding Bedienelemente, die der Scan als zu klein befunden hat, etwa Icons im Header oder Farbfelder, erhalten eine Mindestgröße von 24 × 24 Pixel.

    Bedienelemente, die der Scan als zu klein befunden hat, etwa Icons im Header, Farbfelder oder Mengenschaltflächen, erhalten im Haupt-Stylesheet eine Mindestgröße von 24 × 24 Pixel, angesprochen über ihre Klasse. Die Icons darin behalten ihre Größe. Ein Link oder ein anderes Element, das das Theme inline lässt, wird auf inline-flex gesetzt, mit zentriertem Icon, weil Inline-Elemente eine Mindestgröße ignorieren.

    Abgedeckte Regeln
    • vs-target-size AUTO
    Geänderte Dateitypen
    .css.liquid
    Vorher und nachher Beispieldaten

    assets/base.css.liquid Änderungen an assets/base.css.liquid: 10 hinzugefügt, 0 entfernt

    Änderungen an assets/base.css.liquid: 10 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    1866 1866 }
    1867 1867
    1868 1868 /* ----------------------------------------------------------------- motion */
    1869 Hinzugefügt
    1870 Hinzugefügt /* validiscan:target-size-padding */
    1871 Hinzugefügt .header__icon--account,
    1872 Hinzugefügt .header__icon--cart,
    1873 Hinzugefügt .swatch--button,
    1874 Hinzugefügt .quantity__button {
    1875 Hinzugefügt min-width: 24px;
    1876 Hinzugefügt min-height: 24px;
    1877 Hinzugefügt }
    1878 Hinzugefügt /* /validiscan:target-size-padding */
  • Textfarben mit ausreichendem Kontrast contrast-tokens Besteht Text die Kontrastprüfung nicht und ist seine Farbe an einer einzigen Stelle definiert und nicht gemeinsam genutzt, wird sie auf die nächste Abstufung desselben Farbtons mit dem erforderlichen Kontrast gesetzt.

    Besteht Text die Kontrastprüfung nicht und ist seine Farbe an einer einzigen Stelle definiert, wird diese Farbe auf die nächste hellere oder dunklere Abstufung desselben Farbtons gesetzt, die gegenüber jedem Hintergrund, den der Scan für sie gemeldet hat, den erforderlichen Kontrast erreicht. Die Stelle kann die Stylesheet-Regel sein, die den Text gestaltet, oder eine CSS-Variable oder eine Farbeinstellung in config/settings_data.json, die sonst nichts im Theme verwendet. Eine Farbe, die in Liquid berechnet oder mehrfach definiert wird, bleibt einem Menschen überlassen, ebenso eine gemeinsam genutzte Farbe, weil eine Änderung Farbpaare beträfe, die der Scan nicht gemessen hat.

    Abgedeckte Regeln
    • color-contrast ASSISTED
    Geänderte Dateitypen
    .css.liquid
    Vorher und nachher Beispieldaten

    assets/base.css.liquid Änderungen an assets/base.css.liquid: 3 hinzugefügt, 3 entfernt

    Änderungen an assets/base.css.liquid: 3 hinzugefügt, 3 entfernt
    Zeile vorher Zeile nachher Änderung Code
    745 745 font-size: 0.8125rem;
    746 746 letter-spacing: 0.04em;
    747 747 text-transform: uppercase;
    748 Entfernt color: #929292;
    748 Hinzugefügt color: #767676;
    749 749 }
    750 750
    751 751 .rating {
    1013 1013
    1014 1014 .copyright__content {
    1015 1015 margin: 0;
    1016 Entfernt color: #929292;
    1016 Hinzugefügt color: #6f6f6f;
    1017 1017 }
    1018 1018
    1019 1019 .policies {
    1077 1077
    1078 1078 .cookie-banner__text,
    1079 1079 .cookie-banner__link {
    1080 Entfernt color: #9a9a9a;
    1080 Hinzugefügt color: #767676;
    1081 1081 }
    1082 1082
    1083 1083 .cookie-banner__icon-button {

Bewegung, Slideshows und Ton

  • Weniger Bewegung auf Wunsch der Besucherinnen und Besucher reduced-motion-guard Ist das Gerät auf „Bewegung reduzieren“ eingestellt, werden CSS-Animationen und Übergänge verkürzt, sanftes Scrollen wird abgeschaltet, und ein automatisches Abspielen einer Slideshow, das das Skript des Themes startet, wird übersprungen.

    Ist das Gerät einer Besucherin oder eines Besuchers auf „Bewegung reduzieren“ eingestellt, lässt ein Block am Ende des Haupt-Stylesheets jede CSS-Animation nur einmal und so kurz ablaufen, dass man sie nicht sieht, verkürzt Übergänge und schaltet sanftes Scrollen ab. Startet das Skript des Themes das automatische Abspielen einer Slideshow selbst, wird der Start für diese Besucherinnen und Besucher übersprungen. Bewegung, die ein Skript eines Drittanbieters steuert, ändert dieses Rezept nicht.

    Abgedeckte Regeln
    • vs-motion AUTO
    Geänderte Dateitypen
    .css.liquid
    Vorher und nachher Beispieldaten

    assets/base.css.liquid Änderungen an assets/base.css.liquid: 13 hinzugefügt, 0 entfernt

    Änderungen an assets/base.css.liquid: 13 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    1866 1866 }
    1867 1867
    1868 1868 /* ----------------------------------------------------------------- motion */
    1869 Hinzugefügt
    1870 Hinzugefügt /* validiscan:reduced-motion-guard */
    1871 Hinzugefügt @media (prefers-reduced-motion: reduce) {
    1872 Hinzugefügt *,
    1873 Hinzugefügt *::before,
    1874 Hinzugefügt *::after {
    1875 Hinzugefügt animation-duration: 0.01ms !important;
    1876 Hinzugefügt animation-iteration-count: 1 !important;
    1877 Hinzugefügt transition-duration: 0.01ms !important;
    1878 Hinzugefügt scroll-behavior: auto !important;
    1879 Hinzugefügt }
    1880 Hinzugefügt }
    1881 Hinzugefügt /* /validiscan:reduced-motion-guard */
  • Eine Pause-Schaltfläche für bewegte Slideshows slider-pause-control Eine Slideshow, die sich von selbst bewegt, erhält eine sichtbare, übersetzte Schaltfläche zum Anhalten und Fortsetzen, verbunden mit ihrem eigenen automatischen Abspielen.

    Eine Slideshow, die sich von selbst bewegt, erhält unter ihren Bedienelementen eine sichtbare, übersetzte Schaltfläche zum Anhalten und Fortsetzen, die nur angezeigt wird, wenn das automatische Abspielen eingeschaltet ist. Ein kurzes Skript in der Haupt-Skriptdatei des Themes verbindet die Schaltfläche mit dem automatischen Abspielen des Sliders selbst: der Slideshow von Dawn, Swiper, Slick, Flickity, Splide oder einer CSS-Animation. Für Besucherinnen und Besucher, deren Gerät auf „Bewegung reduzieren“ eingestellt ist, startet die Slideshow angehalten.

    Abgedeckte Regeln
    • vs-carousel AUTO
    Geänderte Dateitypen
    .css.liquid.js.json.liquid
    Vorher und nachher Beispieldaten

    assets/base.css.liquid Änderungen an assets/base.css.liquid: 21 hinzugefügt, 0 entfernt

    Änderungen an assets/base.css.liquid: 21 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    1866 1866 }
    1867 1867
    1868 1868 /* ----------------------------------------------------------------- motion */
    1869 Hinzugefügt
    1870 Hinzugefügt /* validiscan:slider-pause-control */
    1871 Hinzugefügt [data-autoplay-paused],
    1872 Hinzugefügt [data-autoplay-paused] * {
    1873 Hinzugefügt animation-play-state: paused !important;
    1874 Hinzugefügt }
    1875 Hinzugefügt
    1876 Hinzugefügt .slider-pause {
    1877 Hinzugefügt display: inline-flex;
    1878 Hinzugefügt align-items: center;
    1879 Hinzugefügt justify-content: center;
    1880 Hinzugefügt min-width: 2.75rem;
    1881 Hinzugefügt min-height: 2.75rem;
    1882 Hinzugefügt padding: 0.5rem 1rem;
    1883 Hinzugefügt border: 1px solid currentColor;
    1884 Hinzugefügt background: transparent;
    1885 Hinzugefügt color: inherit;
    1886 Hinzugefügt font: inherit;
    1887 Hinzugefügt cursor: pointer;
    1888 Hinzugefügt }
    1889 Hinzugefügt /* /validiscan:slider-pause-control */

    assets/global.js Änderungen an assets/global.js: 53 hinzugefügt, 0 entfernt

    Änderungen an assets/global.js: 53 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    412 412 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
    413 413 else boot();
    414 414 })();
    415 Hinzugefügt
    416 Hinzugefügt /* validiscan:slider-pause-control */
    417 Hinzugefügt (function () {
    418 Hinzugefügt 'use strict';
    419 Hinzugefügt var ROOTS = 'slideshow-component, slider-component, .swiper, .swiper-container, .slick-slider, .flickity-enabled, .splide, [data-autoplay]';
    420 Hinzugefügt var reduce = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;
    421 Hinzugefügt
    422 Hinzugefügt function rootOf(button) {
    423 Hinzugefügt return button.closest(ROOTS) || button.previousElementSibling;
    424 Hinzugefügt }
    425 Hinzugefügt
    426 Hinzugefügt function setPaused(button, paused) {
    427 Hinzugefügt var root = rootOf(button);
    428 Hinzugefügt if (!root) return;
    429 Hinzugefügt if (paused) root.setAttribute('data-autoplay-paused', '');
    430 Hinzugefügt else root.removeAttribute('data-autoplay-paused');
    431 Hinzugefügt if (root.swiper && root.swiper.autoplay) {
    432 Hinzugefügt if (paused) root.swiper.autoplay.stop();
    433 Hinzugefügt else root.swiper.autoplay.start();
    434 Hinzugefügt }
    435 Hinzugefügt var $ = window.jQuery;
    436 Hinzugefügt if ($ && $(root).hasClass('slick-initialized')) $(root).slick(paused ? 'slickPause' : 'slickPlay');
    437 Hinzugefügt var flickity = window.Flickity && window.Flickity.data(root);
    438 Hinzugefügt if (flickity) {
    439 Hinzugefügt if (paused) flickity.pausePlayer();
    440 Hinzugefügt else flickity.unpausePlayer();
    441 Hinzugefügt }
    442 Hinzugefügt var autoplay = root.splide && root.splide.Components && root.splide.Components.Autoplay;
    443 Hinzugefügt if (autoplay) {
    444 Hinzugefügt if (paused) autoplay.pause();
    445 Hinzugefügt else autoplay.play();
    446 Hinzugefügt }
    447 Hinzugefügt if (root.localName.indexOf('-') > 0 && typeof root.pause === 'function' && typeof root.play === 'function') {
    448 Hinzugefügt if (paused) root.pause();
    449 Hinzugefügt else root.play();
    450 Hinzugefügt }
    451 Hinzugefügt button.setAttribute('data-paused', paused ? 'true' : 'false');
    452 Hinzugefügt button.textContent = button.getAttribute(paused ? 'data-label-play' : 'data-label-pause') || button.textContent;
    453 Hinzugefügt }
    454 Hinzugefügt
    455 Hinzugefügt function init() {
    456 Hinzugefügt Array.prototype.forEach.call(document.querySelectorAll('[data-slider-pause]'), function (button) {
    457 Hinzugefügt button.addEventListener('click', function () {
    458 Hinzugefügt setPaused(button, button.getAttribute('data-paused') !== 'true');
    459 Hinzugefügt });
    460 Hinzugefügt if (reduce && reduce.matches) setPaused(button, true);
    461 Hinzugefügt });
    462 Hinzugefügt }
    463 Hinzugefügt
    464 Hinzugefügt if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
    465 Hinzugefügt else init();
    466 Hinzugefügt })();
    467 Hinzugefügt /* /validiscan:slider-pause-control */

    locales/en.default.json Änderungen an locales/en.default.json: 3 hinzugefügt, 1 entfernt

    Änderungen an locales/en.default.json: 3 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    34 34 "total_reviews": "{{ count }} reviews",
    35 35 "link_messages": {
    36 36 "new_window": "Opens in a new window."
    37 Entfernt }
    37 Hinzugefügt },
    38 Hinzugefügt "pause_slideshow": "Pause slideshow",
    39 Hinzugefügt "play_slideshow": "Play slideshow"
    38 40 },
    39 41 "sections": {
    40 42 "header": {

    sections/slideshow.liquid Änderungen an sections/slideshow.liquid: 3 hinzugefügt, 0 entfernt

    Änderungen an sections/slideshow.liquid: 3 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    68 68 <button type="button" class="slider-button slider-button--next" name="next" data-slide-next>
    69 69 {%- render 'icon', icon: 'chevron-right', size: 20 -%}
    70 70 </button>
    71 Hinzugefügt {%- if autoplay %}
    72 Hinzugefügt <button type="button" class="slider-pause" data-slider-pause data-label-pause="{{ 'accessibility.pause_slideshow' | t | escape }}" data-label-play="{{ 'accessibility.play_slideshow' | t | escape }}">{{ 'accessibility.pause_slideshow' | t }}</button>
    73 Hinzugefügt {%- endif %}
    71 74 </div>
    72 75 </slideshow-component>
    73 76
  • Kein Ton, der von selbst startet mute-autoplay Ein Video, das von selbst abspielt, wird stummgeschaltet, und Audio startet nicht mehr von selbst, außer in eingebetteten YouTube- und Vimeo-Playern; auf Shopify wird das Rezept für Befunde von vs-media nicht verwendet.

    Ein Video, das von selbst abspielt, erhält muted und playsinline, sodass es wie ein Hintergrundvideo stumm weiterläuft, und der Filter video_tag von Shopify erhält muted: true. Audio, das von selbst startet, tut das danach nicht mehr. Eingebettete YouTube- und Vimeo-Player bleiben einem Menschen überlassen. In einem Scan von Validiscan wird Ton, der von selbst startet, von der Medienprüfung vs-media gemeldet; sie tritt an die Stelle der axe-core-Regel, die dieses Rezept abdeckt. vs-media hat die Stufe MANUAL, und auf Shopify wird dieses Rezept für ihre Befunde nicht verwendet.

    Abgedeckte Regeln
    • no-autoplay-audio AUTO geprüft durch vs-media
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    sections/announcement-bar.liquid Änderungen an sections/announcement-bar.liquid: 2 hinzugefügt, 2 entfernt

    Änderungen an sections/announcement-bar.liquid: 2 hinzugefügt, 2 entfernt
    Zeile vorher Zeile nachher Änderung Code
    3 3 -%}
    4 4 <div class="announcement-bar color-accent"{% if bar_lang != '' %} lang="{{ bar_lang }}"{% endif %}>
    5 5 <div class="page-width">
    6 Entfernt <audio class="announcement-bar__chime" src="{{ 'chime.wav' | asset_url }}" autoplay></audio>
    7 Entfernt <video class="announcement-bar__clip" src="{{ 'chime.wav' | asset_url }}" autoplay loop width="16" height="16"></video>
    6 Hinzugefügt <audio class="announcement-bar__chime" src="{{ 'chime.wav' | asset_url }}"></audio>
    7 Hinzugefügt <video class="announcement-bar__clip" src="{{ 'chime.wav' | asset_url }}" autoplay loop width="16" height="16" muted playsinline></video>
    8 8 <p class="announcement-bar__message">{{ section.settings.text | escape }}</p>
    9 9 </div>
    10 10 </div>

Formulare, Preise und Warenkorb

  • Beschriftungen, die mit ihren Feldern verbunden sind label-association Eine Beschriftung, die auf der Seite schon sichtbar, aber nicht mit ihrem Formularfeld verbunden ist, wird verbunden, ohne dass sich das Layout ändert.

    Ein Formularfeld, dessen Beschriftung auf der Seite schon sichtbar, aber nicht mit dem Feld verbunden ist, wird verbunden: Ein <label> daneben erhält ein for, das auf das Feld zeigt, oder ein Text unmittelbar vor dem Feld, etwa der Name einer Größen- oder Farboption, wird über aria-labelledby zu seiner Beschriftung, sodass sich das Layout nicht ändert. Screenreader lesen die Beschriftung dann vor, wenn das Feld den Fokus erhält. Ein Feld, das nur einen Platzhalter hat, bleibt einem Menschen überlassen, weil das Schreiben einer Beschriftung eine Inhaltsentscheidung ist.

    Abgedeckte Regeln
    • label AUTO geprüft durch vs-forms-ecommerce
    • select-name ASSISTED
    • vs-forms-ecommerce AUTO
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    sections/main-collection.liquid Änderungen an sections/main-collection.liquid: 2 hinzugefügt, 2 entfernt

    Änderungen an sections/main-collection.liquid: 2 hinzugefügt, 2 entfernt
    Zeile vorher Zeile nachher Änderung Code
    64 64 <div class="collection__products">
    65 65 <div class="collection__toolbar">
    66 66 <div class="collection__sort">
    67 Entfernt <label class="collection__sort-label">Sort by</label>
    68 Entfernt <select name="sort_by" class="select__select" form="FacetFiltersForm">
    67 Hinzugefügt <label class="collection__sort-label" for="SortBy-{{ section.id }}">Sort by</label>
    68 Hinzugefügt <select name="sort_by" class="select__select" form="FacetFiltersForm" id="SortBy-{{ section.id }}">
    69 69 <option value="manual" selected>Featured</option>
    70 70 <option value="best-selling">Best selling</option>
    71 71 <option value="price-ascending">Price, low to high</option>

    sections/main-product.liquid Änderungen an sections/main-product.liquid: 2 hinzugefügt, 2 entfernt

    Änderungen an sections/main-product.liquid: 2 hinzugefügt, 2 entfernt
    Zeile vorher Zeile nachher Änderung Code
    94 94 </div>
    95 95 {%- else %}
    96 96 <div class="product-form__input product-form__input--dropdown">
    97 Entfernt <p class="form__label">{{ option.name | escape }}</p>
    97 Hinzugefügt <p class="form__label" id="Options-{{ section.id }}-{{ forloop.index0 }}-label">{{ option.name | escape }}</p>
    98 98 <div class="select">
    99 Entfernt <select class="select__select" name="options[{{ option.name | escape }}]" data-option-index="{{ option_index }}">
    99 Hinzugefügt <select class="select__select" name="options[{{ option.name | escape }}]" data-option-index="{{ option_index }}" aria-labelledby="Options-{{ section.id }}-{{ forloop.index0 }}-label">
    100 100 {%- for value in option.values %}
    101 101 <option value="{{ value | escape }}"{% if value == option.selected_value %} selected{% endif %}>{{ value | escape }}</option>
    102 102 {%- endfor %}
  • Adress-, Konto- und Anmeldefelder, die Browser ausfüllen können autocomplete-tokens Adress-, Konto-, Anmelde- und Kontaktfelder, die der Scan beanstandet hat, erhalten den autocomplete-Wert für das, wonach sie fragen, sofern der Code ihren Zweck zeigt.

    Adress-, Konto-, Anmelde- und Kontaktfelder, die der Scan beanstandet hat, erhalten den autocomplete-Wert für das, wonach sie fragen, etwa E-Mail-Adresse, Vor- und Nachname, Straßenadresse, Postleitzahl, Land, Telefonnummer oder Passwort. Der Wert wird aus Typ, Name, Beschriftung und Platzhalter des Felds abgeleitet. Gibt ein Snippet seine Felder anhand von Parametern aus, geben die Felder einen Parameter autocomplete aus, und jeder render-Aufruf des Snippets übergibt den Wert, den seine eigenen Argumente verlangen. Browser können die Felder dann ausfüllen, und assistive Technologien erkennen, wofür jedes Feld gedacht ist. Ein Feld, dessen Zweck der Code nicht zeigt, bleibt unverändert.

    Abgedeckte Regeln
    • autocomplete-valid AUTO geprüft durch vs-forms-ecommerce
    • vs-forms-ecommerce AUTO
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    sections/contact-form.liquid Änderungen an sections/contact-form.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/contact-form.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    14 14 {%- form 'contact', id: 'ContactForm', class: 'contact__form' %}
    15 15 <div class="contact__fields">
    16 16 <div class="field">
    17 Entfernt <input class="field__input" type="text" name="contact[name]" placeholder="{{ 'templates.contact.form.name' | t }}">
    17 Hinzugefügt <input class="field__input" type="text" name="contact[name]" placeholder="{{ 'templates.contact.form.name' | t }}" autocomplete="name">
    18 18 </div>
    19 19 <div class="field">
    20 20 <input class="field__input" type="email" name="contact[email]" placeholder="{{ 'templates.contact.form.email' | t }} *" required>

    sections/footer.liquid Änderungen an sections/footer.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/footer.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    11 11 {%- form 'customer', id: 'ContactFooter', class: 'footer__newsletter newsletter-form' -%}
    12 12 <input type="hidden" name="contact[tags]" value="newsletter">
    13 13 <div class="newsletter-form__field-wrapper">
    14 Entfernt <input type="email" name="contact[email]" class="field__input" placeholder="{{ 'newsletter.label' | t }}" autocorrect="off" autocapitalize="off">
    14 Hinzugefügt <input type="email" name="contact[email]" class="field__input" placeholder="{{ 'newsletter.label' | t }}" autocorrect="off" autocapitalize="off" autocomplete="email">
    15 15 <button type="submit" class="button newsletter-form__button" name="commit">{{ 'newsletter.button' | t }}</button>
    16 16 </div>
    17 17 {%- endform -%}

    sections/main-login.liquid Änderungen an sections/main-login.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/main-login.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    10 10 {%- form 'customer_login', novalidate: 'novalidate' %}
    11 11 <div class="field">
    12 12 <label class="field__label" for="CustomerEmail">{{ 'customer.login_page.email' | t }}</label>
    13 Entfernt <input class="field__input" type="email" name="customer[email]" id="CustomerEmail" autocorrect="off" autocapitalize="off">
    13 Hinzugefügt <input class="field__input" type="email" name="customer[email]" id="CustomerEmail" autocorrect="off" autocapitalize="off" autocomplete="email">
    14 14 </div>
    15 15 <div class="field">
    16 16 <label class="field__label" for="CustomerPassword">{{ 'customer.login_page.password' | t }}</label>

    snippets/checkout-field.liquid Änderungen an snippets/checkout-field.liquid: 4 hinzugefügt, 4 entfernt

    Änderungen an snippets/checkout-field.liquid: 4 hinzugefügt, 4 entfernt
    Zeile vorher Zeile nachher Änderung Code
    15 15 <div class="field">
    16 16 {%- case legacy %}
    17 17 {%- when 'placeholder' %}
    18 Entfernt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" placeholder="{{ label }}"{% if required %} required{% endif %}>
    18 Hinzugefügt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" placeholder="{{ label }}"{% if required %} required{% endif %} autocomplete="{{ autocomplete }}">
    19 19 {%- when 'starred' %}
    20 20 <label class="field__label" for="{{ field_id }}">{{ label }} *</label>
    21 Entfernt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}">
    21 Hinzugefügt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="{{ autocomplete }}">
    22 22 {%- when 'off' %}
    23 23 <label class="field__label" for="{{ field_id }}">{{ label }}</label>
    24 Entfernt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="off"{% if required %} required{% endif %}>
    24 Hinzugefügt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="{{ autocomplete }}"{% if required %} required{% endif %}>
    25 25 {%- else %}
    26 26 <label class="field__label" for="{{ field_id }}">{{ label }}</label>
    27 Entfernt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"{% if required %} required{% endif %}>
    27 Hinzugefügt <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"{% if required %} required{% endif %} autocomplete="{{ autocomplete }}">
    28 28 {%- endcase %}
    29 29 </div>
  • Änderungen bei Preis, Bestand und Warenkorb werden angesagt live-region-cart-variant Der Preis, der Hinweis zum Bestand oder die Zwischensumme des Warenkorbs, die das Skript des Themes neu schreibt, wird zu einer Live-Region, die Screenreader ansagen, außer der Bereich enthält auch Schaltflächen oder Links.

    Der Teil einer Seite, den das Skript des Themes neu schreibt, wenn Kundinnen und Kunden eine andere Variante wählen oder eine Menge ändern, etwa der Preis, der Hinweis zum Bestand oder die Zwischensumme des Warenkorbs, wird als Live-Region für Statusmeldungen markiert. Screenreader sagen den neuen Wert dann an, ohne dass Kundinnen und Kunden dorthin wechseln müssen. Das Skript des Themes selbst wird nicht geändert. Ein Bereich, der auch Schaltflächen oder Links enthält, die dabei mitgelesen würden, bleibt unverändert.

    Abgedeckte Regeln
    • vs-live-updates AUTO
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    sections/main-cart.liquid Änderungen an sections/main-cart.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/main-cart.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    37 37
    38 38 <div class="cart__footer">
    39 39 <h2 class="cart__summary-title">Order summary</h2>
    40 Entfernt <p class="totals">
    40 Hinzugefügt <p class="totals" role="status">
    41 41 <span class="totals__label">{{ 'sections.cart.subtotal' | t }}</span>
    42 42 <span class="totals__value" data-cart-subtotal>{{ cart.total_price | money_with_currency }}</span>
    43 43 </p>

    sections/main-product.liquid Änderungen an sections/main-product.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/main-product.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    71 71 </div>
    72 72 {%- endif %}
    73 73
    74 Entfernt <div class="product__price" data-price-container>
    74 Hinzugefügt <div class="product__price" data-price-container role="status">
    75 75 {% render 'price', product: product, use_variant: true %}
    76 76 <p class="product__inventory" data-stock>{% if current_variant.available %}{{ 'products.product.in_stock' | t }}{% else %}{{ 'products.product.out_of_stock' | t }}{% endif %}</p>
    77 77 <p class="product__sku">{{ 'products.product.sku' | t }}: <span data-sku>{{ current_variant.sku }}</span></p>

Namen für Icons, Bilder und eingebettete Inhalte

  • Namen für Schaltflächen und Links, die nur ein Icon zeigen icon-accessible-name Schaltflächen und Links, die nur ein Icon zeigen, erhalten einen Namen, der sagt, was sie tun, sofern der Code ihren Zweck zeigt.

    Schaltflächen und Links, die nur ein Icon zeigen, etwa für Suche, Warenkorb, Konto, Pfeile einer Slideshow, Mengenschaltflächen und Cookie-Auswahl, erhalten einen Namen, der sagt, was sie tun, sofern der Code ihren Zweck zeigt. Der Name ist ein visuell verborgener Text im Bedienelement oder ein aria-label, wo das Theme keine Klasse für verborgenen Text hat. Ein Logo-Link, dessen Bild keine Textalternative hat, erhält den Namen Ihres Shops. Ein Bedienelement, dessen Name aus Ihren eigenen Inhalten stammen müsste, bleibt einem Menschen überlassen.

    Abgedeckte Regeln
    • button-name ASSISTED
    • link-name ASSISTED
    • image-alt ASSISTED
    • vs-carousel AUTO
    • vs-cookie-banner ASSISTED
    Geänderte Dateitypen
    .json.liquid
    buttons Beispieldaten

    locales/en.default.json Änderungen an locales/en.default.json: 3 hinzugefügt, 1 entfernt

    Änderungen an locales/en.default.json: 3 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    34 34 "total_reviews": "{{ count }} reviews",
    35 35 "link_messages": {
    36 36 "new_window": "Opens in a new window."
    37 Entfernt }
    37 Hinzugefügt },
    38 Hinzugefügt "accept_cookies": "Accept cookies",
    39 Hinzugefügt "reject_cookies": "Reject cookies"
    38 40 },
    39 41 "sections": {
    40 42 "header": {

    sections/header.liquid Änderungen an sections/header.liquid: 1 hinzugefügt, 0 entfernt

    Änderungen an sections/header.liquid: 1 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    40 40 <input class="search__input field__input" type="search" name="q" value="" placeholder="{{ 'general.search.placeholder' | t }}" tabindex="1">
    41 41 <button type="submit" class="search__button">
    42 42 {%- render 'icon', icon: 'search', size: 20 -%}
    43 Hinzugefügt <span class="visually-hidden">{{ 'general.search.search' | t }}</span>
    43 44 </button>
    44 45 </form>
    45 46 </div>

    sections/main-product.liquid Änderungen an sections/main-product.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/main-product.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    88 88 <p class="form__label">{{ option.name | escape }}</p>
    89 89 <div class="swatch-list swatch-list--compact">
    90 90 {%- for swatch in option.swatches %}
    91 Entfernt <button type="button" class="swatch swatch--button{% if swatch.selected %} swatch--active{% endif %}" style="--swatch-color: {{ swatch.color }};" data-option-index="{{ option_index }}" data-value="{{ swatch.value | escape }}"></button>
    91 Hinzugefügt <button type="button" class="swatch swatch--button{% if swatch.selected %} swatch--active{% endif %}" style="--swatch-color: {{ swatch.color }};" data-option-index="{{ option_index }}" data-value="{{ swatch.value | escape }}"><span class="visually-hidden">{{ swatch.value | escape }}</span></button>
    92 92 {%- endfor %}
    93 93 </div>
    94 94 </div>

    sections/slideshow.liquid Änderungen an sections/slideshow.liquid: 2 hinzugefügt, 0 entfernt

    Änderungen an sections/slideshow.liquid: 2 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    59 59 <div class="slideshow__controls">
    60 60 <button type="button" class="slider-button slider-button--prev" name="previous" data-slide-prev>
    61 61 {%- render 'icon', icon: 'chevron-left', size: 20 -%}
    62 Hinzugefügt <span class="visually-hidden">{{ 'accessibility.previous_slide' | t }}</span>
    62 63 </button>
    63 64 <div class="slider-counter">
    64 65 {%- for block in section.blocks %}
    67 68 </div>
    68 69 <button type="button" class="slider-button slider-button--next" name="next" data-slide-next>
    69 70 {%- render 'icon', icon: 'chevron-right', size: 20 -%}
    71 Hinzugefügt <span class="visually-hidden">{{ 'accessibility.next_slide' | t }}</span>
    70 72 </button>
    71 73 </div>
    72 74 </slideshow-component>

    snippets/cookie-banner.liquid Änderungen an snippets/cookie-banner.liquid: 2 hinzugefügt, 0 entfernt

    Änderungen an snippets/cookie-banner.liquid: 2 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    23 23 <div class="cookie-banner__actions">
    24 24 <button type="button" class="cookie-banner__icon-button cookie-banner__icon-button--accept" data-cookie-accept>
    25 25 {%- render 'icon', icon: 'check', size: 20 -%}
    26 Hinzugefügt <span class="visually-hidden">{{ 'accessibility.accept_cookies' | t }}</span>
    26 27 </button>
    27 28 <button type="button" class="cookie-banner__icon-button" data-cookie-reject>
    28 29 {%- render 'icon', icon: 'close', size: 20 -%}
    30 Hinzugefügt <span class="visually-hidden">{{ 'accessibility.reject_cookies' | t }}</span>
    29 31 </button>
    30 32 </div>
    31 33 </div>

    snippets/quantity-input.liquid Änderungen an snippets/quantity-input.liquid: 2 hinzugefügt, 0 entfernt

    Änderungen an snippets/quantity-input.liquid: 2 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    9 9 {%- endcomment -%}
    10 10 <div class="quantity quantity--compact" data-quantity{% if line %} data-line="{{ line }}"{% endif %}><button class="quantity__button" name="minus" type="button" data-quantity-minus>
    11 11 {%- render 'icon', icon: 'minus', size: 12 -%}
    12 Hinzugefügt <span class="visually-hidden">{{ 'products.product.quantity.decrease' | t: product: product_title }}</span>
    12 13 </button>
    13 14 <input class="quantity__input" type="number" name="{{ input_name }}" id="{{ input_id }}" value="{{ value | default: 1 }}" min="{% if line %}0{% else %}1{% endif %}" data-quantity-input>
    14 15 <button class="quantity__button" name="plus" type="button" data-quantity-plus>
    15 16 {%- render 'icon', icon: 'plus', size: 12 -%}
    17 Hinzugefügt <span class="visually-hidden">{{ 'products.product.quantity.increase' | t: product: product_title }}</span>
    16 18 </button></div>
    links Beispieldaten

    sections/footer.liquid Änderungen an sections/footer.liquid: 1 hinzugefügt, 0 entfernt

    Änderungen an sections/footer.liquid: 1 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    37 37 {%- for social in shop.social %}
    38 38 <a href="{{ social.url }}" class="list-social__link link">
    39 39 {%- render 'icon', icon: social.icon, size: 20 -%}
    40 Hinzugefügt <span class="visually-hidden">{{ 'general.social.links.' | append: social.icon | t }}</span>
    40 41 </a>
    41 42 {%- endfor %}
    42 43 </ul>

    sections/header.liquid Änderungen an sections/header.liquid: 3 hinzugefügt, 1 entfernt

    Änderungen an sections/header.liquid: 3 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    22 22 </details>
    23 23
    24 24 {% if logo_is_heading %}<h1 class="header__heading">{% else %}<div class="header__heading">{% endif %}
    25 Entfernt <a href="{{ routes.root_url }}" class="header__heading-link"><img src="{{ 'logo.svg' | asset_url }}" width="{{ settings.logo_width }}" height="32" class="header__heading-logo"></a>
    25 Hinzugefügt <a href="{{ routes.root_url }}" class="header__heading-link"><img src="{{ 'logo.svg' | asset_url }}" width="{{ settings.logo_width }}" height="32" class="header__heading-logo" alt="{{ shop.name | escape }}"></a>
    26 26 {% if logo_is_heading %}</h1>{% else %}</div>{% endif %}
    27 27
    28 28 <nav class="header__inline-menu">
    50 50 {%- endif %}
    51 51 <a href="{{ routes.account_login_url }}" class="header__icon header__icon--account link">
    52 52 {%- render 'icon', icon: 'account', size: icon_size -%}
    53 Hinzugefügt <span class="visually-hidden">{{ 'sections.header.account' | t }}</span>
    53 54 </a>
    54 55 <a href="{{ routes.cart_url }}" class="header__icon header__icon--cart link" id="cart-icon-bubble">
    55 56 {%- render 'icon', icon: 'cart', size: icon_size -%}
    57 58 <span class="cart-count-bubble" aria-hidden="true"><span data-cart-count>{{ cart.item_count }}</span></span>
    58 59 {%- endif -%}
    59 60
    61 Hinzugefügt <span class="visually-hidden">{{ 'sections.header.cart' | t }}</span>
    60 62 </a>
    61 63 </div>
    62 64 </header>

    sections/main-cart.liquid Änderungen an sections/main-cart.liquid: 1 hinzugefügt, 0 entfernt

    Änderungen an sections/main-cart.liquid: 1 hinzugefügt, 0 entfernt
    Zeile vorher Zeile nachher Änderung Code
    26 26 {% render 'quantity-input', input_id: qty_id, input_name: 'updates[]', value: item.quantity, product_title: item.product.title, line: line %}
    27 27 <a href="{{ routes.cart_change_url }}?line={{ line }}&amp;quantity=0" class="cart-item__remove cart-item__remove--compact" data-cart-remove>
    28 28 {%- render 'icon', icon: 'trash', size: 16 -%}
    29 Hinzugefügt <span class="visually-hidden">{{ 'sections.cart.remove' | t: title: item.product.title }}</span>
    29 30 </a>
    30 31 </div>
    31 32 <div class="cart-item__totals">
  • Dekorative Bilder vor Screenreadern verborgen decorative-image-alt Nur Bilder, bei denen der Code belegt, dass sie dekorativ sind, werden vor Screenreadern verborgen; die Textalternative jedes anderen Bildes bleibt einem Menschen überlassen.

    Ein Bild wird nur dann als dekorativ markiert, wenn der Code belegt, dass es nichts beiträgt: Es steht in einem Link oder einer Schaltfläche mit eigenem Text, es ist ein Icon neben seiner eigenen Textbeschriftung, oder es ist ein Abstandshalter oder eine Trennlinie. Ein <img> erhält dann ein leeres alt="", ein SVG-Icon erhält aria-hidden="true", sodass Screenreader es überspringen, statt einen Dateinamen oder das Wort „Bild“ vorzulesen. Jedes andere Bild ist Inhalt, und seine Textalternative bleibt einem Menschen überlassen.

    Abgedeckte Regeln
    • image-alt ASSISTED
    • role-img-alt ASSISTED
    • svg-img-alt ASSISTED
    Geänderte Dateitypen
    .liquid
    Vorher und nachher Beispieldaten

    sections/footer.liquid Änderungen an sections/footer.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/footer.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    12 12 <input type="hidden" name="contact[tags]" value="newsletter">
    13 13 <div class="newsletter-form__field-wrapper">
    14 14 <input type="email" name="contact[email]" class="field__input" placeholder="{{ 'newsletter.label' | t }}" autocorrect="off" autocapitalize="off">
    15 Entfernt <button type="submit" class="button newsletter-form__button" name="commit"><img src="{{ 'logo.svg' | asset_url }}" class="newsletter-form__icon" width="16" height="16">{{ 'newsletter.button' | t }}</button>
    15 Hinzugefügt <button type="submit" class="button newsletter-form__button" name="commit"><img src="{{ 'logo.svg' | asset_url }}" class="newsletter-form__icon" width="16" height="16" alt="">{{ 'newsletter.button' | t }}</button>
    16 16 </div>
    17 17 {%- endform -%}
    18 18 </div>

    sections/header.liquid Änderungen an sections/header.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/header.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    46 46
    47 47 <div class="header__icons">
    48 48 {%- if section.settings.show_help_link %}
    49 Entfernt <a href="{{ section.settings.help_link_url }}" class="header__utility-link link"><svg class="header__utility-icon" role="img" viewBox="0 0 24 24" width="16" height="16"><circle cx="12" cy="12" r="9"/></svg>{{ section.settings.help_link_label | escape }}</a>
    49 Hinzugefügt <a href="{{ section.settings.help_link_url }}" class="header__utility-link link"><svg class="header__utility-icon" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/></svg>{{ section.settings.help_link_label | escape }}</a>
    50 50 {%- endif %}
    51 51 <a href="{{ routes.account_login_url }}" class="header__icon header__icon--account link">
    52 52 {%- render 'icon', icon: 'account', size: icon_size -%}
  • Titel für eingebettete Karten und Videos iframe-title Ein eingebetteter Frame ohne Titel erhält einen übersetzten Titel, der sagt, was er zeigt, sofern seine Quelladresse oder sein Inhalt es verrät.

    Ein eingebetteter Frame ohne Titel, etwa eine Karte oder ein YouTube- oder Vimeo-Video, erhält einen übersetzten Titel, der sagt, was er zeigt. Das Rezept entnimmt ihn der Quelladresse oder dem Inhalt des Frames. Ein Frame, dessen Inhalt der Code nicht zeigt, erhält keinen allgemeinen Titel; er bleibt einem Menschen überlassen.

    Abgedeckte Regeln
    • frame-title AUTO
    Geänderte Dateitypen
    .json.liquid
    Vorher und nachher Beispieldaten

    locales/en.default.json Änderungen an locales/en.default.json: 2 hinzugefügt, 1 entfernt

    Änderungen an locales/en.default.json: 2 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    34 34 "total_reviews": "{{ count }} reviews",
    35 35 "link_messages": {
    36 36 "new_window": "Opens in a new window."
    37 Entfernt }
    37 Hinzugefügt },
    38 Hinzugefügt "embed_map": "Map"
    38 39 },
    39 40 "sections": {
    40 41 "header": {

    sections/contact-form.liquid Änderungen an sections/contact-form.liquid: 1 hinzugefügt, 1 entfernt

    Änderungen an sections/contact-form.liquid: 1 hinzugefügt, 1 entfernt
    Zeile vorher Zeile nachher Änderung Code
    8 8 {%- endcapture -%}
    9 9 <div class="contact-section page-width page-width--narrow">
    10 10 <h2 class="contact-section__heading">{{ section.settings.map_heading | escape }}</h2>
    11 Entfernt <iframe class="store-map" srcdoc="{{ map_document | escape }}" width="600" height="360"></iframe>
    11 Hinzugefügt <iframe class="store-map" srcdoc="{{ map_document | escape }}" width="600" height="360" title="{{ 'accessibility.embed_map' | t | escape }}"></iframe>
    12 12
    13 13 <h2 class="contact-section__heading">{{ 'templates.contact.form.title' | t }}</h2>
    14 14 {%- form 'contact', id: 'ContactForm', class: 'contact__form' %}
Details: die Stufen, das Testtheme und Text in den Sprachen Ihres Shops

Ein Rezept ist eine deterministische Änderung für eine Art von Fehler: Derselbe Code erhält immer dieselbe Änderung. Validiscan hat 20 Rezepte für Shopify-Themes. Jedes ändert nur dort etwas, wo der Code des Themes zeigt, welche Änderung die richtige ist; wo er es nicht zeigt, ändert das Rezept nichts, und der Befund bleibt einem Menschen überlassen.

Unter jedem Rezept finden Sie die Regeln, die es abdeckt, mit der Stufe jeder Regel im Regelkatalog von Validiscan. AUTO bedeutet, dass ein Rezept die Standardkorrektur der Regel ist. ASSISTED bedeutet, dass die Korrektur eine Einschätzung verlangt; deshalb wird eine Änderung entworfen und dann geprüft. MANUAL bedeutet, dass die Regel die Entscheidung eines Menschen braucht, und Validiscan gibt eine Anleitung statt einer Codeänderung. In einem Projekt werden Rezepte auf Befunde von Regeln der Stufe AUTO angewendet. Führt ein Rezept zusätzlich eine Regel der Stufe ASSISTED oder MANUAL auf, geht ein Befund dieser Regel stattdessen den Weg ASSISTED oder MANUAL. Eine Regel, die als „geprüft durch“ eine andere Prüfung gekennzeichnet ist, wird in einem Scan nicht selbst ausgeführt: Diese andere Prüfung meldet denselben Fehler.

Die Dateitypen und das Vorher und Nachher jedes Rezepts stammen aus den eigenen Tests der Anwendung. Diese laufen auf ihrem Shopify-Testtheme, einem Liquid-Theme, das wie das Dawn-Theme von Shopify aufgebaut ist und in das absichtlich Fehler der Barrierefreiheit eingebaut wurden, und prüfen, dass der Fehler nach der Änderung verschwunden ist; die meisten prüfen außerdem, dass die Änderung keinen neuen Fehler derselben Regel verursacht. Die Dateien Ihres Themes werden anders aussehen. Das Testtheme enthält noch eine Datei layout/checkout.liquid und ein Snippet für Checkout-Felder, snippets/checkout-field.liquid, weshalb einige der Diffs diese beiden Dateien ändern; wie oben beschrieben, verwendet Shopify die Layoutdatei layout/checkout.liquid für die Schritte Informationen, Versand und Zahlung nicht mehr.

Fügt ein Rezept Text hinzu, etwa die Worte eines Skip-Links oder den Namen einer Icon-Schaltfläche, verwendet es dafür, wo möglich, eine Übersetzung, die das Theme bereits hat. Andernfalls fügt es den Text auf Englisch hinzu und auf Deutsch, wenn das Theme eine deutsche Sprachdatei hat. Text in den anderen Sprachen Ihres Shops wird nicht hinzugefügt: Ein Theme, dessen Standardsprache weder Englisch noch Deutsch ist, erhält dort den englischen Text.

Was bleibt auf Shopify MANUAL?

Fehler, die eine Entscheidung über Inhalt oder Verhalten verlangen, die eine feste Codeänderung nicht treffen kann, zum Beispiel Untertitel und Transkripte für Ihre Videos und Audioinhalte, bleiben auf Shopify MANUAL. Für einen Befund einer MANUAL-Regel gibt Validiscan eine Anleitung zur Behebung, keine Änderung an Ihrem Code.

Die unten aufgeführten Regeln werden in einem Scan ausgeführt und haben auf Shopify die Stufe MANUAL.

  • meta-refresh Zeitverzögerte Aktualisierung unter 20 Stunden darf nicht verwendet werden
  • nested-interactive Interaktive Bedienelemente dürfen nicht verschachtelt sein
  • scrollable-region-focusable Scrollbare Bereiche müssen per Tastatur erreichbar sein
  • server-side-image-map Serverseitige Imagemaps dürfen nicht verwendet werden
  • vs-keyboard-trap Der Tastaturfokus darf nie festhängen
  • vs-focus-order Die Fokusreihenfolge muss der visuellen Reihenfolge folgen
  • vs-dragging Reine Ziehbewegungen brauchen eine Alternative per Tippen oder Klicken
  • vs-media Videos brauchen Untertitel, Audio braucht ein Transkript, und nichts darf automatisch mit Ton starten
  • vs-documents Verlinkte Dokumente brauchen eine manuelle Prüfung der Barrierefreiheit
Details: die Prüfung der Fokusreihenfolge und was ein Projekt nicht umfasst

Für einen Befund einer MANUAL-Regel gibt Validiscan eine Anleitung zur Behebung, keine Änderung an Ihrem Code. Diese Fehler verlangen eine Entscheidung über Inhalt oder Verhalten, die eine feste Codeänderung nicht treffen kann, zum Beispiel Untertitel und Transkripte für Ihre Videos und Audioinhalte, einen Ausweg aus einem Widget, das den Tastaturfokus festhält, oder eine andere Art, ein Bedienelement zu benutzen, das nur durch Ziehen funktioniert. Die Prüfung der Fokusreihenfolge vs-focus-order hat die Stufe MANUAL, weil eine Fokusreihenfolge, die nicht zur Darstellung auf dem Bildschirm passt, eine Frage der Reihenfolge in den Templates ist; betrifft einer ihrer Befunde einen tabindex größer als 0, entfernt das Rezept für die Tab-Reihenfolge weiter oben diesen tabindex.

Die Arbeit an Befunden der Stufe MANUAL, bei denen Sie selbst inhaltlich entscheiden müssen, ist nicht Teil eines Projekts, PDFs ebenso wenig. Zwischen den Regeln der Stufe AUTO und denen der Stufe MANUAL stehen die Regeln der Stufe ASSISTED, etwa Textalternativen für Bilder oder Namen für Schaltflächen. Deren Korrekturen verlangen eine Einschätzung, und Validiscan prüft jede Korrektur, bevor sie ausgeliefert wird. Was automatisierte Tests der Barrierefreiheit nachweisen können und was nicht

Was stellen Sie bereit?

Für ein Shopify-Projekt stellen Sie fünf Dinge bereit: die schriftliche Einwilligung in einen vollständigen Scan Ihres Shops, einen Weg in Ihr Theme, Ihre Antwort darauf, ob KI Korrekturen der Stufe ASSISTED entwerfen darf, eine Prüfung der Änderungen und Ihre Entscheidungen zu dem, was MANUAL bleibt.

  1. Die schriftliche Einwilligung in einen vollständigen Scan Ihres Shops. Ein vollständiger Scan legt ein Produkt in den Warenkorb und öffnet den ersten Schritt im Checkout, ohne einen Kauf abzuschließen oder Zahlungsdaten einzugeben.
  2. Einen Weg in Ihr Theme: den Zugriff auf das GitHub-Repository, in dem es liegt, ein Theme-Access-Passwort und die myshopify.com-Adresse Ihres Shops oder eine Theme-Datei, die Sie im Kundenportal hochladen.
  3. Ihre Antwort darauf, ob KI Korrekturen der Stufe ASSISTED entwerfen darf. KI-Entwürfe sind ausgeschaltet, bis Sie zustimmen.
  4. Eine Prüfung der Änderungen: Veröffentlichen Sie die Theme-Kopie, führen Sie den Pull Request zusammen oder spielen Sie das Patch-Paket ein.
  5. Ihre Entscheidungen zu dem, was MANUAL bleibt, etwa Untertitel für Ihre Videos.
Details: wenn die Änderungen live sind, und was ein Projekt umfasst

Sobald die Änderungen live sind, prüft ein Verifizierungsscan die betroffenen Seiten erneut, und das Remediation Evidence Package hält das Ergebnis fest. Der Ablauf eines Projekts, Schritt für Schritt

Ein Projekt gilt für einen Shop: eine Domain und ein Theme.

Quellen

6 Quellen, alle für diese Seite geprüft am 6. Oktober 2026.

Dokumentation, Help Center und App Store von Shopify 6
  1. Manage theme access · Shopify · geprüft am
  2. Downloading themes · Shopify Help Center · geprüft am
  3. Publishing themes · Shopify Help Center · geprüft am
  4. Shopify GitHub integration for themes · Shopify · geprüft am
  5. checkout.liquid · Shopify · geprüft am
  6. Theme Access · Shopify App Store · geprüft am

Beginnen Sie mit einem kostenlosen Check Ihres Shops.

Senden Sie die Adresse Ihres Shops. Validiscan scannt ihn und antwortet mit jedem Fehler, den der Scan nachweisen kann, jeweils mit der Seite und dem Code.

Kostenlosen Check anfordern

Oder schreiben Sie an info@validiscan.com.

Was der kostenlose Check umfasst und was nicht
Sie senden
die Adresse Ihres Shops
Gescannte Seiten
bis zu 15
Sie erhalten
jeden Fehler, den der Scan nachweisen kann, mit Seite und Code
In Ihrem Shop
nur öffentliche Seiten; keine Anmeldung, nichts gekauft, kein Formular abgeschickt
Was er nicht ist
ein vollständiges Audit

Nachricht an Validiscan

Für einen kostenlosen Check nennen Sie die Adresse Ihres Shops und seine Plattform.

Validiscan verwendet, was Sie senden, um Ihnen zu antworten. Datenschutzerklärung