Ir al contenido principal

Hay propiedades CSS que se usan poco pero, cuando se necesitan, obligan a romper el flujo de trabajo de Tailwind: añadir un @apply, escribir un bloque de CSS suelto o aceptar que el componente lleve estilos fuera del sistema. Tailwind v4.3 trae tres bloques de utilidades nuevas que cubren tres de esos casos recurrentes: scrollbar, zoom y tab.

Ninguno sustituye nada que existiera antes. Son utilidades completamente nuevas para propiedades CSS que sí existían pero que no tenían atajo en Tailwind. Esto es importante a la hora de decidir qué adoptar: no hay nada que migrar, solo cosas que dejas de hacer a mano.

Scrollbar

Dos bloques de utilidades relacionados.

Ancho del scrollbar (scrollbar-*)

<div class="scrollbar-thin overflow-auto">...</div>
Utilidad CSS generado scrollbar-auto scrollbar-width: auto scrollbar-thin scrollbar-width: thin scrollbar-none scrollbar-width: none

Color del scrollbar (scrollbar-thumb-* y scrollbar-track-*)

Aceptan cualquier color del tema más variantes de opacidad. La combinación genera scrollbar-color:

<div class="scrollbar-thin scrollbar-thumb-sky-700 scrollbar-track-sky-100 overflow-auto">
  <!-- contenido -->
</div>

CSS resultante:

scrollbar-width: thin;
scrollbar-color: rgb(3, 102, 214) rgb(240, 249, 255);

scrollbar-gutter-*

Resuelve el problema clásico del layout shift cuando aparece o desaparece el scrollbar:

Utilidad CSS generado scrollbar-gutter-auto scrollbar-gutter: auto scrollbar-gutter-stable scrollbar-gutter: stable scrollbar-gutter-both scrollbar-gutter: both-edges
<div class="scrollbar-gutter-stable overflow-auto">
  <!-- la anchura reservada para el scrollbar se mantiene
       aunque el contenido aún no haga overflow -->
</div>

Dónde lo notarás: en sidebars, modales y panels que aparecen y desaparecen contenido. Cuando aplicas scrollbar-gutter-stable, el contenido no se mueve un par de píxeles cada vez que el scroll se activa.

Zoom

<div class="zoom-75">Reducido al 75%</div>
<div class="zoom-100">Tamaño normal</div>
<div class="zoom-125">Aumentado al 125%</div>
<div class="zoom-[1.1]">Valor arbitrario</div>
<div class="zoom-(--preview-zoom)">Variable CSS</div>

CSS generado: zoom: 0.75 | 1 | 1.25.

Nota importante sobre soporte de navegador: la propiedad CSS zoom solo tiene soporte universal en navegadores recientes (desde 2024). Si necesitas compatibilidad con versiones anteriores, sigue siendo más seguro usar transform: scale(). Para uso interno (paneles de admin, previews dentro del builder, modos focus) está perfecto. Para frontend público con audiencia amplia, evalúa primero.

Casos típicos: vistas previas en miniatura, modos zoom de panel de admin, efectos de hover con escalado real (no scale() que solo afecta visualmente).

Tab

<pre class="tab-2">
function indent() {
  return 'dos espacios'
}
</pre>

<pre class="tab-8">tabulación amplia</pre>

<pre class="tab-[12px]">valor arbitrario en px</pre>

<pre class="tab-(--tab-size)">desde variable CSS</pre>

CSS generado: tab-size: 2 | 8 | 12px | var(--tab-size).

Dónde lo notarás: bloques <pre> con código que mezcla tabuladores y espacios. Sin este control, el navegador asume 8 espacios por tab y los snippets quedan con sangrías exageradas. Con tab-2 o tab-4 el código se ve como el lector espera.

Lo que esto cambia en la práctica

Las tres áreas tienen algo en común: son utilidades que un proyecto puede pasar mucho tiempo sin necesitar, pero cuando aparece el caso, antes había dos caminos —escribir CSS suelto o usar @apply— y ninguno era limpio dentro del sistema. Ahora salen de fábrica.

Para componentes de UI cuidados —especialmente paneles de admin, modales con scroll, vistas con previsualizaciones, bloques de documentación con código— estas utilidades reducen la fricción del "uso este atajo o salgo del sistema". Sigue siendo class="" y suma una línea al markup en vez de un bloque CSS aparte.

El criterio para adoptarlas es directo: cuando aparezca el caso. No hay urgencia de migración porque no sustituyen nada. Solo se trata de saber que ya están disponibles para no escribir CSS custom la próxima vez.


Tailwind 4.3: scrollbar, zoom y tab — tres áreas que dejas de tocar con CSS custom

Bricks publica esta semana la versión 2.3.6. No es una versión con funcionalidades grandes: es una actualización de mantenimiento que corrige un puñado de problemas concretos en multilingüe, WooCommerce, accesibilidad y representación de la interfaz pública. El propio equipo la describe como una versión enfocada en «corrección de errores y mejoras concretas».

Para quien lleva proyectos en producción con Bricks, este tipo de versiones son las que más conviene aplicar pronto: no rompen nada, no introducen comportamiento nuevo y resuelven situaciones que estaban molestando en silencio.

Lo que más se nota en el día a día

Carrusel y deslizador: el elemento aplica correctamente los elementos en configuraciones que parten del móvil. Antes podía no respetar el número que tenías definido para esa pantalla. Si tu sitio tiene carruseles configurados por tamaño de pantalla, esta corrección es relevante.

Buscador del editor: ahora encuentra entradas, páginas y tipos de contenido personalizados marcados como «excluidos de la búsqueda». Antes el buscador interno los respetaba como en la cara pública del sitio, lo que dejaba contenido oculto al editor cuando sí debías poder localizarlo.

WPML: los selectores de plantillas respetan el idioma de la página que estás editando. Si trabajas con WPML, esto evita el clásico problema de seleccionar una plantilla en el idioma equivocado por error.

Activación de licencias: deja de fallar con errores 404 provocados por redirecciones del servidor de licencias.

Componentes: ya no se puede insertar o pegar un componente dentro de sí mismo. Era un caso poco habitual, pero cuando pasaba dejaba el componente en estado inconsistente.

Mejoras de accesibilidad

Tres ajustes pequeños pero importantes para sitios que tienen que cumplir WCAG:

  • Los elementos de valoración de solo lectura tienen ya etiquetas accesibles bien formadas.
  • Los interruptores del panel lateral actualizan aria-label de forma dinámica al abrir y cerrar.
  • El reordenamiento de propiedades de componentes es más accesible al usar el teclado.

Son cambios que una auditoría automática puede no detectar pero que importan para quien navega con lector de pantalla.

WooCommerce 10.8 y conteo de contenido para SEO

Las plantillas de WooCommerce están actualizadas para la versión 10.8.0 del complemento. Si vas a actualizar WooCommerce, conviene tener Bricks 2.3.6 antes.

El cálculo de contenido para SEO cuenta ahora correctamente todo el texto cuando hay bloques Gutenberg «Más» dentro de Bricks. Antes podía quedarse corto, lo que afectaba a los complementos de SEO que miden la longitud del contenido.

Mejora de productividad

Los generadores de escala avisan antes de crear variables duplicadas y permiten cancelar la operación. Pequeño detalle que evita ensuciar el sistema de variables sin darse cuenta.

Cuándo actualizar

Como es una versión de correcciones sin cambios incompatibles anunciados, la recomendación habitual de Bricks aplica: actualizar pronto en pruebas, validar el sitio, llevar a producción.

Si tu instalación tiene WPML, WooCommerce, carruseles configurados por tamaño de pantalla o componentes pesados, esta actualización te va a aliviar varios casos que probablemente tenías marcados como «ya lo miraré». Para sitios simples sin esas piezas, sigue siendo recomendable pero menos urgente.

Por qué importa este tipo de versión

Bricks mantiene un ritmo de versiones menores frecuente, con muchas correcciones y pocas funcionalidades nuevas entre las versiones mayores. Es una señal saludable: el equipo prioriza la estabilidad antes que la novedad. Para quien construye sitios que tienen que vivir años, un constructor con este patrón de mantenimiento es bastante más fiable que uno que solo se mueve cuando hay anuncio grande que hacer.

Más información: bricksbuilder.io/release/bricks-2-3-6/

Bricks 2.3.6: release de mantenimiento con foco en WPML, WooCommerce y accesibilidad

En el post anterior repasamos los cambios que pueden romper código en producción al actualizar a WordPress 7.0 «Armstrong». Cubrirlos es trabajo de saneamiento. Esta segunda entrega va de lo contrario: APIs y patrones nuevos que reducen código existente, abren posibilidades que antes requerían parches, y merecen entrar en tu caja de herramientas desde la próxima estimación.

Registro de bloques solo en PHP con autoRegister

Antes de 7.0, registrar un bloque dinámico solo desde PHP era posible, pero los atributos, los supports y las variantes seguían dependiendo de un block.json paralelo o de register_block_type_from_metadata(). El resultado: incluso bloques sin un solo gramo de JavaScript tenían que arrastrar un archivo JSON, un directorio build/ o algún apaño de duplicación.

En 7.0 se cierra ese ciclo. Declarando 'autoRegister' => true dentro de la llamada a register_block_type() desde PHP, el bloque queda registrado completamente sin archivo JSON adicional:

register_block_type( 'myplugin/dynamic-cta', array(
    'autoRegister'    => true,
    'render_callback' => 'myplugin_render_cta',
    'attributes'      => array(
        'message' => array( 'type' => 'string', 'default' => '' ),
        'tone'    => array( 'type' => 'string', 'default' => 'info' ),
    ),
    'supports'        => array(
        'align'   => true,
        'spacing' => array( 'padding' => true ),
    ),
) );

¿Cuándo merece la pena? Tres casos típicos:

  • Bloques dinámicos generados según contexto del sitio (multitenant, white-label).
  • Plugins que no quieren mantener un build de JavaScript solo para registrar un bloque del lado del servidor.
  • Variantes programáticas de un bloque ya existente sin tocar el editor.

No es una herramienta para todos los bloques —si tu bloque tiene UI compleja en el editor, sigues necesitando JavaScript—, pero para el catálogo creciente de bloques dinámicos puramente render-side es una limpieza importante.

Pattern Overrides para bloques custom

Hasta 7.0, los pattern overrides —la funcionalidad que permite editar puntualmente un atributo de un bloque dentro de un patrón sincronizado sin desincronizar el patrón completo— estaban limitados a una lista cerrada de bloques core. Para bloques custom no era posible.

En 7.0 se expone el filtro block_bindings_supported_attributes, que permite declarar qué atributos de qué bloques son sobreescribibles:

add_filter( 'block_bindings_supported_attributes', function( $supported, $block_name ) {
    if ( 'myplugin/feature-card' === $block_name ) {
        $supported[] = 'title';
        $supported[] = 'description';
        $supported[] = 'icon';
    }
    return $supported;
}, 10, 2 );

Esto abre la puerta a patrones reales para componentes de marca propios: una tarjeta de equipo, un bloque de testimonial, una ficha de servicio. Antes había que duplicar el patrón por cada variante; ahora basta con sobreescribir los atributos puntuales en cada instancia.

Para proyectos que construyen sobre patrones —agencias, sitios editoriales, sistemas de diseño internos— esto cambia el flujo. Una tarjeta con título, descripción e icono custom puede vivir como un único patrón sincronizado y aceptar overrides en cada uso. Menos patrones, menos mantenimiento, más reutilización.

Interactivity API: watch() y data-wp-watch

La Interactivity API gana dos primitivas que cubren un caso común que antes requería código manual de re-render: reaccionar a cambios de un signal sin escribir lógica de suscripción a mano.

En el cliente, watch() permite registrar callbacks que se ejecutan cuando un signal cambia:

import { store } from '@wordpress/interactivity';

const { state, callbacks } = store( 'myplugin', {
    state: {
        cartCount: 0,
    },
    callbacks: {
        onCartChange() {
            const count = state.cartCount;
            // reaccionar al cambio: actualizar UI, hacer fetch, lo que sea
        },
    },
} );

En HTML, el atributo data-wp-watch ata ese callback a un elemento:

<div
  data-wp-interactive="myplugin"
  data-wp-watch="callbacks.onCartChange"
></div>

¿Para qué sirve realmente? Para bloques interactivos con estado compartido entre componentes que viven en distintos puntos del DOM. Un filtro arriba de la página que afecta a tres listados separados. Un carrito de WooCommerce que actualiza un contador en el header y un panel lateral simultáneamente. Un selector de idioma que reorganiza varias secciones.

Antes esto exigía o bien tirar de directivas como data-wp-context con gimnasia para sincronizar, o bien escribir tu propia suscripción manual a los signals. Ahora es declarativo.

@wordpress/boot para páginas custom del site editor

Si has hecho una página de administración custom con @wordpress/element montada manualmente sobre admin_menu, sabes que algo falla en la integración: el command palette con ⌘K no la encuentra, las route validations no se aplican, los stores se montan a mano y todo se siente «aparte» del resto del editor.

@wordpress/boot es un paquete nuevo que arranca páginas custom del site editor con el mismo bootstrap que las nativas. La integración incluye validación de rutas, registro automático en stores core y compatibilidad con el command palette.

Casos donde lo elegiría sin pensar:

  • Una pantalla de configuración avanzada de plugin que vive «dentro» del editor.
  • Una vista de auditoría de patrones para una agencia.
  • Un panel de gestión de licencias con flujo de usuario nativo.

Si tu objetivo es una pantalla puntual en wp-admin/admin.php?page=…, sigue siendo más simple un mount manual. Si vas a vivir dentro del site editor, este paquete reemplaza decenas de líneas de bootstrap.

Resumen accionable

Antes de empezar el próximo proyecto:

  1. Revisa tu catálogo de bloques dinámicos. Cualquiera puramente PHP es candidato a autoRegister.
  2. Identifica patrones que has duplicado para variar título o descripción. Migra a pattern overrides con el filtro block_bindings_supported_attributes.
  3. Si has escrito código manual de suscripción a signals en la Interactivity API, evalúa migrar a watch() y data-wp-watch.
  4. Si tienes pantallas custom integradas con el editor, mira @wordpress/boot antes del siguiente refactor.

En el próximo post entramos en la novedad más mediática del release pero analizada desde el ángulo developer: Connectors API y AI Client. Por qué consumir el AI Client del core va a sustituir tus envoltorios artesanales de OpenAI o Anthropic en proyectos de cliente.

WordPress 7.0 para developers: APIs y patrones nuevos para tu caja

Las container queries de Tailwind ya cubrían el caso más habitual desde hace versiones: que un componente reaccione al ancho del contenedor que lo envuelve, no al ancho del viewport global. Con @container en el padre y modificadores @sm, @md, @lg, @max-* en los hijos, un mismo card se adapta si vive en una sidebar estrecha o en una zona ancha del layout.

v4.3 añade una pieza que faltaba: @container-size, una variante de @container que mide ancho y alto del contenedor. La diferencia parece pequeña pero abre un caso que antes obligaba a recurrir a JavaScript o a CSS custom: componentes que tienen que adaptarse a restricciones verticales.

La diferencia frente a @container clásico

@container por defecto mide solo el ancho del contenedor (inline-size). Las unidades CSS asociadas (cqi, cqw) funcionan dentro de él. El alto, sin embargo, no se mide: aunque pongas cqh o cqb dentro, el navegador no tiene de dónde calcular el valor.

@container-size mide ambas dimensiones. A partir de ese momento, las unidades de block-size (cqb, cqh) sí se resuelven con un valor real.

<!-- @container clásico: solo mide ancho -->
<div class="@container">
  <div class="w-[50cqw]">
    <!-- 50% del ancho del contenedor: funciona -->
  </div>
</div>

<!-- @container-size: mide ancho Y alto -->
<div class="@container-size">
  <div class="h-[50cqb]">
    <!-- 50% del alto del contenedor: funciona también -->
  </div>
</div>

Igual que @container, también admite nombre para identificar contenedores anidados:

<div class="@container-size/sidebar">
  <div class="w-[100cqw] h-[75cqb]">
    <!-- ancho = 100% del contenedor sidebar
         alto = 75% del block-size del mismo contenedor -->
  </div>
</div>

¿Sustituye a @container?

No. Es complementario. Decidir entre uno y otro depende de qué necesitas medir:

Caso Usa Razón Componente responde al ancho disponible @container + @sm/@md/@lg Coste mínimo de medición. Es lo más común. Componente necesita altura proporcional al contenedor @container-size + unidades cqb/cqh Activa la medición vertical. Componente con layout que cambia según ancho y depende de altura @container-size + @sm + cqb Los modificadores @sm/@md siguen funcionando dentro de @container-size.

La regla práctica: usa @container por defecto, y sube a @container-size solo cuando necesites unidades de altura del contenedor. Medir ambas dimensiones tiene un coste mínimo de rendimiento pero existe, por lo que no merece la pena activarlo si no lo vas a usar.

Combinándolo con los modificadores que ya conoces

Todos los modificadores que documentamos en el artículo anterior siguen funcionando dentro de @container-size:

<div class="@container-size">
  <article class="grid grid-cols-1 @sm:grid-cols-2 @max-md:gap-2 h-[60cqb]">
    <!-- 1 columna por defecto;
         2 columnas cuando el contenedor pasa de 384px;
         gap pequeño solo si el contenedor está bajo 448px;
         alto siempre al 60% del block-size del contenedor -->
  </article>
</div>

Eso permite construir componentes verdaderamente autónomos: la regla de adaptación viaja con el componente, no con la página donde se inserta.

Caso típico donde encaja

Pieza de hero con imagen de fondo que debe llenar verticalmente una sección de altura variable (porque la sección se ajusta al contenido de la página, no al viewport). Antes de @container-size, fijar la imagen a un porcentaje del alto del contenedor requería medirlo con JavaScript o usar vh/vw (que miden viewport, no contenedor). Ahora:

<section class="@container-size min-h-[400px]">
  <img class="absolute inset-0 w-full h-[100cqb] object-cover" src="...">
  <div class="relative @md:p-12 p-6">
    <!-- contenido -->
  </div>
</section>

El mismo bloque sirve igual en una landing larga, en un slot ancho de un grid y en una columna estrecha. La imagen siempre cubre el 100% del alto real del contenedor, no del viewport.

Por qué importa la simetría con los modificadores anteriores

Lo que hace útil esta adición no es el modificador en sí, sino que encaja en el modelo mental que ya tenías. @container-size sigue siendo container query: misma sintaxis, mismos breakpoints @sm/@md/@lg, mismas variantes @max-*. Solo añade una dimensión más cuando la necesitas.

Para componentes complejos —cards de producto, sidebars adaptativas, módulos de dashboard que viven en grids dinámicos— acerca a Tailwind a paridad con lo que ya se podía hacer en CSS nativo con container queries, sin obligar a escribir CSS custom. Que la API se mantenga simétrica entre max-*, @max-* y @container-size es lo que hace que el sistema escale sin convertirse en una colección de excepciones.

Tailwind 4.3: @container-size, container queries que también miden altura

WordPress 7.0 «Armstrong» salió el 20 de mayo de 2026. La prensa generalista habla del rediseño del admin y de la IA nativa en core. Con razón: son las cabeceras. Pero si mantienes plugins, temas o proyectos custom, hay una capa entera de cambios menos visibles que merecen tu atención antes que los titulares.

Esta es la primera entrega de una miniserie de cinco posts dedicada a esa otra capa. Empezamos por lo más urgente: los cambios que pueden romper código que tienes en producción ahora mismo.

PHP 7.4 como mínimo

La base de PHP soportado sube a 7.4. Si tu plugin todavía declara compatibilidad con versiones anteriores, toca actualizar el header Requires PHP del plugin, el composer.json si tienes, y la pipeline de tests CI. La mayoría del ecosistema ya estaba ahí, pero conviene revisar antes de que un cliente con hosting antiguo te abra un ticket.

Aprovecha para revisar también si usabas alguna función polyfilleada. Muchas que tenías que parchear (str_contains, str_starts_with, str_ends_with) ahora son nativas y puedes tirar el wrapper.

Soporte legacy html5 para scripts, eliminado

El subargumento script de add_theme_support( 'html5' ) se elimina del todo:

add_theme_support( 'html5', array( 'script' ) );

Si tu tema lo declara, no rompe nada visible, pero la línea ya no hace lo que hacía. Limpia el functions.php. Los demás subargumentos (search-form, comment-form, comment-list, gallery, caption, style) siguen funcionando.

Block API v3 obligatoria para el editor iframed

A partir de 7.0, los bloques con apiVersion: 3 corren en el editor iframed por defecto. Los que declaran v1 o v2 caen automáticamente al modo no-iframed, lo que implica:

  • Diferencias en herencia de estilos del body del documento principal.
  • Problemas de aislamiento CSS cuando otros bloques v3 conviven con los tuyos.
  • Inconsistencia visual entre editor y frontend en bloques con CSS complejo.

Si llevas tiempo posponiendo la migración a v3, este es el momento. El editor no-iframed es a efectos prácticos un modo legacy y va a tener cada vez menos cariño en próximas versiones.

CSS personalizado por bloque ya no se preserva sin edit_css

Hasta 7.0, un usuario sin capacidad edit_css que tocaba un bloque con CSS personalizado podía preservar ese CSS sin querer al guardar. En 7.0 se descarta automáticamente, alineando el comportamiento con lo que ya ocurría con el CSS personalizado general del Customizer.

Si tu plugin gestiona roles de colaborador en flujos multiusuario — agencias, sitios editoriales con autores externos, intranets — comprueba que ninguna pieza depende de este comportamiento residual para mantener estilos puntuales. Si lo hace, mueve el CSS a una fuente con permisos explícitos.

Extensión .heic corregida a .jpg en uploads

Cuando el navegador convierte una imagen HEIC a JPEG antes de subirla — el caso típico al subir desde Safari en iPhone — el archivo final ahora lleva la extensión .jpg correcta. Antes el archivo se subía con extensión .heic aunque su contenido fuera JPEG, lo que provocaba que algunos workflows lo trataran erróneamente como HEIC.

Si tu código inspecciona extensiones para clasificar medios, filtrar uploads, generar miniaturas o ejecutar lógica específica de formato, regulariza el handling. El comportamiento previo era objetivamente erróneo y ahora se ha enderezado, pero el código que confiaba en él va a comportarse distinto.

Resumen accionable

Antes de actualizar un sitio a 7.0:

  1. Revisa los headers Requires PHP de tus plugins. Sube a 7.4 si no estabas ahí.
  2. Busca 'html5' en tus temas y elimina la línea de 'script' si la tienes.
  3. Auditea tus bloques: cualquiera con apiVersion menor que 3 debería tener migración planificada.
  4. Si gestionas sitios con roles de colaborador y CSS por bloque, prueba el flujo en staging antes de actualizar producción.
  5. Revisa el código que inspecciona extensiones de medios subidos.

En el próximo post de la serie entramos en las APIs y patrones nuevos que justifican un upgrade que vaya más allá de mantener el código andando: autoRegister para bloques solo PHP, Pattern Overrides para bloques custom, Interactivity API con watch(), y @wordpress/boot para construir páginas dentro del site editor.

WordPress 7.0 para developers: lo que puede romper tu código

Si trabajas con Claude Code, Cursor, Windsurf u otros agentes, conoces el problema: cada prompt se procesa de forma aislada y la consistencia visual se rompe entre componentes. DESIGN.md —formato abierto creado por Google Labs / Stitch— resuelve esto con un único archivo Markdown en la raíz del repositorio: tokens en YAML frontmatter y razonamiento de diseño en texto plano. El agente lo lee al inicio y mantiene esas decisiones como contexto vivo.

La spec oficial vive en [github.com/google-labs-code/design.md](https://github.com/google-labs-code/design.md) y la CLI se publica como @google/design.md en npm. Alrededor han crecido bibliotecas comunitarias y herramientas para generar tu propio archivo. Aquí tres recursos para empezar a usarlo hoy.

1.00

designmd.ai (https://designmd.ai/)
la biblioteca de referencia

Biblioteca comunitaria con curación más estricta, cientos de sistemas listos para descargar y soporte MCP. Es la entrada más cómoda al ecosistema una vez has visto la spec oficial.

Para qué: descubrir sistemas curados y empezar rápido.

1.00

designmd.app(https://designmd.app/)
la biblioteca extendida

454 sistemas de diseño documentados por la comunidad, categorizados por estética (desde brutalism hasta editorial elegant). Cada archivo viene compatible con Claude Code, Cursor, Kiro, Windsurf y Cline.

Para qué: variedad estética cuando los sistemas curados se quedan cortos.

1.00

systemly.design(https://www.systemly.design/)
el generador

La pieza para producir en lugar de consumir. Genera un sistema completo desde una URL de marca o desde inputs manuales: 128 tokens exportables a JSON (W3C DTCG), CSS, PDF y React (próximamente). Incluye plugin de Figma y soporte para Tailwind + shadcn. No emite estrictamente un «DESIGN.md», pero los tokens W3C se convierten en uno con un script trivial o pidiéndoselo al propio agente.

Para qué: crear el sistema de un cliente desde su marca existente, sin pasar dos días en Figma.

DESIGN.md: tres recursos para diseñar con agentes de IA sin perder coherencia

Tailwind v4.2 introdujo un cambio pequeño pero limpio: las utilidades start-* y end-* quedaron obsoletas en favor de inset-s-* y inset-e-*. La motivación es de coherencia: el resto del sistema usa el prefijo inset- para utilidades de posicionamiento (inset-x-*, inset-y-*, inset-0, inset-auto), y las versiones lógicas inline no encajaban con ese patrón.

Las antiguas siguen funcionando, pero el equipo de Tailwind las dará por retiradas en una versión futura. Es buen momento para migrar proyectos activos sin prisa.

Qué hacían (y siguen haciendo) start-* y end-*

Son logical properties: la versión "inline-start" e "inline-end" de left y right. Se adaptan al modo de escritura del documento.

  • En LTR (castellano, inglés): start-* equivale a left-* y end-* equivale a right-*.
  • En RTL (árabe, hebreo): se invierte, sin tocar el HTML.

Mismo CSS subyacente: inset-inline-start e inset-inline-end. Lo que cambia con v4.2 es solo el prefijo de la clase Tailwind, no la propiedad CSS generada.

Equivalencias

El patrón es directo: sustituir start- por inset-s- y end- por inset-e-. El número o valor que viene después no cambia.

Antes (deprecado) Ahora (recomendado) CSS generado start-0 inset-s-0 inset-inline-start: 0 start-4 inset-s-4 inset-inline-start: 1rem start-auto inset-s-auto inset-inline-start: auto start-full inset-s-full inset-inline-start: 100% start-[10px] inset-s-[10px] inset-inline-start: 10px -start-2 -inset-s-2 inset-inline-start: -0.5rem end-0 inset-e-0 inset-inline-end: 0 end-6 inset-e-6 inset-inline-end: 1.5rem end-[20px] inset-e-[20px] inset-inline-end: 20px

Mismo principio para los valores arbitrarios, negativos y variables CSS: solo cambia el prefijo de la clase.

Migración automática vía CLI

Tailwind ofrece una herramienta oficial que reescribe las clases deprecadas en todo el proyecto:

npx @tailwindcss/upgrade

El comando:

  • Detecta el código del proyecto (HTML, JSX, Vue, plantillas Blade, etc.).
  • Sustituye start-* → inset-s-* y end-* → inset-e-* en todos los archivos.
  • Reporta los cambios aplicados para revisión.

Recomendación práctica: pasarlo en una rama dedicada, hacer commit aislado solo de los renombres, y revisar el diff antes de mergear. El cambio es seguro pero es buena higiene tener el rebrand de utilidades en su propio commit por si en el futuro hay que revertir o auditar.

Migración manual con grep o búsqueda regex

Si prefieres tener control total o tu proyecto tiene patrones que el CLI no detecta bien:

# Encontrar todos los usos
grep -rn -E '\b(-?(start|end))-' src/

# Verificar con dry-run antes de tocar nada
sed -E 's/\b(-?)(start|end)-/\1inset-\2-/g; s/inset-start-/inset-s-/g; s/inset-end-/inset-e-/g' src/file.html

# Aplicar (usar con cuidado en proyectos grandes)
find src -type f -name "*.html" -exec sed -i.bak -E '
  s/\b(-?)start-/\1inset-s-/g;
  s/\b(-?)end-/\1inset-e-/g
' {} \;

Cuidado: este regex puede tener falsos positivos en cadenas que no son clases Tailwind (URLs con /start, atributos data-end, etc.). Si el proyecto es grande y mezcla código, el CLI oficial es más seguro.

Otras utilidades nuevas en v4.2 que conviene conocer

Mientras estés en zona de migración, vale la pena saber que v4.2 también añadió:

  • Espaciado lógico de bloque: pbs-*, pbe-*, mbs-*, mbe-* (padding/margin block-start/end). Complementa los ps-*/pe-* que ya existían para inline-start/end. Útiles para sitios multilingüe que mezclan LTR + RTL.
  • Tamaño lógico: inline-* (ancho lógico) y block-* (alto lógico). Versiones inset también: inset-s-* e inset-e-* que ya hemos cubierto arriba.
  • Tipografía avanzada: font-features-* para font-feature-settings. Acceso directo a ligaduras, kerning y variantes numéricas sin escribir CSS.
  • Paletas de color: mauve, olive, mist, taupe. Tonos neutros con personalidad.
  • Integración Webpack oficial: @tailwindcss/webpack ya disponible.

Cuándo es seguro hacer la migración

Tipo de proyecto Recomendación Proyecto nuevo Usar inset-s-* / inset-e-* directamente desde el primer commit. Proyecto activo en desarrollo Migración automática en un sprint, commit aislado. Proyecto en producción estable, sin desarrollo activo Esperar a la siguiente versión que necesite tocar el frontend y migrar de paso. Proyecto con muchos terceros / plantillas externas Auditar primero qué controlas y qué no. Migrar solo lo propio.

Las clases antiguas seguirán funcionando hasta que Tailwind las elimine —no hay anuncio público de versión exacta, pero el patrón habitual del proyecto es mantener deprecadas durante varios ciclos antes de retirarlas. No hay urgencia, sí hay buen momento.

Por qué el cambio merece la pena

La razón no es solo coherencia visual de nombres. Las clases inset-* son el grupo más completo de utilidades de posicionamiento de Tailwind: incluyen inset-0 para todos los lados, inset-x-* e inset-y-* para ejes completos, inset-auto, variantes negativas y valores arbitrarios. Que inset-s-* e inset-e-* se sumen a esa familia hace que el sistema sea más predecible: si conoces el patrón inset, ya conoces el patrón lógico inline.

Lo que se gana no es velocidad ni capacidad nueva; se gana menos cosas que recordar. En un sistema con miles de clases utilitarias, eso es la diferencia entre tener un vocabulario que cabe en la cabeza y tener uno que obliga a consultar la docs cada vez.

Tailwind 4.2: migrar start-* y end-* a inset-s-* e inset-e-*

Las tiendas WooCommerce con catálogos grandes acumulan un coste invisible: redactar la ficha de cada producto. Título, descripción corta, descripción completa, etiquetas, meta descripción SEO e información de envío repetidos por cada SKU, multiplicados por decenas o cientos de variantes, son horas de trabajo que no se ven en ningún informe pero salen del calendario del que gestiona la tienda.

La pregunta no es si la IA puede ayudar —puede— sino cómo encajarla sin convertir el catálogo en un escaparate de contenido plano. Dos desarrolladores han documentado este mes en DEV Community su experiencia con el mismo patrón aplicado a casos reales. Coinciden en el enfoque y en sus límites.

Cómo funciona un flujo con IA para fichas de producto

Mehdi Mihanzadeh describe el flujo que está implementando en AI Product Studio Pro, un plugin de Clugins para WooCommerce. El proceso tiene cuatro pasos:

  1. El propietario introduce la información mínima del producto.
  2. La IA genera un borrador estructurado con título, descripción, etiquetas y meta descripción SEO.
  3. El propietario revisa y edita.
  4. Solo entonces se publica.

El punto clave es el orden: la IA no publica, solo escribe el primer borrador. Mihanzadeh lo dice sin rodeos: el objetivo no es reemplazar al dueño de la tienda, sino reducir el trabajo repetitivo de escritura y acortar el tiempo hasta tener algo sobre lo que decidir.

Por qué la revisión humana sigue siendo indispensable

Stella Decoro, desarrolladora WooCommerce en Croacia, documenta cómo usó IA durante la mejora de Ecigareta.hr como asistente y nunca como sustituto del criterio manual. Recurrió a herramientas de IA para planificación, estructura de contenido, ideas de SEO, enlazado interno y pruebas con plugins, pero cada decisión terminaba verificándose dentro de WordPress, WooCommerce, Elementor, Rank Math y el propio sitio en producción.

El motivo es directo: el contenido de producto afecta a la confianza del comprador, al posicionamiento en buscadores y a la tasa de conversión. Si la IA genera descripciones sin supervisión, el resultado tiende a volverse repetitivo, impreciso o demasiado genérico, especialmente en tiendas con productos similares entre sí.

El reto real: consistencia sin uniformidad

Mihanzadeh identifica el problema más difícil de este tipo de automatización: la consistencia. Cuando una tienda tiene muchos productos parecidos, las descripciones generadas por IA pueden empezar a sonar todas iguales. El reto técnico es que la IA siga una estructura coherente sin que cada ficha lea exactamente como la anterior.

Esto es lo que separa un flujo con IA bien diseñado de simplemente lanzar descripciones automáticas y rezar. Un buen flujo varía el orden de la información, alterna sinónimos, ajusta el tono según el tipo de producto y obliga al humano a tocar al menos una sección antes de publicar.

Qué se puede automatizar hoy en una tienda WooCommerce

A partir de las experiencias documentadas, las áreas donde la IA aporta valor real son:

  • Borrador inicial de la ficha con título, descripción corta, descripción completa, etiquetas y meta descripción SEO.
  • Mejora de la estructura de categorías con descripciones más claras para el visitante.
  • Contenido informativo del blog que sostenga la estrategia SEO a medio plazo.
  • Ideas de enlazado interno entre páginas del sitio.
  • Detección de mejoras en experiencia de usuario y velocidad de carga.

En todos los casos el patrón se repite: la IA genera una primera versión, el humano revisa y publica.

Caso práctico: 50 variantes en horas, no en un día

Una tienda con 50 variantes de un mismo producto —por ejemplo prendas en distintos colores y tallas— supone, escrita a mano, cerca de un día completo de trabajo. Con un flujo de IA que genere el primer borrador para cada variante, el trabajo se concentra en revisar 50 borradores en lugar de redactar 50 fichas desde cero. La diferencia no es solo de tiempo: cambia la naturaleza del trabajo. El propietario deja de escribir y pasa a decidir, que es donde realmente aporta.

Lo que esto dice del momento actual

La automatización de borradores con IA en WooCommerce ya no es una promesa: hay desarrolladores publicando casos concretos en mayo de 2026 con resultados verificables. Para tiendas con catálogos medianos o grandes, el ahorro es real, y el coste de adopción es bajo porque el patrón "IA escribe, humano revisa" no obliga a confiar en la IA por encima de lo razonable.

El riesgo real no está en usar IA, está en saltarse el paso de revisión. Quien gestiona tiendas con miles de SKU y descubre que puede prescindir de revisar acaba descubriendo, semanas después, que su catálogo lee como el de cualquier otro. La diferencia entre una tienda con voz propia y un escaparate genérico ya no la marca quién usa IA y quién no; la marca quién la usa con criterio.

Flujos de IA para WooCommerce: cómo automatizar borradores de producto sin caer en contenido genérico

Tailwind es mobile-first por defecto. La gran mayoría del trabajo usa los modificadores sm:, md:, lg:, xl: y 2xl: que aplican estilos desde un breakpoint hacia arriba. Pero hay casos en los que necesitas exactamente lo contrario: aplicar un estilo hasta un breakpoint y que desaparezca cuando la pantalla crece.

Para eso están los modificadores max-* (max-sm, max-md, max-lg, max-xl, max-2xl). Funcionan en Tailwind v3 y v4 con la misma sintaxis, y —lo importante— sirven tanto para media queries (responsive según viewport) como para container queries (responsive según el contenedor padre).

Cómo funcionan en media queries

max-sm:text-center aplica text-align: center solo cuando el viewport es menor a 640px. A partir de ahí desaparece. Es la inversa exacta de sm:text-center.

Modificador Aplica cuando viewport CSS equivalente max-sm: < 640px @media (width < 40rem) max-md: < 768px @media (width < 48rem) max-lg: < 1024px @media (width < 64rem) max-xl: < 1280px @media (width < 80rem) max-2xl: < 1536px @media (width < 96rem)

Combinándolos con los modificadores habituales

Aquí es donde max-* brilla de verdad: permite definir un rango entre dos breakpoints sin escribir CSS personalizado.

<!-- Solo aplica flex entre 768px y 1024px -->
<div class="md:max-lg:flex"></div>

El patrón breakpointMin:max-breakpointMax:utility se lee como "desde X hasta Y". Es la única forma limpia de targetear un rango concreto en Tailwind sin recurrir a clases CSS propias ni a breakpoints custom en config.

Ejemplos prácticos:

<!-- Visible solo en tablets (sm a md) -->
<div class="hidden sm:max-md:block"></div>
<!-- Padding mayor solo en desktop medio -->
<div class="lg:max-xl:p-8"></div>
<!-- Mensaje "rotar el dispositivo" solo en pantallas muy pequeñas -->
<p class="hidden max-sm:block">Mejor en horizontal.</p>

La misma sintaxis aplica a container queries

Las container queries son la otra cara del responsive moderno: en lugar de mirar el viewport global, miran el ancho del contenedor padre que tenga @container. Tailwind expone modificadores @sm, @md, @lg que se comportan igual que los responsive estándar pero contra el contenedor, no contra la ventana.

Y, igual que con media queries, existen sus versiones max:

<div class="@container">
  <div class="grid grid-cols-3 @max-md:grid-cols-1">
    <!-- 3 columnas por defecto;
         1 columna cuando el contenedor es menor a 448px -->
  </div>
</div>
Modificador Aplica cuando contenedor CSS equivalente @max-3xs: < 256px @container (width < 16rem) @max-2xs: < 288px @container (width < 18rem) @max-xs: < 320px @container (width < 20rem) @max-sm: < 384px @container (width < 24rem) @max-md: < 448px @container (width < 28rem) @max-lg: < 512px @container (width < 32rem)

Esto desbloquea componentes verdaderamente reutilizables. Un mismo card puede mostrar tres columnas cuando vive en una sidebar ancha y colapsar a una sola cuando vive en un slot estrecho, sin que el viewport global tenga nada que decir. La regla de diseño viaja con el componente, no con la página.

Caso práctico: hero que cambia de estructura solo en tablet

Imagina un hero que en móvil es vertical (texto arriba, imagen abajo), en tablet pasa a horizontal con la imagen a la derecha, y en desktop vuelve a ser vertical porque allí tienes espacio para una composición más grande con la imagen de fondo.

Antes de max-*, esto requería tres modificadores y a menudo revertir clases a mano. Con max-*:

<section class="flex flex-col sm:max-lg:flex-row lg:flex-col">
  ...
</section>

Una sola línea, intención clara: vertical por defecto, horizontal en el rango sm-lg, vertical otra vez de lg hacia arriba.

Cuándo NO usarlo

max-* es elegante pero no es siempre la respuesta. Si tu diseño es genuinamente mobile-first (móvil simple, desktop más rico), los modificadores estándar sm:/md:/lg: dejan el código más legible. max-* brilla cuando el diseño tiene reglas que se aplican por debajo de cierto tamaño: textos centrados solo en móvil, navegaciones colapsadas solo en tablet, fondos retirados solo en pantalla pequeña.

Como regla práctica: si te encuentras escribiendo lg:hidden para esconder algo solo en desktop, considera si max-lg:flex (mostrarlo solo bajo desktop) lee mejor para quien mantenga el código después.

Por qué importa que funcione en ambos contextos

Que max-* use la misma sintaxis en media queries y en container queries hace que el modelo mental sea uno solo: "aplica hasta X". No hay dos APIs que recordar según trabajes a nivel global o a nivel de componente. Es la coherencia que ha hecho que Tailwind escale como sistema y no como una colección de utilidades sueltas.

Para quien construye sitios donde conviven layouts globales (página) y componentes reutilizables (cards, sidebars, módulos repetidos), tener esa simetría entre max-* y @max-* es lo que permite mantener un único vocabulario mental sin saltar entre paradigmas.

Tailwind max-*: el modificador inverso para media queries y container queries

Los page builders de WordPress llevan años organizando la página en secciones, filas, columnas y bloques predefinidos. Es la base que comparten Elementor, Bricks, Divi y la mayoría del ecosistema, y la razón por la que un sitio creado con cualquiera de ellos se reconoce a primera vista. Kirki (kirki.com) propone otra cosa: una página en blanco sin contenedores impuestos, donde cada elemento se coloca libre y se alinea solo si el diseño lo pide.

No es un producto del todo nuevo. El mismo equipo lanzó hace un año en Product Hunt un page builder llamado Droip. Ese producto se ha reescrito desde cero —código nuevo, motor nuevo, flujo nuevo— y se ha renombrado a Kirki. Es decir: Droip era el producto anterior, Kirki es el actual. No son dos empresas distintas ni dos productos que conviven, es el mismo equipo republicando su producto tras rehacerlo. Está disponible como plugin en wordpress.org/plugins/kirki.

Qué cambia respecto al patrón habitual

El cambio principal está en cómo se trabaja la página. En lugar de empezar con una sección que contiene filas que contienen columnas, en Kirki cada elemento existe por sí solo y se coloca donde quieras. Si el diseño pide cuadrícula o columnas, se aplican; si no, el elemento se queda donde lo pusiste. Esto desbloquea diseños con capas superpuestas, posicionamientos no convencionales y composiciones tipo revista que en un page builder de filas obligan a forzar la herramienta o a tocar CSS a mano.

El segundo cambio es lo que genera por debajo. El resultado final es HTML y CSS limpios y estándar, sin capas extra de procesamiento ni etiquetas de envoltorio que no aportan. Para quien tiene que mantener el sitio después o revisar el rendimiento, esto importa más que casi cualquier otra característica visible.

Lo que trae de fábrica

  • CMS integrado con campos personalizados, colecciones, plantillas dinámicas y publicación programada.
  • Colaboración en tiempo real: varios editores en la misma página, comentarios y modo staging antes de publicar.
  • Línea de tiempo visual para animaciones que reaccionan al scroll, al click o al pasar el ratón por encima.
  • Más de 100 plantillas listas y modo desarrollador para ver el código mientras trabajas.
  • Importación directa desde Figma al lienzo.
  • Adaptación a cualquier tamaño de pantalla sin límite a tres o cuatro tamaños como en otros page builders.
  • Más de 20 integraciones (Mailchimp, Google Search Console, etc.).
  • Formularios, popups, mapas y herramientas SEO sin instalar nada adicional.

El modelo es freemium: la versión gratuita no pide tarjeta ni caduca, y hay planes superiores para funciones avanzadas que la página principal no detalla.

Caso típico donde encaja

Una landing con composición visual poco convencional —capas superpuestas, elementos en diagonal, retículas asimétricas, animaciones al hacer scroll— es el escenario donde Kirki muestra músculo frente a un page builder tradicional. Lo mismo aplica a portfolios de diseñador, microsites editoriales o piezas de campaña: el tipo de proyecto donde escribir CSS personalizado para forzar Elementor o Bricks deja de compensar.

La importación desde Figma cierra el caso para quien diseña en Figma y quiere bajar el resultado a WordPress sin reconstruirlo desde cero. Es el flujo que Webflow ofrecía fuera de WordPress; ahora aparece dentro.

De Droip a Kirki: por qué importa la reescritura

Reescribir un producto desde cero, en un mercado donde aparecer con algo nuevo cuesta caro, suele significar que el equipo prefiere asumir ese coste antes que arrastrar decisiones antiguas que ya no encajan. Es señal de que no es una capa más sobre Gutenberg ni una envoltura sobre otro page builder, sino motor propio. Eso afecta a la trayectoria probable del producto a dos o tres años vista.

Cómo encaja en el momento actual

Kirki se suma a una lista corta de page builders que intentan romper el patrón de filas y columnas: Webflow lo hizo desde fuera de WordPress, Bricks lo intenta desde dentro con un modelo todavía cercano a la estructura tradicional, y Gutenberg lleva años aproximándose por la vía de bloques y patrones. Kirki es la apuesta más radical hasta la fecha por el lienzo libre dentro de WordPress manteniendo a la vez una salida HTML y CSS limpia y estándar.

Si la propuesta cuaja, será por dos razones: porque resuelve el dolor real del diseñador que pelea contra contenedores impuestos, y porque no introduce el coste habitual de los page builders no convencionales (código enredado y dependencia del editor para cualquier cambio futuro). Quien construye sitios que tienen que vivir muchos años entiende bien por qué ese segundo punto puede ser el que decida la adopción.

Kirki: el page builder WordPress de lienzo libre