Gathering detailed insights and metrics for react-grid-layout
Gathering detailed insights and metrics for react-grid-layout
Gathering detailed insights and metrics for react-grid-layout
Gathering detailed insights and metrics for react-grid-layout
@types/react-grid-layout
TypeScript definitions for react-grid-layout
vue-responsive-dash
A Responsive, Draggable & Resizable Dashboard (grid) made with vue and typescript. Inspired by React-Grid-Layout & Vue-Grid-Layout
react-grid-layout-builder
A user interface to build react-grid-layout properties
react-grid-layout-modified
A copy of react-grid-layout with some applied PR's which never got merged in
A draggable and resizable grid layout with responsive breakpoints, for React.
npm install react-grid-layout
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
20,551 Stars
771 Commits
2,596 Forks
235 Watching
18 Branches
126 Contributors
Updated on 27 Nov 2024
JavaScript (97.47%)
CSS (1.23%)
Makefile (1.01%)
HTML (0.26%)
Shell (0.04%)
Cumulative downloads
Total Downloads
Last day
-6.5%
120,557
Compared to previous day
Last week
5.4%
645,497
Compared to previous week
Last month
10.6%
2,723,062
Compared to previous month
Last year
35.3%
29,724,677
Compared to previous year
42
React-Grid-Layout is a grid layout system much like Packery or Gridster, for React.
Unlike those systems, it is responsive and supports breakpoints. Breakpoint layouts can be provided by the user or autogenerated.
RGL is React-only and does not require jQuery.
GIF from production usage on BitMEX.com
[Demo | Changelog | CodeSandbox Editable demo]
Know of others? Create a PR to let me know!
<React.StrictMode>
Version | Compatibility |
---|---|
>= 0.17.0 | React 16 & 17 |
>= 0.11.3 | React 0.14 & 15 |
>= 0.10.0 | React 0.14 |
0.8. - 0.9.2 | React 0.13 |
< 0.8 | React 0.12 |
Install the React-Grid-Layout package using npm:
1npm install react-grid-layout
Include the following stylesheets in your application:
/node_modules/react-grid-layout/css/styles.css
/node_modules/react-resizable/css/styles.css
Use ReactGridLayout like any other component. The following example below will produce a grid with three items where:
a
b
will be restricted to a minimum width of 2 grid blocks and a maximum width of 4 grid blocksc
1import GridLayout from "react-grid-layout"; 2 3class MyFirstGrid extends React.Component { 4 render() { 5 // layout is an array of objects, see the demo for more complete usage 6 const layout = [ 7 { i: "a", x: 0, y: 0, w: 1, h: 2, static: true }, 8 { i: "b", x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }, 9 { i: "c", x: 4, y: 0, w: 1, h: 2 } 10 ]; 11 return ( 12 <GridLayout 13 className="layout" 14 layout={layout} 15 cols={12} 16 rowHeight={30} 17 width={1200} 18 > 19 <div key="a">a</div> 20 <div key="b">b</div> 21 <div key="c">c</div> 22 </GridLayout> 23 ); 24 } 25}
You may also choose to set layout properties directly on the children:
1import GridLayout from "react-grid-layout"; 2 3class MyFirstGrid extends React.Component { 4 render() { 5 return ( 6 <GridLayout className="layout" cols={12} rowHeight={30} width={1200}> 7 <div key="a" data-grid={{ x: 0, y: 0, w: 1, h: 2, static: true }}> 8 a 9 </div> 10 <div key="b" data-grid={{ x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }}> 11 b 12 </div> 13 <div key="c" data-grid={{ x: 4, y: 0, w: 1, h: 2 }}> 14 c 15 </div> 16 </GridLayout> 17 ); 18 } 19}
A module usable in a <script>
tag is included here. It uses a UMD shim and
excludes React
, so it must be otherwise available in your application, either via RequireJS or on window.React
.
To make RGL responsive, use the <ResponsiveReactGridLayout>
element:
1import { Responsive as ResponsiveGridLayout } from "react-grid-layout"; 2 3class MyResponsiveGrid extends React.Component { 4 render() { 5 // {lg: layout1, md: layout2, ...} 6 const layouts = getLayoutsFromSomewhere(); 7 return ( 8 <ResponsiveGridLayout 9 className="layout" 10 layouts={layouts} 11 breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} 12 cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }} 13 > 14 <div key="1">1</div> 15 <div key="2">2</div> 16 <div key="3">3</div> 17 </ResponsiveGridLayout> 18 ); 19 } 20}
When in responsive mode, you should supply at least one breakpoint via the layouts
property.
When using layouts
, it is best to supply as many breakpoints as possible, especially the largest one.
If the largest is provided, RGL will attempt to interpolate the rest.
You will also need to provide a width
, when using <ResponsiveReactGridLayout>
it is suggested you use the HOC
WidthProvider
as per the instructions below.
It is possible to supply default mappings via the data-grid
property on individual
items, so that they would be taken into account within layout interpolation.
Both <ResponsiveReactGridLayout>
and <ReactGridLayout>
take width
to calculate
positions on drag events. In simple cases a HOC WidthProvider
can be used to automatically determine
width upon initialization and window resize events.
1import { Responsive, WidthProvider } from "react-grid-layout"; 2 3const ResponsiveGridLayout = WidthProvider(Responsive); 4 5class MyResponsiveGrid extends React.Component { 6 render() { 7 // {lg: layout1, md: layout2, ...} 8 var layouts = getLayoutsFromSomewhere(); 9 return ( 10 <ResponsiveGridLayout 11 className="layout" 12 layouts={layouts} 13 breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} 14 cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }} 15 > 16 <div key="1">1</div> 17 <div key="2">2</div> 18 <div key="3">3</div> 19 </ResponsiveGridLayout> 20 ); 21 } 22}
This allows you to easily replace WidthProvider
with your own Provider HOC if you need more sophisticated logic.
WidthProvider
accepts a single prop, measureBeforeMount
. If true
, WidthProvider
will measure the
container's width before mounting children. Use this if you'd like to completely eliminate any resizing animation
on application/component mount.
Have a more complicated layout? WidthProvider
is very simple and only
listens to window 'resize'
events. If you need more power and flexibility, try the
SizeMe React HOC as an alternative to WidthProvider.
RGL supports the following properties (see the source for the final word on this):
1// 2// Basic props 3// 4 5// This allows setting the initial width on the server side. 6// This is required unless using the HOC <WidthProvider> or similar 7width: number, 8 9// If true, the container height swells and contracts to fit contents 10autoSize: ?boolean = true, 11 12// Number of columns in this layout. 13cols: ?number = 12, 14 15// A CSS selector for tags that will not be draggable. 16// For example: draggableCancel:'.MyNonDraggableAreaClassName' 17// If you forget the leading . it will not work. 18// .react-resizable-handle" is always prepended to this value. 19draggableCancel: ?string = '', 20 21// A CSS selector for tags that will act as the draggable handle. 22// For example: draggableHandle:'.MyDragHandleClassName' 23// If you forget the leading . it will not work. 24draggableHandle: ?string = '', 25 26// Compaction type. 27compactType: ?('vertical' | 'horizontal' | null) = 'vertical'; 28 29// Layout is an array of objects with the format: 30// The index into the layout must match the key used on each item component. 31// If you choose to use custom keys, you can specify that key in the layout 32// array objects using the `i` prop. 33layout: ?Array<{i?: string, x: number, y: number, w: number, h: number}> = null, // If not provided, use data-grid props on children 34 35// Margin between items [x, y] in px. 36margin: ?[number, number] = [10, 10], 37 38// Padding inside the container [x, y] in px 39containerPadding: ?[number, number] = margin, 40 41// Rows have a static height, but you can change this based on breakpoints 42// if you like. 43rowHeight: ?number = 150, 44 45// Configuration of a dropping element. Dropping element is a "virtual" element 46// which appears when you drag over some element from outside. 47// It can be changed by passing specific parameters: 48// i - id of an element 49// w - width of an element 50// h - height of an element 51droppingItem?: { i: string, w: number, h: number } 52 53// 54// Flags 55// 56isDraggable: ?boolean = true, 57isResizable: ?boolean = true, 58isBounded: ?boolean = false, 59// Uses CSS3 translate() instead of position top/left. 60// This makes about 6x faster paint performance 61useCSSTransforms: ?boolean = true, 62// If parent DOM node of ResponsiveReactGridLayout or ReactGridLayout has "transform: scale(n)" css property, 63// we should set scale coefficient to avoid render artefacts while dragging. 64transformScale: ?number = 1, 65 66// If true, grid can be placed one over the other. 67// If set, implies `preventCollision`. 68allowOverlap: ?boolean = false, 69 70// If true, grid items won't change position when being 71// dragged over. If `allowOverlap` is still false, 72// this simply won't allow one to drop on an existing object. 73preventCollision: ?boolean = false, 74 75// If true, droppable elements (with `draggable={true}` attribute) 76// can be dropped on the grid. It triggers "onDrop" callback 77// with position and event object as parameters. 78// It can be useful for dropping an element in a specific position 79// 80// NOTE: In case of using Firefox you should add 81// `onDragStart={e => e.dataTransfer.setData('text/plain', '')}` attribute 82// along with `draggable={true}` otherwise this feature will work incorrect. 83// onDragStart attribute is required for Firefox for a dragging initialization 84// @see https://bugzilla.mozilla.org/show_bug.cgi?id=568313 85isDroppable: ?boolean = false, 86// Defines which resize handles should be rendered. 87// Allows for any combination of: 88// 's' - South handle (bottom-center) 89// 'w' - West handle (left-center) 90// 'e' - East handle (right-center) 91// 'n' - North handle (top-center) 92// 'sw' - Southwest handle (bottom-left) 93// 'nw' - Northwest handle (top-left) 94// 'se' - Southeast handle (bottom-right) 95// 'ne' - Northeast handle (top-right) 96// 97// Note that changing this property dynamically does not work due to a restriction in react-resizable. 98resizeHandles: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se'], 99// Custom component for resize handles 100// See `handle` as used in https://github.com/react-grid-layout/react-resizable#resize-handle 101// Your component should have the class `.react-resizable-handle`, or you should add your custom 102// class to the `draggableCancel` prop. 103resizeHandle?: ReactElement<any> | ((resizeHandleAxis: ResizeHandleAxis, ref: ReactRef<HTMLElement>) => ReactElement<any>), 104 105// 106// Callbacks 107// 108 109// Callback so you can save the layout. 110// Calls back with (currentLayout) after every drag or resize stop. 111onLayoutChange: (layout: Layout) => void, 112 113// 114// All callbacks below have signature (layout, oldItem, newItem, placeholder, e, element). 115// 'start' and 'stop' callbacks pass `undefined` for 'placeholder'. 116// 117type ItemCallback = (layout: Layout, oldItem: LayoutItem, newItem: LayoutItem, 118 placeholder: LayoutItem, e: MouseEvent, element: HTMLElement) => void, 119 120// Calls when drag starts. 121onDragStart: ItemCallback, 122// Calls on each drag movement. 123onDrag: ItemCallback, 124// Calls when drag is complete. 125onDragStop: ItemCallback, 126// Calls when resize starts. 127onResizeStart: ItemCallback, 128// Calls when resize movement happens. 129onResize: ItemCallback, 130// Calls when resize is complete. 131onResizeStop: ItemCallback, 132 133// 134// Dropover functionality 135// 136 137// Calls when an element has been dropped into the grid from outside. 138onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void, 139// Calls when an element is being dragged over the grid from outside as above. 140// This callback should return an object to dynamically change the droppingItem size 141// Return false to short-circuit the dragover 142onDropDragOver: (e: DragOverEvent) => ?({|w?: number, h?: number|} | false), 143 144// Ref for getting a reference for the grid's wrapping div. 145// You can use this instead of a regular ref and the deprecated `ReactDOM.findDOMNode()`` function. 146// Note that this type is React.Ref<HTMLDivElement> in TypeScript, Flow has a bug here 147// https://github.com/facebook/flow/issues/8671#issuecomment-862634865 148innerRef: {current: null | HTMLDivElement},
The responsive grid layout can be used instead. It supports all of the props above, excepting layout
.
The new properties and changes are:
1// {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480} 2// Breakpoint names are arbitrary but must match in the cols and layouts objects. 3breakpoints: ?Object = {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}, 4 5// # of cols. This is a breakpoint -> cols map, e.g. {lg: 12, md: 10, ...} 6cols: ?Object = {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2}, 7 8 9// margin (in pixels). Can be specified either as horizontal and vertical margin, e.g. `[10, 10]` or as a breakpoint -> margin map, e.g. `{lg: [10, 10], md: [10, 10], ...}. 10margin: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}, 11 12 13// containerPadding (in pixels). Can be specified either as horizontal and vertical padding, e.g. `[10, 10]` or as a breakpoint -> containerPadding map, e.g. `{lg: [10, 10], md: [10, 10], ...}. 14containerPadding: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]}, 15 16 17// layouts is an object mapping breakpoints to layouts. 18// e.g. {lg: Layout, md: Layout, ...} 19layouts: {[key: $Keys<breakpoints>]: Layout}, 20 21// 22// Callbacks 23// 24 25// Calls back with breakpoint and new # cols 26onBreakpointChange: (newBreakpoint: string, newCols: number) => void, 27 28// Callback so you can save the layout. 29// AllLayouts are keyed by breakpoint. 30onLayoutChange: (currentLayout: Layout, allLayouts: {[key: $Keys<breakpoints>]: Layout}) => void, 31 32// Callback when the width changes, so you can modify the layout as needed. 33onWidthChange: (containerWidth: number, margin: [number, number], cols: number, containerPadding: [number, number]) => void; 34
RGL supports the following properties on grid items or layout items. When initializing a grid,
build a layout array (as in the first example above), or attach this object as the data-grid
property
to each of your child elements (as in the second example).
If data-grid
is provided on an item, it will take precedence over an item in the layout
with the same key (i
).
Note that if a grid item is provided but incomplete (missing one of x, y, w, or h
), an error
will be thrown so you can correct your layout.
If no properties are provided for a grid item, one will be generated with a width and height of 1
.
You can set minimums and maximums for each dimension. This is for resizing; it of course has no effect if resizing is disabled. Errors will be thrown if your mins and maxes overlap incorrectly, or your initial dimensions are out of range.
Any <GridItem>
properties defined directly will take precedence over globally-set options. For
example, if the layout has the property isDraggable: false
, but the grid item has the prop isDraggable: true
, the item
will be draggable, even if the item is marked static: true
.
1{ 2 3 // A string corresponding to the component key 4 i: string, 5 6 // These are all in grid units, not pixels 7 x: number, 8 y: number, 9 w: number, 10 h: number, 11 minW: ?number = 0, 12 maxW: ?number = Infinity, 13 minH: ?number = 0, 14 maxH: ?number = Infinity, 15 16 // If true, equal to `isDraggable: false, isResizable: false`. 17 static: ?boolean = false, 18 // If false, will not be draggable. Overrides `static`. 19 isDraggable: ?boolean = true, 20 // If false, will not be resizable. Overrides `static`. 21 isResizable: ?boolean = true, 22 // By default, a handle is only shown on the bottom-right (southeast) corner. 23 // As of RGL >= 1.4.0, resizing on any corner works just fine! 24 resizeHandles?: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se'] 25 // If true and draggable, item will be moved only within grid. 26 isBounded: ?boolean = false 27}
Grid item widths are based on container and number of columns. The size of a grid unit's height is based on rowHeight
.
Note that an item that has h=2
is not exactly twice as tall as one with h=1
unless you have no margin
!
In order for the grid to not be ragged, when an item spans grid units, it must also span margins. So you must add the height or width or the margin you are spanning for each unit. So actual pixel height is (rowHeight * h) + (marginH * (h - 1)
.
For example, with rowHeight=30
, margin=[10,10]
and a unit with height 4, the calculation is (30 * 4) + (10 * 3)
If this is a problem for you, set margin=[0,0]
and handle visual spacing between your elements inside the elements' content.
<ReactGridLayout>
has an optimized shouldComponentUpdate
implementation, but it relies on the user memoizing the children
array:
1// lib/ReactGridLayout.jsx
2// ...
3shouldComponentUpdate(nextProps: Props, nextState: State) {
4 return (
5 // NOTE: this is almost always unequal. Therefore the only way to get better performance
6 // from SCU is if the user intentionally memoizes children. If they do, and they can
7 // handle changes properly, performance will increase.
8 this.props.children !== nextProps.children ||
9 !fastRGLPropsEqual(this.props, nextProps, isEqual) ||
10 !isEqual(this.state.activeDrag, nextState.activeDrag)
11 );
12}
13// ...
If you memoize your children, you can take advantage of this, and reap faster rerenders. For example:
1function MyGrid(props) { 2 const children = React.useMemo(() => { 3 return new Array(props.count).fill(undefined).map((val, idx) => { 4 return <div key={idx} data-grid={{ x: idx, y: 1, w: 1, h: 1 }} />; 5 }); 6 }, [props.count]); 7 return <ReactGridLayout cols={12}>{children}</ReactGridLayout>; 8}
Because the children
prop doesn't change between rerenders, updates to <MyGrid>
won't result in new renders, improving performance.
Using hooks to save your layout state on change will cause the layouts to re-render as the ResponsiveGridLayout will change it's value on every render. To avoid this you should wrap your WidthProvider in a useMemo:
1const ResponsiveReactGridLayout = useMemo(() => WidthProvider(Responsive), []);
If you use React Components as grid children, they need to do a few things:
style
,className
, onMouseDown
, onMouseUp
and onTouchEnd
to that same DOM node.For example:
1const CustomGridItemComponent = React.forwardRef(({style, className, onMouseDown, onMouseUp, onTouchEnd, children, ...props}, ref) => {
2 return (
3 <div style={{ /* styles */, ...style}} className={className} ref={ref} onMouseDown={onMouseDown} onMouseUp={onMouseUp} onTouchEnd={onTouchEnd}>
4 {/* Some other content */}
5 {children} {/* Make sure to include children to add resizable handle */}
6 </div>
7 );
8})
The same is true of custom elements as draggable handles using the draggableHandle
prop. This is so that
the underlying react-draggable
library can get a reference to the DOM node underneath, manipulate
positioning via style
, and set classes.
If you have a feature request, please add it as an issue or make a pull request.
If you have a bug to report, please reproduce the bug in CodeSandbox to help us easily isolate it.
data-grid
key)No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 11/30 approved changesets -- score normalized to 3
Reason
2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
21 existing vulnerabilities detected
Details
Score
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More