Media and files
Media gallery
A grid of thumbnails with selection (Shift click selects a range, Escape clears), select all, delete, drag or Alt and arrow keys to reorder, and the image viewer on click. It needs monsoon.js. Without it the links open the images and the checkboxes submit with the form.
Needs monsoon.js. The styles work on their own, and the behavior comes from the optional interactive layer: add <script src="https://cdn.jsdelivr.net/npm/monsooncss/dist/monsoon.js" defer></script> or import 'monsooncss/js'. See the interactive layer.
Example
<div class="gallery max-w-2xl" data-m-media-gallery><ul class="gallery-list"><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fdba74'/%3E%3Cstop%20offset='1'%20stop-color='%23f472b6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fff7d6'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%237c3aed'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%233b0764'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%231e1b4b'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Lake Aurel, just after sunset"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fdba74'/%3E%3Cstop%20offset='1'%20stop-color='%23f472b6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fff7d6'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%237c3aed'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%233b0764'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%231e1b4b'%20opacity='.85'/%3E%3C/svg%3E" alt="Violet ridges at dusk"></a><label class="gallery-check"><input type="checkbox" name="media" value="1" aria-label="Select violet ridges at dusk"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%237dd3fc'/%3E%3Cstop%20offset='1'%20stop-color='%23e0f2fe'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fef9c3'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%230ea5e9'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%230369a1'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%230c4a6e'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Morning over the bay"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%237dd3fc'/%3E%3Cstop%20offset='1'%20stop-color='%23e0f2fe'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fef9c3'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%230ea5e9'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%230369a1'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%230c4a6e'%20opacity='.85'/%3E%3C/svg%3E" alt="Blue bay under a pale sky"></a><label class="gallery-check"><input type="checkbox" name="media" value="2" aria-label="Select blue bay under a pale sky"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='900'%20viewBox='0%200%201200%20900'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23bbf7d0'/%3E%3Cstop%20offset='1'%20stop-color='%23fef3c7'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='900'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='306'%20r='99'%20fill='%23fde68a'/%3E%3Cpath%20d='M0%20558L240%20378L456%20522L720%20324L1200%20594V900H0Z'%20fill='%2315803d'/%3E%3Cpath%20d='M0%20666L336%20504L624%20648L936%20540L1200%20684V900H0Z'%20fill='%2314532d'/%3E%3Crect%20y='756'%20width='1200'%20height='144'%20fill='%23052e16'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Pine valley in late summer"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='900'%20viewBox='0%200%201200%20900'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23bbf7d0'/%3E%3Cstop%20offset='1'%20stop-color='%23fef3c7'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='900'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='306'%20r='99'%20fill='%23fde68a'/%3E%3Cpath%20d='M0%20558L240%20378L456%20522L720%20324L1200%20594V900H0Z'%20fill='%2315803d'/%3E%3Cpath%20d='M0%20666L336%20504L624%20648L936%20540L1200%20684V900H0Z'%20fill='%2314532d'/%3E%3Crect%20y='756'%20width='1200'%20height='144'%20fill='%23052e16'%20opacity='.85'/%3E%3C/svg%3E" alt="Green hills and a golden sky"></a><label class="gallery-check"><input type="checkbox" name="media" value="3" aria-label="Select green hills and a golden sky"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='900'%20height='1200'%20viewBox='0%200%20900%201200'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fde68a'/%3E%3Cstop%20offset='1'%20stop-color='%23fb923c'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='900'%20height='1200'%20fill='url(%23s)'/%3E%3Ccircle%20cx='630'%20cy='408'%20r='99'%20fill='%23fffbeb'/%3E%3Cpath%20d='M0%20744L180%20504L342%20696L540%20432L900%20792V1200H0Z'%20fill='%23c2410c'/%3E%3Cpath%20d='M0%20888L252%20672L468%20864L702%20720L900%20912V1200H0Z'%20fill='%237c2d12'/%3E%3Crect%20y='1008'%20width='900'%20height='192'%20fill='%23431407'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Dunes at noon, shot in portrait"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='900'%20height='1200'%20viewBox='0%200%20900%201200'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fde68a'/%3E%3Cstop%20offset='1'%20stop-color='%23fb923c'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='900'%20height='1200'%20fill='url(%23s)'/%3E%3Ccircle%20cx='630'%20cy='408'%20r='99'%20fill='%23fffbeb'/%3E%3Cpath%20d='M0%20744L180%20504L342%20696L540%20432L900%20792V1200H0Z'%20fill='%23c2410c'/%3E%3Cpath%20d='M0%20888L252%20672L468%20864L702%20720L900%20912V1200H0Z'%20fill='%237c2d12'/%3E%3Crect%20y='1008'%20width='900'%20height='192'%20fill='%23431407'%20opacity='.85'/%3E%3C/svg%3E" alt="Orange dunes in tall format"></a><label class="gallery-check"><input type="checkbox" name="media" value="4" aria-label="Select orange dunes in tall format"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='700'%20viewBox='0%200%201200%20700'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%231e1b4b'/%3E%3Cstop%20offset='1'%20stop-color='%236d28d9'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='700'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='238'%20r='77'%20fill='%23e0e7ff'/%3E%3Cpath%20d='M0%20434L240%20294L456%20406L720%20252L1200%20462V700H0Z'%20fill='%23312e81'/%3E%3Cpath%20d='M0%20518L336%20392L624%20504L936%20420L1200%20532V700H0Z'%20fill='%230f172a'/%3E%3Crect%20y='588'%20width='1200'%20height='112'%20fill='%23020617'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Moonrise over the pass"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='700'%20viewBox='0%200%201200%20700'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%231e1b4b'/%3E%3Cstop%20offset='1'%20stop-color='%236d28d9'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='700'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='238'%20r='77'%20fill='%23e0e7ff'/%3E%3Cpath%20d='M0%20434L240%20294L456%20406L720%20252L1200%20462V700H0Z'%20fill='%23312e81'/%3E%3Cpath%20d='M0%20518L336%20392L624%20504L936%20420L1200%20532V700H0Z'%20fill='%230f172a'/%3E%3Crect%20y='588'%20width='1200'%20height='112'%20fill='%23020617'%20opacity='.85'/%3E%3C/svg%3E" alt="Purple night sky over dark hills"></a><label class="gallery-check"><input type="checkbox" name="media" value="5" aria-label="Select purple night sky over dark hills"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1000'%20height='1000'%20viewBox='0%200%201000%201000'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23e0e7ff'/%3E%3Cstop%20offset='1'%20stop-color='%23f8fafc'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1000'%20height='1000'%20fill='url(%23s)'/%3E%3Ccircle%20cx='700'%20cy='340'%20r='110'%20fill='%23fef3c7'/%3E%3Cpath%20d='M0%20620L200%20420L380%20580L600%20360L1000%20660V1000H0Z'%20fill='%2394a3b8'/%3E%3Cpath%20d='M0%20740L280%20560L520%20720L780%20600L1000%20760V1000H0Z'%20fill='%23475569'/%3E%3Crect%20y='840'%20width='1000'%20height='160'%20fill='%231e293b'%20opacity='.85'/%3E%3C/svg%3E" data-caption="First snow on the ridge"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1000'%20height='1000'%20viewBox='0%200%201000%201000'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23e0e7ff'/%3E%3Cstop%20offset='1'%20stop-color='%23f8fafc'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1000'%20height='1000'%20fill='url(%23s)'/%3E%3Ccircle%20cx='700'%20cy='340'%20r='110'%20fill='%23fef3c7'/%3E%3Cpath%20d='M0%20620L200%20420L380%20580L600%20360L1000%20660V1000H0Z'%20fill='%2394a3b8'/%3E%3Cpath%20d='M0%20740L280%20560L520%20720L780%20600L1000%20760V1000H0Z'%20fill='%23475569'/%3E%3Crect%20y='840'%20width='1000'%20height='160'%20fill='%231e293b'%20opacity='.85'/%3E%3C/svg%3E" alt="Grey peaks in soft light"></a><label class="gallery-check"><input type="checkbox" name="media" value="6" aria-label="Select grey peaks in soft light"></label></li></ul></div>JavaScript API
Attribute
data-m-media-gallery on a .gallery with a ul.gallery-list of li.gallery-item
Options
| Option | Description |
|---|---|
data-m-media-gallery-viewer | false turns off the image viewer. |
data-m-media-gallery-loop | Passed to the viewer. |
data-m-media-gallery-thumbs | Passed to the viewer. |
Methods
| Method | Description |
|---|---|
Monsoon.mediaGallery(el).selected | The selected items. |
Monsoon.mediaGallery(el).values | Values of the selected checkboxes. |
Monsoon.mediaGallery(el).selectAll() and clear() | Changes the selection. |
Monsoon.mediaGallery(el).delete() | Deletes the selected items. |
Monsoon.mediaGallery(el).viewer | The image viewer API. |
Events
| Event | Description |
|---|---|
monsoon:gallery-select | detail.items and detail.values |
monsoon:gallery-delete | Cancelable, detail.items and detail.values; call preventDefault() to keep them. |
monsoon:gallery-reorder | detail.from, detail.to and detail.order (values in the new order). |
Keyboard
Space on a checkbox selects, Shift click selects a range, Ctrl or Cmd click on a picture selects, Delete removes the selection, Alt and arrows move a picture, Escape clears.
Classes
8 classes. Click a name to copy it. Utilities on the same element always win over component defaults, so any of them can be adjusted with plain utility classes.
| Class | Type | What it does |
|---|---|---|
| Base | Base class of the media gallery. On a <div> in the example. Sets grid display, gap, width, border, background and text color, and 4 custom properties.CSS |
|
| Modifier | Modifier, combined with the gallery class. Not used in the example above. Sets flex display, alignment, gap, height, padding and border.CSS |
|
| Modifier | Modifier, combined with the gallery class. Not used in the example above. Sets text color, text size and font weight.CSS |
|
| Modifier | Modifier, combined with the gallery class. Not used in the example above. Sets flex display, alignment and gap.CSS |
|
| Part | Part of the media gallery. On an <ul> in the example. Sets grid display, grid tracks, gap, margin, padding and transform.CSS |
|
| Part | Part of the media gallery. On a <li> in the example. Sets overflow, corner radius, background, shadow, transition and block display.CSS |
|
| Part | Part of the media gallery. On a <label> in the example. Sets absolute position, offsets, grid display, alignment, width and height.CSS |
|
| Modifier | Modifier, combined with the gallery class. Not used in the example above. Sets absolute position, offsets, padding, background, text color and text size.CSS |
Usage
The styles ship inside the same stylesheet as the utilities, and the behavior comes from the optional monsoon.js script, which enhances any element with a matching data-m attribute, including markup added later.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/monsooncss">
<script src="https://cdn.jsdelivr.net/npm/monsooncss/dist/monsoon.js" defer></script>
<!-- Media gallery: start from the base class, then add modifiers -->
<div class="gallery max-w-2xl" data-m-media-gallery><ul class="gallery-list"><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fdba74'/%3E%3Cstop%20offset='1'%20stop-color='%23f472b6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fff7d6'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%237c3aed'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%233b0764'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%231e1b4b'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Lake Aurel, just after sunset"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fdba74'/%3E%3Cstop%20offset='1'%20stop-color='%23f472b6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fff7d6'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%237c3aed'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%233b0764'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%231e1b4b'%20opacity='.85'/%3E%3C/svg%3E" alt="Violet ridges at dusk"></a><label class="gallery-check"><input type="checkbox" name="media" value="1" aria-label="Select violet ridges at dusk"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%237dd3fc'/%3E%3Cstop%20offset='1'%20stop-color='%23e0f2fe'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fef9c3'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%230ea5e9'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%230369a1'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%230c4a6e'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Morning over the bay"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%237dd3fc'/%3E%3Cstop%20offset='1'%20stop-color='%23e0f2fe'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fef9c3'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%230ea5e9'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%230369a1'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%230c4a6e'%20opacity='.85'/%3E%3C/svg%3E" alt="Blue bay under a pale sky"></a><label class="gallery-check"><input type="checkbox" name="media" value="2" aria-label="Select blue bay under a pale sky"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='900'%20viewBox='0%200%201200%20900'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23bbf7d0'/%3E%3Cstop%20offset='1'%20stop-color='%23fef3c7'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='900'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='306'%20r='99'%20fill='%23fde68a'/%3E%3Cpath%20d='M0%20558L240%20378L456%20522L720%20324L1200%20594V900H0Z'%20fill='%2315803d'/%3E%3Cpath%20d='M0%20666L336%20504L624%20648L936%20540L1200%20684V900H0Z'%20fill='%2314532d'/%3E%3Crect%20y='756'%20width='1200'%20height='144'%20fill='%23052e16'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Pine valley in late summer"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='900'%20viewBox='0%200%201200%20900'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23bbf7d0'/%3E%3Cstop%20offset='1'%20stop-color='%23fef3c7'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='900'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='306'%20r='99'%20fill='%23fde68a'/%3E%3Cpath%20d='M0%20558L240%20378L456%20522L720%20324L1200%20594V900H0Z'%20fill='%2315803d'/%3E%3Cpath%20d='M0%20666L336%20504L624%20648L936%20540L1200%20684V900H0Z'%20fill='%2314532d'/%3E%3Crect%20y='756'%20width='1200'%20height='144'%20fill='%23052e16'%20opacity='.85'/%3E%3C/svg%3E" alt="Green hills and a golden sky"></a><label class="gallery-check"><input type="checkbox" name="media" value="3" aria-label="Select green hills and a golden sky"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='900'%20height='1200'%20viewBox='0%200%20900%201200'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fde68a'/%3E%3Cstop%20offset='1'%20stop-color='%23fb923c'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='900'%20height='1200'%20fill='url(%23s)'/%3E%3Ccircle%20cx='630'%20cy='408'%20r='99'%20fill='%23fffbeb'/%3E%3Cpath%20d='M0%20744L180%20504L342%20696L540%20432L900%20792V1200H0Z'%20fill='%23c2410c'/%3E%3Cpath%20d='M0%20888L252%20672L468%20864L702%20720L900%20912V1200H0Z'%20fill='%237c2d12'/%3E%3Crect%20y='1008'%20width='900'%20height='192'%20fill='%23431407'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Dunes at noon, shot in portrait"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='900'%20height='1200'%20viewBox='0%200%20900%201200'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fde68a'/%3E%3Cstop%20offset='1'%20stop-color='%23fb923c'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='900'%20height='1200'%20fill='url(%23s)'/%3E%3Ccircle%20cx='630'%20cy='408'%20r='99'%20fill='%23fffbeb'/%3E%3Cpath%20d='M0%20744L180%20504L342%20696L540%20432L900%20792V1200H0Z'%20fill='%23c2410c'/%3E%3Cpath%20d='M0%20888L252%20672L468%20864L702%20720L900%20912V1200H0Z'%20fill='%237c2d12'/%3E%3Crect%20y='1008'%20width='900'%20height='192'%20fill='%23431407'%20opacity='.85'/%3E%3C/svg%3E" alt="Orange dunes in tall format"></a><label class="gallery-check"><input type="checkbox" name="media" value="4" aria-label="Select orange dunes in tall format"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='700'%20viewBox='0%200%201200%20700'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%231e1b4b'/%3E%3Cstop%20offset='1'%20stop-color='%236d28d9'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='700'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='238'%20r='77'%20fill='%23e0e7ff'/%3E%3Cpath%20d='M0%20434L240%20294L456%20406L720%20252L1200%20462V700H0Z'%20fill='%23312e81'/%3E%3Cpath%20d='M0%20518L336%20392L624%20504L936%20420L1200%20532V700H0Z'%20fill='%230f172a'/%3E%3Crect%20y='588'%20width='1200'%20height='112'%20fill='%23020617'%20opacity='.85'/%3E%3C/svg%3E" data-caption="Moonrise over the pass"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='700'%20viewBox='0%200%201200%20700'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%231e1b4b'/%3E%3Cstop%20offset='1'%20stop-color='%236d28d9'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='700'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='238'%20r='77'%20fill='%23e0e7ff'/%3E%3Cpath%20d='M0%20434L240%20294L456%20406L720%20252L1200%20462V700H0Z'%20fill='%23312e81'/%3E%3Cpath%20d='M0%20518L336%20392L624%20504L936%20420L1200%20532V700H0Z'%20fill='%230f172a'/%3E%3Crect%20y='588'%20width='1200'%20height='112'%20fill='%23020617'%20opacity='.85'/%3E%3C/svg%3E" alt="Purple night sky over dark hills"></a><label class="gallery-check"><input type="checkbox" name="media" value="5" aria-label="Select purple night sky over dark hills"></label></li><li class="gallery-item"><a href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1000'%20height='1000'%20viewBox='0%200%201000%201000'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23e0e7ff'/%3E%3Cstop%20offset='1'%20stop-color='%23f8fafc'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1000'%20height='1000'%20fill='url(%23s)'/%3E%3Ccircle%20cx='700'%20cy='340'%20r='110'%20fill='%23fef3c7'/%3E%3Cpath%20d='M0%20620L200%20420L380%20580L600%20360L1000%20660V1000H0Z'%20fill='%2394a3b8'/%3E%3Cpath%20d='M0%20740L280%20560L520%20720L780%20600L1000%20760V1000H0Z'%20fill='%23475569'/%3E%3Crect%20y='840'%20width='1000'%20height='160'%20fill='%231e293b'%20opacity='.85'/%3E%3C/svg%3E" data-caption="First snow on the ridge"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1000'%20height='1000'%20viewBox='0%200%201000%201000'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23e0e7ff'/%3E%3Cstop%20offset='1'%20stop-color='%23f8fafc'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1000'%20height='1000'%20fill='url(%23s)'/%3E%3Ccircle%20cx='700'%20cy='340'%20r='110'%20fill='%23fef3c7'/%3E%3Cpath%20d='M0%20620L200%20420L380%20580L600%20360L1000%20660V1000H0Z'%20fill='%2394a3b8'/%3E%3Cpath%20d='M0%20740L280%20560L520%20720L780%20600L1000%20760V1000H0Z'%20fill='%23475569'/%3E%3Crect%20y='840'%20width='1000'%20height='160'%20fill='%231e293b'%20opacity='.85'/%3E%3C/svg%3E" alt="Grey peaks in soft light"></a><label class="gallery-check"><input type="checkbox" name="media" value="6" aria-label="Select grey peaks in soft light"></label></li></ul></div>Theme it with --seed on any ancestor, for example style="--seed: #0d9488", and force a scheme with class="dark" or class="light" on a wrapper.
Accessibility
- Give every control a visible
labellinked withfor, or anaria-labelwhen the purpose is obvious from context. Link help and error text witharia-describedby; invalid styles use:user-invalid, so they appear only after the user interacts. - Checkboxes and radios stay real inputs, so they keep native keyboard behavior (Space toggles, arrow keys move within a radio group) and form submission.
- Give meaningful images an
alttext and decorative onesalt="". Initials avatars should expose the full name to screen readers. - Every interactive part shows a visible focus ring with
:focus-visible, and tone colors pair with-foregroundtokens that keep text at 4.5:1 or better in light and dark mode.