beta
Mosaic Gallery <mv-mosaic>
Mosaico de imagens que se reorganiza sozinho: a foto escolhida vira o bloco grande e cada bloco se transforma até o novo lugar em uma única View Transition, recortado em vez de esticado. Variante rail: uma faixa de painéis em que o painel sob o mouse ou com foco se alarga, os vizinhos cedem um pouco e os outros se estreitam.
Categoria Mídia Tipo Web Component (<mv-mosaic>) Status beta Keywords gallery, mosaic, grid, view-transition, layout-animation, rail, accordion, images, expand, keyboard
When to use
An editorial or portfolio grid should enlarge the chosen photo and glide the others to new spots A horizontal strip of image panels should widen the hovered or focused one, like an accordion Projects, destinations or team photos need their captions featured in the active tile
Avoid when
Product views need thumbnails, zoom and fullscreen → use Product Gallery instead The collection has dozens of images; the rearranging motion works best with a small set of tiles
Obtenha Mosaic Gallery. Incluído em todos os planos: o Pro pack traz todos os 317 componentes, com a CLI e o servidor MCP usados abaixo.
Ver planos
Instalação
node scripts/add.mjs mosaic-gallery --out ./src/marvelous
Agente de IA com o servidor MCP do Marvelous UI: install_components({ slugs: ["mosaic-gallery"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Arquivos copiados (dependências incluídas): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/focus.js, core/motion.js, components/mosaic-gallery/mosaic-gallery.js, components/mosaic-gallery/mosaic-gallery.css.
Uso
Marcação de referência, para usar como ponto de partida e personalizar com atributos, data-* e variáveis CSS:
<div id="mv-mosaic-demo">
<style>
#mv-mosaic-demo { display: grid; gap: 2.25rem; width: 100%; max-width: 52rem; }
#mv-mosaic-demo section { display: grid; gap: .75rem; }
#mv-mosaic-demo header { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
#mv-mosaic-demo header strong { font-size: .9375rem; }
#mv-mosaic-demo header small { color: var(--mv-fg-subtle); }
</style>
<section>
<header><strong>Selected projects</strong><small>Click or press Enter on a project to feature it</small></header>
<mv-mosaic label="Selected projects" style="--mv-mosaic-columns: 3; --mv-mosaic-row: 8.5rem">
<figure data-active><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%231b1f4b'/%3E%3Cstop offset='.6' stop-color='%235b4b9a'/%3E%3Cstop offset='1' stop-color='%23f2a37c'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23ffcf8a' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23ffcf8a' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23ffd9a8' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23ffd9a8' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='610' cy='300' r='190' fill='url(%23h)'/%3E%3Ccircle cx='610' cy='300' r='54' fill='%23ffd9a8'/%3E%3Cg fill='%232a2a5c' opacity='.9'%3E%3Crect x='0' y='233' width='40' height='367'/%3E%3Crect x='44' y='354' width='60' height='246'/%3E%3Crect x='108' y='299' width='91' height='301'/%3E%3Crect x='203' y='262' width='63' height='338'/%3E%3Crect x='270' y='298' width='93' height='302'/%3E%3Crect x='367' y='282' width='88' height='318'/%3E%3Crect x='459' y='349' width='97' height='251'/%3E%3Crect x='560' y='270' width='66' height='330'/%3E%3Crect x='630' y='381' width='89' height='219'/%3E%3Crect x='723' y='310' width='88' height='290'/%3E%3C/g%3E%3Cg fill='%23141633'%3E%3Crect x='-10' y='264' width='153' height='336'/%3E%3Crect x='153' y='332' width='81' height='268'/%3E%3Crect x='244' y='292' width='153' height='308'/%3E%3Crect x='407' y='317' width='128' height='283'/%3E%3Crect x='545' y='241' width='152' height='359'/%3E%3Crect x='707' y='373' width='104' height='227'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='264' width='153' height='336'/%3E%3Crect x='153' y='332' width='81' height='268'/%3E%3Crect x='244' y='292' width='153' height='308'/%3E%3Crect x='407' y='317' width='128' height='283'/%3E%3Crect x='545' y='241' width='152' height='359'/%3E%3Crect x='707' y='373' width='104' height='227'/%3E%3C/g%3E%3C/svg%3E" alt="Library with glowing windows at dusk"><figcaption><strong>Harbor Library, Oslo</strong><span>Timber reading rooms over the fjord</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%230c3b4a'/%3E%3Cstop offset='.6' stop-color='%232f8f9d'/%3E%3Cstop offset='1' stop-color='%23c7ecea'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23e8fffb' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23e8fffb' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23f4fffd' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23f4fffd' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='190' cy='170' r='190' fill='url(%23h)'/%3E%3Ccircle cx='190' cy='170' r='54' fill='%23f4fffd'/%3E%3Cg fill='%2319525e' opacity='.9'%3E%3Crect x='0' y='334' width='99' height='266'/%3E%3Crect x='103' y='339' width='51' height='261'/%3E%3Crect x='157' y='340' width='70' height='260'/%3E%3Crect x='231' y='295' width='106' height='305'/%3E%3Crect x='341' y='241' width='91' height='359'/%3E%3Crect x='436' y='344' width='44' height='256'/%3E%3Crect x='484' y='304' width='79' height='296'/%3E%3Crect x='567' y='357' width='70' height='243'/%3E%3Crect x='641' y='381' width='104' height='219'/%3E%3Crect x='748' y='331' width='66' height='269'/%3E%3C/g%3E%3Cg fill='%230b2a33'%3E%3Crect x='-10' y='237' width='130' height='363'/%3E%3Crect x='130' y='412' width='116' height='188'/%3E%3Crect x='256' y='385' width='107' height='215'/%3E%3Crect x='373' y='352' width='103' height='248'/%3E%3Crect x='485' y='328' width='100' height='272'/%3E%3Crect x='595' y='396' width='125' height='204'/%3E%3Crect x='731' y='345' width='152' height='255'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='237' width='130' height='363'/%3E%3Crect x='130' y='412' width='116' height='188'/%3E%3Crect x='256' y='385' width='107' height='215'/%3E%3Crect x='373' y='352' width='103' height='248'/%3E%3Crect x='485' y='328' width='100' height='272'/%3E%3Crect x='595' y='396' width='125' height='204'/%3E%3Crect x='731' y='345' width='152' height='255'/%3E%3C/g%3E%3C/svg%3E" alt="Apartment towers in teal evening light"><figcaption><strong>Tide House, Lisbon</strong><span>Six floors of shared housing by the river</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%233a1631'/%3E%3Cstop offset='.6' stop-color='%23b04a5a'/%3E%3Cstop offset='1' stop-color='%23f7c59f'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23ffe0a3' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23ffe0a3' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23fff0d6' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23fff0d6' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='420' cy='340' r='190' fill='url(%23h)'/%3E%3Ccircle cx='420' cy='340' r='54' fill='%23fff0d6'/%3E%3Cg fill='%235e2440' opacity='.9'%3E%3Crect x='0' y='282' width='100' height='318'/%3E%3Crect x='104' y='302' width='84' height='298'/%3E%3Crect x='193' y='273' width='75' height='327'/%3E%3Crect x='272' y='323' width='106' height='277'/%3E%3Crect x='382' y='347' width='90' height='253'/%3E%3Crect x='476' y='330' width='81' height='270'/%3E%3Crect x='561' y='323' width='63' height='277'/%3E%3Crect x='628' y='241' width='96' height='359'/%3E%3Crect x='727' y='251' width='48' height='349'/%3E%3Crect x='779' y='321' width='45' height='279'/%3E%3C/g%3E%3Cg fill='%2324101f'%3E%3Crect x='-10' y='432' width='84' height='168'/%3E%3Crect x='84' y='399' width='160' height='201'/%3E%3Crect x='253' y='417' width='127' height='183'/%3E%3Crect x='390' y='314' width='111' height='286'/%3E%3Crect x='512' y='238' width='82' height='362'/%3E%3Crect x='604' y='245' width='150' height='355'/%3E%3Crect x='764' y='241' width='150' height='359'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='432' width='84' height='168'/%3E%3Crect x='84' y='399' width='160' height='201'/%3E%3Crect x='253' y='417' width='127' height='183'/%3E%3Crect x='390' y='314' width='111' height='286'/%3E%3Crect x='512' y='238' width='82' height='362'/%3E%3Crect x='604' y='245' width='150' height='355'/%3E%3Crect x='764' y='241' width='150' height='359'/%3E%3C/g%3E%3C/svg%3E" alt="Market halls in a pink sunset"><figcaption><strong>Rose Market, Marrakech</strong><span>A covered market for 140 stalls</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%2310233f'/%3E%3Cstop offset='.6' stop-color='%23355c8c'/%3E%3Cstop offset='1' stop-color='%239ec1e6'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23bfe0ff' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23bfe0ff' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23eaf4ff' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23eaf4ff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='640' cy='150' r='190' fill='url(%23h)'/%3E%3Ccircle cx='640' cy='150' r='54' fill='%23eaf4ff'/%3E%3Cg fill='%231d3657' opacity='.9'%3E%3Crect x='0' y='343' width='93' height='257'/%3E%3Crect x='97' y='348' width='41' height='252'/%3E%3Crect x='142' y='390' width='45' height='210'/%3E%3Crect x='191' y='351' width='83' height='249'/%3E%3Crect x='279' y='307' width='92' height='293'/%3E%3Crect x='374' y='350' width='88' height='250'/%3E%3Crect x='467' y='350' width='102' height='250'/%3E%3Crect x='572' y='238' width='66' height='362'/%3E%3Crect x='642' y='307' width='48' height='293'/%3E%3Crect x='695' y='235' width='40' height='365'/%3E%3Crect x='739' y='233' width='85' height='367'/%3E%3C/g%3E%3Cg fill='%230a1629'%3E%3Crect x='-10' y='243' width='72' height='357'/%3E%3Crect x='72' y='227' width='87' height='373'/%3E%3Crect x='169' y='294' width='121' height='306'/%3E%3Crect x='300' y='399' width='94' height='201'/%3E%3Crect x='404' y='320' width='89' height='280'/%3E%3Crect x='502' y='273' width='75' height='327'/%3E%3Crect x='587' y='286' width='133' height='314'/%3E%3Crect x='730' y='442' width='115' height='158'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='243' width='72' height='357'/%3E%3Crect x='72' y='227' width='87' height='373'/%3E%3Crect x='169' y='294' width='121' height='306'/%3E%3Crect x='300' y='399' width='94' height='201'/%3E%3Crect x='404' y='320' width='89' height='280'/%3E%3Crect x='502' y='273' width='75' height='327'/%3E%3Crect x='587' y='286' width='133' height='314'/%3E%3Crect x='730' y='442' width='115' height='158'/%3E%3C/g%3E%3C/svg%3E" alt="Office towers under a pale blue sky"><figcaption><strong>North Pier Offices, Toronto</strong><span>Offices wrapped in cold-rolled glass</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%232b2410'/%3E%3Cstop offset='.6' stop-color='%238c6a2f'/%3E%3Cstop offset='1' stop-color='%23f3d58a'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23ffe6a0' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23ffe6a0' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23fff5d1' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23fff5d1' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='260' cy='280' r='190' fill='url(%23h)'/%3E%3Ccircle cx='260' cy='280' r='54' fill='%23fff5d1'/%3E%3Cg fill='%234a3a17' opacity='.9'%3E%3Crect x='0' y='234' width='48' height='366'/%3E%3Crect x='52' y='273' width='49' height='327'/%3E%3Crect x='105' y='384' width='103' height='216'/%3E%3Crect x='211' y='244' width='102' height='356'/%3E%3Crect x='317' y='228' width='109' height='372'/%3E%3Crect x='431' y='319' width='94' height='281'/%3E%3Crect x='528' y='266' width='57' height='334'/%3E%3Crect x='590' y='322' width='102' height='278'/%3E%3Crect x='695' y='321' width='56' height='279'/%3E%3Crect x='756' y='295' width='102' height='305'/%3E%3C/g%3E%3Cg fill='%231c170a'%3E%3Crect x='-10' y='307' width='102' height='293'/%3E%3Crect x='102' y='373' width='136' height='227'/%3E%3Crect x='248' y='353' width='135' height='247'/%3E%3Crect x='393' y='378' width='88' height='222'/%3E%3Crect x='491' y='221' width='159' height='379'/%3E%3Crect x='660' y='249' width='127' height='351'/%3E%3Crect x='797' y='404' width='153' height='196'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='307' width='102' height='293'/%3E%3Crect x='102' y='373' width='136' height='227'/%3E%3Crect x='248' y='353' width='135' height='247'/%3E%3Crect x='393' y='378' width='88' height='222'/%3E%3Crect x='491' y='221' width='159' height='379'/%3E%3Crect x='660' y='249' width='127' height='351'/%3E%3Crect x='797' y='404' width='153' height='196'/%3E%3C/g%3E%3C/svg%3E" alt="Hotel blocks in golden desert light"><figcaption><strong>Sand Court, Dubai</strong><span>Courtyard hotel with shaded terraces</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%231f1236'/%3E%3Cstop offset='.6' stop-color='%236a3d8f'/%3E%3Cstop offset='1' stop-color='%23e7a6c8'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23ffd1ea' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23ffd1ea' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23ffe3f2' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23ffe3f2' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='540' cy='220' r='190' fill='url(%23h)'/%3E%3Ccircle cx='540' cy='220' r='54' fill='%23ffe3f2'/%3E%3Cg fill='%233a2257' opacity='.9'%3E%3Crect x='0' y='367' width='85' height='233'/%3E%3Crect x='89' y='295' width='75' height='305'/%3E%3Crect x='168' y='229' width='94' height='371'/%3E%3Crect x='266' y='358' width='74' height='242'/%3E%3Crect x='344' y='362' width='71' height='238'/%3E%3Crect x='419' y='301' width='86' height='299'/%3E%3Crect x='509' y='304' width='79' height='296'/%3E%3Crect x='593' y='328' width='93' height='272'/%3E%3Crect x='690' y='386' width='93' height='214'/%3E%3Crect x='786' y='298' width='61' height='302'/%3E%3C/g%3E%3Cg fill='%23140b24'%3E%3Crect x='-10' y='284' width='88' height='316'/%3E%3Crect x='88' y='396' width='96' height='204'/%3E%3Crect x='194' y='351' width='129' height='249'/%3E%3Crect x='334' y='272' width='77' height='328'/%3E%3Crect x='421' y='239' width='144' height='361'/%3E%3Crect x='575' y='293' width='152' height='307'/%3E%3Crect x='737' y='444' width='156' height='156'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='284' width='88' height='316'/%3E%3Crect x='88' y='396' width='96' height='204'/%3E%3Crect x='194' y='351' width='129' height='249'/%3E%3Crect x='334' y='272' width='77' height='328'/%3E%3Crect x='421' y='239' width='144' height='361'/%3E%3Crect x='575' y='293' width='152' height='307'/%3E%3Crect x='737' y='444' width='156' height='156'/%3E%3C/g%3E%3C/svg%3E" alt="School buildings under a violet sky"><figcaption><strong>Lantern School, Seoul</strong><span>A primary school lit from within</span></figcaption></figure>
</mv-mosaic>
</section>
<section>
<header><strong>Studios</strong><small>variant="rail": hover, focus or use the arrow keys</small></header>
<mv-mosaic variant="rail" label="Studios" style="--mv-mosaic-rail-height: 16rem">
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%2310233f'/%3E%3Cstop offset='.6' stop-color='%23355c8c'/%3E%3Cstop offset='1' stop-color='%239ec1e6'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23bfe0ff' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23bfe0ff' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23eaf4ff' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23eaf4ff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='640' cy='150' r='190' fill='url(%23h)'/%3E%3Ccircle cx='640' cy='150' r='54' fill='%23eaf4ff'/%3E%3Cg fill='%231d3657' opacity='.9'%3E%3Crect x='0' y='343' width='93' height='257'/%3E%3Crect x='97' y='348' width='41' height='252'/%3E%3Crect x='142' y='390' width='45' height='210'/%3E%3Crect x='191' y='351' width='83' height='249'/%3E%3Crect x='279' y='307' width='92' height='293'/%3E%3Crect x='374' y='350' width='88' height='250'/%3E%3Crect x='467' y='350' width='102' height='250'/%3E%3Crect x='572' y='238' width='66' height='362'/%3E%3Crect x='642' y='307' width='48' height='293'/%3E%3Crect x='695' y='235' width='40' height='365'/%3E%3Crect x='739' y='233' width='85' height='367'/%3E%3C/g%3E%3Cg fill='%230a1629'%3E%3Crect x='-10' y='243' width='72' height='357'/%3E%3Crect x='72' y='227' width='87' height='373'/%3E%3Crect x='169' y='294' width='121' height='306'/%3E%3Crect x='300' y='399' width='94' height='201'/%3E%3Crect x='404' y='320' width='89' height='280'/%3E%3Crect x='502' y='273' width='75' height='327'/%3E%3Crect x='587' y='286' width='133' height='314'/%3E%3Crect x='730' y='442' width='115' height='158'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='243' width='72' height='357'/%3E%3Crect x='72' y='227' width='87' height='373'/%3E%3Crect x='169' y='294' width='121' height='306'/%3E%3Crect x='300' y='399' width='94' height='201'/%3E%3Crect x='404' y='320' width='89' height='280'/%3E%3Crect x='502' y='273' width='75' height='327'/%3E%3Crect x='587' y='286' width='133' height='314'/%3E%3Crect x='730' y='442' width='115' height='158'/%3E%3C/g%3E%3C/svg%3E" alt="Office towers under a pale blue sky"><figcaption><strong>North Pier Offices, Toronto</strong><span>Offices wrapped in cold-rolled glass</span></figcaption></figure>
<figure data-active><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%230c3b4a'/%3E%3Cstop offset='.6' stop-color='%232f8f9d'/%3E%3Cstop offset='1' stop-color='%23c7ecea'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23e8fffb' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23e8fffb' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23f4fffd' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23f4fffd' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='190' cy='170' r='190' fill='url(%23h)'/%3E%3Ccircle cx='190' cy='170' r='54' fill='%23f4fffd'/%3E%3Cg fill='%2319525e' opacity='.9'%3E%3Crect x='0' y='334' width='99' height='266'/%3E%3Crect x='103' y='339' width='51' height='261'/%3E%3Crect x='157' y='340' width='70' height='260'/%3E%3Crect x='231' y='295' width='106' height='305'/%3E%3Crect x='341' y='241' width='91' height='359'/%3E%3Crect x='436' y='344' width='44' height='256'/%3E%3Crect x='484' y='304' width='79' height='296'/%3E%3Crect x='567' y='357' width='70' height='243'/%3E%3Crect x='641' y='381' width='104' height='219'/%3E%3Crect x='748' y='331' width='66' height='269'/%3E%3C/g%3E%3Cg fill='%230b2a33'%3E%3Crect x='-10' y='237' width='130' height='363'/%3E%3Crect x='130' y='412' width='116' height='188'/%3E%3Crect x='256' y='385' width='107' height='215'/%3E%3Crect x='373' y='352' width='103' height='248'/%3E%3Crect x='485' y='328' width='100' height='272'/%3E%3Crect x='595' y='396' width='125' height='204'/%3E%3Crect x='731' y='345' width='152' height='255'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='237' width='130' height='363'/%3E%3Crect x='130' y='412' width='116' height='188'/%3E%3Crect x='256' y='385' width='107' height='215'/%3E%3Crect x='373' y='352' width='103' height='248'/%3E%3Crect x='485' y='328' width='100' height='272'/%3E%3Crect x='595' y='396' width='125' height='204'/%3E%3Crect x='731' y='345' width='152' height='255'/%3E%3C/g%3E%3C/svg%3E" alt="Apartment towers in teal evening light"><figcaption><strong>Tide House, Lisbon</strong><span>Six floors of shared housing by the river</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%231f1236'/%3E%3Cstop offset='.6' stop-color='%236a3d8f'/%3E%3Cstop offset='1' stop-color='%23e7a6c8'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23ffd1ea' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23ffd1ea' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23ffe3f2' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23ffe3f2' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='540' cy='220' r='190' fill='url(%23h)'/%3E%3Ccircle cx='540' cy='220' r='54' fill='%23ffe3f2'/%3E%3Cg fill='%233a2257' opacity='.9'%3E%3Crect x='0' y='367' width='85' height='233'/%3E%3Crect x='89' y='295' width='75' height='305'/%3E%3Crect x='168' y='229' width='94' height='371'/%3E%3Crect x='266' y='358' width='74' height='242'/%3E%3Crect x='344' y='362' width='71' height='238'/%3E%3Crect x='419' y='301' width='86' height='299'/%3E%3Crect x='509' y='304' width='79' height='296'/%3E%3Crect x='593' y='328' width='93' height='272'/%3E%3Crect x='690' y='386' width='93' height='214'/%3E%3Crect x='786' y='298' width='61' height='302'/%3E%3C/g%3E%3Cg fill='%23140b24'%3E%3Crect x='-10' y='284' width='88' height='316'/%3E%3Crect x='88' y='396' width='96' height='204'/%3E%3Crect x='194' y='351' width='129' height='249'/%3E%3Crect x='334' y='272' width='77' height='328'/%3E%3Crect x='421' y='239' width='144' height='361'/%3E%3Crect x='575' y='293' width='152' height='307'/%3E%3Crect x='737' y='444' width='156' height='156'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='284' width='88' height='316'/%3E%3Crect x='88' y='396' width='96' height='204'/%3E%3Crect x='194' y='351' width='129' height='249'/%3E%3Crect x='334' y='272' width='77' height='328'/%3E%3Crect x='421' y='239' width='144' height='361'/%3E%3Crect x='575' y='293' width='152' height='307'/%3E%3Crect x='737' y='444' width='156' height='156'/%3E%3C/g%3E%3C/svg%3E" alt="School buildings under a violet sky"><figcaption><strong>Lantern School, Seoul</strong><span>A primary school lit from within</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%233a1631'/%3E%3Cstop offset='.6' stop-color='%23b04a5a'/%3E%3Cstop offset='1' stop-color='%23f7c59f'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23ffe0a3' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23ffe0a3' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23fff0d6' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23fff0d6' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='420' cy='340' r='190' fill='url(%23h)'/%3E%3Ccircle cx='420' cy='340' r='54' fill='%23fff0d6'/%3E%3Cg fill='%235e2440' opacity='.9'%3E%3Crect x='0' y='282' width='100' height='318'/%3E%3Crect x='104' y='302' width='84' height='298'/%3E%3Crect x='193' y='273' width='75' height='327'/%3E%3Crect x='272' y='323' width='106' height='277'/%3E%3Crect x='382' y='347' width='90' height='253'/%3E%3Crect x='476' y='330' width='81' height='270'/%3E%3Crect x='561' y='323' width='63' height='277'/%3E%3Crect x='628' y='241' width='96' height='359'/%3E%3Crect x='727' y='251' width='48' height='349'/%3E%3Crect x='779' y='321' width='45' height='279'/%3E%3C/g%3E%3Cg fill='%2324101f'%3E%3Crect x='-10' y='432' width='84' height='168'/%3E%3Crect x='84' y='399' width='160' height='201'/%3E%3Crect x='253' y='417' width='127' height='183'/%3E%3Crect x='390' y='314' width='111' height='286'/%3E%3Crect x='512' y='238' width='82' height='362'/%3E%3Crect x='604' y='245' width='150' height='355'/%3E%3Crect x='764' y='241' width='150' height='359'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='432' width='84' height='168'/%3E%3Crect x='84' y='399' width='160' height='201'/%3E%3Crect x='253' y='417' width='127' height='183'/%3E%3Crect x='390' y='314' width='111' height='286'/%3E%3Crect x='512' y='238' width='82' height='362'/%3E%3Crect x='604' y='245' width='150' height='355'/%3E%3Crect x='764' y='241' width='150' height='359'/%3E%3C/g%3E%3C/svg%3E" alt="Market halls in a pink sunset"><figcaption><strong>Rose Market, Marrakech</strong><span>A covered market for 140 stalls</span></figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 600' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='k' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%232b2410'/%3E%3Cstop offset='.6' stop-color='%238c6a2f'/%3E%3Cstop offset='1' stop-color='%23f3d58a'/%3E%3C/linearGradient%3E%3Cpattern id='w' width='36' height='44' patternUnits='userSpaceOnUse'%3E%3Crect x='8' y='10' width='8' height='11' fill='%23ffe6a0' opacity='.8'/%3E%3Crect x='22' y='32' width='8' height='11' fill='%23ffe6a0' opacity='.45'/%3E%3C/pattern%3E%3CradialGradient id='h'%3E%3Cstop offset='0' stop-color='%23fff5d1' stop-opacity='.85'/%3E%3Cstop offset='1' stop-color='%23fff5d1' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='800' height='600' fill='url(%23k)'/%3E%3Ccircle cx='260' cy='280' r='190' fill='url(%23h)'/%3E%3Ccircle cx='260' cy='280' r='54' fill='%23fff5d1'/%3E%3Cg fill='%234a3a17' opacity='.9'%3E%3Crect x='0' y='234' width='48' height='366'/%3E%3Crect x='52' y='273' width='49' height='327'/%3E%3Crect x='105' y='384' width='103' height='216'/%3E%3Crect x='211' y='244' width='102' height='356'/%3E%3Crect x='317' y='228' width='109' height='372'/%3E%3Crect x='431' y='319' width='94' height='281'/%3E%3Crect x='528' y='266' width='57' height='334'/%3E%3Crect x='590' y='322' width='102' height='278'/%3E%3Crect x='695' y='321' width='56' height='279'/%3E%3Crect x='756' y='295' width='102' height='305'/%3E%3C/g%3E%3Cg fill='%231c170a'%3E%3Crect x='-10' y='307' width='102' height='293'/%3E%3Crect x='102' y='373' width='136' height='227'/%3E%3Crect x='248' y='353' width='135' height='247'/%3E%3Crect x='393' y='378' width='88' height='222'/%3E%3Crect x='491' y='221' width='159' height='379'/%3E%3Crect x='660' y='249' width='127' height='351'/%3E%3Crect x='797' y='404' width='153' height='196'/%3E%3C/g%3E%3Cg fill='url(%23w)'%3E%3Crect x='-10' y='307' width='102' height='293'/%3E%3Crect x='102' y='373' width='136' height='227'/%3E%3Crect x='248' y='353' width='135' height='247'/%3E%3Crect x='393' y='378' width='88' height='222'/%3E%3Crect x='491' y='221' width='159' height='379'/%3E%3Crect x='660' y='249' width='127' height='351'/%3E%3Crect x='797' y='404' width='153' height='196'/%3E%3C/g%3E%3C/svg%3E" alt="Hotel blocks in golden desert light"><figcaption><strong>Sand Court, Dubai</strong><span>Courtyard hotel with shaded terraces</span></figcaption></figure>
</mv-mosaic>
</section>
</div>
API
Attributes
Name Tipo Default Description variantmosaic | rail mosaicmosaic: a grid where the active tile spans 2×2; rail: a strip of expanding panels. activateclick | hover clickmosaic: hover also activates the hovered tile after 140 ms (fine pointers; touch still taps). labelstring Accessible name of the group. durationnumber 640Rearrangement duration (ms), mosaic only.
Properties
Name Tipo Description activeIndexnumber Index of the active tile (settable). itemsElement[] Tiles (direct children, except [data-mv-ignore]).
Methods
Name Description select(index, { focus })Activates a tile (mosaic: with an animated rearrangement).
Events
Name Description mv-changeActive tile changed. detail: { index, item }.
Content structure
Name Description childrenOne tile per child, typically <figure><img alt><figcaption><strong>Title</strong><span>Detail</span></figcaption></figure>. data-active = tile open initially.
CSS classes
Name Description mv-mosaic-itemAdded to every tile; data-active marks the chosen tile, data-open the widened rail panel.
CSS variables
Name Default Description --mv-mosaic-columns4Mosaic columns (the active tile spans 2). --mv-mosaic-row8.5remRow height. --mv-mosaic-gapvar(--mv-space-2)Gap. --mv-mosaic-radius14pxTile corner radius, kept during the morph. --mv-mosaic-rail-height22remrail: strip height. --mv-mosaic-grow5rail: grow factor of the open panel (neighbours take 14% of the extra). --mv-mosaic-scrim / --mv-mosaic-caption-coloroklch(0.16 0.02 280 / 0.74) / oklch(0.99 0 0)Caption gradient and text color over the photos.
Accessibility
Named role="group"; each tile is a role="button" with aria-pressed (active tile) and a name taken from its caption, else its image alt. Roving tabindex: one tile in the tab order, arrow keys in visual order (the large tile first), Home/End, Enter/Space to activate. Links inside the active tile work normally. In rail, keyboard focus widens a panel like hover, and arrow keys also activate it. The morph only captures the tiles: the rest of the page stays live and clickable. Reduced motion (OS setting or data-motion="reduce") or no View Transitions: the grid rearranges at once. Forced colors: tiles outlined, active tile in Highlight, captions on Canvas.