Muuri is a JavaScript layout engine that allows you to build all kinds of layouts (no kidding!) and make them responsive, sortable, filterable, draggable and/or animated. Comparing to what's out there Muuri is a combination of Packery, Masonry, Isotope and Sortable. Wanna see it in action? Check out the demo on the website.
Features
You can build pretty amazing layouts without a single line of JavaScript these days. However, sometimes (rarely though) CSS just isn't enough, and that's where Muuri comes along. At it's very core Muuri is a layout engine which is limited only by your imagination. You can seriously build any kind of layout, asynchronously in web workers if you wish.
Custom layouts aside, you might need to sprinkle some flare (animation) and/or interactivity (filtering / sorting / drag & drop) on your layout (be it CSS or JS based). Stuff gets complex pretty fast and most of us probably reach for existing libraries to handle the complexity at that point. This is why most of these extra features are built into Muuri's core, so you don't have to go hunting for additional libraries or re-inventing the wheel for the nth time.
The long-term goal of Muuri is to provide a simple (and as low-level as possible) API for building amazing layouts with unmatched performance and most of the complexity abstracted away.
Install via npm:
npm install muuri
Or download:
Or link directly:
<script src="https://cdn.jsdelivr.net/npm/muuri@0.9.5/dist/muuri.min.js"></script>
Muuri uses Web Animations to handle all the animations by default. If you need to use Muuri on a browser that does not support Web Animations you need to use a polyfill.
Install via npm:
npm install web-animations-js
Or download:
Or link directly:
<script src="https://cdn.jsdelivr.net/npm/web-animations-js@2.3.2/web-animations.min.js"></script>
This can be anything.
Yippee!
overflow: auto; or overflow: scroll; to the grid element. Muuri's calculation logic does not account for that and you will see some item jumps when dragging starts. Always use a wrapper element for the grid element where you set the auto/scroll overflow values..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%;
}
The bare minimum configuration is demonstrated below. You must always provide the grid element (or a selector so Muuri can fetch the element for you), everything else is optional.
var grid = new Muuri('.grid');
You can view this little tutorial demo here. After that you might want to check some other demos as well.
Muuri is a constructor function and should be always instantiated with the new keyword. For the sake of clarity, we refer to a Muuri instance as grid throughout the documentation.
Syntax
Muuri( element, [options] )
Parameters
null.Default options
The default options are stored in Muuri.defaultOptions object, which in it's default state contains the following configuration:
{
// 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',
// Sorting
sortData: null,
// Drag & Drop
dragEnabled: false,
dragContainer: null,
dragHandle: null,
dragStartPredicate: {
distance: 0,
delay: 0
},
dragAxis: 'xy',
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'
}
You can modify the default options easily:
Muuri.defaultOptions.showDuration = 400;
Muuri.defaultOptions.dragSortPredicate.action = 'swap';
This is how you would use the options:
// Minimum configuration.
var gridA = new Muuri('.grid-a');
// Providing some options.
var gridB = new Muuri('.grid-b', {
items: '.item',
});
The initial item elements, which should be children of the grid element. All elements that are not children of the grid element (e.g. if they are not in the DOM yet) will be appended to the grid element. You can provide an array of elements, NodeList, HTMLCollection or a selector (string). If you provide a selector Muuri uses it to filter the current child elements of the container element and sets them as initial items. By default all current child elements of the provided grid element are used as initial items.
'*'.Examples
// Use specific items.
var grid = new Muuri(elem, {
items: [elemA, elemB, elemC],
});
// Use node list.
var grid = new Muuri(elem, {
items: elem.querySelectorAll('.item'),
});
// Use selector.
var grid = new Muuri(elem, {
items: '.item',
});
Show animation duration in milliseconds. Set to 0 to disable show animation.
300.Examples
var grid = new Muuri(elem, {
showDuration: 600,
});
Show animation easing. Accepts any valid [Animation easing](https://developer.mozilla.
$ claude mcp add muuri \
-- python -m otcore.mcp_server <graph>