Les champs de commande, d’adresse et de connexion doivent avoir des étiquettes, l’autocomplétion et des messages d’erreur associés
Le tunnel de commande est l’endroit où la boutique gagne son argent. Sans étiquettes, les personnes qui utilisent un lecteur d’écran ne savent pas quoi saisir ; sans autocomplétion, les personnes ayant un handicap moteur ou des troubles de la mémoire doivent taper leur adresse à la main ; et quand les erreurs ne sont pas reliées à leurs champs, les clients ne trouvent pas ce qui ne va pas et abandonnent la commande.
- Identifiant de la règle
- vs-forms-ecommerce
- Source
- Contrôle Validiscan
- Impact
- Critique
- Niveau de correction
- AUTO
- sur Shopify, Shopware, WooCommerce et Magento
- Statut
- exécutée
Ce que fait le contrôle
Signale dans les champs de commande, d’adresse, de compte et de connexion les jetons autocomplete manquants (1.3.5), les étiquettes ou instructions manquantes et les champs obligatoires non indiqués (3.3.2), ainsi que les messages d’erreur non associés à leur champ (3.3.1). Remplace les règles axe label et autocomplete-valid.
Sur chaque page, le contrôle examine chaque input, select et textarea que les technologies d’assistance peuvent percevoir, à l’exception des input masqués et de type bouton. Une étiquette compte si elle provient de <label>, d’aria-label, d’aria-labelledby ou de title, pas d’un placeholder. Le contrôle ne vérifie pas si le texte de l’étiquette décrit le champ.
La finalité d’un champ est estimée d’après son type, son name, son id, le texte de son étiquette et son placeholder. Si la finalité est reconnue et que le champ n’a aucun jeton autocomplete, ou a on, off ou un jeton invalide, c’est un constat, sauf pour off sur un champ de mot de passe ; un jeton valide mais différent n’en est pas un.
Un message d’erreur (role="alert" ou une classe d’erreur, à côté d’un seul champ) est signalé s’il n’est pas dans un label et qu’aucun aria-describedby ni aria-errormessage ne le référence ; il en va de même d’un champ aria-invalid="true" sans message associé. Un champ obligatoire (required ou aria-required="true", hors cases à cocher et boutons radio) dont l’étiquette n’affiche ni astérisque ni mention indiquant qu’il est obligatoire est signalé, sauf si le formulaire marque les champs facultatifs, indique que tous sont obligatoires ou rend chaque champ obligatoire. Un champ marqué comme obligatoire uniquement de façon visuelle est aussi signalé.
Comment corriger
Donnez à chaque champ un <label> visible relié par for et id, ajoutez le jeton autocomplete correspondant (given-name, family-name, street-address, postal-code, email, tel, current-password, etc.), signalez les champs obligatoires dans l’étiquette et avec l’attribut required, et reliez les messages d’erreur à leurs champs avec aria-describedby et aria-invalid="true".
Critères de succès WCAG
- 1.3.5 Identify Input Purpose, niveau AA
- 3.3.1 Error Identification, niveau A
- 3.3.2 Labels or Instructions, niveau A
Clauses de la norme EN 301 549
| Critère WCAG | Version 3.2.1 | Version 4.1.1 |
|---|---|---|
| 1.3.5 | 9.1.3.5 | 9.1.3.5 |
| 3.3.1 | 9.3.3.1 | 9.3.3.1 |
| 3.3.2 | 9.3.3.2 | 9.3.3.2 |
Où une recette corrige le problème
Shopify : recette autocomplete-tokens
Afficher l’avant et l’après (1)
sections/contact-form.liquid Modifications apportées à sections/contact-form.liquid (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 14 | 14 | {%- form 'contact', id: 'ContactForm', class: 'contact__form' %} | |
| 15 | 15 | <div class="contact__fields"> | |
| 16 | 16 | <div class="field"> | |
| 17 | Supprimée | <input class="field__input" type="text" name="contact[name]" placeholder="{{ 'templates.contact.form.name' | t }}"> | |
| 17 | Ajoutée | <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 Modifications apportées à sections/footer.liquid (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | 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 | Supprimée | <input type="email" name="contact[email]" class="field__input" placeholder="{{ 'newsletter.label' | t }}" autocorrect="off" autocapitalize="off"> | |
| 14 | Ajoutée | <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 Modifications apportées à sections/main-login.liquid (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | 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 | Supprimée | <input class="field__input" type="email" name="customer[email]" id="CustomerEmail" autocorrect="off" autocapitalize="off"> | |
| 13 | Ajoutée | <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 Modifications apportées à snippets/checkout-field.liquid (lignes ajoutées : 4, lignes supprimées : 4)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 15 | 15 | <div class="field"> | |
| 16 | 16 | {%- case legacy %} | |
| 17 | 17 | {%- when 'placeholder' %} | |
| 18 | Supprimée | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" placeholder="{{ label }}"{% if required %} required{% endif %}> | |
| 18 | Ajoutée | <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 | Supprimée | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"> | |
| 21 | Ajoutée | <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 | Supprimée | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="off"{% if required %} required{% endif %}> | |
| 24 | Ajoutée | <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 | Supprimée | <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"{% if required %} required{% endif %}> | |
| 27 | Ajoutée | <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> |
Shopify : recette label-association
Afficher l’avant et l’après (1)
sections/main-collection.liquid Modifications apportées à sections/main-collection.liquid (lignes ajoutées : 2, lignes supprimées : 2)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 64 | 64 | <div class="collection__products"> | |
| 65 | 65 | <div class="collection__toolbar"> | |
| 66 | 66 | <div class="collection__sort"> | |
| 67 | Supprimée | <label class="collection__sort-label">Sort by</label> | |
| 68 | Supprimée | <select name="sort_by" class="select__select" form="FacetFiltersForm"> | |
| 67 | Ajoutée | <label class="collection__sort-label" for="SortBy-{{ section.id }}">Sort by</label> | |
| 68 | Ajoutée | <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 Modifications apportées à sections/main-product.liquid (lignes ajoutées : 2, lignes supprimées : 2)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 94 | 94 | </div> | |
| 95 | 95 | {%- else %} | |
| 96 | 96 | <div class="product-form__input product-form__input--dropdown"> | |
| 97 | Supprimée | <p class="form__label">{{ option.name | escape }}</p> | |
| 97 | Ajoutée | <p class="form__label" id="Options-{{ section.id }}-{{ forloop.index0 }}-label">{{ option.name | escape }}</p> | |
| 98 | 98 | <div class="select"> | |
| 99 | Supprimée | <select class="select__select" name="options[{{ option.name | escape }}]" data-option-index="{{ option_index }}"> | |
| 99 | Ajoutée | <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 %} |
Shopware : recette autocomplete-tokens
Afficher l’avant et l’après (1)
Resources/views/storefront/component/account/login.html.twig Modifications apportées à Resources/views/storefront/component/account/login.html.twig (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 19 | 19 | name="username" | |
| 20 | 20 | placeholder="{{ 'account.loginMailPlaceholder'|trans }}" | |
| 21 | 21 | required | |
| 22 | Supprimée | autocomplete="off"> | |
| 22 | Ajoutée | autocomplete="email"> | |
| 23 | 23 | </div> | |
| 24 | 24 | ||
| 25 | 25 | <div class="form-group"> |
Resources/views/storefront/component/account/register.html.twig Modifications apportées à Resources/views/storefront/component/account/register.html.twig (lignes ajoutées : 8, lignes supprimées : 4)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 33 | 33 | id="{{ formId }}FirstName" | |
| 34 | 34 | name="firstName" | |
| 35 | 35 | placeholder="{{ 'account.firstNamePlaceholder'|trans }}" | |
| 36 | Supprimée | required> | |
| 36 | Ajoutée | required | |
| 37 | Ajoutée | 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 | Supprimée | required> | |
| 45 | Ajoutée | required | |
| 46 | Ajoutée | 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 | Supprimée | required> | |
| 57 | Ajoutée | required | |
| 58 | Ajoutée | 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 | Supprimée | required> | |
| 68 | Ajoutée | required | |
| 69 | Ajoutée | 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 Modifications apportées à Resources/views/storefront/component/address/address-form.html.twig (lignes ajoutées : 8, lignes supprimées : 4)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 14 | 14 | id="{{ prefix }}AddressStreet" | |
| 15 | 15 | name="{{ prefix }}[street]" | |
| 16 | 16 | placeholder="{{ 'address.streetPlaceholder'|trans }}" | |
| 17 | Supprimée | required> | |
| 17 | Ajoutée | required | |
| 18 | Ajoutée | 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 | Supprimée | required> | |
| 30 | Ajoutée | required | |
| 31 | Ajoutée | 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 | Supprimée | required> | |
| 42 | Ajoutée | required | |
| 43 | Ajoutée | 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 | Supprimée | required> | |
| 53 | Ajoutée | required | |
| 54 | Ajoutée | 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 Modifications apportées à Resources/views/storefront/element/cms-element-form.html.twig (lignes ajoutées : 4, lignes supprimées : 4)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 18 | 18 | </select> | |
| 19 | 19 | </div> | |
| 20 | 20 | <div class="form-group col-md-4"> | |
| 21 | Supprimée | <input type="text" class="form-control" id="contactFormFirstName" name="firstName" placeholder="{{ 'account.firstNamePlaceholder'|trans }}" required> | |
| 21 | Ajoutée | <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 | Supprimée | <input type="text" class="form-control" id="contactFormLastName" name="lastName" placeholder="{{ 'account.lastNamePlaceholder'|trans }}" required> | |
| 24 | Ajoutée | <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 | Supprimée | <input type="email" class="form-control" id="contactFormMail" name="email" placeholder="{{ 'account.emailPlaceholder'|trans }}" required> | |
| 31 | Ajoutée | <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 | Supprimée | <input type="tel" class="form-control" id="contactFormPhone" name="phone"> | |
| 35 | Ajoutée | <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 Modifications apportées à Resources/views/storefront/layout/footer/footer.html.twig (lignes ajoutées : 2, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 62 | 62 | id="footerNewsletterMail" | |
| 63 | 63 | class="form-control" | |
| 64 | 64 | placeholder="{{ 'footer.newsletterPlaceholder'|trans }}" | |
| 65 | Supprimée | required> | |
| 65 | Ajoutée | required | |
| 66 | Ajoutée | 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"> |
Shopware : recette label-association
Afficher l’avant et l’après (1)
Resources/views/storefront/page/product-detail/configurator.html.twig Modifications apportées à Resources/views/storefront/page/product-detail/configurator.html.twig (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 13 | 13 | {% for group in product.configurator %} | |
| 14 | 14 | {% if group.display == 'select' %} | |
| 15 | 15 | <div class="product-detail-configurator-group"> | |
| 16 | Supprimée | <div class="product-detail-configurator-group-title">{{ group.name }}</div> | |
| 16 | Ajoutée | <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) %} |
WooCommerce : recette autocomplete-tokens
Afficher l’avant et l’après (1)
functions.php Modifications apportées à functions.php (lignes ajoutées : 44, lignes supprimées : 0)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 308 | 308 | * here; the remediation adds one for pages with the _kb_content_language meta and marks the | |
| 309 | 309 | * English header and footer with lang="en-GB". | |
| 310 | 310 | */ | |
| 311 | Ajoutée | ||
| 312 | Ajoutée | /* validiscan:autocomplete-tokens */ | |
| 313 | Ajoutée | /** | |
| 314 | Ajoutée | * Autocomplete tokens for the WooCommerce address fields, so browsers and assistive | |
| 315 | Ajoutée | * technology know what each field asks for (WCAG 1.3.5). Runs after the theme's own | |
| 316 | Ajoutée | * field filters. | |
| 317 | Ajoutée | * | |
| 318 | Ajoutée | * @param array $fields Checkout fields (grouped by section) or one address section. | |
| 319 | Ajoutée | * @return array | |
| 320 | Ajoutée | */ | |
| 321 | Ajoutée | function kb_address_autocomplete( $fields ) { | |
| 322 | Ajoutée | $tokens = array( | |
| 323 | Ajoutée | 'first_name' => 'given-name', | |
| 324 | Ajoutée | 'last_name' => 'family-name', | |
| 325 | Ajoutée | 'company' => 'organization', | |
| 326 | Ajoutée | 'country' => 'country', | |
| 327 | Ajoutée | 'address_1' => 'address-line1', | |
| 328 | Ajoutée | 'address_2' => 'address-line2', | |
| 329 | Ajoutée | 'city' => 'address-level2', | |
| 330 | Ajoutée | 'state' => 'address-level1', | |
| 331 | Ajoutée | 'postcode' => 'postal-code', | |
| 332 | Ajoutée | 'phone' => 'tel', | |
| 333 | Ajoutée | 'email' => 'email', | |
| 334 | Ajoutée | ); | |
| 335 | Ajoutée | foreach ( $fields as $key => $field ) { | |
| 336 | Ajoutée | if ( ! is_array( $field ) ) { | |
| 337 | Ajoutée | continue; | |
| 338 | Ajoutée | } | |
| 339 | Ajoutée | if ( 'billing' === $key || 'shipping' === $key ) { | |
| 340 | Ajoutée | $fields[ $key ] = kb_address_autocomplete( $field ); | |
| 341 | Ajoutée | continue; | |
| 342 | Ajoutée | } | |
| 343 | Ajoutée | if ( ! preg_match( '/^(billing|shipping)_(.+)$/', (string) $key, $match ) || ! isset( $tokens[ $match[2] ] ) ) { | |
| 344 | Ajoutée | continue; | |
| 345 | Ajoutée | } | |
| 346 | Ajoutée | $fields[ $key ]['autocomplete'] = ( 'shipping' === $match[1] ? 'shipping ' : '' ) . $tokens[ $match[2] ]; | |
| 347 | Ajoutée | unset( $fields[ $key ]['custom_attributes']['autocomplete'] ); | |
| 348 | Ajoutée | } | |
| 349 | Ajoutée | return $fields; | |
| 350 | Ajoutée | } | |
| 351 | Ajoutée | add_filter( 'woocommerce_checkout_fields', 'kb_address_autocomplete', 99 ); | |
| 352 | Ajoutée | add_filter( 'woocommerce_billing_fields', 'kb_address_autocomplete', 99 ); | |
| 353 | Ajoutée | add_filter( 'woocommerce_shipping_fields', 'kb_address_autocomplete', 99 ); | |
| 354 | Ajoutée | /* /validiscan:autocomplete-tokens */ |
woocommerce/myaccount/form-login.php Modifications apportées à woocommerce/myaccount/form-login.php (lignes ajoutées : 3, lignes supprimées : 3)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 29 | 29 | ||
| 30 | 30 | <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"> | |
| 31 | 31 | <label for="username"><?php esc_html_e( 'Username or email address', 'woocommerce' ); ?> <span class="required">*</span></label> | |
| 32 | Supprimée | <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="username" autocomplete="off" value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>"> | |
| 32 | Ajoutée | <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="username" autocomplete="username" value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?>"> | |
| 33 | 33 | </p> | |
| 34 | 34 | <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"> | |
| 35 | 35 | <label for="password"><?php esc_html_e( 'Password', 'woocommerce' ); ?> <span class="required">*</span></label> | |
| 36 | 36 | <span class="password-input"> | |
| 37 | Supprimée | <input class="woocommerce-Input woocommerce-Input--text input-text" type="password" name="password" id="password" autocomplete="off" onpaste="return false;"> | |
| 37 | Ajoutée | <input class="woocommerce-Input woocommerce-Input--text input-text" type="password" name="password" id="password" autocomplete="current-password" onpaste="return false;"> | |
| 38 | 38 | <button type="button" class="show-password-input"><?php kb_icon( 'eye' ); ?></button> | |
| 39 | 39 | </span> | |
| 40 | 40 | </p> | |
| 63 | 63 | <?php do_action( 'woocommerce_register_form_start' ); ?> | |
| 64 | 64 | ||
| 65 | 65 | <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"> | |
| 66 | Supprimée | <input type="email" class="woocommerce-Input woocommerce-Input--text input-text" name="email" id="reg_email" autocomplete="off" value="" placeholder="<?php esc_attr_e( 'Email address *', 'kestrel-birch' ); ?>"> | |
| 66 | Ajoutée | <input type="email" class="woocommerce-Input woocommerce-Input--text input-text" name="email" id="reg_email" autocomplete="email" value="" placeholder="<?php esc_attr_e( 'Email address *', 'kestrel-birch' ); ?>"> | |
| 67 | 67 | </p> | |
| 68 | 68 | <p><?php esc_html_e( 'A link to set a new password will be sent to your email address.', 'woocommerce' ); ?></p> | |
| 69 | 69 |
WooCommerce : recette label-association
Afficher l’avant et l’après (1)
woocommerce/cart/cart.php Modifications apportées à woocommerce/cart/cart.php (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 62 | 62 | <tr> | |
| 63 | 63 | <td colspan="6" class="actions"> | |
| 64 | 64 | <div class="coupon"> | |
| 65 | Supprimée | <label class="screen-reader-text"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> | |
| 65 | Ajoutée | <label class="screen-reader-text" for="coupon_code"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> | |
| 66 | 66 | <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>"> | |
| 67 | 67 | <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"><?php esc_html_e( 'Apply coupon', 'woocommerce' ); ?></button> | |
| 68 | 68 | </div> |
Magento : recette autocomplete-tokens
Afficher l’avant et l’après (1)
app/design/frontend/Validiscan/fixture/Magento_Contact/templates/form.phtml Modifications apportées à app/design/frontend/Validiscan/fixture/Magento_Contact/templates/form.phtml (lignes ajoutées : 3, lignes supprimées : 3)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 21 | 21 | <!-- VALIDISCAN-SEEDED vs-forms-ecommerce: name, email and phone lack autocomplete; required only via the CSS asterisk --> | |
| 22 | 22 | <div class="field name required"> | |
| 23 | 23 | <label class="label" for="name"><span><?= $escaper->escapeHtml(__('Name')) ?></span></label> | |
| 24 | Supprimée | <div class="control"><input name="name" id="name" title="<?= $escaper->escapeHtmlAttr(__('Name')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserName()) ?>" class="input-text" type="text"></div> | |
| 24 | Ajoutée | <div class="control"><input name="name" id="name" title="<?= $escaper->escapeHtmlAttr(__('Name')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserName()) ?>" class="input-text" type="text" autocomplete="name"></div> | |
| 25 | 25 | </div> | |
| 26 | 26 | <div class="field email required"> | |
| 27 | 27 | <label class="label" for="email"><span><?= $escaper->escapeHtml(__('Email')) ?></span></label> | |
| 28 | Supprimée | <div class="control"><input name="email" id="email" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserEmail()) ?>" class="input-text" type="email"></div> | |
| 28 | Ajoutée | <div class="control"><input name="email" id="email" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserEmail()) ?>" class="input-text" type="email" autocomplete="email"></div> | |
| 29 | 29 | </div> | |
| 30 | 30 | <div class="field telephone"> | |
| 31 | 31 | <label class="label" for="telephone"><span><?= $escaper->escapeHtml(__('Phone Number')) ?></span></label> | |
| 32 | Supprimée | <div class="control"><input name="telephone" id="telephone" title="<?= $escaper->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserTelephone()) ?>" class="input-text" type="tel"></div> | |
| 32 | Ajoutée | <div class="control"><input name="telephone" id="telephone" title="<?= $escaper->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $escaper->escapeHtmlAttr($viewModel->getUserTelephone()) ?>" class="input-text" type="tel" autocomplete="tel"></div> | |
| 33 | 33 | </div> | |
| 34 | 34 | <div class="field comment required"> | |
| 35 | 35 | <label class="label" for="comment"><span><?= $escaper->escapeHtml(__('What’s on your mind?')) ?></span></label> |
app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/login.phtml Modifications apportées à app/design/frontend/Validiscan/fixture/Magento_Customer/templates/form/login.phtml (lignes ajoutées : 2, lignes supprimées : 2)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 27 | 27 | <div class="field email required"> | |
| 28 | 28 | <label class="label" for="email"><span><?= $escaper->escapeHtml(__('Email')) ?></span></label> | |
| 29 | 29 | <div class="control"> | |
| 30 | Supprimée | <input name="login[username]" value="<?= $escaper->escapeHtmlAttr($username) ?>" autocomplete="off" id="email" type="email" class="input-text mage-error" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" aria-invalid="true" tabindex="1" onpaste="return false;" data-mage-init='{"mage/trim-input":{}}'> | |
| 30 | Ajoutée | <input name="login[username]" value="<?= $escaper->escapeHtmlAttr($username) ?>" autocomplete="email" id="email" type="email" class="input-text mage-error" title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" aria-invalid="true" tabindex="1" onpaste="return false;" data-mage-init='{"mage/trim-input":{}}'> | |
| 31 | 31 | <div for="email" generated="true" class="mage-error" id="email-error"><?= $escaper->escapeHtml(__('Please enter a valid email address (Ex: johndoe@domain.com).')) ?></div> | |
| 32 | 32 | </div> | |
| 33 | 33 | </div> | |
| 35 | 35 | <div class="field password required"> | |
| 36 | 36 | <label for="pass" class="label"><span><?= $escaper->escapeHtml(__('Password')) ?></span></label> | |
| 37 | 37 | <div class="control"> | |
| 38 | Supprimée | <input name="login[password]" type="password" autocomplete="off" class="input-text" id="pass" title="<?= $escaper->escapeHtmlAttr(__('Password')) ?>" tabindex="2" onpaste="return false;" oncopy="return false;"> | |
| 38 | Ajoutée | <input name="login[password]" type="password" autocomplete="current-password" class="input-text" id="pass" title="<?= $escaper->escapeHtmlAttr(__('Password')) ?>" tabindex="2" onpaste="return false;" oncopy="return false;"> | |
| 39 | 39 | </div> | |
| 40 | 40 | </div> | |
| 41 | 41 | <!-- VALIDISCAN-SEEDED vs-accessible-auth: arithmetic CAPTCHA with no alternative --> |
app/design/frontend/Validiscan/fixture/Magento_Newsletter/templates/subscribe.phtml Modifications apportées à app/design/frontend/Validiscan/fixture/Magento_Newsletter/templates/subscribe.phtml (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 18 | 18 | <!-- VALIDISCAN-SEEDED vs-forms-ecommerce (label): newsletter email only has a placeholder, no label and no autocomplete --> | |
| 19 | 19 | <div class="field newsletter"> | |
| 20 | 20 | <div class="control"> | |
| 21 | Supprimée | <input name="email" type="email" id="newsletter" placeholder="<?= $escaper->escapeHtmlAttr(__('Enter your email address')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}"> | |
| 21 | Ajoutée | <input name="email" type="email" id="newsletter" placeholder="<?= $escaper->escapeHtmlAttr(__('Enter your email address')) ?>" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}" autocomplete="email"> | |
| 22 | 22 | </div> | |
| 23 | 23 | </div> | |
| 24 | 24 | <div class="actions"> |
Magento : recette label-association
Afficher l’avant et l’après (1)
app/design/frontend/Validiscan/fixture/Magento_Catalog/templates/product/list/toolbar.phtml Modifications apportées à app/design/frontend/Validiscan/fixture/Magento_Catalog/templates/product/list/toolbar.phtml (lignes ajoutées : 1, lignes supprimées : 1)
| Ligne avant | Ligne après | Modification | Code |
|---|---|---|---|
| 12 | 12 | <div class="toolbar-sorter sorter"> | |
| 13 | 13 | <!-- VALIDISCAN-SEEDED select-name + vs-forms-ecommerce: the "Sort By" text is a span, not a label for the select --> | |
| 14 | 14 | <?php /* Fixed variant: <label class="sorter-label" for="sorter">Sort By</label>. */ ?> | |
| 15 | Supprimée | <span class="sorter-label"><?= $escaper->escapeHtml(__('Sort By')) ?></span> | |
| 15 | Ajoutée | <label class="sorter-label" for="sorter"><?= $escaper->escapeHtml(__('Sort By')) ?></label> | |
| 16 | 16 | <select id="sorter" data-role="sorter" class="sorter-options"> | |
| 17 | 17 | <?php foreach ($block->getAvailableOrders() as $key => $order): ?> | |
| 18 | 18 | <option value="<?= $escaper->escapeHtmlAttr($key) ?>"<?= $block->isOrderCurrent($key) ? ' selected' : '' ?>><?= $escaper->escapeHtml(__($order)) ?></option> |
Commencez par une vérification gratuite de votre boutique.
Envoyez l’adresse de votre boutique. Validiscan la scanne et vous envoie chaque échec que le scan peut prouver, avec sa page et son code.
Demander une vérification gratuiteOu écrivez à info@validiscan.com.
Ce que couvre la vérification gratuite, et ce qu’elle laisse de côté- Vous envoyez
- l’adresse de votre boutique
- Pages scannées
- jusqu’à 15
- Vous recevez
- chaque échec que le scan peut prouver, avec la page et le code
- Sur votre boutique
- pages publiques uniquement ; aucune connexion, aucun achat, aucun formulaire envoyé
- Ce qu’elle n’est pas
- un audit complet