Dashboard Layout and Spacing#
Superset dashboards are composed of a tree of layout components (Grid → Row → Column → ChartHolder) rendered by React. Spacing between and inside those components is driven by a small set of numeric constants and by Emotion/styled-component rules scattered across a handful of files. Custom CSS authored in the Dashboard CSS editor targets the same class names produced by those styled components.
Grid Constants#
All spacing math originates in superset-frontend/src/dashboard/util/constants.ts:
| Constant | Value | Meaning |
|---|---|---|
GRID_BASE_UNIT | 8 px | Base unit for all spacing calculations |
GRID_GUTTER_SIZE | 16 px (2 × GRID_BASE_UNIT) | Space between columns within a row |
GRID_COLUMN_COUNT | 12 | Total column units across the full dashboard width |
GRID_MIN_COLUMN_COUNT | 1 | Minimum width of any chart in column units |
GRID_MIN_ROW_UNITS | 5 | Minimum height of any chart in row units |
GRID_MAX_ROW_UNITS | 100 | Maximum chart height in row units |
GRID_DEFAULT_CHART_WIDTH | 4 | Default chart width in column units |
Chart pixel dimensions are computed in ChartHolder.tsx:
chartWidth = widthMultiple × columnWidth + (widthMultiple − 1) × GRID_GUTTER_SIZE − CHART_MARGIN
chartHeight = component.meta.height × GRID_BASE_UNIT − CHART_MARGIN
CHART_MARGIN is 32 px , reserving space for the chart card padding.
Component Hierarchy and Class Names#
.dashboard-grid ← DashboardGrid root div
.grid-content ← GridContent styled-div
.grid-row ← Row → GridRow styled-div
.grid-column ← Column → ColumnStyles styled-div
.dashboard-component ← ChartHolder outer div
.dashboard-component-chart-holder
.dashboard-chart-id-<N> ← per-chart CSS hook
.dashboard-grid / .grid-content#
DashboardGrid.jsx wraps everything in a plain div.dashboard-grid. Inside it, the GridContent styled-div :
- Uses
flex-direction: columnto stack rows vertically. - Adds
margin-bottom: theme.sizeUnit × 4(32 px) between rows in view mode (removed in edit mode). - The
.grid-containerouter margins (margin-top/bottom: 32 px,margin-right: 64 px) are set inStyledDashboardContentinsideDashboardBuilder.tsx.
Column widths are computed from the measured container width :
columnPlusGutterWidth = (width + GRID_GUTTER_SIZE) / GRID_COLUMN_COUNT
columnWidth = columnPlusGutterWidth − GRID_GUTTER_SIZE
.grid-row#
Rendered by Row.jsx as the GridRow styled-div :
display: flex; flex-direction: row; flex-wrap: nowrap; align-items: flex-start- Adds
margin-right: 32 pxbetween children (charts/columns) in view mode. - Empty rows (
.grid-row--empty) havemin-height: 200 px(theme.sizeUnit × 25).
.grid-column#
Rendered by Column.jsx as the ColumnStyles styled-div :
width: 100%; position: relative- Children get
margin-bottom: 32 px(sametheme.sizeUnit × 4pattern) in view mode. - In edit mode, a dashed border overlay (1 px
colorBorder, turnscolorPrimaryon hover) is added via the::afterpseudo-element.
.dashboard-component-chart-holder#
The innermost card div in ChartHolder.tsx also receives:
dashboard-componentdashboard-chart-id-<chartId>— unique per chart, enabling custom CSS rules targeting individual charts.fade-in/fade-out— filter-focus highlight state.
The card's own padding (32 px on all sides) and background come from the StyledDashboardContent rule in DashboardBuilder.tsx :
.dashboard-component-chart-holder {
width: 100%; height: 100%;
background-color: theme.colorBgContainer;
padding: theme.sizeUnit × 4; /* 32 px */
overflow-y: visible;
}
This 32 px padding is also reflected in CHART_MARGIN = 32 — the constant subtracted from the computed chart pixel dimensions so the chart content fits inside the padded card.
Edit-Mode Visual Differences#
DashboardBuilder.tsx applies .dashboard--editing to DashboardContentWrapper :
.grid-row::aftergets a dashedcolorBorderoverlay; it turns2 px dashed colorPrimarywhen the row is hovered (.grid-row--hovered)..dashboard-component-chart-holder::afteroverlay changes from transparent to1 px dashed colorPrimaryon hover.- Chart content (
.chart-container) getsopacity: 0.2,cursor: move, andpointer-events: noneon the slice; hovering the holder restores opacity to0.7. - Row gutters (
margin-right) and column gutters (margin-bottom) are removed in edit mode — instead, rows inside.dashboard-component-tabs-contentgetpadding-top: 32 pxto preserve hit area .
DashboardWrapper.tsx adds dragdroppable--dragging when a drag is in flight , activating drop-target highlight styles (border-color: primary.light1, background-color: primary.light3). Row hover menus inside columns are inset by left: -24 px via a scoped rule there .
Custom CSS Hooks#
Custom dashboard CSS is injected into <head> by injectCustomCss.ts (via a useEffect in DashboardPage) and is not automatically scoped to the dashboard subtree — authors must prefix selectors manually (e.g. .dashboard-grid .my-widget { … }) to avoid bleeding into the global chrome . Key stable selectors to target:
| Selector | Targets |
|---|---|
.dashboard-grid | Entire grid area |
.grid-row | Any row container |
.grid-column | Any column container |
.dashboard-component-chart-holder | All chart cards |
.dashboard-chart-id-<N> | One specific chart card (by chart ID) |
.background--white / .background--transparent | Row/column background style |
The BACKGROUND_WHITE and BACKGROUND_TRANSPARENT style options are defined alongside the grid constants in constants.ts.