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.

CategoriaMídia
TipoWeb Component (<mv-mosaic>)
Statusbeta
Keywordsgallery, 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

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

NameTipoDefaultDescription
variantmosaic | railmosaicmosaic: a grid where the active tile spans 2×2; rail: a strip of expanding panels.
activateclick | hoverclickmosaic: hover also activates the hovered tile after 140 ms (fine pointers; touch still taps).
labelstringAccessible name of the group.
durationnumber640Rearrangement duration (ms), mosaic only.

Properties

NameTipoDescription
activeIndexnumberIndex of the active tile (settable).
itemsElement[]Tiles (direct children, except [data-mv-ignore]).

Methods

NameDescription
select(index, { focus })Activates a tile (mosaic: with an animated rearrangement).

Events

NameDescription
mv-changeActive tile changed. detail: { index, item }.

Content structure

NameDescription
childrenOne tile per child, typically <figure><img alt><figcaption><strong>Title</strong><span>Detail</span></figcaption></figure>. data-active = tile open initially.

CSS classes

NameDescription
mv-mosaic-itemAdded to every tile; data-active marks the chosen tile, data-open the widened rail panel.

CSS variables

NameDefaultDescription
--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.

Esta página foi traduzida com IA. Informar um problema de tradução