Masonry
Usage notes
A Masonry displays items in a waterfall grid, usually used with cards.
(double click on item to remove it)
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
card
Toggle markup
<style>
coral-masonry {
border: 1px dashed #ccc;
border-radius: 4px;
margin: 1rem;
padding: 0.5rem;
}
coral-masonry.is-complete > coral-masonry-item.is-beforeInserting:first-child {
/* Set top to padding height for a straight transition */
transform: translate(-200%, 0.5rem);
}
coral-masonry-item {
margin: 0.5rem;
}
coral-masonry article {
padding: 0.5rem;
width: 100%;
height: 100%;
box-sizing: border-box;
}
coral-masonry img {
max-width: 100%;
}
[coral-masonry-draghandle]:before {
content: "⠿";
}
</style>
<label>
ariaGrid
<span id="ariaGrid">
<a href="#" class="coral-Link">off</a> |
<a href="#" class="coral-Link">on</a> |
</span>
</label>
<br>
<label>
Selection mode
<span id="selection">
<a href="#" class="coral-Link">none</a> |
<a href="#" class="coral-Link">single</a> |
<a href="#" class="coral-Link">multiple</a>
</span>
</label>
<br>
<label>
Layout
<span id="layout">
<a href="#" class="coral-Link">fixed-centered</a> |
<a href="#" class="coral-Link">fixed-spread</a> |
<a href="#" class="coral-Link">variable</a> |
<a href="#" class="coral-Link">dashboard</a>
</span>
</label>
<br>
<label>
Column width
<input type="number" style="width:40px;background:transparent;border:none;" name="columnWidth">
</label>
<br>
<label>
Items
<a href="#" class="coral-Link prepend" data-count="1">prepend 1</a> |
<a href="#" class="coral-Link prepend" data-count="10">prepend 10</a> |
<a href="#" class="coral-Link append" data-count="1">append 1</a> |
<a href="#" class="coral-Link append" data-count="10">append 10</a> |
<a href="#" class="coral-Link append" data-count="100">append 100</a> |
</label>
<i>(double click on item to remove it)</i>
<div>
<coral-masonry orderable="" id="masonry" layout="fixed-centered" columnwidth="250" aria-label="Masonry" ariagrid="on">
<coral-masonry-item class="coral-Well">
<article>
<span coral-masonry-draghandle=""></span>
With image
<img src="https://via.placeholder.com/600x300" alt="600 × 300">
</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well">
<article>
<span coral-masonry-draghandle=""></span>
card
<br>card
</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well" colspan="2">
<article>
<span coral-masonry-draghandle=""></span>
card
<br>card
<br>card
</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well">
<article>
<span coral-masonry-draghandle=""></span>
card
<br>card
<br>card
<br>card
</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well" colspan="2">
<article>card
<br>card
<br>card
<br>card
<br>card</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well">
<article>card
<br>card
<br>card
<br>card
<br>card
<br>card</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well">
<article>card
<br>card</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well" colspan="2">
<article>card
<br>card
<br>card</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well">
<article>card
<br>card
<br>card
<br>card</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well" colspan="2">
<article>card
<br>card
<br>card
<br>card
<br>card</article>
</coral-masonry-item>
<coral-masonry-item class="coral-Well">
<article>card
<br>card
<br>card
<br>card
<br>card
<br>card</article>
</coral-masonry-item>
</coral-masonry>
</div>
<script>
window.addEventListener('load', function() {
let uid = 0;
function getUID() {
return 'coral-masonry-' + uid++;
}
const masonry = document.getElementById('masonry');
masonry.items.getAll().forEach(function (item) {
const article = item.querySelector('article');
article.setAttribute('role', 'presentation');
if (!item.id) {
item.id = getUID();
}
article.id = article.id || item.id + '-content';
});
const ariaGridSelector = document.getElementById('ariaGrid');
ariaGridSelector.addEventListener('click', function(event) {
masonry.setAttribute('ariagrid', event.target.textContent);
});
const layoutSelector = document.getElementById('layout');
layoutSelector.addEventListener('click', function(event) {
masonry.setAttribute('layout', event.target.textContent);
});
const selectionSelector = document.getElementById('selection');
selectionSelector.addEventListener('click', function(event) {
masonry.setAttribute('selectionmode', event.target.textContent);
});
const columnWidthSelector = document.querySelector('[name=columnWidth]');
columnWidthSelector.value = masonry.getAttribute('columnwidth');
columnWidthSelector.addEventListener('input', function() {
masonry.setAttribute('columnwidth', this.value);
});
masonry.on('dblclick', 'coral-masonry-item', function(event) {
event.matchedTarget.remove();
});
document.addEventListener('click', function(event) {
const prepend = event.target.matches('.prepend');
if (prepend) {
let count = event.target.dataset.count;
for (let i = 0; i < count; i++) {
masonry.items.add(createItem(), masonry.items.first());
}
}
});
document.addEventListener('click', function(event) {
const append = event.target.matches('.append');
if (append) {
const startTime = Date.now();
const count = event.target.dataset.count;
for (let i = 0; i < count; i++) {
masonry.items.add(createItem());
}
window.requestAnimationFrame(function() {
console.log('Appending time:', Date.now() - startTime);
});
}
});
let image = false;
function createItem() {
image = !image;
return image ? createImageItem() : createTextItem();
}
function randomSize() {
return (2 + Math.round(Math.random() * 4)) * 100;
}
function createImageItem() {
const id = getUID();
const contentId = id + '-content';
const width = randomSize();
const height = randomSize();
const url = 'https://via.placeholder.com/' + width + 'x' + height;
const item = document.createElement('coral-masonry-item');
item.id = id;
item.classList.add('coral-Well');
item.content.innerHTML = '<img id="' + contentId + '" alt="' + width + ' × ' + height + '" src="' + url + '" style="width: ' + (width / 2) + 'px; height: ' + (height / 2) + 'px;">';
return item;
}
function createTextItem() {
const id = getUID();
const contentId = id + '-content';
const rows = 1 + Math.round(Math.random() * 6);
const html = new Array(rows + 1).join('card<br>').slice(0, -4);
const item = document.createElement('coral-masonry-item');
item.id = id;
item.classList.add('coral-Well');
item.content.innerHTML = '<article role="presentation" id="' + contentId + '">' + html + '</article>';
return item;
}
});
</script>