Theming

React Flow has been built with deep customization in mind. Many of our users fully transform the look and feel of React Flow to match their own brand or design system. This guide will introduce you to the different ways you can customize React Flow’s appearance.

Default styles

React Flow’s default styles are enough to get going with the built-in nodes. They provide some sensible defaults for styles like padding, border radius, and animated edges. You can see what they look like below:

Example: examples/styling/default-style

App.tsx
import { useCallback } from 'react';
import {
  ReactFlow,
  Background,
  Controls,
  MiniMap,
  useNodesState,
  useEdgesState,
  addEdge,
  Position,
} from '@xyflow/react';
import './index.css';
 
const nodeDefaults = {
  sourcePosition: Position.Right,
  targetPosition: Position.Left,
};
 
const initialNodes = [
  {
    id: '1',
    position: { x: 0, y: 150 },
    data: { label: 'default style 1' },
    ...nodeDefaults,
  },
  {
    id: '2',
    position: { x: 250, y: 0 },
    data: { label: 'default style 2' },
    ...nodeDefaults,
  },
  {
    id: '3',
    position: { x: 250, y: 150 },
    data: { label: 'default style 3' },
    ...nodeDefaults,
  },
  {
    id: '4',
    position: { x: 250, y: 300 },
    data: { label: 'default style 4' },
    ...nodeDefaults,
  },
];
 
const initialEdges = [
  {
    id: 'e1-2',
    source: '1',
    target: '2',
    animated: true,
  },
  {
    id: 'e1-3',
    source: '1',
    target: '3',
  },
  {
    id: 'e1-4',
    source: '1',
    target: '4',
  },
];
 
const Flow = () => {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
 
  const onConnect = useCallback((params) => setEdges((els) => addEdge(params, els)), []);
 
  return (
    <ReactFlow
      nodes={nodes}
      edges={edges}
      onNodesChange={onNodesChange}
      onEdgesChange={onEdgesChange}
      onConnect={onConnect}
      fitView
      colorMode="system"
    >
      <Background />
      <Controls />
      <MiniMap />
    </ReactFlow>
  );
};
 
export default Flow;
index.css
@import url('@xyflow/react/dist/style.css');
html,
body {
  margin: 0;
  font-family: sans-serif;
}
 
#app {
  width: 100vw;
  height: 100vh;
}
index.tsx
import { createRoot } from 'react-dom/client';
import App from './App';
 
 
const container = document.querySelector('#app');
const root = createRoot(container);
 
root.render(<App />);

You’ll typically load these default styles by importing them in you App.jsx file or other entry point:

import '@xyflow/react/dist/style.css';

Without dipping into custom nodes and edges, there are three ways you can style React Flow’s basic look:

  • Passing inline styles through style props
  • Overriding the built-in classes with custom CSS
  • Overriding the CSS variables React Flow uses
Built in dark and light mode

You can choose one of the built-in color modes by using the colorMode prop (‘dark’, ‘light’ or ‘system’) as seen in the dark mode example.

import ReactFlow from '@xyflow/react';
 
export default function Flow() {
  return <ReactFlow colorMode="dark" nodes={[...]} edges={[...]} />
}

When you use the colorMode prop, React Flow adds a class to the root element (.react-flow) that you can use to style your flow based on the color mode:

.dark .react-flow__node {
  background: #777;
  color: white;
}
 
.light .react-flow__node {
  background: white;
  color: #111;
}
Customizing with style props

The easiest way to start customizing the look and feel of your flows is to use the style prop found on many of React Flow’s components to inline your own CSS.

import ReactFlow from '@xyflow/react'
 
const styles = {
  background: 'red',
  width: '100%',
  height: 300,
};
 
export default function Flow() {
  return <ReactFlow style={styles} nodes={[...]} edges={[...]} />
}
CSS variables

If you don’t want to replace the default styles entirely but just want to tweak the overall look and feel, you can override some of the CSS variables we use throughout the library. For an example of how to use these CSS variables, check out our Feature Overview example.

These variables are mostly self-explanatory. Below is a table of all the variables you might want to tweak and their default values for reference:

These variables are used to define the defaults for the various elements of React Flow. This means they can still be overridden by inline styles or custom classes on a per-element basis. If you want to override these variables, you can do so by adding:

.react-flow {
  --xy-node-background-color-default: #ff5050;
}
Be aware that these variables are defined under `.react-flow` and under `:root`.
Overriding built-in classes

Some consider heavy use of inline styles to be an anti-pattern. In that case, you can override the built-in classes that React Flow uses with your own CSS. There are many classes attached to all sorts of elements in React Flow, but the ones you’ll likely want to override are listed below:

Be careful if you go poking around the source code looking for other classes to override. Some classes are used internally and are required in order for the library to be functional. If you replace them you may end up with unexpected bugs or errors!

Third-party solutions

You can choose to opt-out of React Flow’s default styling altogether and use a third-party styling solution instead. If you want to do this, you must make sure you still import the base styles.

import '@xyflow/react/dist/base.css';
These base styles are **required** for React Flow to function correctly. If you don't expected!

Example: examples/styling/base-style

App.jsx
import { useCallback } from 'react';
import {
  ReactFlow,
  Background,
  Controls,
  MiniMap,
  useNodesState,
  useEdgesState,
  addEdge,
  Position,
} from '@xyflow/react';
import './index.css';
 
const nodeDefaults = {
  sourcePosition: Position.Right,
  targetPosition: Position.Left,
};
 
const initialNodes = [
  {
    id: '1',
    position: { x: 0, y: 150 },
    data: { label: 'base style 1' },
    ...nodeDefaults,
  },
  {
    id: '2',
    position: { x: 250, y: 0 },
    data: { label: 'base style 2' },
    ...nodeDefaults,
  },
  {
    id: '3',
    position: { x: 250, y: 150 },
    data: { label: 'base style 3' },
    ...nodeDefaults,
  },
  {
    id: '4',
    position: { x: 250, y: 300 },
    data: { label: 'base style 4' },
    ...nodeDefaults,
  },
];
 
const initialEdges = [
  {
    id: 'e1-2',
    source: '1',
    target: '2',
  },
  {
    id: 'e1-3',
    source: '1',
    target: '3',
  },
  {
    id: 'e1-4',
    source: '1',
    target: '4',
  },
];
 
const Flow = () => {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
 
  const onConnect = useCallback((params) => setEdges((els) => addEdge(params, els)), []);
 
  return (
    <ReactFlow
      nodes={nodes}
      edges={edges}
      onNodesChange={onNodesChange}
      onEdgesChange={onEdgesChange}
      onConnect={onConnect}
      fitView
      colorMode="system"
    >
      <Background />
      <Controls />
      <MiniMap />
    </ReactFlow>
  );
};
 
export default Flow;
index.css
@import url('@xyflow/react/dist/base.css');
html,
body {
  margin: 0;
  font-family: sans-serif;
  box-sizing: border-box;
}
 
#app {
  width: 100vw;
  height: 100vh;
}
TailwindCSS

Custom nodes and edges are just React components, and you can use any styling solution you’d like to style them. For example, you might want to use Tailwind to style your nodes:

function CustomNode({ data }) {
  return (
    <div className="bg-background rounded-md border-2 border-stone-400 px-4 py-2 shadow-md">
      <div className="flex">
        <div className="bg-card flex h-12 w-12 items-center justify-center rounded-full">
          {data.emoji}
        </div>
        <div className="ml-2">
          <div className="text-lg font-bold">{data.name}</div>
          <div className="text-gray-500">{data.job}</div>
        </div>
      </div>
 
      <Handle type="target" position={Position.Top} className="w-16 bg-teal-500" />
      <Handle type="source" position={Position.Bottom} className="w-16 bg-teal-500" />
    </div>
  );
}
Import the React Flow stylesheet into the base layer so that Tailwind can override the default styles.
@import '@xyflow/react/dist/style.css' layer(base);
@import 'tailwindcss';

For a complete example of using Tailwind with React Flow, check out the example!