Tutorial WordPress: Diseñar un bloque “Comparar características” con ticks y cruces CSS

·

·

Introducción

Este tutorial explica paso a paso cómo diseñar un bloque de comparación de características para WordPress que muestre ticks (✔) y cruces (✖) únicamente con CSS. El objetivo es crear un bloque accesible, responsive y fácil de insertar vía shortcode o como bloque personalizado, con estilos limpios y altamente personalizables.

Concepto y accesibilidad

La idea es utilizar una estructura semántica (tabla para comparativas tabulares) y añadir clases (.yes / .no) en las celdas para que el CSS genere los iconos mediante pseudo-elementos (::before). Para lectores de pantalla se incluye texto oculto visualmente con una etiqueta (que actúa como texto accesible) y atributos aria-label. Esto asegura que el contenido sea legible para todos.

Estrategia:

  • Estructura: Tabla con primera columna para la característica y columnas siguientes para planes/productos.
  • Marcado: Celdas con clases .yes o .no y texto accesible dentro de un .
  • Estilos: Pseudo-elementos para mostrar ✔ y ✖, variables CSS para colores y personalización.
  • Responsive: Opciones para convertir la tabla en tarjetas en móviles o permitir desplazamiento horizontal.

HTML: marcado de ejemplo (tabla)

Ejemplo mínimo de la tabla que servirá como base:

Característica Plan A Plan B
Soporte por email Incluido No incluido
Almacenamiento No incluido Incluido

CSS: ticks y cruces con pseudo-elementos

A continuación, el CSS que crea los iconos, añade estilos base y la clase para ocultar visualmente el texto accesible. Se usan variables CSS para facilitar la personalización.

/ Variables globales (ajustables) /
:root {
  --compare-border: #e6e6e6
  --yes-color: #2ecc71
  --no-color: #e74c3c
  --cell-padding: 12px 16px
}

/ Estilos base de la tabla /
.compare-table {
  width: 100%
  border-collapse: collapse
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial
  margin: 1rem 0
}
.compare-table th,
.compare-table td {
  padding: var(--cell-padding)
  border: 1px solid var(--compare-border)
  text-align: center
  vertical-align: middle
}
.compare-table th {
  background: #fafafa
  font-weight: 600
  text-transform: none
}
.compare-table td:first-child,
.compare-table th:first-child {
  text-align: left
}

/ Iconos generados por pseudo-elementos /
.compare-table td.yes::before,
.compare-table td.no::before {
  display: inline-block
  width: 1.1em
  height: 1.1em
  line-height: 1.1em
  margin-right: 0.5em
  font-weight: 700
  font-size: 1em
  vertical-align: middle
}

/ Tick (✔) /
.compare-table td.yes::before {
  content: ✔
  color: var(--yes-color)
}

/ Cross (✖) /
.compare-table td.no::before {
  content: ✖
  color: var(--no-color)
}

/ Texto accesible, visible solo para lectores de pantalla /
.sr-only {
  position: absolute !important
  width: 1px !important
  height: 1px !important
  padding: 0 !important
  margin: -1px !important
  overflow: hidden !important
  clip: rect(0 0 0 0) !important
  white-space: nowrap !important
  border: 0 !important
}

Variantes de estilo

Si prefieres íconos SVG más consistentes o con mejor control visual, puedes reemplazar el content por un background-image con data URI SVG y usar mask/ background-color para colorear dinámicamente. Otra opción es usar fuentes de iconos (p. ej. Font Awesome) e insertar el carácter correspondiente en content.

Responsive: adaptar la comparativa para móviles

Dos enfoques comunes:

  1. Scroll horizontal: Dejar la tabla como está y permitir overflow-x en contenedor padre.
  2. Transformar en tarjetas: Convertir cada fila en un bloque apilado para pantallas estrechas (más legible en móviles).

CSS para scroll horizontal:

/ Contenedor que envuelve la tabla (en tu tema o bloque) /
.compare-table-wrapper {
  overflow-x: auto
  -webkit-overflow-scrolling: touch
}

CSS simplificado para convertir cada fila en tarjeta (técnica: display:block sobre filas y celdas en móvil):

@media (max-width: 720px) {
  .compare-table,
  .compare-table thead,
  .compare-table tbody,
  .compare-table th,
  .compare-table td,
  .compare-table tr {
    display: block
  }

  .compare-table thead tr {
    display: none / ocultar cabecera original /
  }

  .compare-table tr {
    margin: 0 0 1rem 0
    border: 1px solid var(--compare-border)
    padding: 0.5rem
  }

  .compare-table td {
    display: flex
    justify-content: space-between
    align-items: center
    padding: 0.6rem 0.8rem
    border: none
    border-bottom: 1px solid var(--compare-border)
  }

  .compare-table td:first-child {
    font-weight: 600
  }

  .compare-table td::before {
    / apagamos pseudo-content en este modo porque la estructura ya muestra el icono en posición natural /
    content: none
  }
}

Integración en WordPress

Se muestran dos vías sencillas y prácticas para integrar el bloque en WordPress: un shortcode en PHP (rápido) y la idea básica para un bloque de Gutenberg (JS). El ejemplo del shortcode encola un CSS con los estilos anteriores.

Shortcode en PHP

PHP para registrar un shortcode [compare] que recibe atributos y contenido con filas:

/ Encola el CSS desde el plugin o functions.php /
function cf_enqueue_styles() {
  wp_enqueue_style(cf-compare-style, plugin_dir_url(__FILE__) . css/compare-features.css, array(), 1.0)
}
add_action(wp_enqueue_scripts, cf_enqueue_styles)

/ Shortcode [compare columns=Plan A,Plan B] con contenido:
   Característicayes,no
   Otrano,yes
/
function cf_compare_shortcode(atts, content = null) {
  atts = shortcode_atts(array(columns => Plan A,Plan B), atts, compare)
  cols = array_map(trim, explode(,, atts[columns]))
  ob_start()
  ?>
  
values = isset(parts[1]) ? array_map(trim, explode(,, parts[1])) : array() for (i = 0 i < count(cols) i ) { val = isset(values[i]) ? strtolower(values[i]) : isYes = in_array(val, array(yes, 1, true, si, sí)) class = isYes ? yes : no label = isYes ? Incluido : No incluido echo } echo } } ?>
Característica
. esc_html(parts[0]) . . esc_html(label) .

Bloque de Gutenberg (idea básica)

Para un bloque de Gutenberg se usaría registerBlockType con un editor que permita añadir filas y columnas dinámicamente. El bloque puede guardar HTML estático (save retorna la tabla) o usar render_callback en PHP para renderizado servidor. A continuación, la idea esencial de registro en JS (resumida):

/ Resumen: archivo block.js (requiere build con @wordpress/scripts) /
const { registerBlockType } = wp.blocks
const { RichText, InspectorControls } = wp.blockEditor
registerBlockType(cf/compare, {
  title: Comparativa de características,
  icon: editor-table,
  category: widgets,
  attributes: {
    columns: { type: string, default: Plan A,Plan B },
    rows: { type: string, default:  } // contenido serializado: línea por línea Característicayes,no
  },
  edit({ attributes, setAttributes }) {
    // Editor simplificado: un textarea para filas y uno para columnas.
    // Implementar UI real con Repeatable fields es recomendable.
    return (
      wp.element.createElement(div, {},
        wp.element.createElement(label, {}, Columnas (separadas por coma)),
        wp.element.createElement(textarea, {
          value: attributes.columns,
          onChange: (e) => setAttributes({ columns: e.target.value })
        }),
        wp.element.createElement(label, {}, Filas (cada línea: Característicayes,no)),
        wp.element.createElement(textarea, {
          value: attributes.rows,
          onChange: (e) => setAttributes({ rows: e.target.value })
        })
      )
    )
  },
  save() {
    return null // usar render_callback en PHP o serializar HTML aquí
  }
})

Buenas prácticas y consejos

  • Semántica: usar tabla para comparaciones tabulares. Evitar tablas para layout.
  • Accesibilidad: añadir aria-label a celdas y texto oculto (.sr-only) que describa “Incluido” / “No incluido”.
  • Colores: usar contraste suficiente entre color de icono y fondo para cumplir WCAG.
  • Personalización: exponer variables CSS para colores y tamaños para que el tema pueda sobrescribirlas.
  • Internationalización: si generas cadenas desde PHP, aplicar traducciones con __() / esc_html__().

Extensiones y mejoras avanzadas

Opciones para evolucionar el componente:

  • Animaciones sutiles al cambiar valores (transiciones en color y scale del pseudo-elemento).
  • Soporte para estados intermedios (por ejemplo, parcialmente incluido) usando otra clase (.partial) y un símbolo diferente o SVG).
  • Incorporar iconos SVG para mejor control visual y retina crispness (usar data-uri o inline SVG en el markup si lo necesitas).
  • Agregar filtros en el bloque de Gutenberg para ordenar columnas, destacar la más popular, etc.

Ejemplo completo del CSS consolidado

/ Consolidado - pegar en css/compare-features.css /
:root {
  --compare-border: #e6e6e6
  --yes-color: #2ecc71
  --no-color: #e74c3c
  --cell-padding: 12px 16px
}
.compare-table-wrapper { overflow-x: auto -webkit-overflow-scrolling: touch }
.compare-table { width:100% border-collapse:collapse font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial margin:1rem 0 }
.compare-table th, .compare-table td { padding: var(--cell-padding) border:1px solid var(--compare-border) text-align:center vertical-align:middle }
.compare-table th { background:#fafafa font-weight:600 }
.compare-table td:first-child, .compare-table th:first-child { text-align:left }
.compare-table td.yes::before, .compare-table td.no::before { display:inline-block width:1.1em height:1.1em line-height:1.1em margin-right:0.5em font-weight:700 font-size:1em vertical-align:middle }
.compare-table td.yes::before { content:✔ color:var(--yes-color) }
.compare-table td.no::before { content:✖ color:var(--no-color) }
.sr-only { position:absolute !important width:1px !important height:1px !important padding:0 !important margin:-1px !important overflow:hidden !important clip:rect(0 0 0 0) !important white-space:nowrap !important border:0 !important }
@media (max-width:720px) {
  .compare-table, .compare-table thead, .compare-table tbody, .compare-table th, .compare-table td, .compare-table tr { display:block }
  .compare-table thead tr { display:none }
  .compare-table tr { margin:0 0 1rem 0 border:1px solid var(--compare-border) padding:0.5rem }
  .compare-table td { display:flex justify-content:space-between align-items:center padding:0.6rem 0.8rem border:none border-bottom:1px solid var(--compare-border) }
  .compare-table td:first-child { font-weight:600 }
  .compare-table td::before { content:none }
}

Resumen

Con una estructura semántica, clases sencillas (.yes / .no) y pseudo-elementos CSS para los iconos, puedes crear una comparativa elegante, accesible y fácil de integrar en WordPress ya sea como shortcode o bloque. Manteniendo variables CSS y un CSS modular, el bloque será sencillo de personalizar desde cualquier tema.



Leave a Reply

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