Responsive & Fluid Drag-and-Drop Grid Layout with jQuery - gridstack.js

Responsive & Fluid Drag-and-Drop Grid Layout with jQuery - gridstack.js
File Size: 259 KB
Views Total:
Last Update:
Publish Date:
Official Website: Go to website
License: MIT

Gridstack.js is a jQuery widget/grid layout plugin inspired by Gridster that allows you to dynamically and responsively rearrange grid items through drag and drop.

More features:

  • Also supports touch events.
  • Resizable grid items.
  • Supports nested grid items.
  • Compatible with Bootstrap 3/4 framework.

View more:


Basic Usage:

1. Include the required stylesheet in the head section of the document.

<!-- Local -->
<link href="/path/to/gridstack.css" rel="stylesheet" />
<!-- Or From A CDN -->
<link rel="stylesheet" href="[email protected]/dist/gridstack.min.css" />

2. Include the jQuery Gridstack.js plugin and other required resources at the end of the document.

<!-- Dependencies -->
<script src="/path/to/cdn/jquery.min.js"></script>
<script src="/path/to/cdn/jquery-ui.min.js"></script>
<script src="/path/to/cdn/jquery.ui.touch-punch.min.js"></script>

<!-- jQuery Gridstack.js -->
<script src="gridstack.all.js"></script>
<!-- Or from a CDN -->
<script src="[email protected]/dist/gridstack.all.js"></script>
<!-- Polyfill for old IE -->
<script src="gridstack.poly.js"></script>

3. Create a sample draggable grid layout as follows.

  • data-gs-animate: turns animation on (for grid)
  • data-gs-column: amount of columns (for grid)
  • data-gs-max-row: maximum rows amount, defaults to 0 (for grid)
  • data-gs-current-height: current rows amount (for grid)
  • data-gs-id: unique ID (for item)
  • data-gs-x, data-gs-y: element position (for item)
  • data-gs-width, data-gs-height: element size (for item)
  • data-gs-max-width, data-gs-min-width, data-gs-max-height, data-gs-min-height: element constraints (for item)
  • data-gs-no-resize: disable element resizing (for item)
  • data-gs-no-move: disable element moving (for item)
  • data-gs-auto-position: tells to ignore data-gs-x and data-gs-y attributes and to place element to the first available position (for item)
  • data-gs-locked: the widget will be locked. It means another widgets couldn't move it during dragging or resizing. The widget is still can be dragged or resized. You need to add data-gs-no-resize and data-gs-no-move attributes to completely lock the widget (for item)
  • data-gs-resize-handles: resize handles (for item)
<div class="grid-stack" data-gs-width="12">
  <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="4">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="8" data-gs-y="0" data-gs-width="2" data-gs-height="2" data-gs-min-width="2" data-gs-no-resize="yes">
    <div class="grid-stack-item-content"> <span class="fa fa-hand-o-up"></span> Drag me! </div>
  <div class="grid-stack-item" data-gs-x="10" data-gs-y="0" data-gs-width="2" data-gs-height="2">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="0" data-gs-y="4" data-gs-width="2" data-gs-height="2">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="2" data-gs-y="4" data-gs-width="2" data-gs-height="4">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="8" data-gs-y="4" data-gs-width="4" data-gs-height="2">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="0" data-gs-y="6" data-gs-width="2" data-gs-height="2">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="4" data-gs-y="6" data-gs-width="4" data-gs-height="2">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="8" data-gs-y="6" data-gs-width="2" data-gs-height="2">
    <div class="grid-stack-item-content"></div>
  <div class="grid-stack-item" data-gs-x="10" data-gs-y="6" data-gs-width="2" data-gs-height="2">
    <div class="grid-stack-item-content"></div>

4. Call the plugin and create a responsive & fluid 12 columns grid layout.

$(function () {
    column: 12

5. All possible options and defaults available.


  // turns animation on
  animate: false,

  // amount of columns
  column: 12,

  // max number rows
  maxRow: 0,

  // maximum rows amount
  height: 0, 

  // widget class
  itemClass: 'grid-stack-item',

  // class for placeholder
  placeholderClass: 'grid-stack-placeholder',

  // text for placeholder
  placeholderText: '',

  // draggable handle selector
  handle: '.grid-stack-item-content',

  // class for handle
  handleClass: null,

  // one cell height
  cellHeight: 60,

  // vertical gap size
  verticalMargin: 20,

  // unit
  verticalMarginUnit: 'px',
  cellHeightUnit: 'px',

  // if false it tells to do not initialize existing items
  auto: true,
  // minimal width.
  minWidth: 768,

  // class set on grid when in one column mode
  oneColumnModeClass: 'grid-stack-one-column-mode',

  // set to true if you want oneColumnMode to use the DOM order and ignore x,y from normal multi column layouts during sorting. This enables you to have custom 1 column layout that differ from the rest.
  oneColumnModeDomSort: false,

  // enable floating widgets
  float: false,

  // makes grid static
  staticGrid: false,

  // if true the resizing handles are shown even the user is not hovering over the widget
  alwaysShowResizeHandle: false,

  // allows to owerride jQuery UI draggable options
  draggable: {handle: '.grid-stack-item-content', scroll: true, appendTo: 'body'},

  // let user drag nested grid items out of a parent or not
  dragOut: false,

  // allows to owerride jQuery UI resizable options
  resizable: {autoHide: true, handles: 'se'},

  // disallows dragging of widgets
  disableDrag: false

  // disallows resizing of widgets
  disableResize: false,

  // if `true` turns grid to RTL. 
  // Possible values are `true`, `false`, `'auto'`
  rtl: 'auto',

  // if `true` widgets could be removed by dragging outside of the grid
  removable: false,

  // time in milliseconds before widget is being removed while dragging outside of the grid
  removeTimeout: 2000,

  // CSS class when in one column mode
  disableOneColumnMode: 'grid-stack-one-column-mode',

  // class that implement drag'n'drop functionallity for gridstack
  ddPlugin: null


6. Public methods.

// Creates a new widget.
grid.addWidget(el, x, y, width, height, autoPosition, minWidth, maxWidth, minHeight, maxHeight, id);

// Initailizes batch updates. 
// You will see no changes until commit method is called.

// Relayout grid items to reclaim any empty space.

// Gets current cell height.

// Update current cell height.
// grid.cell_height(grid.cell_width() * 1.2);
grid.cellHeight(val, noUpdate);

// Gets current cell width.

// Returns current vertical margin value.

// value - new vertical margin value.
// noUpdate - if true, styles will not be updated.
verticalMargin(value, noUpdate)

// Finishes batch updates. Updates DOM nodes. You must call it after batch_update.

// set/get floating widgets

// Disables / enables widgets moving/resizing.
grid.movable('.grid-stack-item', false);
grid.resizable('.grid-stack-item', true); 

// Get the position of the cell under a pixel on screen.
// position - the position of the pixel to resolve in absolute coordinates, as an object with top and leftproperties
// useOffset - if true, value will be based on offset vs position (Optional. Default false). Useful when grid is within position: relative element
// Returns an object with properties x and y i.e. the column and row in the grid.
grid.getCellFromPixel(position, useOffset);

// Checks if specified area is empty.
grid.isAreaEmpty(x, y, width, height);

// Locks/unlocks widget.
// el - widget to modify.
// val - if true widget will be locked.
grid.locked(el, val);

// Make new widgets after new items are appended to the grid.

// Set the minWidth/maxWidth for a widget.
grid.minWidth(el, val);
grid.maxWidth(el, val);

// Set the minHeight/maxWidth for a widget.
grid.minHeight(el, val);
grid.maxHeight(el, val);

// Removes widget from the grid.
// detachNode - if false node won't be removed from the DOM
grid.removeWidget(el, detachNode);

// Removes all widgets from the grid.
// detachNode - if false node won't be removed from the DOM

// Changes widget size
grid.resize(el, width, height);

// Changes widget position
grid.move(el, x, y);

// Enables/Disables resizing.
grid.resizable(el, val);

// Enables/Disables moving.
grid.movable(el, val);

// Updates widget position/size.
grid.update(el, x, y, width, height);

// Returns true if the height of the grid will be less the vertical constraint. Always returns true if grid doesn't have height constraint.
grid.willItFit(x, y, width, height, autoPosition);

// Toggle the grid animation state.
// doAnimate - if true the grid will animate.

// Modify number of columns in the grid
// doNotPropagate - if true existing widgets will not be updated.
grid.setColumn(column, doNotPropagate);

// Update widget position/size.

// Toggle the grid static state
// staticValue - if true the grid becomes static.
grid.update(el, x, y, width, height));

// Destroy the instance
// detachGrid - if false nodes and grid will not be removed from the DOM

7. Event listeners available.

$('.grid-stack').on('added', function(event, items) {
  // after new items are added

$('.grid-stack').on('change', function(event, items) {
  // fired on change

$('.grid-stack').on('disable', function(event) {
  // var grid =;

$('.grid-stack').on('dragstart', function(event, ui) {
  // var grid = this;
  // var element =;

$('.grid-stack').on('dragstop',  function(event, ui) {
  // var grid = this;
  // var element =;

$('.grid-stack').on('dropped',  function(event, previousWidget, newWidget) {
  // after dropped

$('.grid-stack').on('enable',  function(event) {
  // var grid =;

$('.grid-stack').on('removed',  function(event, items) {
  // after removed

$('.grid-stack').on('resizestart',  function(event, ui) {
  // var grid = this;
  // var element =;

$('.grid-stack').on('gsresizestop',  function(event, items) {
  // on stop resizing

8. Please check out doc/ for more information about gridstack.js API.


v0.6.4 (2020-02-18)

  • optimized change callback to save original x,y,w,h values and only call those that changed
  • more bugs fixed

v0.6.2 (2020-02-04)

  • fix oneColumnMode missing CSS to do layout
  • del oneColumnModeClass / .grid-stack-one-column-mode and associated code. If you depended on this, use class .grid-stack-1 instead since it is 1 column layout anyway

v0.6.2 (2020-02-04)

  • add oneColumnModeDomSort true|false to let you specify a custom layout (use dom order instead of x,y) for oneColumnMode setColumn(1)
  • fix oneColumnMode to only restore if we auto went to it as window sizes up
  • editing in 1 column (or few columns) does a better job updating higher layout (track before and after and move items accordingly). Tracking item swap would be even better still.

v0.6.1 (2020-02-03)

  • one column mode (<768px by default) now simply calls setColumn(1) and remembers prev columns (so we can restore). This gives us full resize/re-order of items capabilities rather than a locked CSS only layout (see prev rev changes).

v0.6.0 (2019-12-25)

  • add float(val) to set/get the grid float mode, which will relayout 
  • add compact() to reclaim any empty space and relayout grid items
  • add options.dragOut to let user drag nested grid items out of a parent or not (default false) and jQuery UI draggable.containment can now be specified in options. You can now drag&drop between 2 nested grids
  • Allow percentage as a valid unit for height
  • fixed callbacks to get either added, removed, change or combination if adding a node require also to change its (x,y) for example. Also you can now call batchUpdate() before calling a bunch of addWidget() and get a single event callback (more efficient)
  • removeAll() is now much faster (no relayout) and calls removed event just once with a list
  • setColumn() complete re-write and is no longer "Experimental". We now do a reasonable job at sizing/position the widgets (especially 1 column) and also now cache each column layout so you can go back to say 12 column and not loose original layout
  • fix bug where addWidget(el) (no data) would not render item at correct location, and overlap item at (0,0)
  • you can now pre-define size of dragable elements from a sidebar using standard data-gs-width and data-gs-height

v0.5.4 (2019-11-28)

  • no code change, just packing issues

v0.5.4 (2019-11-27)

  • fix for griditems with x=0 placement wrong order
  • fix cellHeight(val) not working due to style change 
  • add gridstack.poly.js for IE and older browsers, removed core-js lib from samples (<1k vs 85k), and all IE8 mentions
  • add jquery-ui.js (and min.js) as minimal subset we need (55k vs 248k), which is now part of gridstack.all.js. Include individual parts if you need your own lib instead of all.js
  • changed jquery dependency to lowest we can use (>=1.8)


  • Doc updated


  • Update dependencies, remove .bithoundrc (bithound is closing), update syntax for sortBy


  • Temporary bugfix

v1.0.0 (2017-09-12)

  • Build last few merges, fix indentation, allow the maximum height to be the style `min-height` / `cellHeight` in cases where that is larger than the biggest cell y + cell height.
  • "trashzone" improvement
  • Fix build by breaking line before 120 characters.

v0.3.0 (2017-04-22)

  • remove placeholder when dragging widget below grid (already worked when dragging left, above, and to the right of grid).
  • prevent extra checks for removing widget when dragging off grid.
  • trigger added when a widget is added via dropping from one grid to another.
  • trigger removed when a widget is removed via dropping from one grid to another.
  • trigger removed when a widget is removed via dropping on a removable zone.
  • trigger custom event for resizestop called gsresizestop.
  • prevent dragging/resizing in oneColumnMode.
  • add oneColumnModeClass option to grid.
  • remove 768px CSS styles, moved to grid-stack-one-column-mode class.
  • add max-width override on grid-stck-one-column-mode.
  • add internal functionisNodeChangedPosition, minor optimization to move/drag.
  • drag'n'drop plugin system. Move jQuery UI dependencies to separate plugin file.

v0.2.6 (2016-08-17)

  • update requirements to the latest versions
  • fix jQuery size()
  • Fixed setStatic not working
  • fix cellWidth method

v0.2.5 (2016-03-03)

  • update names to respect js naming convention.
  • cellHeight and verticalMargin can now be string (e.g. '3em', '20px').
  • add maxWidth/maxHeight methods.
  • add enableMove/enableResize methods.
  • fix window resize issue.
  • add options disableDrag and disableResize.
  • fix batchUpdate/commit 
  • remove dependency of FontAwesome
  • RTL support
  • 'auto' value for cellHeight option
  • fix setStatic method
  • add setAnimation method to API
  • add setGridWidth method
  • add removable/removeTimeout
  • add detachGrid parameter to destroy method
  • add useOffset parameter to getCellFromPixel method
  • add minWidth, maxWidth, minHeight, maxHeight, id parameters to addWidget
  • add added and removed events for when a widget is added or removed, respectively


  • Include resizable, draggable opts in all listeners for resizable, draggable, respectively. Fixes issue particularly when passing handle to draggable - was listening to everything on el rather than this.opts.draggable.handle.


  • Adding make_widget functionality


  • Fixed: Grid ID and Extra CSS use same prefix


  • fix handle option


  • Make sure not to include placeholders when calling prepare element.


  • Trigger change event for add/remove


  • Add destroy method.


  • Add a API to set minWidth and minHeight to a node


  • add 'static_grid' option


  • fix closure compiler/linter warnings


  • extra CSS


  • do not fire onchange event with empty array


  • fix ‘w’ resize


  • fix floating mode


  • lodash.js support


  • improve memory usage
  • added more demos.


  • fix styles initialization
  • add `detach_node` param to `remove_widget`


  • remove default value for max height


  • improve default resizable options


  • avoid runtime error in IE8


  • improve stylesheet creation
  • resizable/draggable options


  • fix IE9 resize handle issue


  • add disable/enable methods


  • respect max/min constrains when resize widgets


  • add get_cell_from_pixel
  • AMD support
  • fix nodes sorting
  • improved touch devices support
  • add always_show_resize_handle option


  • added knockout.js support
  • added AMD support


  • improve touch support


  • Fixed: Dragging widgets around can still cause unexpected changes in other widgets


  • add cell_width/cell_height


  • minify css
  • Animates grid-stack container itself.


  • fix widgets packing in float mode
  • fix locked for not floating grid.


  • set animation after grid initialization


  • improve 'y' calc when dragging


  • add height option


  • fix css rules generation


  • auto-generate css rules for width and y


  • add remove_all method


  • add movable/resizable API methods


  • add data-gs-no-move attribute to disable drag'n drop on specified elements.


  • add float option


  • added one-column mode for small devices


  • added auto positioning


  • update container height after add/remove


This awesome jQuery plugin is developed by gridstack. For more Advanced Usages, please check the demo page or visit the official website.