Neu Dashboard
A complete 320 × 215 px neumorphic panel on a single tint: a header with an inset badge, three raised counters that press in on hover (0.2 s) and a seven-bar purple histogram in a carved tray. 100% CSS, bar heights are set in the HTML.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Glassmorphism has 47 effects, including 6 free. Explore the category →
3 usage examples



How it works
The panel .neu-dash (320 px, padding: 20px, 20 px radius) is painted #e0e5ec with two shadows: #b8bec7 8px 8px 16px bottom right and #fff -8px -8px 16px top left. It stacks four depth levels, all on the same tint. Raised: the three counters .neu-dash-stat (86.7 × 65 px, 14 px radius, 4 px shadows). Inset: the badge .neu-dash-badge (2 px inset shadows, green #10b981 text at 11.2 px) and the histogram tray .neu-dash-chart (280 × 60 px, 3 px inset, 8 px inner padding). Colored: the seven bars .neu-dash-bar, equal flex shares (32.6 px, 6 px gap), rounded on top (4 px), vertical gradient #8b5cf6 → #a78bfa at 70% opacity. Each bar's height is an inline percentage (style="height: 40%") of the tray's usable height, 44 px: measured, 40% gives 17.6 px.
Two hover reactions, no JavaScript, measured in Chromium 151, Firefox 153 and WebKit 26.5. A hovered counter swaps its outer shadows for 3 px inner ones (transition: .2s): it presses in under the pointer, like a key. A hovered bar goes from 70 to 100% opacity. Values are 17.6 px weight 800 #374151, labels 10.4 px #9ca3af, the h4 title 13.6 px weight 700. All content is text in the HTML: to plug in real data, replace the values and the bars' height on the server or in JavaScript.
The panel comes with its material: the .demo-preview frame declares the same #e0e5ec surface as the panel and 32 px of vertical margin, without imposing anything on body. Without that surface, on a black background, the light #fff shadow would become a white halo all around (19.8:1 with the background, against 1.3:1 with its own surface). With it, the relief reads as intended, and the panel stays readable pasted into a white page. If you remove that frame, give the section holding the panel the same tint.
Accessibility
- Contrast: values and title
#374151measure 8.1:1 on#e0e5ec. Labels#9ca3afat 10.4 px only reach 2.0:1, the green badge#10b9812.0:1 too: below 4.5:1, they are hard to read in daylight. Switch labels to#4b5563(6.0:1) and the badge to#065f46(6.1:1), as in the rower scene. Bars stand out at 2.3:1 at the bottom and 1.7:1 at the top (70% opacity), below the 3:1 required for graphics: setopacity: 1if the histogram carries information. - Histogram: seven empty
divs, no text and no value — a screen reader reads nothing. Give.neu-dash-chartarole="img"and anaria-labelsumming up the trend (“Energy used per day, Monday to Sunday, higher at the weekend”), or add the values in a visually hidden table. - Hover only: the counters only press in with the mouse; they are neither links nor buttons. That is consistent for a reading panel. If they should open a detail, make them
<button>s and add:focus-visibleto the:hoverrule so the keyboard sees the same dip. - Relief and color: neumorphic relief is low-contrast by nature (dark shadow 1.5:1 on the surface); no information should rely on it alone. Here each counter has a text label, and the badge carries its sign (+ or −) on top of the green color. No continuous motion:
prefers-reduced-motionhas nothing to cut.
Browser compatibility
CSS only: double and inset box-shadow, CSS grid, flexbox, linear-gradient, opacity, transition. Zero JavaScript, zero dependencies. Measured pasted into a blank page in Chromium 151, Firefox 153 and Playwright's WebKit 26.5: same shadows at rest, same switch to inset on hover (inset 3px 3px 6px). The title asks for Inter; without it, the default sans-serif font takes over.
The minimum versions are those of CSS grid, which lays out the three counters. Without it (2016 browsers and older), the counters stack in a column but stay readable. On touch screens there is no hover: the panel stays in its resting state, complete.
The code
HTML structure to paste into your page (the CSS + JS come with Premium):
<div class="demo-preview">
<div class="neu-dash-scene">
<div class="neu-dash">
<div class="neu-dash-header">
<h4>…</h4>
<span class="neu-dash-badge">…</span>
</div>
<div class="neu-dash-stats">
<div class="neu-dash-stat">
<span class="neu-dash-stat-value">…</span>
<span class="neu-dash-stat-label">…</span>
</div>
…
</div>
<div class="neu-dash-chart">
<div class="neu-dash-bar" style="height: 40%"></div>
…
</div>
</div>
</div>
</div>
The full HTML + CSS + JS of Neu Dashboard, ready to paste — plus all 840 effects. Or $299 once, lifetime access.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Surface tint (CSS — background: #e0e5ec on .neu-dash, the badge, the counters, the tray and .demo-preview) |
#e0e5ec | Change it everywhere at once and recompute both shadows (about 15% darker, and white). A background of another tint than the panel makes a halo appear around the light shadow. |
Bar height (HTML — style="height: 40%" on each .neu-dash-bar) |
40, 65, 45, 80, 55, 90, 70% | Percentage of the tray's usable height (44 px). Compute it from your data (value ÷ maximum × 100). 0% hides the bar (day without data). |
Number of bars (HTML — .neu-dash-bar) |
7 | Bars share the width (flex: 1): 12 bars for a year are 16.5 px each; 30 bars for a month drop to 3 px — then reduce gap to 2 px (6.9 px per bar). |
Counter hover (CSS — .neu-dash-stat:hover { box-shadow: … inset }) |
3 px press-in over 0.2 s | Remove the rule if the counters lead nowhere; add :focus-visible if they become buttons. |
Bar and badge colors (CSS — .neu-dash-bar { background }, .neu-dash-badge { color }) |
#8b5cf6 → #a78bfa at 70% · badge #10b981 | A single accent color keeps the panel calm. For a negative change, switch the badge to dark red (#b91c1c, 5.1:1) and keep the − sign. |
Panel width (CSS — .neu-dash { width: 320px }) |
320 px (86.7 px counters) | Counters are a third of the width minus the gaps: a long label like “Efficiency (COP)” already wraps onto two lines at 320 px. Beyond 400 px, counters become wide and flat — switch to 4 columns then. |
FAQ
bar.style.height = (value / max * 100) + '%' for each bar, textContent for the values. No chart library is needed for seven bars..neu-dash-bar gets its height as a percentage of the groove, inline (style="height: 40%"); the width shares itself out (flex: 1), so 5 or 12 bars fit with no other setting. Compute the height from the largest value: bars.forEach((b, i) => b.style.height = values[i] / max * 100 + '%'). For the bars to grow instead of jumping, add height .4s ease to their transition (the code only animates opacity). Update the three counters (.neu-dash-stat-value) and the badge at the same time, and the chart's aria-label if you follow the accessibility advice above.