Mosaico (ns-frame/mosaic)
Un bento donde las piezas no tienen que ser rectángulos. Cada área se dibuja con celdas, como en grid-template-areas, pero puede tener forma de L, T, U o escalera. Las piezas encajan entre sí con el mismo hueco en las rectas y en las curvas, y uno o varios orbes pueden abrir un hueco que recorta a sus vecinas.
<script type="module" src="ns-frame.js"></script>
<script type="module" src="ns-mosaic.js"></script>
<div class="ns-mosaic hero-grid" data-ns-mosaic="wave ripple">
<article data-ns-area="h">Portada</article>
<article data-ns-area="a">…</article>
<article data-ns-area="b">…</article>
<article data-ns-area="x">…</article>
<article data-ns-area="y">…</article>
<div data-ns-orb><img src="foto.jpg" alt="…"></div>
</div>
.hero-grid {
--ns-areas: 'a h h b' 'a h h b' 'x x y y';
--ns-row: 150px;
--ns-gap: 14px;
--ns-mosaic-radius: 22px;
--ns-orb: 3 3 90 hex;
}
@media (max-width: 760px) {
.hero-grid { --ns-areas: 'h h' 'h h' 'a b' 'x y'; --ns-orb: 2 3 56 hex; --ns-row: 120px }
}
Plantilla
| Variable | Qué hace | Por defecto |
|---|---|---|
--ns-areas |
Filas entre comillas; cada nombre es un área; . deja la celda vacía |
— |
--ns-row |
Alto de cada fila | 150px |
--ns-gap |
Hueco entre piezas | 14px |
--ns-mosaic-radius |
Radio de las esquinas convexas | 18px |
--ns-mosaic-radius-in |
Radio de las esquinas cóncavas | el radio + hueco |
--ns-mosaic-radius-out |
Radio de las esquinas del contorno exterior del mosaico | el radio |
Hasta ahora se llamaban
--ns-round,--ns-round-iny--ns-round-out,--ns-orb-roundy--ns-mo-*: siguen funcionando. Los nombres nuevos siguen la convención de toda la librería (--ns-<módulo>-radius,--ns-<módulo>-…-time). |--ns-pad| Padding del contenido de cada pieza |22px|
- Hueco constante: las esquinas cóncavas miden el radio más el hueco, así que una esquina convexa que encaja en una cóncava deja la misma distancia en la curva.
- Responsive con CSS: la plantilla es una variable. Cámbiala con media queries o container queries; al cambiar, las piezas se reubican (y con View Transitions se animan).
- El texto recorre toda la figura: en una pieza que no es un rectángulo (L, T, escalera o mordida por un orbe), el texto fluye línea a línea por todo el contorno real, curvas incluidas, con
--ns-padde margen en cada punto del borde. Se hace conshape-outsidenativo: el motor mide la silueta y coloca unos flotantes invisibles (.ns-fly.ns-fr, conaria-hidden) al principio de la pieza. En este modo la pieza lleva la clase.ns-flowydisplay: flow-root, así que su contenido debe ser de bloque o en línea: un hijo condisplay: flex,griduoverflow: hiddense coloca como un rectángulo entero debajo de los flotantes. Para piezas que maquetas tú (por ejemplo, alineadas abajo con flex), usadata-ns-flow="off"en el mosaico o en la pieza. - Rectángulos: en las piezas rectangulares, y con
data-ns-flow="off", el contenido va en un rectángulo de celdas. Si el mayor no basta, el motor prueba los demás (en una L, el brazo largo y el ancho) y elige el primero donde el contenido cabe entero. Al cargar las fuentes web se vuelve a medir. - Accesible: el orden del DOM no cambia; sólo cambia dónde se dibuja cada pieza.
- Cada hijo necesita
data-ns-area. Un área que no aparece en la plantilla se oculta.
Orbes
--ns-orb: 3 3 96; /* columna, fila, radio: un círculo */
--ns-orb: 3 3 86 hex; /* hexágono (el radio es la apotema) */
--ns-orb: 3 3 70 diamond 15; /* rombo girado 15° */
--ns-orb: 3 3 70 hex, 2 4 44 circle; /* varios, cada uno con su forma */
- La posición va en líneas de la cuadrícula:
1es el borde inicial y3es el hueco entre la columna 2 y la 3. Se admiten decimales. - Formas:
circle,hex,diamond,square,triyoct. - El hueco es concéntrico con el orbe: los lados se desplazan el valor de
--ns-orb-gap(por defecto, el hueco del mosaico) y las esquinas repiten el radio de--ns-orb-cornermás ese hueco. Donde el borde de la pieza se une al hueco hay una curva de enlace de radio--ns-orb-radius. - Cada orbe de la lista se empareja, en orden, con un hijo
[data-ns-orb], que se posiciona y recorta solo. Puede tener contenido: una foto, un dato o un botón. Si sólo es decoración, ponaria-hidden="true".
Luz conectada (data-ns-mosaic)
Efectos que tratan todo el mosaico como una sola figura. Se combinan libremente:
| Valor | Dónde | Qué hace |
|---|---|---|
wave |
bordes y fondos | Ondas que salen del primer orbe (o del centro) y cruzan todas las piezas |
ripple |
bordes y fondos | Una onda nace donde tocas o haces clic |
glow |
bordes y fondos | Una luz sigue al puntero por toda la figura |
sweep |
bordes y fondos | Un barrido diagonal recorre el mosaico |
scan |
bordes y fondos | Una línea horizontal baja por el mosaico |
stream |
bordes | Corriente: tres luces corren por los bordes de las propias piezas y, donde una pieza toca a su vecina, cruzan el hueco y siguen por el borde de la siguiente (también por el anillo de los orbes), en rutas distintas. Cada luz se desvanece en degradado y lleva un foco que enciende los bordes por donde pasa. --ns-mosaic-speed (px/s, 160) |
trace |
bordes | Una luz corta recorre a la vez el contorno de cada pieza |
pulse |
bordes | Todos los bordes respiran juntos |
aurora |
fondos | Dos manchas de color derivan despacio por toda la figura |
dots / grid |
fondos | Puntos o retícula continuos: el patrón no se corta entre piezas |
Ajustes: --ns-mosaic-light (color de la luz), --ns-mosaic-width (grosor en los bordes), --ns-mosaic-fx-time (duración), --ns-mosaic-fill (intensidad sobre los fondos), --ns-mosaic-a1 y --ns-mosaic-a2 (colores de la aurora), --ns-mosaic-dot y --ns-mosaic-line (color de los patrones). (--ns-mosaic-time es otra cosa: la duración de arrange().) Además, --ns-mosaic-glow-size (radio de la luz que sigue al puntero, 240) y --ns-mosaic-ripple-time (duración de la onda al tocar: 1100, 1100ms o 1.1s). Las duraciones y el color cambian al momento; la velocidad de stream y los dos últimos, con refresh().
Los efectos se combinan (data-ns-mosaic="stream dots"), pero cada uno suma trabajo: en una página para móviles, uno o dos. Fuera de la pantalla se pausan solos.
Móvil y escritorio por separado. En pantallas táctiles (hover: none y pointer: coarse) no hay un puntero que flote: glow no tiene a quién seguir y ripple convierte cada toque, que casi siempre es para hacer scroll, en una onda. Por eso en táctil se quitan esos dos por defecto. Para elegir tú qué efectos se ven en táctil, usa data-ns-mosaic-touch (vacío = ninguno):
<div class="ns-mosaic" data-ns-mosaic="glow ripple trace" data-ns-mosaic-touch="trace">
Si el dispositivo cambia de modo (una tableta a la que se conecta un ratón), la lista se vuelve a elegir sola.
- Los bordes y las luces usan una sola capa sobre el mosaico, con los contornos de todas las piezas como máscara (una imagen que se rasteriza al cambiar la figura). La aurora y los patrones van en un
::beforede cada pieza, por detrás del contenido, alineados en coordenadas del mosaico. - Las luces se mueven en el compositor: cada una es una capa que sólo cambia con
transformuopacity, y el resplandor de los bordes son dos filtros CSS (un halo desenfocado y undrop-shadow), no un filtro SVG (bajo el que nada va a la GPU). El trazo libre (trace) es el único que se repinta: un trazo discontinuo que avanza no tiene equivalente ahí. Las animaciones se pausan fuera de pantalla (y siguen donde iban al volver), se desactivan conprefers-reduced-motion, y en alto contraste la capa desaparece. - Las capas animadas sólo se rehacen si cambian la figura o los efectos: un
resizeque no cambia nada (en el móvil, la barra del navegador al subir y bajar) no reinicia las animaciones. - Como
::beforequeda para los fondos compartidos, no combinesaurora,dotsogridcon las clases de patrón dens-fx.cssen la misma pieza.
API
import { refresh, parseAreas } from 'ns-frame/mosaic'
refresh() // recalcula (p. ej. tras cambiar --ns-orb desde JS)
parseAreas("'a a b' 'c d b'") // [['a','a','b'], ['c','d','b']]
Buenas prácticas: entre 5 y 10 piezas, una pieza ancla clara, orbes en cruces de líneas (donde se tocan 3 o 4 piezas) y filas lo bastante altas para que el recorte del orbe no se coma el texto.