Plenty of internal admin panels and monitoring screens carry a full component framework just to get a sidebar and a few cards onto the page. Plain CSS handles that job fine these days.

Container queries are the biggest reason. According to web.dev, they became Baseline widely available in August 2025, so a card can switch layouts based on the width of its own grid cell and no longer has to wait on a viewport breakpoint.

What Is a CSS Dashboard?

See the Pen
Dashboard UI
by Håvard Brynjulfsen (@havardob)
on CodePen.


Admin Dashboard with Materialize

See the Pen
Admin Dashboard with Materialize
by Tirth Patel (@T-P)
on CodePen.

Take the data away and what’s left is one page split into named regions. Navigation, KPI cards, tables and chart containers all sit in those regions, positioned with CSS Grid, Flexbox and custom properties.

The stylesheet decides layout, theme and responsive behavior. The HTML stays plain, and the data comes from wherever the project already keeps it.

Most dashboards end up with the same skeleton. The header carries search and account controls, and the sidebar holds navigation. Everything else lives in the main area, which is the widget grid with the KPI cards, tables and chart containers inside it.

Since the whole user interface lives in one stylesheet, changing the sidebar width or the accent color takes a one-line edit.

The term gets stretched in a few directions, though. Libraries such as Highcharts Dashboards ship their own markup, and the Highcharts documentation lists a fixed set of class names (such as highcharts-dashboards-row and highcharts-dashboards-cell) that developers override with plain CSS.

Hosted tools go further in the same direction. Checkly lets customers restyle its dashboards through a custom CSS editor, but only on its Team and Enterprise plans, and the vendor still controls the markup.

Then there’s the version where the markup and the stylesheet are both yours. That’s what the rest of this article assumes.

CSS places widgets and styles them. Fetching data and drawing chart values stays with JavaScript.

What is shaping UX design today?

Uncover the newest UX design statistics: user behavior, design trends, ROI data, and insights driving better digital experiences.

Check Them Out →

Which CSS Layout Module Fits Each Dashboard Region?

See the Pen
Dashboard Design with Flexbox
by Aysenur Turk (@TurkAysenur)
on CodePen.

Grid runs the page frame and the widget area. Flexbox works better once you’re inside a single component, and subgrid only comes in when neighboring cards need their content to line up.

RegionModuleReason
Page frame (header, sidebar, main)CSS GridRows and columns defined together, named areas
Widget areaCSS GridAuto-fit columns, per-card spans
Card header, toolbar, nav itemsFlexboxOne axis, sized by content
Card content across a rowSubgridReuses parent tracks so labels and values align

A grid layout fits the frame because the header, sidebar and main region depend on each other’s size. Flexbox can’t express that relationship without nested wrappers.

A flex-only frame still works for a single-column admin panel. Once there’s more than one content column, Grid saves you the extra wrapper divs and the percentage math.

Subgrid fixes cards whose titles wrap to different heights and push their values out of line, because the nested grid reuses the parent’s tracks. MDN lists it as Baseline widely available, supported across browsers since September 2023.

Each of these has a spot where it quietly breaks. A subgridded dimension has no implicit grid, so any surplus items land in the last track (MDN).

The 1fr column catches people more often. It has an automatic minimum size, so a wide table stretches the layout past the screen until the track is written as minmax(0, 1fr). Flexbox has the same habit, since items refuse to shrink below their content width unless min-width is set to 0.

Use Grid for the frame and Flexbox inside components. Reach for subgrid only when cards need shared alignment. That split covers most dashboards.

Building the Dashboard Frame with grid-template-areas

The idea is to name the regions on the elements and describe the whole layout once, on the container. The main region then scrolls on its own.

  1. Write semantic HTML with a header, a nav or aside for the sidebar, and a main element.
  2. Give each element a grid-area name (header, sidebar and main).
  3. On the container, set display: grid, grid-template-columns: 240px minmax(0, 1fr), and grid-template-areas: “sidebar header” “sidebar main”.
  4. Set the container height to 100svh and grid-template-rows to auto minmax(0, 1fr), so the frame fills the screen and the page itself never scrolls.
  5. Add overflow: auto to main. The header and sidebar stay in place because they sit outside the scrolling region.

The area names have to describe a complete grid of rectangles. MDN’s guide to grid template areas states that every row needs the same number of cells and every named area must be rectangular, otherwise the property is ignored. That one bites easily, since a single typo in one row throws the whole declaration away.

Height needs care on phones. According to MDN, plain vh equals the large viewport, so a 100vh frame can run under the browser toolbar while the toolbar is showing.

svh sizes to the small viewport, so the frame always fits. dvh tracks the toolbar as it moves, but MDN notes that dynamic units are not stable even when the viewport is unchanged, which makes them a poor fit for a large scrolling region. I’d skip dvh here.

The minmax(0, 1fr) in step 3 is what stops a wide data table from stretching the main track.

I’d sketch the track sizes in a visual CSS grid generator first. It saves a few rounds of trial and error.

How to Make a CSS Dashboard Responsive

On a dashboard, responsive design mostly means keeping the data readable. Stacking everything into one column isn’t the goal. A table that scrolls sideways inside its card beats a table squeezed to an unreadable width.

The card grid doesn’t need breakpoints at all. repeat(auto-fit, minmax(240px, 1fr)) fills each row with as many cards as fit.

The page skeleton is different. Below a chosen width the sidebar moves to the top or into an off-canvas panel, and that’s still a job for media queries. MDN’s grid template areas guide shows the same pattern: assign the area names to the elements once, then redefine only grid-template-areas inside the query, so a sidebar can move without any change to the HTML.

Widgets are where container queries come in. A card shows full detail in a wide cell and a compact summary in a narrow one, whatever the viewport does.

Size container queries became Baseline newly available in February 2023, and web.dev’s August 2025 digest marks them widely available, which matches Baseline’s 30-month rule.

Style queries are newer. Container style queries for custom properties became Baseline newly available on 19 May 2026, when Firefox 151 joined Chrome and Edge 111 and Safari 18. Because they are not yet widely available, give visitors on older Firefox versions a fallback.

Every container has one limit. Setting container-type applies containment, so a container cannot take its size from its own contents on the queried axis.

Sidebar, Header, KPI Card and Data Table Styling

See the Pen
Admin Dashboard
by Robin Selmer (@robinselmer)
on CodePen.

The sidebar works best as a fixed-width track with a clear active link. Keep the text labels visible by default in the sidebar navigation and collapse to icons only on narrow screens.

In the frame built above, the header already stays put because main scrolls beneath it. Use position: sticky only when the whole page scrolls, and add scroll-padding-top equal to the header height so anchor links do not land underneath it.

Each KPI card needs a value and a label, plus some kind of change indicator. Pull border-radius, shadow and padding from shared custom properties so the cards match, then adapt existing card styles and vary only the accent color per metric.

Tables go inside an overflow-x: auto wrapper, and the header row should be sticky. Row actions need a hit area of at least 24 by 24 CSS pixels.

That 24-pixel floor is WCAG 2.2 success criterion 2.5.8 (Level AA). W3C’s Understanding document shows six icon buttons at 20 by 20 pixels passing with 4 pixels between them and failing with none.

Chart containers should reserve their space before the chart renders, with aspect-ratio or a fixed min-height, so a late-loading chart does not push the cards below it.

Every component should pull color from custom properties, and radius and spacing as well. That habit pays off the moment the theme changes.

Chart Rendering Options for a CSS Dashboard

See the Pen
Dashboard UI #1 : Project management with Charts
by Olsi Odobashi (@olsiodobashi)
on CodePen.

Draw small, static charts with CSS or inline SVG. Bring in a charting library when a chart needs tooltips or zoom, or when the data updates live.

A progress bar or share-of-total ring needs no more than a custom property and conic-gradient(), and the theme tokens recolor it for free. Examples of pure CSS charts usually stop there, because axes and tooltips are not something a stylesheet can supply.

Inline SVG in HTML goes further. Each mark is an element, so CSS can color it and a title element can name it for screen readers.

OptionProsCons
CSS-onlyNo JavaScript, themed by tokensNo axes, no tooltips
Inline SVGFull shape control, styled by CSSHand-built markup grows fast
Library (Chart.js, ApexCharts)Tooltips, zoom, live updatesScript weight, extra accessibility work

Libraries cost you in weight first. The ApexCharts installation docs list the default script-tag bundle at 263,188 bytes gzipped and the bare core at 157,032 (measured on version 8.0.0), which is a lot to ship for three bars.

Accessibility takes extra work too. Chart.js draws on a canvas, and its documentation says canvas content is not available to screen readers unless the page adds an aria-label with role=”img”, or fallback text inside the canvas tags.

The same page warns that a generic “browser does not support canvas” message counts as inaccessible fallback content.

Pick the lightest option that still shows the data honestly.

How to Add Dark Mode with Custom Properties

See the Pen
Dark UI – Bank dashboard concept
by Håvard Brynjulfsen (@havardob)
on CodePen.

Define each color token once on :root, set color-scheme to light dark, and let light-dark() pick the value. A prefers-color-scheme media query does the same job with more lines.

MDN lists light-dark() as Baseline 2024 newly available, working across browsers since May 2024. It only runs when color-scheme is light dark, usually declared on :root. The function also has an image form (two images instead of two colors), but that part is newer and not Baseline: Chrome, Edge and Firefox added it in version 150, and Safari (up to 26.5) does not support it.

Following the system setting is the simpler route. The tokens switch with the operating system and there’s no JavaScript and no stored state. The catch is that users cannot override it from inside the dashboard.

Letting the user choose takes more work. A data-theme attribute on the html element holds light, dark or auto, a short script reads the saved choice before first paint, and a control flips the attribute and stores the new value.

Bootstrap 5.3 takes the second route, with data-bs-theme on the html element or on a single component. Its documentation notes that switching the Sass mixin to the media query output removes per-component themes.

The same docs suggest loading the toggler script at the top of the page to reduce flicker on reload. That flicker is the usual failure of attribute-based themes, where the page paints light and then flips.

Hard-coded hex values inside components ignore the token swap, which is why one card stays light in a dark theme. Chart series need their own dark set too, and an accessible color palette generator helps when choosing the pairs.

Where the image form of light-dark() is supported, a logo can swap with the theme in one declaration. Elsewhere, use a prefers-color-scheme media query for the logo.

How to Check a CSS Dashboard for Accessibility and Performance

These are the thresholds worth testing against, all taken from W3C and web.dev.

  • Text contrast of 4.5:1, or 3:1 for large-scale text of 18 point or 14 point bold (W3C, WCAG 2.2 SC 1.4.3)
  • Interface components and chart marks at 3:1, unless visible labels and values carry the same information (W3C, SC 1.4.11)
  • Largest Contentful Paint at 2.5 seconds or less (web.dev)
  • Interaction to Next Paint at 200 milliseconds or less (web.dev)
  • Cumulative Layout Shift at 0.1 or less (web.dev)

Accessibility checks

Landmarks come first. Header, nav, main and aside map onto the frame regions and give screen reader users places to jump to.

Text and chart marks must meet the contrast ratios above in both themes. Check color contrast on each one, because a pair that passes on the light surface can fail on the dark one.

Focus is the easy one to forget. A sticky header or footer that completely covers a focused control fails WCAG 2.2 SC 2.4.11 (Focus Not Obscured, Minimum) at Level AA. W3C names scroll-padding as a sufficient technique (C43) and lists a header hiding focus as failure F110.

The prefers-reduced-motion: reduce media feature has been Baseline widely available since January 2020 (MDN), so card hover motion and chart entry animations can be toned down for users who ask.

Data tables also need real header cells and a caption, which the accessible tables guidance walks through.

Performance checks

Core Web Vitals are judged at the 75th percentile of page loads, split by mobile and desktop, according to web.dev. A page passes only when all three metrics meet their targets.

Interaction to Next Paint became a stable Core Web Vital in 2024 and replaced First Input Delay, so a test plan that still cites FID is out of date.

Lighthouse’s default page-load run cannot measure INP because it loads pages with no user input. Total Blocking Time is the lab proxy, and field data is the only full answer (web.dev, page last updated September 2025).

Layout shift is the metric a CSS dashboard controls most directly. Fixed sidebar tracks and reserved chart heights keep widgets in place while data loads.

Profile blur and shadow effects in DevTools instead of guessing at their cost.

When a CSS Dashboard Is the Wrong Choice

Plain CSS is the wrong tool when users need to rearrange widgets and have the layout saved for next time. It’s also a poor fit when the team needs ready-made forms, modals and date pickers on a deadline.

Webix shows what the first case takes. Its Dashboard widget lets users drag panels into new cells and resize them with a handle, then save and restore the layout through a cookie, local storage or session storage. It only ships in the Webix Pro edition, though.

SituationBetter fitWhy
Fixed internal screen, few widgetsPlain CSS dashboardNo dependency to update
Many forms, modals, date pickersBootstrap or a Tailwind CSS kitPrebuilt components
Widgets users arrange and saveDashboard library such as WebixDrag, resize, state saving built in
Large or live datasetsCharting library inside the CSS frameRendering handled in JavaScript

A framework trades stylesheet weight and override work for build time. That trade pays off once the interface needs more than a few components.

A Tailwind CSS dashboard keeps the layout in utility classes inside the markup, which suits teams that already work that way. It does not remove the need for a charting library.

For an internal tool with fewer than a handful of fixed widgets, plain CSS wins.

CSS Dashboard Examples To Check Out

Dashboard UI by Azri Kahar

See the Pen
Dashboard UI
by Azri Kahar (@azrikahar)
on CodePen.

Circl Dashboard

Products Dashboard UI by Aybuke Ceylan

See the Pen
Products Dashboard UI
by Aybüke Ceylan (@aybukeceylan)
on CodePen.

Healthcare Dashboard UI

See the Pen
Healthcare Dashboard UI
by Zafer AYAN (@zaferayan)
on CodePen.

Responsive Flexbox by ZingChart

See the Pen
Responsive Flexbox Dashboard
by ZingChart (@zingchart)
on CodePen.

Beautiful Dashboard UI by AbubakerSaeed

See the Pen
Beautiful Dashboard UI
by Abubaker Saeed (@AbubakerSaeed)
on CodePen.

Dashboard by Óscar Eusse

See the Pen
Dashboard
by Óscar Eusse (@o-eusse)
on CodePen.

Project/Kanban Board

See the Pen
Project/Kanban Board – with Tailwind CSS
by Rob Stinson (@robstinson)
on CodePen.

CSS Dashboard by alphardex

See the Pen
Dashboard
by alphardex (@alphardex)
on CodePen.

Dashboard UI by Mert Cukuren

See the Pen
Dashboard UI
by Mert Cukuren (@knyttneve)
on CodePen.

Dashboard Demo by Miles Manners

See the Pen
Dashboard Demo
by Miles Manners (@milesmanners)
on CodePen.

Deals Management Dashboard for Account Management by Chris Coyler

See the Pen
Deals Management Dashboard for Account Managers
by Chris Coyier (@chriscoyier)
on CodePen.

Dashboard New by Felix

See the Pen
Dashboard New
by Felix (@felixsusanto)
on CodePen.

CSS Grid Admin Dashboard

See the Pen
CSS Grid Admin Dashboard
by Max Böck (@mxbck)
on CodePen.

Stock App Dashboard

See the Pen
Dribbble Stock App Dashboard
by Filip Vitas (@FilipVitas)
on CodePen.

Dashboard Magic by Joseph Rex

See the Pen
Dashboard
by Joseph Rex (@josephrexme)
on CodePen.

Masterpiece by Mike Torosian

See the Pen
Dashboard UI
by Mike Torosian (@mtorosian)
on CodePen.

New User Tour – Dashboard

See the Pen
New user tour – Dashboard
by Manpreet Singh Gulati (@manpreet)
on CodePen.

Sabarinathan’s Trendsetter

See the Pen
Dashboard Layout Design – iPad Pro
by Sabarinathan Masilamani (@nathan5x)
on CodePen.

Vojtech’s User-Centric Design

See the Pen
Users Dashboard
by Vojtěch Musil (@blex)
on CodePen.

Keeping it Basic with Rizwan Ahmed

See the Pen
Basic Responsive Admin Dashboard
by Rizwan Ahmed (@rizwanahmed19)
on CodePen.

Kim77’s Crowd-Pleaser

See the Pen
Responsive Dashboard
by kim77 (@goodpublisher77)
on CodePen.

Lato’s Brilliance by Steven Tan

See the Pen
Lato – Dashboard
by Steven Tan (@chienleng)
on CodePen.

Matthew’s Clean Design

See the Pen
Simple CSS Grid Dashboard
by Matthew Holland (@trooperandz)
on CodePen.

Eric’s Practice Ground

See the Pen
Dashboard Css Grid Practice
by Eric (@adjeteyboy)
on CodePen.

Student Life by Praveen Bisht

See the Pen
Student Dashboard | Using CSS
by Praveen Bisht (@prvnbist)
on CodePen.

High Stakes with Liombe

See the Pen
GitBets – Betting Dashboard UI
by Liombe (@Liombe)
on CodePen.

Claymorphic Dash Magic by Mozzarella

See the Pen
Claymorphic Dashboard * (Responsive, CSS Only)
by MOZZARELLA (@TheMOZZARELLA)
on CodePen.

Tom Barton’s Slice of Dash

See the Pen
Dashboard
by Tom Barton (@tombarton)
on CodePen.

Vibes with Internal Video Platform UI

See the Pen
Internal Video Platform UI
by Aybüke Ceylan (@aybukeceylan)
on CodePeMedian.

Neo’s Dash Adventure

Mustafa Omar’s CSS Brilliance

See the Pen
Dashboard
by Mustafa Omar (@themustafaomar)
on CodePen.

Job Recruiter Vibes by Aybüke Ceylan

See the Pen
Job Recruiter Dashboard UI
by Aybüke Ceylan (@aybukeceylan)
on CodePen.

MatPress’s Material Magic

CSS Dashboard FAQ

Where can I find free CSS dashboard templates?

GitHub and free template sites carry most of them. TemplateMo lists free dashboards built with pure HTML, CSS and JavaScript, while Tabler is an open-source HTML dashboard kit built on Bootstrap.

Check the stack before downloading. A template that pulls in Bootstrap or Tailwind CSS is not a framework-free build.

Can a sidebar open and close without JavaScript?

Yes. A hidden checkbox with a label toggles the :checked state, and :has() lets the page react to it. :has() became Baseline newly available in December 2023.

Give the checkbox an accessible name and a visible focus style. The open or closed state resets on reload unless a script stores it.

How do I build a bento-style widget grid?

Set a fixed number of columns and let selected cards span extra tracks with grid-column and grid-row. Penpot’s own tutorial builds a bento layout for a sales dashboard on a four-column, four-row grid, with selected cards spanning several cells.

Add grid-auto-flow: dense to fill gaps, but know that it can pull cards out of DOM order, which changes the keyboard tab sequence.

How should I prototype a dashboard layout before coding it?

Sketch the header, sidebar and widget regions in a design tool first. Penpot builds CSS Grid layouts visually without code, and a CodePen scratch pad turns the track sizes into live CSS.

Keep the prototype to boxes and sizes. Colors and tokens come after the frame works.

Where to Start When Building a CSS Dashboard

Get the grid frame right first, set up design tokens second, and leave the widgets for last. That order puts the costliest changes up front, before anything depends on them.

Start with named areas for the header, sidebar and main. Custom properties for color, spacing and type come next, and cards, tables and charts go into the finished frame after that.

Reordering regions after widgets exist forces edits to every card. Tokens defined early let a theme change land in one rule block.

The catch is that the layout lives only in the stylesheet, so source order in the markup still has to match the reading order. Grid placement does not change the tab sequence.

Bogdan Sandu
Latest posts by Bogdan Sandu (see all)