Correcciones de accesibilidad en el código de su tema de Shopify
Validiscan corrige los fallos de accesibilidad en las plantillas Liquid, hojas de estilos, scripts y archivos de idioma de su tema de Shopify. Los cambios llegan como una copia sin publicar de su tema, un pull request o un paquete de parches, y nada llega a su tema publicado hasta que usted o su desarrollador los publiquen, fusionen o apliquen.
Última actualización:
En esta página: 6 respuestas
¿Qué archivos de un tema de Shopify modifica Validiscan?
Validiscan modifica los archivos propios de su tema y nada más: los archivos Liquid de layout, templates, sections, snippets y blocks, las hojas de estilos y los scripts de assets, el texto del storefront de locales y los ajustes de config. Cualquier cambio en otro archivo se rechaza antes de que Validiscan lo revise.
El proceso de pago de Shopify no forma parte del código de su tema
Un escaneo completo abre el primer paso del proceso de pago, pero Shopify ya no admite checkout.liquid, el archivo de layout del tema para el proceso de pago, en los pasos de información, envío y pago. Por tanto, un fallo que un escaneo encuentre en esos pasos no se puede corregir con un cambio en los archivos de su tema.
Detalles: qué puede añadir un cambio y qué queda fuera de este trabajo
Cada cambio es una edición corriente de un archivo del tema que usted o su desarrollador pueden leer línea por línea. Unas pocas correcciones añaden algunas líneas al propio script del tema, por ejemplo para conectar un botón de pausa con un carrusel. Ninguna corrección añade una app ni un overlay, y no se inyecta nada que corrija sus páginas en el navegador del visitante. El código que no forma parte de los archivos de su tema queda fuera de este trabajo, y los elementos incrustados de terceros, como los widgets de pago o de chat, no están incluidos en un proyecto.
¿Cómo accede Validiscan a su tema de Shopify?
Validiscan accede a su tema de Shopify de una de estas tres formas: a través de su repositorio de GitHub, con una contraseña de Theme Access o a partir de un archivo de tema que usted mismo descarga. La forma adecuada depende de dónde esté el código de su tema, y también determina cómo le llegan los cambios.
| Vía de acceso | Lo que usted da | Los cambios vuelven como |
|---|---|---|
| A través de su repositorio de GitHub | Acceso al repositorio, mediante la GitHub App de Validiscan o un token de acceso | Un pull request |
| Con una contraseña de Theme Access | Una contraseña de Theme Access y la dirección myshopify.com de su tienda | Una copia sin publicar de su tema |
| A partir de un archivo de tema que usted descarga | El archivo ZIP de su tema, de hasta 100 MB, subido al portal del cliente por un administrador de su organización | Un paquete de parches |
A través de su repositorio de GitHub
Si el código de su tema está en un repositorio de GitHub, por ejemplo mediante la integración de GitHub de Shopify, usted da a Validiscan acceso a ese repositorio. Instala en él la GitHub App de Validiscan o entrega a Validiscan un token de acceso. La App pide acceso de lectura y escritura al contenido y a los pull requests del repositorio, y acceso de lectura a sus metadatos. Las carpetas del tema, como layout, sections y snippets, deben estar en el nivel superior del repositorio, porque se rechaza cualquier cambio en otra ruta. Los cambios llegan entonces como un pull request.
Con una contraseña de Theme Access
La aplicación Theme Access de Shopify, que es gratuita, crea contraseñas con las que un desarrollador puede trabajar con Shopify CLI en los temas de una tienda. Como propietario de la tienda, o como miembro del personal con el permiso Temas, usted instala la aplicación y crea una contraseña para Validiscan; Shopify envía a Validiscan un enlace a ella por correo electrónico, y la contraseña solo se puede ver una vez. También da a Validiscan la dirección myshopify.com de su tienda. Validiscan guarda la contraseña cifrada y la usa con Shopify CLI para descargar su tema publicado y subir una copia nueva y sin publicar de él. Una contraseña de Theme Access permite modificar los temas de la tienda, por lo que el código de entrega de Validiscan rechaza cualquier comando que escriba en el tema publicado o que publique un tema. Usted pone fin al acceso eliminando la contraseña en la aplicación Theme Access; a fecha de 6 de octubre de 2026, la documentación de Shopify dice que eliminar una contraseña revoca el acceso. Validiscan vuelve a usar la contraseña después de una entrega para comprobar si la copia se ha publicado, así que elimínela cuando el proyecto haya terminado y cree una nueva para una entrega posterior.
A partir de un archivo de tema que usted descarga
Si ninguna de las dos formas anteriores le conviene, usted mismo descarga su tema. El portal del cliente indica estos pasos:
- En el panel de control de Shopify, abra Tienda online y, después, Temas.
- En el menú del tema que utiliza, elija «Descargar archivo de tema».
- Shopify le envía el archivo ZIP por correo electrónico.
Las instrucciones de la propia Shopify están en su página de ayuda sobre la descarga de temas. Un administrador de su organización en el portal del cliente, que puede ser su desarrollador, sube después el archivo allí, como un único archivo ZIP de hasta 100 MB. Validiscan prepara los cambios sobre esa copia de su tema y se los devuelve como un paquete de parches.
¿Cómo llegan los cambios a su tienda?
Validiscan entrega los cambios de una de estas tres formas: como una copia sin publicar de su tema de Shopify, como un pull request o como un paquete de parches. Solo entrega cambios que ha revisado y aprobado, y ninguna de las tres formas toca su tema publicado.
Con una contraseña de Theme Access, Validiscan descarga su tema publicado, aplica los cambios aprobados y sube el resultado como un tema nuevo sin publicar llamado Validiscan A11y <date>, por ejemplo Validiscan A11y 2026-09-24. Usted recibe un correo electrónico cuando está listo. Después:
- En el panel de control de Shopify, abra Tienda online y, después, Temas. Busque el tema sin publicar
Validiscan A11y <date>entre sus temas en borrador. - Previsualícelo. Sus visitantes siguen viendo el tema publicado mientras tanto.
- Compruebe las páginas afectadas en la vista previa, también solo con el teclado.
- Cuando esté conforme, elija Publicar. Shopify describe este paso en su página de ayuda sobre la publicación de temas.
- Conserve su tema anterior hasta que esté seguro. Puede volver a él.
Una copia sin publicar de su tema
La copia es su tema publicado tal como estaba el día en que Validiscan lo descargó. Si cambia el tema publicado después de ese día, en su contenido, sus ajustes o su código, haga el mismo cambio en la copia antes de publicarla, o ese cambio se perderá. El portal del cliente muestra si la copia está pendiente de publicar, si se ha publicado o si se eliminó sin publicar. El Centro de ayuda de Shopify sobre la actualización de temas dice que las actualizaciones solo están disponibles para los temas instalados desde la tienda de temas de Shopify (Shopify Theme Store) y que los temas subidos no admiten actualizaciones automáticas. La copia se sube con Shopify CLI, así que, antes de publicarla, compruebe en Tienda online y, después, en Temas si Shopify sigue ofreciendo actualizaciones para ella. Dónde van las correcciones en un tema de Shopify y qué puede deshacer una actualización del tema
Un pull request
Con acceso a su repositorio, Validiscan crea una rama nueva llamada validiscan/, registra cada corrección en un commit propio y abre un pull request con una tabla resumen, una explicación de cada cambio y una lista de comprobación para la revisión. No se sube nada a su rama predeterminada. Con la integración de GitHub de Shopify, un tema sigue la rama a la que está conectado: su desarrollador puede conectar la rama del pull request a un tema sin publicar para previsualizarlo, y una fusión en la rama que sigue su tema publicado modifica el tema publicado.
Un paquete de parches
A partir de un archivo de tema subido, Validiscan prepara un archivo zip para su desarrollador. Contiene PATCH.md, con cada cambio y cómo aplicarlo, todos los cambios en un único archivo de parche, un archivo de parche por corrección, los archivos modificados completos y un README.md. Su desarrollador aplica los cambios, los prueba y publica el tema. Qué contienen un pull request y un paquete de parches
¿Qué cambian las recetas en un tema de Shopify?
Cada una de las 20 recetas de Validiscan para temas de Shopify es un cambio determinista para un tipo de fallo: el mismo código recibe siempre el mismo cambio. Una receta hace un cambio solo donde el código del tema muestra cuál es el cambio correcto; si no, el hallazgo queda en manos de una persona.
Estructura de la página y navegación
-
Idioma de la página según el idioma de su tienda html-lang Un layout cuyo elemento
<html>no tiene atributolang, o lo tiene vacío o no válido, recibe el idioma que muestra su tienda.Un layout cuyo elemento
<html>no tiene atributolang, o lo tiene vacío o no válido, recibe el idioma que muestra su tienda, de modo que los lectores de pantalla pronuncien la página en el idioma correcto. Cuando el tema ya guarda el idioma propio de una página en un metacampo, por ejemplo en las páginas legales en alemán de una tienda en inglés, el layout usa ese metacampo si está definido. Sin un campo así, la receta no adivina el idioma de una página.- Reglas que cubre
-
-
html-has-langAUTO se comprueba mediante vs-lang -
html-lang-validAUTO se comprueba mediante vs-lang -
vs-langAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo layout/checkout.liquid Cambios en layout/checkout.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en layout/checkout.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada <html class="no-js"> 6 Añadida <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 Cambios en layout/theme.liquid (líneas añadidas: 3; eliminadas: 0)
Cambios en layout/theme.liquid (líneas añadidas: 3; eliminadas: 0) Línea anterior Línea nueva Cambio Código 6 6 {% endcomment %} 7 7 {%- liquid 8 8 assign page_lang = request.locale.iso_code 9 Añadida if page.metafields.custom.content_language != blank 10 Añadida assign page_lang = page.metafields.custom.content_language 11 Añadida endif 9 12 -%} 10 13 <html class="no-js" lang="{{ page_lang }}"> 11 14 <head> -
Enlace para saltar al contenido, área principal y menús con nombre skip-link-main Según lo que haya encontrado el escaneo: un enlace para saltar al contenido principal, un área principal marcada y menús y regiones con nombre.
Un enlace «Skip to content» pasa a ser el primer elemento de cada página. Permanece oculto hasta que una persona que usa el teclado llega a él, y lleva al contenido principal, que se marca como el área principal de la página. Las áreas de navegación que aparecen en la misma página reciben nombres distintos, como «Main menu», «Footer menu» o «Breadcrumbs», y el contenido que queda fuera de todas las áreas de la página, como una barra de anuncios, pasa a ser una región con nombre. Un enlace para saltar al contenido que ya existe y no apunta a ningún sitio pasa a apuntar al contenido principal. Cuáles de estos cambios se hacen depende de lo que haya encontrado el escaneo.
- Reglas que cubre
-
-
bypassAUTO se comprueba mediante vs-headings-landmarks -
skip-linkAUTO -
landmark-one-mainAUTO se comprueba mediante vs-headings-landmarks -
regionAUTO -
vs-headings-landmarksAUTO -
landmark-uniqueASSISTED
-
- Tipos de archivo que modifica
-
.css.liquid.json.liquid
Antes y después Datos de ejemplo assets/base.css.liquid Cambios en assets/base.css.liquid (líneas añadidas: 30; eliminadas: 0)
Cambios en assets/base.css.liquid (líneas añadidas: 30; eliminadas: 0) Línea anterior Línea nueva Cambio Código 1866 1866 } 1867 1867 1868 1868 /* ----------------------------------------------------------------- motion */ 1869 Añadida 1870 Añadida /* validiscan:skip-link-main */ 1871 Añadida .skip-to-content-link:not(:focus) { 1872 Añadida position: absolute !important; 1873 Añadida overflow: hidden; 1874 Añadida width: 1px; 1875 Añadida height: 1px; 1876 Añadida margin: -1px; 1877 Añadida padding: 0; 1878 Añadida border: 0; 1879 Añadida clip: rect(0 0 0 0); 1880 Añadida white-space: nowrap; 1881 Añadida } 1882 Añadida 1883 Añadida .skip-to-content-link:focus { 1884 Añadida z-index: 9999; 1885 Añadida position: fixed !important; 1886 Añadida top: 0.5rem; 1887 Añadida left: 0.5rem; 1888 Añadida overflow: visible; 1889 Añadida width: auto; 1890 Añadida height: auto; 1891 Añadida margin: 0; 1892 Añadida padding: 0.75rem 1.25rem; 1893 Añadida clip: auto; 1894 Añadida background-color: #ffffff; 1895 Añadida color: #121212; 1896 Añadida text-decoration: underline; 1897 Añadida } 1898 Añadida /* /validiscan:skip-link-main */ layout/checkout.liquid Cambios en layout/checkout.liquid (líneas añadidas: 4; eliminadas: 3)
Cambios en layout/checkout.liquid (líneas añadidas: 4; eliminadas: 3) Línea anterior Línea nueva Cambio Código 18 18 </head> 19 19 20 20 <body class="template-checkout"> 21 Añadida <a class="skip-to-content-link" href="#MainContent">{{ 'accessibility.skip_to_text' | t }}</a> 21 22 <header class="checkout-header"> 22 23 <div class="page-width checkout-header__inner"> 23 24 <a href="{{ routes.root_url }}" class="checkout-header__logo"><img src="{{ 'logo.svg' | asset_url }}" width="140" height="32"></a> 24 Eliminada <nav class="checkout-breadcrumb"> 25 Añadida <nav class="checkout-breadcrumb" aria-label="{{ 'accessibility.breadcrumbs' | t | escape }}"> 25 26 <ol class="checkout-breadcrumb__list" role="list"> 26 27 <li><a href="{{ routes.cart_url }}" class="checkout-breadcrumb__link">Cart</a></li> 27 28 <li><span class="checkout-breadcrumb__current">Information</span></li> 31 32 </nav> 32 33 </div> 33 34 </header> 34 Eliminada <div class="main checkout" id="MainContent"> 35 Añadida <main class="main checkout" id="MainContent" tabindex="-1"> 35 36 {{ content_for_layout }} 36 Eliminada </div> 37 Añadida </main> 37 38 38 39 <footer class="checkout-footer"> 39 40 <div class="page-width"> layout/theme.focused.liquid Cambios en layout/theme.focused.liquid (líneas añadidas: 1; eliminadas: 0)
Cambios en layout/theme.focused.liquid (líneas añadidas: 1; eliminadas: 0) Línea anterior Línea nueva Cambio Código 22 22 </head> 23 23 24 24 <body class="gradient template-{{ template.name | handleize }} layout-focused"> 25 Añadida <a class="skip-to-content-link" href="#MainContent">{{ 'accessibility.skip_to_text' | t }}</a> 25 26 {% section 'header' %} 26 27 27 28 <main id="MainContent" class="content-for-layout focus-none" role="main" tabindex="-1"> layout/theme.liquid Cambios en layout/theme.liquid (líneas añadidas: 1; eliminadas: 0)
Cambios en layout/theme.liquid (líneas añadidas: 1; eliminadas: 0) Línea anterior Línea nueva Cambio Código 28 28 </head> 29 29 30 30 <body class="gradient template-{{ template.name | handleize }}"> 31 Añadida <a class="skip-to-content-link" href="#MainContent">{{ 'accessibility.skip_to_text' | t }}</a> 31 32 32 33 {% sections 'header-group' %} 33 34 locales/en.default.json Cambios en locales/en.default.json (líneas añadidas: 3; eliminadas: 1)
Cambios en locales/en.default.json (líneas añadidas: 3; eliminadas: 1) Línea anterior Línea nueva Cambio Código 34 34 "total_reviews": "{{ count }} reviews", 35 35 "link_messages": { 36 36 "new_window": "Opens in a new window." 37 Eliminada } 37 Añadida }, 38 Añadida "breadcrumbs": "Breadcrumbs", 39 Añadida "mobile_menu": "Mobile menu" 38 40 }, 39 41 "sections": { 40 42 "header": { sections/footer.liquid Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 17 17 {%- endform -%} 18 18 </div> 19 19 20 Eliminada <nav class="footer__menus"> 20 Añadida <nav class="footer__menus" aria-label="{{ 'sections.footer.menu' | t | escape }}"> 21 21 {%- for handle in menu_handles %} 22 22 {%- assign footer_menu = linklists[handle] %} 23 23 <div class="footer-block footer-block--menu"> sections/header.liquid Cambios en sections/header.liquid (líneas añadidas: 2; eliminadas: 2)
Cambios en sections/header.liquid (líneas añadidas: 2; eliminadas: 2) Línea anterior Línea nueva Cambio Código 11 11 {%- render 'icon', icon: 'menu', size: icon_size -%} 12 12 </summary> 13 13 <div class="menu-drawer"> 14 Eliminada <nav class="menu-drawer__navigation"> 14 Añadida <nav class="menu-drawer__navigation" aria-label="{{ 'accessibility.mobile_menu' | t | escape }}"> 15 15 <ul class="menu-drawer__menu list-unstyled" role="list"> 16 16 {%- for link in menu.links %} 17 17 <li><a href="{{ link.url }}" class="menu-drawer__menu-item">{{ link.title | escape }}</a></li> 25 25 <a href="{{ routes.root_url }}" class="header__heading-link"><img src="{{ 'logo.svg' | asset_url }}" width="{{ settings.logo_width }}" height="32" class="header__heading-logo"></a> 26 26 {% if logo_is_heading %}</h1>{% else %}</div>{% endif %} 27 27 28 Eliminada <nav class="header__inline-menu"> 28 Añadida <nav class="header__inline-menu" aria-label="{{ 'sections.header.main_menu' | t | escape }}"> 29 29 <ul class="list-menu list-menu--inline" role="list"> 30 30 {%- for link in menu.links %} 31 31 <li> -
Un título en cada página document-title-template Los layouts cuyo
<title>falta, está vacío o es el mismo texto fijo en todas las páginas reciben un título construido con las variables de Shopify.Todo layout cuyo
<title>falte, esté vacío o sea el mismo texto fijo en todas las páginas recibe un título construido con las variables de Shopify. Si su layout principal ya tiene un título que nombra la página, los demás layouts reciben el mismo. En caso contrario, el título contiene el título de la página, el número de página de una lista paginada y el nombre de la tienda, con la palabra «página» traducida mediante los archivos de idioma del tema.- Reglas que cubre
-
-
document-titleAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo layout/theme.focused.liquid Cambios en layout/theme.focused.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en layout/theme.focused.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada <title></title> 14 Añadida <title>{{ page_title }}{% unless page_title contains shop.name %} – {{ 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' %} -
Encabezados sin niveles omitidos heading-levels Un encabezado que se salta un nivel recibe el nivel inmediatamente inferior al del encabezado anterior; la receta no añade ningún encabezado oculto.
Un encabezado que se salta un nivel, como un h4 justo después de un h2, recibe el nivel inmediatamente inferior al del encabezado anterior, en el archivo de sección donde está escrito. Cuando el tema da estilo a los encabezados según su nivel, una pequeña regla de estilo conserva el aspecto anterior del encabezado. En una página sin encabezado principal, el elemento que ya parece su título se convierte en el h1; en la página de inicio, esto se hace con la opción del propio tema de mostrar el logotipo como h1. Si una página no tiene ningún elemento así, la receta no añade ningún encabezado oculto, porque eso es una decisión de contenido.
- Reglas que cubre
-
-
heading-orderAUTO se comprueba mediante vs-headings-landmarks -
page-has-heading-oneAUTO se comprueba mediante vs-headings-landmarks -
vs-headings-landmarksAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/featured-collection.liquid Cambios en sections/featured-collection.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/featured-collection.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 1 1 {%- liquid 2 2 assign featured = section.settings.collection 3 Eliminada assign card_heading = 'h4' 3 Añadida 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 Cambios en sections/header.liquid (líneas añadidas: 3; eliminadas: 0)
Cambios en sections/header.liquid (líneas añadidas: 3; eliminadas: 0) Línea anterior Línea nueva Cambio Código 3 3 assign menu = linklists[section.settings.menu] 4 4 assign icon_size = 18 5 5 assign logo_is_heading = false 6 Añadida if request.page_type == 'index' 7 Añadida assign logo_is_heading = true 8 Añadida 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 Cambios en sections/main-collection.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/main-collection.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 6 6 wishlist heart nested inside the product image link. 7 7 {%- endcomment -%} 8 8 {%- liquid 9 Eliminada assign card_heading = 'h4' 9 Añadida 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 Cambios en sections/main-product.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/main-product.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada assign sub_heading = 'h4' 16 Añadida 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 Cambios en sections/main-search.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/main-search.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 1 1 {%- liquid 2 Eliminada assign card_heading = 'h4' 2 Añadida 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>
Uso del teclado y foco
-
Un contorno de foco visible focus-visible-styles Un contorno para el foco del teclado en el color de acento de su tema o en un color alternativo, con un contraste de al menos 3:1 con el fondo de la página.
La hoja de estilos principal recibe un contorno para el foco del teclado: de 2 píxeles, continuo, a 2 píxeles del elemento, en el color de acento de su tema (o en el color del texto, o en negro o blanco, cuando el tema no tiene color de acento), aclarado u oscurecido dentro del mismo matiz hasta alcanzar un contraste de al menos 3:1 con el fondo de la página. Las reglas del tema que seguirían ocultando el contorno pierden su
outline: none, salvo que muestren el foco de otra manera, por ejemplo con un borde o una sombra. El contorno tiene un solo color para todo el tema, así que en las secciones con un esquema de colores oscuro puede necesitar un color más claro, algo que su desarrollador comprueba en la vista previa.- Reglas que cubre
-
-
vs-focus-visibleAUTO
-
- Tipos de archivo que modifica
-
.css.liquid
Antes y después Datos de ejemplo assets/base.css.liquid Cambios en assets/base.css.liquid (líneas añadidas: 7; eliminadas: 0)
Cambios en assets/base.css.liquid (líneas añadidas: 7; eliminadas: 0) Línea anterior Línea nueva Cambio Código 1866 1866 } 1867 1867 1868 1868 /* ----------------------------------------------------------------- motion */ 1869 Añadida 1870 Añadida /* validiscan:focus-visible-styles */ 1871 Añadida :focus-visible { 1872 Añadida outline: 2px solid #1f4d3a; 1873 Añadida outline-offset: 2px; 1874 Añadida } 1875 Añadida /* /validiscan:focus-visible-styles */ -
Un orden de tabulación que sigue el orden de la página remove-positive-tabindex Un
tabindexmayor que 0 se elimina o se pone a 0, para que la tecla Tab siga el orden de la página, salvo que lo escriba el código de plantilla del tema.Un
tabindexmayor que 0 lleva un elemento al principio del orden del teclado. La receta lo elimina de los enlaces, los botones, los campos de formulario y otros elementos que de todos modos pueden recibir el foco, y lo pone a 0 en los demás elementos, de modo que siguen siendo alcanzables y la tecla Tab recorre la página en su orden. Untabindexque escribe el código de plantilla del tema queda en manos de una persona. La receta también se ocupa de los hallazgos de la comprobación del orden del focovs-focus-orderque tratan de untabindexmayor que 0; el resto de esa comprobación sigue siendo MANUAL.- Reglas que cubre
-
-
tabindexAUTO -
vs-focus-orderMANUAL
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/header.liquid Cambios en sections/header.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/header.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 37 37 38 38 <div class="header__search"> 39 39 <form action="{{ routes.search_url }}" method="get" role="search" class="search"> 40 Eliminada <input class="search__input field__input" type="search" name="q" value="" placeholder="{{ 'general.search.placeholder' | t }}" tabindex="1"> 40 Añadida <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>
Zoom, zonas táctiles y contraste
-
Zoom permitido en los móviles meta-viewport-zoom
user-scalable=noy cualquiermaximum-scaleinferior a 5 se eliminan de las etiquetas viewport, para que los visitantes puedan ampliar hasta el 500 %, salvo que el límite lo establezca el código de plantilla del tema.La receta elimina
user-scalable=noy cualquiermaximum-scaleinferior a 5 de las etiquetas viewport de los archivos Liquid del tema, de modo que los visitantes puedan ampliar su tienda con el gesto de pellizco hasta el 500 %. Los demás ajustes del viewport quedan exactamente como estaban. Un límite de zoom que establece el código de plantilla del tema queda en manos de una persona.- Reglas que cubre
-
-
meta-viewportAUTO -
meta-viewport-largeAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo layout/checkout.liquid Cambios en layout/checkout.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en layout/checkout.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 6 6 <html class="no-js"> 7 7 <head> 8 8 <meta charset="utf-8"> 9 Eliminada <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> 9 Añadida <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 Cambios en layout/theme.focused.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en layout/theme.focused.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 10 10 <head> 11 11 <meta charset="utf-8"> 12 12 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 13 Eliminada <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> 13 Añadida <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 Cambios en layout/theme.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en layout/theme.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 11 11 <head> 12 12 <meta charset="utf-8"> 13 13 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 14 Eliminada <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> 14 Añadida <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 %} -
Zonas táctiles más grandes target-size-padding Los controles que el escaneo encontró demasiado pequeños, como los iconos de la cabecera o las muestras de color, reciben un tamaño mínimo de 24 × 24 píxeles.
Los controles que el escaneo encontró demasiado pequeños, como los iconos de la cabecera, las muestras de color o los botones de cantidad, reciben un tamaño mínimo de 24 × 24 píxeles mediante una regla de la hoja de estilos principal que los selecciona por su clase. Los iconos que contienen conservan su tamaño. Un enlace u otro elemento que el tema deja en línea pasa a
inline-flexcon su icono centrado, porque los elementos en línea ignoran el tamaño mínimo.- Reglas que cubre
-
-
vs-target-sizeAUTO
-
- Tipos de archivo que modifica
-
.css.liquid
Antes y después Datos de ejemplo assets/base.css.liquid Cambios en assets/base.css.liquid (líneas añadidas: 10; eliminadas: 0)
Cambios en assets/base.css.liquid (líneas añadidas: 10; eliminadas: 0) Línea anterior Línea nueva Cambio Código 1866 1866 } 1867 1867 1868 1868 /* ----------------------------------------------------------------- motion */ 1869 Añadida 1870 Añadida /* validiscan:target-size-padding */ 1871 Añadida .header__icon--account, 1872 Añadida .header__icon--cart, 1873 Añadida .swatch--button, 1874 Añadida .quantity__button { 1875 Añadida min-width: 24px; 1876 Añadida min-height: 24px; 1877 Añadida } 1878 Añadida /* /validiscan:target-size-padding */ -
Colores de texto con contraste suficiente contrast-tokens Un color de texto que no supera la comprobación de contraste, definido en un solo lugar y no compartido, pasa al tono más próximo del mismo matiz que alcanza el contraste exigido.
Cuando un texto no supera la comprobación de contraste y su color está definido en un solo lugar, ese color pasa al tono más próximo del mismo matiz, más claro o más oscuro, que alcanza el contraste exigido sobre todos los fondos que el escaneo registró para él. Ese lugar puede ser la regla de la hoja de estilos que da estilo al texto, o una variable CSS o un ajuste de color de
config/que ninguna otra parte del tema utiliza. Un color calculado en Liquid o definido más de una vez queda en manos de una persona, y lo mismo ocurre con un color compartido, porque cambiarlo afectaría a pares de colores que el escaneo no midió.settings_data.json - Reglas que cubre
-
-
color-contrastASSISTED
-
- Tipos de archivo que modifica
-
.css.liquid
Antes y después Datos de ejemplo assets/base.css.liquid Cambios en assets/base.css.liquid (líneas añadidas: 3; eliminadas: 3)
Cambios en assets/base.css.liquid (líneas añadidas: 3; eliminadas: 3) Línea anterior Línea nueva Cambio Código 745 745 font-size: 0.8125rem; 746 746 letter-spacing: 0.04em; 747 747 text-transform: uppercase; 748 Eliminada color: #929292; 748 Añadida color: #767676; 749 749 } 750 750 751 751 .rating { 1013 1013 1014 1014 .copyright__content { 1015 1015 margin: 0; 1016 Eliminada color: #929292; 1016 Añadida color: #6f6f6f; 1017 1017 } 1018 1018 1019 1019 .policies { 1077 1077 1078 1078 .cookie-banner__text, 1079 1079 .cookie-banner__link { 1080 Eliminada color: #9a9a9a; 1080 Añadida color: #767676; 1081 1081 } 1082 1082 1083 1083 .cookie-banner__icon-button {
Movimiento, carruseles y sonido
-
Menos movimiento cuando el visitante lo pide reduced-motion-guard Para los visitantes cuyo dispositivo pide reducir el movimiento, las animaciones CSS y las transiciones se acortan, el desplazamiento suave se desactiva y se omite el avance automático de un carrusel que inicia el script del tema.
Cuando el dispositivo de un visitante está configurado para reducir el movimiento, un bloque al final de la hoja de estilos principal hace que cada animación CSS se ejecute una sola vez, durante un tiempo demasiado breve para verse, acorta las transiciones y desactiva el desplazamiento suave. Cuando es el script del tema el que inicia el avance automático de un carrusel, ese inicio se omite para esos visitantes. Esta receta no modifica el movimiento que controla un script de terceros.
- Reglas que cubre
-
-
vs-motionAUTO
-
- Tipos de archivo que modifica
-
.css.liquid
Antes y después Datos de ejemplo assets/base.css.liquid Cambios en assets/base.css.liquid (líneas añadidas: 13; eliminadas: 0)
Cambios en assets/base.css.liquid (líneas añadidas: 13; eliminadas: 0) Línea anterior Línea nueva Cambio Código 1866 1866 } 1867 1867 1868 1868 /* ----------------------------------------------------------------- motion */ 1869 Añadida 1870 Añadida /* validiscan:reduced-motion-guard */ 1871 Añadida @media (prefers-reduced-motion: reduce) { 1872 Añadida *, 1873 Añadida *::before, 1874 Añadida *::after { 1875 Añadida animation-duration: 0.01ms !important; 1876 Añadida animation-iteration-count: 1 !important; 1877 Añadida transition-duration: 0.01ms !important; 1878 Añadida scroll-behavior: auto !important; 1879 Añadida } 1880 Añadida } 1881 Añadida /* /validiscan:reduced-motion-guard */ -
Un botón de pausa para los carruseles en movimiento slider-pause-control Un carrusel que se mueve por sí solo recibe un botón visible, con el texto traducido, para ponerlo en pausa y reanudarlo, conectado con su propio avance automático.
Un carrusel que se mueve por sí solo recibe, entre sus controles, un botón visible, con el texto traducido, para ponerlo en pausa y reanudarlo; el botón solo se muestra cuando el avance automático está activado. Un script breve en el archivo de script principal del tema conecta el botón con el avance automático del propio carrusel: el carrusel de Dawn, Swiper, Slick, Flickity, Splide o una animación CSS. Para los visitantes cuyo dispositivo pide reducir el movimiento, el carrusel empieza en pausa.
- Reglas que cubre
-
-
vs-carouselAUTO
-
- Tipos de archivo que modifica
-
.css.liquid.js.json.liquid
Antes y después Datos de ejemplo assets/base.css.liquid Cambios en assets/base.css.liquid (líneas añadidas: 21; eliminadas: 0)
Cambios en assets/base.css.liquid (líneas añadidas: 21; eliminadas: 0) Línea anterior Línea nueva Cambio Código 1866 1866 } 1867 1867 1868 1868 /* ----------------------------------------------------------------- motion */ 1869 Añadida 1870 Añadida /* validiscan:slider-pause-control */ 1871 Añadida [data-autoplay-paused], 1872 Añadida [data-autoplay-paused] * { 1873 Añadida animation-play-state: paused !important; 1874 Añadida } 1875 Añadida 1876 Añadida .slider-pause { 1877 Añadida display: inline-flex; 1878 Añadida align-items: center; 1879 Añadida justify-content: center; 1880 Añadida min-width: 2.75rem; 1881 Añadida min-height: 2.75rem; 1882 Añadida padding: 0.5rem 1rem; 1883 Añadida border: 1px solid currentColor; 1884 Añadida background: transparent; 1885 Añadida color: inherit; 1886 Añadida font: inherit; 1887 Añadida cursor: pointer; 1888 Añadida } 1889 Añadida /* /validiscan:slider-pause-control */ assets/global.js Cambios en assets/global.js (líneas añadidas: 53; eliminadas: 0)
Cambios en assets/global.js (líneas añadidas: 53; eliminadas: 0) Línea anterior Línea nueva Cambio Código 412 412 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); 413 413 else boot(); 414 414 })(); 415 Añadida 416 Añadida /* validiscan:slider-pause-control */ 417 Añadida (function () { 418 Añadida 'use strict'; 419 Añadida var ROOTS = 'slideshow-component, slider-component, .swiper, .swiper-container, .slick-slider, .flickity-enabled, .splide, [data-autoplay]'; 420 Añadida var reduce = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null; 421 Añadida 422 Añadida function rootOf(button) { 423 Añadida return button.closest(ROOTS) || button.previousElementSibling; 424 Añadida } 425 Añadida 426 Añadida function setPaused(button, paused) { 427 Añadida var root = rootOf(button); 428 Añadida if (!root) return; 429 Añadida if (paused) root.setAttribute('data-autoplay-paused', ''); 430 Añadida else root.removeAttribute('data-autoplay-paused'); 431 Añadida if (root.swiper && root.swiper.autoplay) { 432 Añadida if (paused) root.swiper.autoplay.stop(); 433 Añadida else root.swiper.autoplay.start(); 434 Añadida } 435 Añadida var $ = window.jQuery; 436 Añadida if ($ && $(root).hasClass('slick-initialized')) $(root).slick(paused ? 'slickPause' : 'slickPlay'); 437 Añadida var flickity = window.Flickity && window.Flickity.data(root); 438 Añadida if (flickity) { 439 Añadida if (paused) flickity.pausePlayer(); 440 Añadida else flickity.unpausePlayer(); 441 Añadida } 442 Añadida var autoplay = root.splide && root.splide.Components && root.splide.Components.Autoplay; 443 Añadida if (autoplay) { 444 Añadida if (paused) autoplay.pause(); 445 Añadida else autoplay.play(); 446 Añadida } 447 Añadida if (root.localName.indexOf('-') > 0 && typeof root.pause === 'function' && typeof root.play === 'function') { 448 Añadida if (paused) root.pause(); 449 Añadida else root.play(); 450 Añadida } 451 Añadida button.setAttribute('data-paused', paused ? 'true' : 'false'); 452 Añadida button.textContent = button.getAttribute(paused ? 'data-label-play' : 'data-label-pause') || button.textContent; 453 Añadida } 454 Añadida 455 Añadida function init() { 456 Añadida Array.prototype.forEach.call(document.querySelectorAll('[data-slider-pause]'), function (button) { 457 Añadida button.addEventListener('click', function () { 458 Añadida setPaused(button, button.getAttribute('data-paused') !== 'true'); 459 Añadida }); 460 Añadida if (reduce && reduce.matches) setPaused(button, true); 461 Añadida }); 462 Añadida } 463 Añadida 464 Añadida if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); 465 Añadida else init(); 466 Añadida })(); 467 Añadida /* /validiscan:slider-pause-control */ locales/en.default.json Cambios en locales/en.default.json (líneas añadidas: 3; eliminadas: 1)
Cambios en locales/en.default.json (líneas añadidas: 3; eliminadas: 1) Línea anterior Línea nueva Cambio Código 34 34 "total_reviews": "{{ count }} reviews", 35 35 "link_messages": { 36 36 "new_window": "Opens in a new window." 37 Eliminada } 37 Añadida }, 38 Añadida "pause_slideshow": "Pause slideshow", 39 Añadida "play_slideshow": "Play slideshow" 38 40 }, 39 41 "sections": { 40 42 "header": { sections/slideshow.liquid Cambios en sections/slideshow.liquid (líneas añadidas: 3; eliminadas: 0)
Cambios en sections/slideshow.liquid (líneas añadidas: 3; eliminadas: 0) Línea anterior Línea nueva Cambio Código 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 Añadida {%- if autoplay %} 72 Añadida <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 Añadida {%- endif %} 71 74 </div> 72 75 </slideshow-component> 73 76 -
Sin texto que parpadee ni se desplace remove-blink-marquee Los elementos
<blink>y<marquee>pasan a ser elementos estáticos con el mismo contenido, las mismas clases y los mismos ids, de modo que ningún texto se mueve por sí solo.Los elementos
<blink>y<marquee>del tema pasan a ser elementos estáticos con el mismo contenido, las mismas clases y los mismos ids: un<span>para blink, un<div>para marquee, o un<span>cuando el marquee está dentro de un párrafo o de un enlace. Se eliminan los ajustes de desplazamiento del marquee, de modo que ningún texto se mueve por sí solo.- Reglas que cubre
-
-
blinkAUTO -
marqueeAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/announcement-bar.liquid Cambios en sections/announcement-bar.liquid (líneas añadidas: 2; eliminadas: 2)
Cambios en sections/announcement-bar.liquid (líneas añadidas: 2; eliminadas: 2) Línea anterior Línea nueva Cambio Código 3 3 -%} 4 4 <div class="announcement-bar color-accent"{% if bar_lang != '' %} lang="{{ bar_lang }}"{% endif %}> 5 5 <div class="page-width"> 6 Eliminada <marquee class="announcement-bar__message" behavior="scroll" direction="left" scrollamount="4">{{ section.settings.text | escape }}</marquee> 7 Eliminada <p class="announcement-bar__note"><blink class="announcement-bar__flag">New</blink> winter collection</p> 6 Añadida <div class="announcement-bar__message">{{ section.settings.text | escape }}</div> 7 Añadida <p class="announcement-bar__note"><span class="announcement-bar__flag">New</span> winter collection</p> 8 8 </div> 9 9 </div> 10 10 -
Sin sonido que empiece por sí solo mute-autoplay Un vídeo que se reproduce por sí solo queda en silencio y el audio deja de empezar por sí solo, salvo en los reproductores incrustados de YouTube y Vimeo; en Shopify, la receta no se usa para los hallazgos de
vs-media.Un vídeo que se reproduce por sí solo recibe
mutedyplaysinline, de modo que sigue reproduciéndose en silencio, como hace un vídeo de fondo, y el filtrovideo_tagde Shopify recibemuted: true. El audio que empieza por sí solo deja de hacerlo. Los reproductores incrustados de YouTube y Vimeo quedan en manos de una persona. En un escaneo de Validiscan, el sonido que empieza por sí solo lo notifica la comprobación de contenido multimediavs-media, que sustituye a la regla de axe-core que esta receta cubre.vs-mediatiene el nivel MANUAL, y en Shopify esta receta no se usa para sus hallazgos.- Reglas que cubre
-
-
no-autoplay-audioAUTO se comprueba mediante vs-media
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/announcement-bar.liquid Cambios en sections/announcement-bar.liquid (líneas añadidas: 2; eliminadas: 2)
Cambios en sections/announcement-bar.liquid (líneas añadidas: 2; eliminadas: 2) Línea anterior Línea nueva Cambio Código 3 3 -%} 4 4 <div class="announcement-bar color-accent"{% if bar_lang != '' %} lang="{{ bar_lang }}"{% endif %}> 5 5 <div class="page-width"> 6 Eliminada <audio class="announcement-bar__chime" src="{{ 'chime.wav' | asset_url }}" autoplay></audio> 7 Eliminada <video class="announcement-bar__clip" src="{{ 'chime.wav' | asset_url }}" autoplay loop width="16" height="16"></video> 6 Añadida <audio class="announcement-bar__chime" src="{{ 'chime.wav' | asset_url }}"></audio> 7 Añadida <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>
Formularios, precios y carrito
-
Etiquetas conectadas a sus campos label-association Una etiqueta ya visible en la página pero no conectada con su campo de formulario se conecta con él, sin que cambie el diseño.
Cuando el texto de la etiqueta de un campo de formulario ya está visible en la página pero no está conectado con el campo, la receta los conecta: un
<label>situado junto al campo recibe unforque apunta a él, o un texto justo antes del campo, como el nombre de una opción de talla o de color, pasa a ser su etiqueta mediantearia-labelledby, de modo que el diseño no cambia. Los lectores de pantalla leen entonces la etiqueta cuando el campo recibe el foco. Un campo que solo tiene un placeholder queda en manos de una persona, porque redactar una etiqueta es una decisión de contenido.- Reglas que cubre
-
-
labelAUTO se comprueba mediante vs-forms-ecommerce -
select-nameASSISTED -
vs-forms-ecommerceAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/main-collection.liquid Cambios en sections/main-collection.liquid (líneas añadidas: 2; eliminadas: 2)
Cambios en sections/main-collection.liquid (líneas añadidas: 2; eliminadas: 2) Línea anterior Línea nueva Cambio Código 64 64 <div class="collection__products"> 65 65 <div class="collection__toolbar"> 66 66 <div class="collection__sort"> 67 Eliminada <label class="collection__sort-label">Sort by</label> 68 Eliminada <select name="sort_by" class="select__select" form="FacetFiltersForm"> 67 Añadida <label class="collection__sort-label" for="SortBy-{{ section.id }}">Sort by</label> 68 Añadida <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 Cambios en sections/main-product.liquid (líneas añadidas: 2; eliminadas: 2)
Cambios en sections/main-product.liquid (líneas añadidas: 2; eliminadas: 2) Línea anterior Línea nueva Cambio Código 94 94 </div> 95 95 {%- else %} 96 96 <div class="product-form__input product-form__input--dropdown"> 97 Eliminada <p class="form__label">{{ option.name | escape }}</p> 97 Añadida <p class="form__label" id="Options-{{ section.id }}-{{ forloop.index0 }}-label">{{ option.name | escape }}</p> 98 98 <div class="select"> 99 Eliminada <select class="select__select" name="options[{{ option.name | escape }}]" data-option-index="{{ option_index }}"> 99 Añadida <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 %} -
Campos de dirección, de cuenta y de inicio de sesión que los navegadores pueden rellenar autocomplete-tokens Los campos de dirección, de cuenta, de inicio de sesión y de contacto que el escaneo marcó reciben el valor de
autocompletecorrespondiente a lo que piden, cuando el código lo muestra.Los campos de dirección, de cuenta, de inicio de sesión y de contacto que el escaneo marcó reciben el valor de
autocompletecorrespondiente a lo que piden, como correo electrónico, nombre y apellidos, calle y número, código postal, país, número de teléfono o contraseña. El valor se deduce del tipo, el nombre, la etiqueta y el placeholder del campo. Cuando un snippet imprime sus campos a partir de parámetros, los campos imprimen un parámetroautocomplete, y cada llamadarenderdel snippet le pasa el valor que corresponde a sus propios argumentos. Así, los navegadores pueden rellenar los campos y los productos de apoyo pueden saber para qué sirve cada uno. Un campo cuya finalidad el código no muestra se deja como está.- Reglas que cubre
-
-
autocomplete-validAUTO se comprueba mediante vs-forms-ecommerce -
vs-forms-ecommerceAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/contact-form.liquid Cambios en sections/contact-form.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/contact-form.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 14 14 {%- form 'contact', id: 'ContactForm', class: 'contact__form' %} 15 15 <div class="contact__fields"> 16 16 <div class="field"> 17 Eliminada <input class="field__input" type="text" name="contact[name]" placeholder="{{ 'templates.contact.form.name' | t }}"> 17 Añadida <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 Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada <input type="email" name="contact[email]" class="field__input" placeholder="{{ 'newsletter.label' | t }}" autocorrect="off" autocapitalize="off"> 14 Añadida <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 Cambios en sections/main-login.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/main-login.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada <input class="field__input" type="email" name="customer[email]" id="CustomerEmail" autocorrect="off" autocapitalize="off"> 13 Añadida <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 Cambios en snippets/checkout-field.liquid (líneas añadidas: 4; eliminadas: 4)
Cambios en snippets/checkout-field.liquid (líneas añadidas: 4; eliminadas: 4) Línea anterior Línea nueva Cambio Código 15 15 <div class="field"> 16 16 {%- case legacy %} 17 17 {%- when 'placeholder' %} 18 Eliminada <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" placeholder="{{ label }}"{% if required %} required{% endif %}> 18 Añadida <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 Eliminada <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"> 21 Añadida <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 Eliminada <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}" autocomplete="off"{% if required %} required{% endif %}> 24 Añadida <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 Eliminada <input class="field__input" type="{{ field_type }}" id="{{ field_id }}" name="{{ field_name }}"{% if required %} required{% endif %}> 27 Añadida <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> -
Anuncio de los cambios de precio, existencias y carrito live-region-cart-variant El precio, el aviso de existencias o el subtotal del carrito que reescribe el script del tema se marca como región de estado que anuncian los lectores de pantalla, salvo que el área contenga también botones o enlaces.
La parte de una página que el script del tema reescribe cuando un cliente elige otra variante o cambia una cantidad, como el precio, el aviso de existencias o el subtotal del carrito, se marca como región de estado. Los lectores de pantalla anuncian entonces el valor nuevo sin que el cliente tenga que moverse hasta allí. El propio script del tema no se modifica. Un área que también contiene botones o enlaces, que se leerían en voz alta con ella, se deja como está.
- Reglas que cubre
-
-
vs-live-updatesAUTO
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/main-cart.liquid Cambios en sections/main-cart.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/main-cart.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 37 37 38 38 <div class="cart__footer"> 39 39 <h2 class="cart__summary-title">Order summary</h2> 40 Eliminada <p class="totals"> 40 Añadida <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 Cambios en sections/main-product.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/main-product.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 71 71 </div> 72 72 {%- endif %} 73 73 74 Eliminada <div class="product__price" data-price-container> 74 Añadida <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>
Nombres para iconos, imágenes y elementos incrustados
-
Nombres para botones y enlaces que solo muestran un icono icon-accessible-name Los botones y enlaces que muestran solo un icono reciben un nombre que dice qué hacen, cuando el código muestra su finalidad.
Los botones y enlaces que muestran solo un icono, como los de búsqueda, carrito, cuenta, las flechas de un carrusel, los botones de cantidad y las opciones de cookies, reciben un nombre que dice qué hacen, cuando el código muestra su finalidad. El nombre es un texto oculto visualmente dentro del control, o un
aria-labelcuando el tema no tiene una clase para texto oculto. Un enlace con el logotipo cuya imagen no tiene alternativa textual recibe el nombre de su tienda. Un control cuyo nombre tendría que salir de su propio contenido queda en manos de una persona.- Reglas que cubre
-
-
button-nameASSISTED -
link-nameASSISTED -
image-altASSISTED -
vs-carouselAUTO -
vs-cookie-bannerASSISTED
-
- Tipos de archivo que modifica
-
.json.liquid
buttons Datos de ejemplo locales/en.default.json Cambios en locales/en.default.json (líneas añadidas: 3; eliminadas: 1)
Cambios en locales/en.default.json (líneas añadidas: 3; eliminadas: 1) Línea anterior Línea nueva Cambio Código 34 34 "total_reviews": "{{ count }} reviews", 35 35 "link_messages": { 36 36 "new_window": "Opens in a new window." 37 Eliminada } 37 Añadida }, 38 Añadida "accept_cookies": "Accept cookies", 39 Añadida "reject_cookies": "Reject cookies" 38 40 }, 39 41 "sections": { 40 42 "header": { sections/header.liquid Cambios en sections/header.liquid (líneas añadidas: 1; eliminadas: 0)
Cambios en sections/header.liquid (líneas añadidas: 1; eliminadas: 0) Línea anterior Línea nueva Cambio Código 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 Añadida <span class="visually-hidden">{{ 'general.search.search' | t }}</span> 43 44 </button> 44 45 </form> 45 46 </div> sections/main-product.liquid Cambios en sections/main-product.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/main-product.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada <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 Añadida <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 Cambios en sections/slideshow.liquid (líneas añadidas: 2; eliminadas: 0)
Cambios en sections/slideshow.liquid (líneas añadidas: 2; eliminadas: 0) Línea anterior Línea nueva Cambio Código 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 Añadida <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 Añadida <span class="visually-hidden">{{ 'accessibility.next_slide' | t }}</span> 70 72 </button> 71 73 </div> 72 74 </slideshow-component> snippets/cookie-banner.liquid Cambios en snippets/cookie-banner.liquid (líneas añadidas: 2; eliminadas: 0)
Cambios en snippets/cookie-banner.liquid (líneas añadidas: 2; eliminadas: 0) Línea anterior Línea nueva Cambio Código 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 Añadida <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 Añadida <span class="visually-hidden">{{ 'accessibility.reject_cookies' | t }}</span> 29 31 </button> 30 32 </div> 31 33 </div> snippets/quantity-input.liquid Cambios en snippets/quantity-input.liquid (líneas añadidas: 2; eliminadas: 0)
Cambios en snippets/quantity-input.liquid (líneas añadidas: 2; eliminadas: 0) Línea anterior Línea nueva Cambio Código 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 Añadida <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 Añadida <span class="visually-hidden">{{ 'products.product.quantity.increase' | t: product: product_title }}</span> 16 18 </button></div> links Datos de ejemplo sections/footer.liquid Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 0)
Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 0) Línea anterior Línea nueva Cambio Código 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 Añadida <span class="visually-hidden">{{ 'general.social.links.' | append: social.icon | t }}</span> 40 41 </a> 41 42 {%- endfor %} 42 43 </ul> sections/header.liquid Cambios en sections/header.liquid (líneas añadidas: 3; eliminadas: 1)
Cambios en sections/header.liquid (líneas añadidas: 3; eliminadas: 1) Línea anterior Línea nueva Cambio Código 22 22 </details> 23 23 24 24 {% if logo_is_heading %}<h1 class="header__heading">{% else %}<div class="header__heading">{% endif %} 25 Eliminada <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 Añadida <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 Añadida <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 Añadida <span class="visually-hidden">{{ 'sections.header.cart' | t }}</span> 60 62 </a> 61 63 </div> 62 64 </header> sections/main-cart.liquid Cambios en sections/main-cart.liquid (líneas añadidas: 1; eliminadas: 0)
Cambios en sections/main-cart.liquid (líneas añadidas: 1; eliminadas: 0) Línea anterior Línea nueva Cambio Código 26 26 {% render 'quantity-input', input_id: qty_id, input_name: 'updates[]', value: item.quantity, product_title: item.product.title, line: line %} 27 27 <a href="{{ routes.cart_change_url }}?line={{ line }}&quantity=0" class="cart-item__remove cart-item__remove--compact" data-cart-remove> 28 28 {%- render 'icon', icon: 'trash', size: 16 -%} 29 Añadida <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"> -
Imágenes decorativas ocultas a los lectores de pantalla decorative-image-alt Solo se ocultan a los lectores de pantalla las imágenes que el código demuestra decorativas; la alternativa textual de todas las demás queda en manos de una persona.
Una imagen se marca como decorativa solo cuando el código demuestra que no aporta nada: está dentro de un enlace o un botón que tiene su propio texto, es un icono junto a su propia etiqueta de texto, o es un espaciador o un separador. Un
<img>recibe entonces unalt=""vacío, y un icono SVG recibearia-hidden="true", de modo que los lectores de pantalla lo omiten en lugar de leer en voz alta un nombre de archivo o la palabra «imagen». Todas las demás imágenes son contenido, y su alternativa textual queda en manos de una persona.- Reglas que cubre
-
-
image-altASSISTED -
role-img-altASSISTED -
svg-img-altASSISTED
-
- Tipos de archivo que modifica
-
.liquid
Antes y después Datos de ejemplo sections/footer.liquid Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/footer.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada <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 Añadida <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 Cambios en sections/header.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/header.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 46 46 47 47 <div class="header__icons"> 48 48 {%- if section.settings.show_help_link %} 49 Eliminada <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 Añadida <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 -%} -
Títulos para mapas y vídeos incrustados iframe-title Un marco incrustado sin título recibe un título traducido que dice qué muestra, cuando su dirección de origen o su contenido lo indican.
Un marco incrustado sin título, como un mapa o un vídeo de YouTube o de Vimeo, recibe un título traducido que dice qué muestra. La receta lo toma de la dirección de origen o del contenido del marco. Un marco cuyo contenido el código no muestra no recibe ningún título genérico; queda en manos de una persona.
- Reglas que cubre
-
-
frame-titleAUTO
-
- Tipos de archivo que modifica
-
.json.liquid
Antes y después Datos de ejemplo locales/en.default.json Cambios en locales/en.default.json (líneas añadidas: 2; eliminadas: 1)
Cambios en locales/en.default.json (líneas añadidas: 2; eliminadas: 1) Línea anterior Línea nueva Cambio Código 34 34 "total_reviews": "{{ count }} reviews", 35 35 "link_messages": { 36 36 "new_window": "Opens in a new window." 37 Eliminada } 37 Añadida }, 38 Añadida "embed_map": "Map" 38 39 }, 39 40 "sections": { 40 41 "header": { sections/contact-form.liquid Cambios en sections/contact-form.liquid (líneas añadidas: 1; eliminadas: 1)
Cambios en sections/contact-form.liquid (líneas añadidas: 1; eliminadas: 1) Línea anterior Línea nueva Cambio Código 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 Eliminada <iframe class="store-map" srcdoc="{{ map_document | escape }}" width="600" height="360"></iframe> 11 Añadida <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' %}
Detalles: los niveles, el tema de prueba y el texto en los idiomas de su tienda
Una receta es un cambio determinista para un tipo de fallo: el mismo código recibe siempre el mismo cambio. Validiscan tiene 20 recetas para temas de Shopify. Cada una hace un cambio solo donde el código del tema muestra cuál es el cambio correcto; donde no lo muestra, la receta no cambia nada y el hallazgo queda en manos de una persona.
Debajo de cada receta encontrará las reglas que cubre, con el nivel de cada regla en el catálogo de Validiscan. AUTO significa que una receta es la corrección estándar de la regla. ASSISTED significa que la corrección requiere criterio, así que se redacta un cambio y después se revisa. MANUAL significa que la regla requiere la decisión de una persona, y Validiscan ofrece orientación en lugar de un cambio de código. En un proyecto, las recetas se aplican a los hallazgos de reglas de nivel AUTO. Cuando una receta enumera también una regla de nivel ASSISTED o MANUAL, un hallazgo de esa regla sigue en su lugar la vía ASSISTED o MANUAL. Una regla marcada como «se comprueba mediante» otra comprobación no se ejecuta por separado en un escaneo: esa comprobación informa del mismo fallo.
Los tipos de archivo y el antes y el después de cada receta proceden de las pruebas de la propia aplicación. Estas se ejecutan sobre el tema de prueba de Shopify de la aplicación, un tema Liquid construido como el tema Dawn de Shopify con fallos de accesibilidad introducidos a propósito, y comprueban que el fallo ha desaparecido después del cambio; la mayoría comprueba además que el cambio no causa ningún fallo nuevo de la misma regla. Los archivos de su tema tendrán otro aspecto. El tema de prueba todavía contiene un archivo layout/checkout.liquid y un snippet de campo del proceso de pago, snippets/, por lo que algunos de los diffs los modifican; como se ha descrito más arriba, Shopify ya no usa ese archivo en los pasos de información, envío y pago.
Cuando una receta añade texto, como las palabras de un enlace para saltar al contenido o el nombre de un botón de icono, reutiliza, si puede, una traducción que el tema ya tiene. Si no, añade el texto en inglés, y en alemán cuando el tema tiene un archivo de idioma en alemán. No se añade texto en los demás idiomas de su tienda: un tema cuyo idioma predeterminado no es ni el inglés ni el alemán recibe allí el texto en inglés.
¿Qué sigue siendo MANUAL en Shopify?
Los fallos que requieren una decisión sobre el contenido o el comportamiento que un cambio de código fijo no puede tomar, por ejemplo los subtítulos y las transcripciones de sus vídeos y su audio, siguen siendo MANUAL en Shopify. Para un hallazgo de una regla MANUAL, Validiscan ofrece orientación sobre cómo corregirlo, no un cambio en su código.
Las reglas de más abajo se ejecutan en un escaneo y tienen el nivel MANUAL en Shopify.
-
meta-refreshNo debe usarse una actualización diferida de menos de 20 horas -
nested-interactiveLos controles interactivos no deben estar anidados -
scrollable-region-focusableLas zonas desplazables deben ser accesibles con el teclado -
server-side-image-mapNo deben usarse mapas de imagen del lado del servidor -
vs-keyboard-trapEl foco del teclado nunca debe quedar atrapado -
vs-focus-orderEl orden del foco debe seguir el orden visual -
vs-draggingLos controles que solo funcionan arrastrando necesitan una alternativa con un solo puntero -
vs-mediaLos vídeos necesitan subtítulos, el audio necesita una transcripción y nada debe reproducirse automáticamente con sonido -
vs-documentsLos documentos enlazados necesitan una revisión manual de accesibilidad
Detalles: la comprobación del orden del foco y lo que un proyecto deja fuera
Para un hallazgo de una regla MANUAL, Validiscan ofrece orientación sobre cómo corregirlo, no un cambio en su código. Estos fallos requieren una decisión sobre el contenido o el comportamiento que un cambio de código fijo no puede tomar, por ejemplo los subtítulos y las transcripciones de sus vídeos y su audio, una forma de salir de un widget que atrapa el foco del teclado, u otra forma de usar un control que solo funciona arrastrando. La comprobación del orden del foco vs-focus-order tiene el nivel MANUAL porque un orden del foco que no coincide con la pantalla es una cuestión de cómo están ordenadas las plantillas; cuando uno de sus hallazgos se refiere a un tabindex mayor que 0, la receta del orden de tabulación descrita más arriba elimina ese tabindex.
El trabajo que suponen los hallazgos MANUAL que requieren decisiones sobre su propio contenido no forma parte de un proyecto, como tampoco los PDF. Entre las reglas de nivel AUTO y las de nivel MANUAL están las de nivel ASSISTED, como las alternativas textuales de las imágenes o los nombres de los botones: sus correcciones requieren criterio, y Validiscan revisa cada corrección antes de entregarla. Lo que las pruebas automatizadas de accesibilidad pueden demostrar y lo que no
¿Qué aporta usted?
Para un proyecto de Shopify, usted aporta cinco cosas: permiso por escrito para un escaneo completo de su tienda, una vía de acceso a su tema, su respuesta sobre si la IA puede redactar correcciones de nivel ASSISTED, una revisión de los cambios y sus decisiones sobre lo que sigue siendo MANUAL.
- Permiso por escrito para un escaneo completo de su tienda. Un escaneo completo añade un producto al carrito y abre el primer paso del proceso de pago, sin completar una compra ni introducir datos de pago.
- Una vía de acceso a su tema: acceso al repositorio de GitHub que lo contiene, una contraseña de Theme Access y la dirección
myshopify.comde su tienda, o un archivo de tema subido al portal del cliente. - Su respuesta sobre si la IA puede redactar correcciones de nivel ASSISTED. La redacción con IA está desactivada hasta que usted lo acepte.
- Una revisión de los cambios: publicar la copia del tema, fusionar el pull request o aplicar el paquete de parches.
- Sus decisiones sobre lo que sigue siendo MANUAL, como los subtítulos de sus vídeos.
Detalles: cuando los cambios están en producción y qué cubre un proyecto
Cuando los cambios están en producción, un escaneo de verificación vuelve a comprobar las páginas afectadas, y el Remediation Evidence Package registra el resultado. Cómo se desarrolla un proyecto, paso a paso
Un proyecto cubre una tienda: un dominio y un tema.
Fuentes
6 fuentes, todas comprobadas para esta página el 6 de octubre de 2026.
Documentación, Centro de ayuda y App Store de Shopify 6
- Manage theme access · Shopify · comprobado el
- Downloading themes · Shopify Help Center · comprobado el
- Publishing themes · Shopify Help Center · comprobado el
- Shopify GitHub integration for themes · Shopify · comprobado el
- checkout.liquid · Shopify · comprobado el
- Theme Access · Shopify App Store · comprobado el
Empiece con una revisión gratuita de su tienda.
Envíe la dirección de su tienda. Validiscan la escanea y le responde con cada fallo que el escaneo pueda demostrar, con la página y el código.
Solicitar revisión gratuitaO escriba a info@validiscan.com.
Qué cubre la revisión gratuita y qué deja fuera- Usted envía
- la dirección de su tienda
- Páginas escaneadas
- hasta 15
- Usted recibe
- todos los fallos que el escaneo puede demostrar, con la página y el código
- En su tienda
- solo páginas públicas; sin inicio de sesión, nada comprado, ningún formulario enviado
- Lo que no es
- una auditoría completa