
muuri is a versatile JavaScript library that helps you create responsive, draggable, filterable, searchable grid layouts with smooth web animations.
Install it via package managers:
# Yarn yarn add muuri # NPM $ npm install muuri # Bower $ bower install muuri
Basic usage:
1. Include the main JavaScript file ‘muuri.js’ on the webpage.
<script src="muuri.min.js"></script>
2. Include the Web Animations Polyfill if needed.
<script src="https://cdn.jsdelivr.net/npm/[email protected]/web-animations.min.js"></script>
3. Add your own grid items to the layout.
<div class="grid">
<div class="item">
<div class="item-content">
Item 1
</div>
</div>
<div class="item">
<div class="item-content">
Item 2
</div>
</div>
<div class="item">
<div class="item-content">
Item 3
</div>
</div>
...
</div>4. Initialize the grid layout:
var grid = new Muuri('.grid');5. Apply your own CSS styles to the layout & grid items:
.grid {
position: relative;
}
.item {
display: block;
position: absolute;
width: 100px;
height: 100px;
margin: 5px;
z-index: 1;
background: #000;
color: #fff;
}
.item.muuri-item-dragging {
z-index: 3;
}
.item.muuri-item-releasing {
z-index: 2;
}
.item.muuri-item-hidden {
z-index: 0;
}
.item-content {
position: relative;
width: 100%;
height: 100%;
}6. Config the grid layout with the following options.
var grid = new Muuri('.grid',{
// Initial item elements
items: '*',
// Default show animation
showDuration: 300,
showEasing: 'ease',
// Default hide animation
hideDuration: 300,
hideEasing: 'ease',
// Item's visible/hidden state styles
visibleStyles: {
opacity: '1',
transform: 'scale(1)'
},
hiddenStyles: {
opacity: '0',
transform: 'scale(0.5)'
},
// Layout
layout: {
fillGaps: false,
horizontal: false,
alignRight: false,
alignBottom: false,
rounding: false
},
layoutOnResize: 150,
layoutOnInit: true,
layoutDuration: 300,
layoutEasing: 'ease',
/* e.g.
sortData: {
foo: function (item, element) {
return parseFloat(element.getAttribute('data-foo'));
},
bar: function (item, element) {
return element.getAttribute('data-bar').toUpperCase();
},
},
*/
sortData: null,
// Drag & Drop Options
dragEnabled: false,
dragContainer: null,
dragHandle: null,
dragStartPredicate: {
distance: 0,
delay: 0
},
dragAxis: 'xy', // 'x', 'y'
dragSort: true,
dragSortHeuristics: {
sortInterval: 100,
minDragDistance: 10,
minBounceBackAngle: 1
},
dragSortPredicate: {
threshold: 50,
action: 'move',
migrateAction: 'move'
},
dragRelease: {
duration: 300,
easing: 'ease',
useDragContainer: true
},
dragCssProps: {
touchAction: 'none',
userSelect: 'none',
userDrag: 'none',
tapHighlightColor: 'rgba(0, 0, 0, 0)',
touchCallout: 'none',
contentZooming: 'none'
},
dragPlaceholder: {
enabled: false,
createElement: null,
onCreate: null,
onRemove: null
},
dragAutoScroll: {
targets: [],
handle: null,
threshold: 50,
safeZone: 0.2,
speed: Muuri.AutoScroller.smoothSpeed(1000, 2000, 2500),
sortDuringScroll: true,
smoothStop: false,
onStart: null,
onStop: null
},
// Classnames
containerClass: 'muuri',
itemClass: 'muuri-item',
itemVisibleClass: 'muuri-item-shown',
itemHiddenClass: 'muuri-item-hidden',
itemPositioningClass: 'muuri-item-positioning',
itemDraggingClass: 'muuri-item-dragging',
itemReleasingClass: 'muuri-item-releasing',
itemPlaceholderClass: 'muuri-item-placeholder'
});7. You can also set options globally.
Muuri.defaultOptions.showDuration = 400; Muuri.defaultOptions.dragSortPredicate.action = 'swap';
8. Grid methods.
// get the grid element grid.getElement(); // get a specific grid element grid.getElement(target); // get a single grid item grid.getItem(target); // get all items grid.getItems(); // get all items in an array of item instances/elements/indices. grid.refreshItems([target]); // refresh the sort data of the grid's items. grid.refreshSortData(); // synchronize the item elements in the DOM to match the order of the items in the grid grid.synchronize(); // calculate item positions and move items to their calculated positions grid.layout([instant], [callback]); // add new items // options.active — boolean / undefined // options.index — number // options.layout — boolean / function / string grid.add(elements, [options]); // remove items // options.removeElements — boolean // options.layout — boolean / function / string grid.remove(elements, [options]); // show the selected items // options.instant — boolean // options.syncWithLayout — boolean // options.onFinish — function // options.layout — boolean / function / string grid.show(items, [options]); // hide the selected items // options.instant — boolean // options.syncWithLayout — boolean // options.onFinish — function // options.layout — boolean / function / string grid.hide(items, [options]); // filter items. // predicate — function / string // options.instant — boolean // options.syncWithLayout — boolean // options.onFinish — function // options.layout — boolean / function / string grid.filter(predicate, [options]); // sort items // comparer — array / function / string // options.descending — boolean // options.layout — boolean / function / string grid.sort(comparer, [options]); // move an item to another position in the grid // item — element / Muuri.Item / number // position — element / Muuri.Item / number // options.action — string // options.layout — boolean / function / string grid.move(item, position, [options]); // move an item into another grid // item — element / Muuri.Item / number // grid — Muuri // position — element / Muuri.Item / number // options.appendTo — element // options.layoutSender — boolean / function / string // options.layoutReceiver — boolean / function / string grid.send(item, grid, position, [options]); // bind/unbind an event listener. grid.on(event, listener); grid.off(event, listener); // destroy the grid and remove the items or not grid.destroy([removeElements]);
8. Item methods.
// get the grid instance the item belongs to item.getGrid(); // get the item element. item.getElement(); // get item element's cached width item.getWidth(); // get item element's cached height item.getHeight(); // get item element's cached margins item.getMargin(); // get item element's cached position item.getPosition(); // check if the item is currently active item.isActive(); // check if the item is currently visibl item.isVisible(); // check if the item is currently animating to visible. item.isShowing(); // check if the item is currently animating to hidden. item.isHiding(); // check if the item is currently being positioned. item.isPositioning(); // check if the item is currently being dragged. item.isDragging(); // check if the item is currently being released. item.isReleasing(); // check if the item is destroyed. item.isDestroyed();
9. Event handlers.
grid.on('synchronize', function () {
console.log('Synced!');
});
grid.on('layoutStart', function (items, isInstant) {
console.log(items, isInstant);
});
grid.on('layoutEnd', function (items) {
console.log(items);
// For good measure you might want to filter out all the non-active items,
// because it's techniclly possible that some of the items are
// destroyed/hidden when we receive this event.
var activeItems = items.filter(function (item) {
return item.isActive();
});
});
grid.on('layoutAbort', function (items) {
console.log(items);
// For good measure you might want to filter out all the non-active items,
// because it's techniclly possible that some of the items are destroyed or
// hidden when we receive this event.
var activeItems = items.filter(function (item) {
return item.isActive();
});
});
grid.on('add', function (items) {
console.log(items);
});
grid.on('remove', function (items, indices) {
console.log(items, indices);
});
grid.on('showStart', function (items) {
console.log(items);
});
grid.on('showEnd', function (items) {
console.log(items);
});
grid.on('hideStart', function (items) {
console.log(items);
});
grid.on('hideEnd', function (items) {
console.log(items);
});
grid.on('filter', function (shownItems, hiddenItems) {
console.log(shownItems);
console.log(hiddenItems);
});
grid.on('sort', function (currentOrder, previousOrder) {
console.log(currentOrder);
console.log(previousOrder);
});
grid.on('move', function (data) {
console.log(data);
});
grid.on('send', function (data) {
console.log(data);
});
grid.on('beforeSend', function (data) {
console.log(data);
});
grid.on('receive', function (data) {
console.log(data);
});
grid.on('beforeReceive', function (data) {
console.log(data);
});
grid.on('dragInit', function (item, event) {
console.log(event);
console.log(item);
});
grid.on('dragStart', function (item, event) {
console.log(event);
console.log(item);
});
grid.on('dragMove', function (item, event) {
console.log(event);
console.log(item);
});
grid.on('dragScroll', function (item, event) {
console.log(event);
console.log(item);
});
grid.on('dragEnd', function (item, event) {
console.log(event);
console.log(item);
});
grid.on('dragReleaseStart', function (item) {
console.log(item);
});
grid.on('dragReleaseEnd', function (item) {
console.log(item);
});
grid.on('destroy', function () {
console.log('Muuri is no more...');
});Changelog:
v0.9.5 (07/10/2021)
- update







