Repository navigation
Styles
This page explains how cell styles work in the draw.io code: the style string syntax, the stylesheet, how a cell's style is resolved, how to read and change styles in code, colours and dark mode, and the defaults for new cells. It is for plugin authors, forkers and anyone generating diagrams. The full list of style keys and values is maintained in the style reference; this page groups the important ones and points to the code that reads them.
To see the style of any shape, select it and use Edit > Edit Style (Ctrl+E).
A cell style is a string stored in the cell's style attribute:
rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;
ellipse;whiteSpace=wrap;html=1;aspect=fixed;
text;html=1;align=center;verticalAlign=middle;
mxStylesheet.prototype.getCellStyle (mxStylesheet.js) parses it:
- Entries are separated by
;. An entry with=is akey=valuepair; an entry without=is the name of a style in the stylesheet (ellipse,text,swimlane, ...), whose keys are merged in. Unknown names are ignored. - Entries apply from left to right, starting from the default vertex or edge style. By convention named styles come first.
- A value of
noneremoves the key from the resolved style, for example to remove a key that a named style or the defaults set. Colour keys treat a missing value as no colour, sofillColor=nonemeans no fill. - A style that starts with
;does not start from the default vertex or edge style. - Numeric values are converted to numbers; everything else stays a string. Booleans are
0and1. - The format has no escaping, so values cannot contain
;or=. Values that need them are URI-encoded (fontSource, the JSON form ofchildLayout), and images are stored as data URIs without;base64:image=data:image/png,iVBORw0....EditorUi.prototype.convertDataUriremoves;base64when an image is added, andmxGraph.prototype.postProcessCellStyleputs it back when the style is resolved.
The key names are the values of the STYLE_* constants in mxConstants.js (mxConstants.STYLE_FILLCOLOR is 'fillColor'), plus many keys that draw.io adds and reads by name in Graph.js, Shapes.js and diagramly/Editor.js. Graph.cellStyles, Graph.textStyles and Graph.edgeStyles list the keys that the default style for new cells carries over (see Defaults for new cells). Editor.commonVertexProperties, Editor.commonEdgeProperties and the customProperties arrays of the shape classes (in diagramly/Editor.js) list further keys with their types and defaults; they drive the Property table in the Format panel.
The stylesheet maps style names to sets of keys. draw.io's is styles/default.xml:
<mxStylesheet>
<add as="defaultVertex">
<add as="shape" value="label"/>
<add as="fillColor" value="default"/>
...
</add>
<add as="defaultEdge"> ... </add>
<add as="text"> ... </add>
<add as="edgeLabel" extend="text"> ... </add>
...
</mxStylesheet>defaultVertex and defaultEdge are the starting point for every vertex and edge. The other named styles are text, edgeLabel, label, icon, swimlane, group, ellipse, rhombus, triangle, line, image, roundImage, rhombusImage, arrow, plus the colour presets fancy, gray, blue, ... and plain-gray, plain-blue, ....
How it is loaded:
-
Graph.prototype.loadStylesheetdecodesthis.themes[this.defaultThemeName]into the graph'smxStylesheetwithmxCodec(mxStylesheetCodec). In draw.io,defaultThemeNameisdefault-style2. - The build turns
default.xmlintoGraph-Stylesheet.js, which setsGraph.prototype.defaultThemes['default-style2'](and'darkTheme'to the same document) and is compiled intoapp.min.js. In development mode (?dev=1)App.mainloadsstyles/default.xmlinstead. Edits todefault.xmltherefore need a rebuild (see Building). - There is no separate dark stylesheet: dark mode uses the same styles and resolves
defaultcolours at render time (see Colours and dark mode).styles/dark-default.xmlandstyles/default-old.xmlare in the repository but the current code does not load them.
The stylesheet is not saved in diagram files. A plugin can add named styles at runtime:
var style = {};
style[mxConstants.STYLE_FILLCOLOR] = '#fff2cc';
style[mxConstants.STYLE_STROKECOLOR] = '#d6b656';
graph.getStylesheet().putCellStyle('myHighlight', style); // style="myHighlight;html=1;"but the names only resolve where the plugin is loaded; in other draw.io installations, the viewer or exports made elsewhere those cells lose the keys. Write the keys into the cell style instead when the file leaves your environment.
graph.getCellStyle(cell, resolve) (mxGraph.js) builds a style object:
- Start with a copy of
defaultEdgefor edges, otherwisedefaultVertex. - Apply the cell's style string with
mxStylesheet.getCellStyle(named styles,key=value,none). - If
resolveis not false, rungraph.postProcessCellStyle(cell, style):-
mxGraph: resolves image bundle keys and turns short data URIs back into valid ones. -
Graph.replaceDefaultColors: replaces the colour valuedefaultwith the theme colours (see below). -
Graph.updateHorizontalStyle: setshorizontalfor collapsed cells in a stack layout. -
Graph.processFontStyle(diagramly): loads a web font whenfontSourceis set.
-
graph.getCurrentCellStyle(cell) returns the style cached in the cell state (graph.view.getState(cell).style) when the cell is rendered, otherwise getCellStyle(cell). Use it for reading effective values; it is what the editor uses. Use graph.getCellStyle(cell, false) for the unresolved values (default and none kept as written). Values are numbers or strings, so read them with mxUtils.getValue(style, key, defaultValue) and compare booleans with == '1' or == 1 as the code does.
The view uses the resolved style to pick the shape (shape), the perimeter (perimeter, by name through mxStyleRegistry), the edge router (edgeStyle) and everything the shape paints.
| Call | Purpose |
|---|---|
model.getStyle(cell) |
The raw style string. |
graph.getCurrentCellStyle(cell), graph.getCellStyle(cell, resolve)
|
Resolved style object (see above). |
graph.setCellStyles(key, value, cells) |
Set one key on several cells; null removes it. Undoable. Defaults to the selection. |
graph.toggleCellStyles(key, defaultValue, cells) |
Toggle a 0/1 key. |
graph.setCellStyleFlags(key, flag, value, cells) |
Set or clear a bit, for example in fontStyle. |
graph.setCellStyle(style, cells) |
Replace the whole style string. |
graph.updateCellStyles(styleObject, cells) |
Set every key of an object on the cells. |
model.setStyle(cell, style) |
Replace one cell's style string (undoable). |
mxUtils.setStyle(style, key, value) |
String helper: returns the style with the key set or removed. |
mxUtils.getStylenames(style), mxUtils.addStylename(style, name), mxUtils.removeStylename(style, name)
|
Named-style helpers. |
Graph.prototype.setCellStyles adds special handling for some keys (curved also sets curveGeometry on edges; tableRender converts table borders), so prefer it to editing strings yourself.
Draw.loadPlugin(function(ui)
{
var graph = ui.editor.graph;
var cells = graph.getSelectionCells();
graph.getModel().beginUpdate();
try
{
graph.setCellStyles(mxConstants.STYLE_FILLCOLOR, '#f8cecc', cells);
graph.setCellStyles('rounded', '1', cells);
graph.setCellStyleFlags(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_BOLD, true, cells);
}
finally
{
graph.getModel().endUpdate();
}
var style = graph.getCurrentCellStyle(cells[0]);
console.log(mxUtils.getValue(style, 'fillColor', 'none'));
});Grouped by purpose; see the style reference for values and the complete list.
| Group | Keys |
|---|---|
| Shape |
shape, perimeter, direction (north, south, east, west), rotation, flipH, flipV, aspect=fixed, rounded, arcSize, absoluteArcSize
|
| Fill and line |
fillColor, gradientColor, gradientDirection, strokeColor, strokeWidth, dashed, dashPattern, opacity, fillOpacity, strokeOpacity, shadow, glass, sketch (hand-drawn, with fillStyle, hachureGap, ...) |
| Text |
html=1 (HTML label), whiteSpace=wrap, fontFamily, fontSize, fontColor, fontStyle (bit flags: 1 bold, 2 italic, 4 underline, 8 strikethrough), fontSource, align, verticalAlign, labelPosition, verticalLabelPosition, spacing, spacingTop / Left / Bottom / Right, labelBackgroundColor, labelBorderColor, textOpacity, horizontal=0 (vertical text), overflow, noLabel, autosize
|
| Image |
shape=image, image, imageAspect, imageWidth, imageHeight, imageAlign, imageBackground, imageBorder, clipPath
|
| Edge routing |
edgeStyle, elbow, curved, rounded, orthogonalLoop, jettySize, jumpStyle, jumpSize
|
| Edge ends |
startArrow, endArrow, startFill, endFill, startSize, endSize, exitX, exitY, exitDx, exitDy, exitPerimeter, entryX, entryY, entryDx, entryDy, entryPerimeter, sourcePerimeterSpacing, targetPerimeterSpacing
|
| Containers |
container, collapsible, swimlane shape with startSize, childLayout, expand, recursiveResize, dropTarget, part
|
| Behaviour |
locked, movable, resizable, rotatable, deletable, editable, cloneable, bendable, connectable, pointerEvents, points
|
Some of these need explanation:
-
html: withhtml=1the label is HTML, sanitised when rendered; without it, the label is plain text.graph.isHtmlLabel(cell)also returns true forwhiteSpace=wrap, but the text is then escaped and only wrapped. -
edgeStyle: the name of a registered router, for exampleorthogonalEdgeStyle,elbowEdgeStyle(withelbow=verticalorhorizontal),entityRelationEdgeStyle,segmentEdgeStyle,isometricEdgeStyle, ornonefor straight segments through the waypoints.curved=1draws curves through the route;rounded=1rounds the corners. The routers are inmxEdgeStyle.jsandShapes.jsand are registered by name withmxStyleRegistry.putValue(mxStyleRegistry.js). -
exitX/exitY/entryX/entryY: fixed connection points as fractions (0..1) of the terminal's bounds, withexitDx/exitDypixel offsets;exitPerimeter=0keeps the point where it is instead of projecting it onto the perimeter. Without them the edge floats. -
points: the connection points offered on a vertex, as a JSON array of[x, y]or[x, y, perimeter, dx, dy], for examplepoints=[[0,0],[0.5,0],[1,0,0,-10,10]](Graph.prototype.getAllConnectionConstraints). Without it the shape's or stencil's own constraints are used. -
container/collapsible: a vertex accepts children when dropped onto it ifcontainer=1; swimlanes are containers unlesscontainer=0.collapsible=0hides the fold icon of a container;collapsible=1enables folding for a non-container. -
childLayout: runs a layout on the children whenever they change (Graph.prototype.initLayoutManager):stackLayout(withhorizontalStack,resizeParent,resizeLast,stackSpacing,marginTop, ...),treeLayout,flowLayout,circleLayout,organicLayout,tableLayout,rack, or a URI-encoded JSON layout array (see the JSON layout specification). -
locked:locked=1locks the cell and its descendants (Graph.isCellLockedchecks ancestors). Edit > Lock/Unlock (Ctrl+L) setslocked,movable,resizable,rotatable,deletable,editableandconnectabletogether. -
part=1: the cell is part of its parent vertex; dragging it moves the parent (Graph.prototype.getCompositeParent).
Links, tooltips, tags and placeholders are not style keys; they are attributes of the cell's user object (see Graph model).
shape names either a registered shape class or a stencil:
-
Registered shapes are JavaScript classes registered with
mxCellRenderer.registerShape(name, constructor). The core shapes (rectangle,ellipse,rhombus,cylinder,connector,actor,triangle,hexagon,cloud,line,arrow,arrowConnector,doubleEllipse,swimlane,image,label) are registered inmxCellRenderer.js; draw.io adds about a hundred more inShapes.js(cylinder3,note,process,umlLifeline,table, ...). -
Stencils are shapes defined in XML and looked up with
mxStencilRegistry.getStencil(name)when no class is registered under the name. The shape libraries use names such asshape=mxgraph.aws4.resourceIcon, loaded on demand by prefix. -
Inline stencils:
shape=stencil(...)holds a compressed stencil XML in the style itself (Edit Shape in the editor writes these).
A stencil can define connection points; points= in the style overrides them. Writing and registering shapes is covered in Shapes and stencils.
A colour value is one of:
| Value | Meaning |
|---|---|
#rrggbb, rgb(...), a CSS colour name |
Fixed colour. |
none |
No colour. |
default |
Theme colour, resolved by Graph.prototype.replaceDefaultColors: the foreground Graph.prototype.shapeForegroundColor (light-dark(#000000, #ffffff)) for strokeColor, fontColor, gradientColor, labelBorderColor, imageBorder, and the background Graph.prototype.shapeBackgroundColor (white in light mode, Editor.darkColor #121212 in dark mode) for fillColor, labelBackgroundColor, swimlaneFillColor, imageBackground. |
light-dark(<light>, <dark>) |
Separate colours for light and dark mode, as written by the colour dialog when a dark colour is set. |
The defaults in default.xml use default, which is why a shape without colours adapts to dark mode. For a key set to default, the style key default<Key> changes the result: invert swaps the light and dark values, and page uses the page background colour (for example labelBackgroundColor=default;defaultLabelBackgroundColor=page), see Graph.prototype.getDefaultColor.
The adaptiveColors attribute of each page (the Adaptive Colors submenu in the editor; Graph.prototype.getAdaptiveColors) decides what happens to fixed colours when the diagram is shown in dark mode:
| Value | Effect |
|---|---|
auto (default) |
Every fixed colour gets a computed dark variant (mxUtils.getInverseColor, through mxUtils.parseLightDarkColor). |
simple |
Fixed colours stay as they are; only default and light-dark() colours change. |
none |
The diagram is always drawn in light mode. |
The default for pages without the attribute is Graph.defaultAdaptiveColors, set with the defaultAdaptiveColors configuration option.
There are three layers of defaults:
-
The stylesheet (
defaultVertex,defaultEdge) applies to every cell, also in files, the viewer and exports. -
Graph.prototype.defaultVertexStyleandGraph.prototype.defaultEdgeStyleare the editor's defaults for new cells.defaultVertexStyleis empty anddefaultEdgeStyleis{edgeStyle: 'orthogonalEdgeStyle', rounded: '0', jettySize: 'auto', orthogonalLoop: '1'}. Set them with thedefaultVertexStyleanddefaultEdgeStyleconfiguration options. -
graph.currentVertexStyleandgraph.currentEdgeStylestart as copies of those and change when the user runs Set as Default Style, picks a theme in the Format panel or a connector style in the toolbar with no edge selected, or, with theupdateDefaultStyleconfiguration option, on every style change.Graph.prototype.pasteCellStylesapplies them to cells inserted from the sidebar and by paste (thecellsInsertedevent), skipping keys the cell's own style already sets. New edges drawn in the editor getgraph.createCurrentEdgeStyle().
Cells you add with graph.insertVertex or graph.insertEdge in code get none of the editor defaults in (2) and (3), only the stylesheet; pass a complete style string, for example whiteSpace=wrap;html=1; for vertices and edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1; for edges, or call graph.pasteCellStyles(cells) to apply the current defaults.
-
Themes in the Format panel (nothing selected, the Style tab) come from
Editor.styles: an array of{commonStyle, vertexStyle, edgeStyle, graph: {background, gridColor}}objects. Picking one sets the current styles, restyles all cells on the page and sets the page background and grid colour. Replace the list with thestylesconfiguration option. -
Colour schemes (the quick colour buttons for selected shapes) come from
StyleFormatPanel.prototype.defaultColorSchemes, replaced or extended with thedefaultColorSchemesandcustomColorSchemesoptions.
The options are described in Configure the diagram editor and Configuration.
With the compressStyles configuration option, a data-URI image or inline stencil that several cells use is stored once in the file and referenced as image=def(n) / shape=def(n). This is a file-level feature of mxModelCodec; the resolved styles are the same. See File format and Style compression.
- Graph model: cells, transactions and the view.
- File format: where styles are stored.
- Shapes and stencils: custom shapes and stencil XML.
- Configuration: default styles, themes and colour schemes.
- Extending the editor and Plugins.
Describes the dev branch of jgraph/drawio as of release 32.3.0 (October 2026). Internal JavaScript APIs change between releases; check the code of the version you use. · Questions: Discussions · Bugs: Issues · Vulnerabilities: report privately · User docs: drawio.com/docs
Get started
Concepts
Guides
- Self-hosting
- Configuration
- Storage backends
- OneDrive app registration
- Embedding
- Diagrams in GitHub
- Plugins
- Extending the editor
- Shapes and stencils
- Import and export
- Desktop app
- Internationalization
Reference
Project
Elsewhere