Tutorial WordPress: Estilizar variaciones como botones (no dropdown) con solo CSS

·

·

Introducción

Este tutorial explica cómo estilizar las variaciones de producto (variations) en WooCommerce/WordPress para que se muestren como botones en lugar de un dropdown, usando únicamente CSS en la parte visual. Incluye ejemplos concretos, opciones cuando tu tema imprime select en lugar de radios y recomendaciones de accesibilidad y compatibilidad. El objetivo es que el usuario vea y seleccione cada opción como un botón independiente (píldora o segmento), manteniendo la funcionalidad nativa de selección de variación.

Requisitos previos y consideraciones

Paso 1 — Verifica el HTML que imprime tu tema

Ejemplos de markup que te interesan:

ltdiv class=variations>
  ltdiv class=variation>
    ltlabelgtColorlt/labelgt
    ltdiv class=variation-radios data-attribute_name=attribute_pa_colorgt
      ltinput type=radio id=pa_color_red name=attribute_pa_color value=redgt
      ltlabel for=pa_color_redgtRojolt/labelgt
      ltinput type=radio id=pa_color_blue name=attribute_pa_color value=bluegt
      ltlabel for=pa_color_bluegtAzullt/labelgt
    lt/divgt
  lt/divgt
lt/divgt

Si ves un ltselectgt, tu tema imprime dropdowns. En ese caso, sigue lectura para opciones.

Paso 2 — CSS recomendado para radios que se vean como botones

La técnica más limpia: ocultar visualmente los radios pero mantenerlos accesibles y estilizar sus labels como botones. Aquí tienes una hoja de estilo completa, con estados para hover, focus, checked y disabled. Puedes pegarla en el CSS de tu tema o en Personalizar gt CSS adicional.

/ Contenedor base /
.variation-radios {
  display: flex
  flex-wrap: wrap
  gap: 0.5rem / separación entre botones /
  margin-top: 0.4rem
}

/ Ocultar el input visualmente pero mantener accesible /
.variation-radios input[type=radio] {
  position: absolute
  opacity: 0
  width: 1px
  height: 1px
  margin: -1px
  overflow: hidden
  clip: rect(0 0 0 0)
  white-space: nowrap
  border: 0
  padding: 0
}

/ Estilo de los labels que actúan de botones /
.variation-radios label {
  display: inline-flex
  align-items: center
  justify-content: center
  min-width: 56px
  padding: 0.45rem 0.9rem
  border-radius: 999px / full pill /
  border: 1px solid transparent
  background: #f3f4f6
  color: #111827
  cursor: pointer
  font-size: 0.95rem
  line-height: 1
  transition: background .16s ease, transform .06s ease, box-shadow .12s ease
  box-shadow: none
  user-select: none
}

/ Hover y focus /
.variation-radios label:hover,
.variation-radios input[type=radio]:focus   label {
  background: #e6eef8
  transform: translateY(-1px)
  box-shadow: 0 1px 2px rgba(16,24,40,0.04)
  outline: none
}

/ Estado seleccionado (usando el combinador   cuando el input viene antes) /
.variation-radios input[type=radio]:checked   label {
  background: linear-gradient(180deg,#1f6feb,#1658c0)
  color: #fff
  border-color: rgba(0,0,0,0.06)
  box-shadow: 0 4px 12px rgba(23,70,161,0.18)
  transform: none
}

/ Estado disabled /
.variation-radios input[type=radio]:disabled   label,
.variation-radios label[aria-disabled=true] {
  opacity: 0.5
  cursor: not-allowed
  filter: grayscale(0.02)
}

/ Responsivo: en pantallas muy pequeñas ajustar tamaños /
@media (max-width: 420px) {
  .variation-radios label {
    min-width: 44px
    padding: 0.36rem 0.6rem
    font-size: 0.88rem
  }
}

Explicaciones clave:

Ejemplo avanzado: swatches de color (iconos dentro del label)

/ Swatch circular con color de fondo /
.variation-radios label.swatch {
  padding: 6px
  min-width: 36px
  min-height: 36px
  border-radius: 6px
  background: transparent
  border: 1px solid #e5e7eb
}
.variation-radios label.swatch .swatch-dot {
  display: block
  width: 22px
  height: 22px
  border-radius: 50%
  border: 1px solid rgba(0,0,0,0.05)
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3)
}
/ Checked style for swatch /
.variation-radios input[type=radio]:checked   label.swatch {
  border-color: #111827
  box-shadow: 0 0 0 3px rgba(30,64,175,0.12)
}

Paso 3 — Si tu tienda imprime ltselectgt (opciones)

Si ves un ltselectgt, estas son las alternativas:

  1. Mejor opción (recomendada): Cambiar la salida HTML a radios en el servidor (un pequeño fragmento PHP que convierte la generación del dropdown en radios). Esto no es sólo visual: facilita la interacción, accesibilidad y control por CSS como hemos mostrado.
  2. Solución sólo CSS (limitada): Puedes estilizar el ltselectgt para que parezca un botón o grupo de botones, pero seguirá siendo un único control que abre un menú desplegable. No podrás mostrar varias opciones simultáneamente como botones individuales y obtener el comportamiento nativo de elegir uno sin JS/HTML adicional.

Snippet PHP opcional: imprimir radios en lugar de dropdown

Si decides emitir radios (recomendado), este snippet reemplaza el HTML del dropdown de variación por un grupo de input radios. Añádelo al functions.php de tu child theme o en un plugin de snippets.

add_filter(woocommerce_dropdown_variation_attribute_options_html, wc_variation_radio_buttons, 10, 2)
function wc_variation_radio_buttons(html, args) {
    args = wp_parse_args(args, array(
        options => false,
        product => false,
        attribute => false,
        selected => false,
        name => ,
    ))

    if (empty(args[options])  empty(args[product])  empty(args[attribute])) {
        return html
    }

    options   = args[options]
    product   = args[product]
    attribute = args[attribute]
    name      = args[name]

    // Obtener términos del producto/atributo
    terms = wc_get_product_terms(product->get_id(), attribute, array(fields => all))

    if (empty(terms)) {
        return html
    }

    container  = 
foreach (terms as term) { value = esc_attr(term->slug) id = esc_attr(attribute . _ . value) label = esc_html(term->name) checked = (isset(_REQUEST[attribute_ . attribute]) _REQUEST[attribute_ . attribute] === term->slug) ? checked : container .= container .= } container .=
return container }

Este código es opcional pero transforma la estructura HTML para que el CSS anterior funcione sin problemas.

Solución CSS sólo visual para ltselectgt (limitada)

Si no puedes cambiar HTML pero quieres mejorar la apariencia del dropdown, puedes skinnear el select para que luzca más integrado y menos nativo. No da botones separados ni selección múltiple sin JS.

/ Hacer que el select parezca una píldora /
.variations select {
  -webkit-appearance: none
  -moz-appearance: none
  appearance: none
  background: #f3f4f6 url(data:image/svg xmlutf8,) right 10px center no-repeat
  padding: 0.5rem 2.2rem 0.5rem 0.9rem
  border-radius: 999px
  border: 1px solid #e5e7eb
  color: #111827
  min-width: 160px
}

Ventaja: estética mejorada. Inconveniente: sigue siendo un dropdown con el comportamiento nativo.

Integración con la lógica de variaciones de WooCommerce

Accesibilidad y pruebas

Problemas comunes y soluciones rápidas

Conclusión

La manera más robusta y elegante de mostrar variaciones como botones sin JavaScript es asegurar que el HTML genere inputs radio y aplicar el CSS explicado aquí para convertir los labels en botones/píldoras visuales. Si no puedes cambiar el HTML, puedes mejorar el aspecto del dropdown con CSS, aunque con limitaciones funcionales. Siempre prueba accesibilidad y la integración con los scripts de WooCommerce para mantener la experiencia de compra completa.



Leave a Reply

Your email address will not be published. Required fields are marked *