react-draggable vs react-resizable vs react-split-pane vs react-split vs react-splitter-layout
React Layout Management Libraries Comparison
1 Year
react-draggablereact-resizablereact-split-panereact-splitreact-splitter-layoutSimilar Packages:
What's React Layout Management Libraries?

These libraries provide various functionalities for managing layout interactions in React applications. They enable developers to create draggable, resizable, and split layouts, enhancing user experience by allowing dynamic adjustments to the UI. Each library has its unique focus, catering to different use cases in layout management, from simple drag-and-drop to complex split-pane interfaces.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
react-draggable2,627,6209,175244 kB2472 years agoMIT
react-resizable1,151,6302,511116 kB782 years agoMIT
react-split-pane174,7123,269-1675 years agoMIT
react-split110,8806,20938.2 kB172-MIT
react-splitter-layout13,973431-386 years agoMIT
Feature Comparison: react-draggable vs react-resizable vs react-split-pane vs react-split vs react-splitter-layout

Draggable Functionality

  • react-draggable:

    react-draggable provides an easy-to-use API for making elements draggable. It allows you to handle drag events and provides options for controlling the movement, including bounds and axis constraints. This makes it suitable for implementing drag-and-drop features in a straightforward manner.

  • react-resizable:

    react-resizable does not focus on drag functionality but can be combined with draggable elements to create resizable components. It allows you to define handles for resizing and provides a simple interface for managing size changes, but it lacks built-in drag capabilities.

  • react-split-pane:

    react-split-pane offers a split-pane layout where each pane can be resized, but it does not provide drag-and-drop capabilities for moving elements around. It is more about managing the layout rather than dragging items.

  • react-split:

    react-split focuses on splitting areas into resizable sections, but it does not inherently support dragging elements outside of the split context. It is designed for layout management rather than individual element dragging.

  • react-splitter-layout:

    react-splitter-layout combines both splitting and dragging features, allowing users to adjust the layout dynamically. It supports draggable splitters and can manage complex layouts with multiple resizable sections.

Resizable Components

  • react-draggable:

    react-draggable does not provide resizing capabilities; it focuses solely on dragging elements. If you need resizing, you would have to integrate it with another library like react-resizable.

  • react-resizable:

    react-resizable is specifically designed for resizing components. It allows you to set minimum and maximum sizes, making it ideal for applications where user control over dimensions is necessary.

  • react-split-pane:

    react-split-pane provides robust resizing capabilities, allowing users to adjust the size of panes with ease. It includes features for setting limits on resizing, making it suitable for applications with complex layouts.

  • react-split:

    react-split allows for resizing of split sections but does not provide the same level of control as react-resizable. It is more about managing the overall layout rather than individual component resizing.

  • react-splitter-layout:

    react-splitter-layout offers advanced resizing options, allowing for flexible layout designs. Users can resize sections dynamically, and it supports complex configurations with multiple resizable areas.

Ease of Integration

  • react-draggable:

    react-draggable is lightweight and easy to integrate into existing projects. It requires minimal setup and can be added to any component that needs dragging functionality.

  • react-resizable:

    react-resizable is also straightforward to integrate, requiring only a few lines of code to implement resizing on components. It is designed to work seamlessly with other React components.

  • react-split-pane:

    react-split-pane requires a bit more setup due to its more complex features, but it is still manageable for developers familiar with React. It provides a comprehensive API for customizing pane behavior.

  • react-split:

    react-split is simple to use and can be integrated quickly into projects that require basic split layouts. It has a minimal API that makes it easy to get started.

  • react-splitter-layout:

    react-splitter-layout may have a steeper learning curve due to its advanced features, but it offers great flexibility for developers looking to create intricate layouts. Its API is well-documented, aiding integration.

Customization Options

  • react-draggable:

    react-draggable allows for some customization of drag behavior, such as setting boundaries and axis constraints, but it is limited in terms of styling the draggable elements themselves.

  • react-resizable:

    react-resizable offers customization for resize handles and can be styled to fit the application's design. Developers can define how the resize handles appear and behave.

  • react-split-pane:

    react-split-pane allows for significant customization of pane sizes and styles, including the ability to define minimum and maximum sizes and customize the appearance of the splitter.

  • react-split:

    react-split provides basic customization options for the split areas but is limited in terms of styling and behavior compared to other libraries.

  • react-splitter-layout:

    react-splitter-layout provides extensive customization options, allowing developers to define styles for splitters and panes, as well as control their behavior in detail.

Performance

  • react-draggable:

    react-draggable is optimized for performance, handling drag events efficiently without causing significant re-renders. It is designed to be lightweight and responsive.

  • react-resizable:

    react-resizable maintains good performance by minimizing re-renders during resizing operations. It is efficient for applications where resizing is a frequent action.

  • react-split-pane:

    react-split-pane is designed for performance, ensuring that resizing operations do not lead to excessive re-renders, making it suitable for applications with multiple panes.

  • react-split:

    react-split is lightweight and performs well for basic split layouts, but performance may vary with complex nested splits.

  • react-splitter-layout:

    react-splitter-layout is optimized for performance in complex layouts, ensuring smooth resizing and minimal impact on rendering times.

How to Choose: react-draggable vs react-resizable vs react-split-pane vs react-split vs react-splitter-layout
  • react-draggable:

    Choose react-draggable if you need a simple and straightforward way to make elements draggable within your application. It's best for scenarios where you want to implement drag-and-drop functionality without the need for resizing or complex layouts.

  • react-resizable:

    Select react-resizable if your primary requirement is to allow users to resize components. This library is ideal for applications that need adjustable UI elements, such as panels or widgets, where user control over size is essential.

  • react-split-pane:

    Use react-split-pane when you need a more robust solution for creating adjustable split layouts with additional features like minimum and maximum sizes for panes. This package is great for complex applications where user experience is enhanced by customizable layouts.

  • react-split:

    Opt for react-split if you want a lightweight solution for creating split layouts. This library is suitable for applications that require a simple way to divide space into resizable sections, like editors or dashboards.

  • react-splitter-layout:

    Choose react-splitter-layout for a more advanced layout management solution that combines splitting and resizing capabilities with a flexible layout system. It's perfect for applications that require intricate layout designs with multiple resizable sections.

README for react-draggable

React-Draggable

TravisCI Build Status Appveyor Build Status npm downloads gzip size version

A simple component for making elements draggable.

<Draggable>
  <div>I can now be moved around!</div>
</Draggable>

|Version | Compatibility| |------------|--------------| |4.x | React 16.3+ | |3.x | React 15-16 | |2.x | React 0.14 - 15 | |1.x | React 0.13 - 0.14 | |0.x | React 0.10 - 0.13 |


Technical Documentation

Installing

$ npm install react-draggable

If you aren't using browserify/webpack, a UMD version of react-draggable is available. It is updated per-release only. This bundle is also what is loaded when installing from npm. It expects external React and ReactDOM.

If you want a UMD version of the latest master revision, you can generate it yourself from master by cloning this repository and running $ make. This will create umd dist files in the dist/ folder.

Exports

The default export is <Draggable>. At the .DraggableCore property is <DraggableCore>. Here's how to use it:

// ES6
import Draggable from 'react-draggable'; // The default
import {DraggableCore} from 'react-draggable'; // <DraggableCore>
import Draggable, {DraggableCore} from 'react-draggable'; // Both at the same time

// CommonJS
let Draggable = require('react-draggable');
let DraggableCore = Draggable.DraggableCore;

<Draggable>

A <Draggable> element wraps an existing element and extends it with new event handlers and styles. It does not create a wrapper element in the DOM.

Draggable items are moved using CSS Transforms. This allows items to be dragged regardless of their current positioning (relative, absolute, or static). Elements can also be moved between drags without incident.

If the item you are dragging already has a CSS Transform applied, it will be overwritten by <Draggable>. Use an intermediate wrapper (<Draggable><span>...</span></Draggable>) in this case.

Draggable Usage

View the Demo and its source for more.

import React from 'react';
import ReactDOM from 'react-dom';
import Draggable from 'react-draggable';

class App extends React.Component {

  eventLogger = (e: MouseEvent, data: Object) => {
    console.log('Event: ', e);
    console.log('Data: ', data);
  };

  render() {
    return (
      <Draggable
        axis="x"
        handle=".handle"
        defaultPosition={{x: 0, y: 0}}
        position={null}
        grid={[25, 25]}
        scale={1}
        onStart={this.handleStart}
        onDrag={this.handleDrag}
        onStop={this.handleStop}>
        <div>
          <div className="handle">Drag from here</div>
          <div>This readme is really dragging on...</div>
        </div>
      </Draggable>
    );
  }
}

ReactDOM.render(<App/>, document.body);

Draggable API

The <Draggable/> component transparently adds draggability to its children.

Note: Only a single child is allowed or an Error will be thrown.

For the <Draggable/> component to correctly attach itself to its child, the child element must provide support for the following props:

  • style is used to give the transform css to the child.
  • className is used to apply the proper classes to the object being dragged.
  • onMouseDown, onMouseUp, onTouchStart, and onTouchEnd are used to keep track of dragging state.

React.DOM elements support the above properties by default, so you may use those elements as children without any changes. If you wish to use a React component you created, you'll need to be sure to transfer prop.

<Draggable> Props:

//
// Types:
//
type DraggableEventHandler = (e: Event, data: DraggableData) => void | false;
type DraggableData = {
  node: HTMLElement,
  // lastX + deltaX === x
  x: number, y: number,
  deltaX: number, deltaY: number,
  lastX: number, lastY: number
};

//
// Props:
//
{
// If set to `true`, will allow dragging on non left-button clicks.
allowAnyClick: boolean,

// Determines which axis the draggable can move. This only affects
// flushing to the DOM. Callbacks will still include all values.
// Accepted values:
// - `both` allows movement horizontally and vertically (default).
// - `x` limits movement to horizontal axis.
// - `y` limits movement to vertical axis.
// - 'none' stops all movement.
axis: string,

// Specifies movement boundaries. Accepted values:
// - `parent` restricts movement within the node's offsetParent
//    (nearest node with position relative or absolute), or
// - a selector, restricts movement within the targeted node
// - An object with `left, top, right, and bottom` properties.
//   These indicate how far in each direction the draggable
//   can be moved.
bounds: {left?: number, top?: number, right?: number, bottom?: number} | string,

// Specifies a selector to be used to prevent drag initialization. The string is passed to
// Element.matches, so it's possible to use multiple selectors like `.first, .second`.
// Example: '.body'
cancel: string,

// Class names for draggable UI.
// Default to 'react-draggable', 'react-draggable-dragging', and 'react-draggable-dragged'
defaultClassName: string,
defaultClassNameDragging: string,
defaultClassNameDragged: string,

// Specifies the `x` and `y` that the dragged item should start at.
// This is generally not necessary to use (you can use absolute or relative
// positioning of the child directly), but can be helpful for uniformity in
// your callbacks and with css transforms.
defaultPosition: {x: number, y: number},

// If true, will not call any drag handlers.
disabled: boolean,

// Specifies the x and y that dragging should snap to.
grid: [number, number],

// Specifies a selector to be used as the handle that initiates drag.
// Example: '.handle'
handle: string,

// If desired, you can provide your own offsetParent for drag calculations.
// By default, we use the Draggable's offsetParent. This can be useful for elements
// with odd display types or floats.
offsetParent: HTMLElement,

// Called whenever the user mouses down. Called regardless of handle or
// disabled status.
onMouseDown: (e: MouseEvent) => void,

// Called when dragging starts. If `false` is returned any handler,
// the action will cancel.
onStart: DraggableEventHandler,

// Called while dragging.
onDrag: DraggableEventHandler,

// Called when dragging stops.
onStop: DraggableEventHandler,

// If running in React Strict mode, ReactDOM.findDOMNode() is deprecated.
// Unfortunately, in order for <Draggable> to work properly, we need raw access
// to the underlying DOM node. If you want to avoid the warning, pass a `nodeRef`
// as in this example:
//
// function MyComponent() {
//   const nodeRef = React.useRef(null);
//   return (
//     <Draggable nodeRef={nodeRef}>
//       <div ref={nodeRef}>Example Target</div>
//     </Draggable>
//   );
// }
//
// This can be used for arbitrarily nested components, so long as the ref ends up
// pointing to the actual child DOM node and not a custom component.
//
// For rich components, you need to both forward the ref *and props* to the underlying DOM
// element. Props must be forwarded so that DOM event handlers can be attached. 
// For example:
//
//   const Component1 = React.forwardRef(function (props, ref) {
//     return <div {...props} ref={ref}>Nested component</div>;
//   });
//
//   const nodeRef = React.useRef(null);
//   <DraggableCore onDrag={onDrag} nodeRef={nodeRef}>
//     <Component1 ref={nodeRef} />
//   </DraggableCore>
//
// Thanks to react-transition-group for the inspiration.
//
// `nodeRef` is also available on <DraggableCore>.
nodeRef: React.Ref<typeof React.Component>,

// Much like React form elements, if this property is present, the item
// becomes 'controlled' and is not responsive to user input. Use `position`
// if you need to have direct control of the element.
position: {x: number, y: number}

// A position offset to start with. Useful for giving an initial position
// to the element. Differs from `defaultPosition` in that it does not
// affect the position returned in draggable callbacks, and in that it
// accepts strings, like `{x: '10%', y: '10%'}`.
positionOffset: {x: number | string, y: number | string},

// Specifies the scale of the canvas your are dragging this element on. This allows
// you to, for example, get the correct drag deltas while you are zoomed in or out via
// a transform or matrix in the parent of this element.
scale: number
}

Note that sending className, style, or transform as properties will error - set them on the child element directly.

Controlled vs. Uncontrolled

<Draggable> is a 'batteries-included' component that manages its own state. If you want to completely control the lifecycle of the component, use <DraggableCore>.

For some users, they may want the nice state management that <Draggable> provides, but occasionally want to programmatically reposition their components. <Draggable> allows this customization via a system that is similar to how React handles form components.

If the prop position: {x: number, y: number} is defined, the <Draggable> will ignore its internal state and use the provided position instead. Alternatively, you can seed the position using defaultPosition. Technically, since <Draggable> works only on position deltas, you could also seed the initial position using CSS top/left.

We make one modification to the React philosophy here - we still allow dragging while a component is controlled. We then expect you to use at least an onDrag or onStop handler to synchronize state.

To disable dragging while controlled, send the prop disabled={true} - at this point the <Draggable> will operate like a completely static component.

<DraggableCore>

For users that require absolute control, a <DraggableCore> element is available. This is useful as an abstraction over touch and mouse events, but with full control. <DraggableCore> has no internal state.

See React-Resizable and React-Grid-Layout for some usage examples.

<DraggableCore> is a useful building block for other libraries that simply want to abstract browser-specific quirks and receive callbacks when a user attempts to move an element. It does not set styles or transforms on itself and thus must have callbacks attached to be useful.

DraggableCore API

<DraggableCore> takes a limited subset of options:

{
  allowAnyClick: boolean,
  cancel: string,
  disabled: boolean,
  enableUserSelectHack: boolean,
  offsetParent: HTMLElement,
  grid: [number, number],
  handle: string,
  onStart: DraggableEventHandler,
  onDrag: DraggableEventHandler,
  onStop: DraggableEventHandler,
  onMouseDown: (e: MouseEvent) => void,
  scale: number
}

Note that there is no start position. <DraggableCore> simply calls drag handlers with the below parameters, indicating its position (as inferred from the underlying MouseEvent) and deltas. It is up to the parent to set actual positions on <DraggableCore>.

Drag callbacks (onStart, onDrag, onStop) are called with the same arguments as <Draggable>.


Contributing

  • Fork the project
  • Run the project in development mode: $ npm run dev
  • Make changes.
  • Add appropriate tests
  • $ npm test
  • If tests don't pass, make them pass.
  • Update README with appropriate docs.
  • Commit and PR

Release checklist

  • Update CHANGELOG
  • make release-patch, make release-minor, or make-release-major
  • make publish

License

MIT