Mosaic Gallery <mv-mosaic>
스스로 재배치되는 이미지 모자이크입니다. 선택한 사진이 큰 타일이 되고, 모든 타일이 한 번의 View Transition으로 새 자리로 모핑하며, 늘어나지 않고 잘려서 맞춰집니다.
일시 정지 재생
작동 방식
스스로 재배치되는 이미지 모자이크입니다. 선택한 사진이 큰 타일이 되고, 모든 타일이 한 번의 View Transition으로 새 자리로 모핑하며, 늘어나지 않고 잘려서 맞춰집니다. Rail 변형은 패널이 늘어선 띠로, 호버하거나 포커스한 패널이 넓어지고 이웃 패널은 조금 양보하며 나머지는 좁아집니다.
카테고리 미디어 유형 Web Component (<mv-mosaic>) 상태 안정 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
설치
node scripts/add.mjs mosaic-gallery --out ./src/marvelous
Marvelous UI MCP 서버를 사용하는 AI 에이전트: install_components({ slugs: ["mosaic-gallery"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
복사되는 파일(의존성 포함): 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.
사용법
기본 마크업입니다. 여기서 시작해 속성, data-*, 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 유형 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 유형 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.