Draggable Dashboard Template

£10

A calm project-dashboard landing page with draggable, keyboard-reorderable widgets, a practical build-your-workspace section, expandable release rooms and split-flap metrics.

ScrollTriggerFlipDraggable Lenis intermediate
9 more details
draggablekeyboard-reorderflip-layoutclick-togglesplit-flapbento-gridscroll-revealstagger 4 colour palettes
Draggable Dashboard Template - website template preview

This template reads better at your own screen size than in the frame below:

About this template

A complete landing page for Daymark, a fictional project-dashboard product that keeps budgets, releases, people and handover in one configurable room. Its restrained stone, navy and muted status palette makes the bento structure feel like operational software rather than a collection of decorative cards.

Read the full template overview

The hero acts as a live dashboard: drag a handle to reprioritise its blocks and Flip settles the full grid without allowing the section height to collapse. Farther down, a dedicated project-room builder makes the same interaction useful with budget, launch, team, release-check, velocity and note widgets, plus working checklist controls and a reset action. Every move has an arrow-key equivalent and polite screen-reader announcement.

Expandable release rooms, split-flap portfolio metrics and guarded scroll reveals complete the page. Four complete brand directions ship in the stylesheet, changing the hero composition, widget hierarchy, navigation, statement layout, typography, shape, spacing and depth as well as colour. A buyer can rename widgets, choose or edit a direction and adjust tile spans without changing the interaction code.

What's included

14 items
  • Complete deployable dashboard-product site: nav, draggable hero, portfolio metrics, project-room builder, product detail grid, statement, conversion section and footer
  • Signature draggable hero board: grab a dotted handle to physically reorder blocks, with collision feedback, a lifted drag state and a Flip-powered settle
  • Keyboard-equivalent board controls: focus any handle and use arrow keys to reorder, with screen-reader announcements
  • Flip tile expansion: a tile morphs into a full-width panel while its neighbours reflow, with the grid height held so the page never jumps
  • Split-flap stat board built from the figures in the markup, so the page states the right number with no JavaScript and a screen reader hears the value rather than a stream of rolling characters
  • Two bento clusters with deliberately different rhythms: a 2x2 cover and tall tiles up top, more and smaller tiles below with one running the full width
  • Four art plates drawn as inline SVG, a risograph overprint, a halftone field, a plotted line chart and a duotone monogram, so there is nothing to source
  • Tile spans are set by class, so adding, removing or rearranging tiles is a CSS edit rather than a markup rewrite
  • Four complete brand directions: restrained Daymark, square Ledger, dark technical Signal and serif Editorial
  • Brand switching changes hero composition, widget hierarchy, navigation, statement layout, typography, radius, spacing, borders and depth, not only colour
  • Every translucent value resolves from the active direction's RGB triples, preventing mixed-brand remnants
  • Lenis smooth scrolling wired in and fully optional
  • Accessible: real buttons with aria-expanded, focus moved into the panel and returned on close, Escape to close, AA contrast on both surfaces, and a complete page with JavaScript off
  • Four brand directions, each with its own display face (sans, slab, mono, news serif), swapped from one data-palette attribute

Perfect for

6 use cases
  • Project-management and operations SaaS products demonstrating configurable dashboards
  • Client portals where teams need budgets, milestones, people and release checks in one view
  • Analytics products that let customers prioritise and rearrange widgets
  • Internal tools needing an approachable marketing site with a credible driven UI
  • Portfolio-management software presenting live status without a dark enterprise-dashboard aesthetic
  • Learning how to drive a Flip layout change while holding container height through the absolute phase

How it works

6 sections

Structure

One script initialises each section with a single setup and teardown path and one motion branch, and every lookup is guarded so a section that is not there is skipped silently. Tiles are placed by span rather than by fixed grid lines, which is what lets the rest of the grid genuinely re-place itself when one tile takes the full row. Delete any section, or any tile, and the rest keeps working.

The draggable boards

GSAP Draggable is attached only to generated handles, so links, checklist controls and selectable copy keep their native behaviour. During a drag, hitTest marks the widget beneath the lifted tile; release moves the real DOM node and Flip.from settles every block into the new grid order. Both the hero and project-room builder lock and tween their min-height through Flip's absolute phase, so the section below can never slide underneath. Focused handles mirror the interaction with arrow keys and announce each move through an aria-live region.

The tile expansion

A toggle inside the tile flips a class that changes the tile's grid area to the full row, then Flip.from animates that layout change for the tile and every sibling that moved. absolute: true is what lets a tile travel across rows, and it is also the hazard: it lifts the animating tiles out of the grid's normal flow, so the grid's height would collapse mid-tween and everything below would jump. The script locks the grid's min-height to its pre-tween height and tweens that to the post-layout height over the same duration, then hands the box back to normal layout. The detail content is staggered in only after the morph lands, because text reflowing inside a box that is still changing width reads as a wobble.

The stat board

Each figure ships in the markup as plain text. The script splits it into per-character cells, marks the cells aria-hidden, and makes the authored figure visually hidden so it stays the accessible value. Each cell then rolls backwards through a glyph wheel to its own character, cascading left to right, and lands with a back-eased overshoot. The total number of animated cells is capped so a longer board cannot turn into a per-frame text-writing problem.

Accessibility and reduced motion

Every toggle is a real button with aria-expanded, so Enter and Space work for free; opening moves focus into the panel and closing returns it to the trigger, and Escape closes from anywhere. On a coarse pointer the toggle stretches over the whole tile so a tap anywhere opens it. Reduced motion gets the same layout with no tweens: tiles still open and close, because that is function rather than decoration, and the stat board simply shows its figures.

Without JavaScript

Every detail panel is just the next part of its tile, and every stat is plain text, so the page reads as one complete document. The JavaScript-gating class is added synchronously in the head, before first paint, and the script removes it again if GSAP did not load, which means a blocked CDN degrades to that same complete document rather than to a page of empty tiles.

Plugins ScrollTrigger, Flip, Draggable
Difficulty Intermediate
Smooth scroll Lenis integration
Colour palettes 4 ready-made palettes, each measured for AA contrast. Switch with one attribute, or copy the values you want into :root. Try them in the preview above.
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this template's demo, 9 September 2026. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Questions about this template

Can visitors really rearrange the dashboard?

Yes, that is the signature. Grab a dotted handle and physically reorder blocks, with collision feedback, a lifted drag state and a Flip-powered settle. Focus a handle instead and arrow keys do the same reorder with screen-reader announcements, so it is not a mouse-only party trick.

What are the four brand directions?

Restrained Daymark, square Ledger, dark technical Signal and serif Editorial, and they change far more than colour: hero composition, widget hierarchy, navigation, statement layout, typography, radius, spacing, borders and depth all move. Every translucent value resolves from the active direction's RGB triples so you never get mixed-brand remnants.

Do I need product screenshots?

No. Four art plates are drawn as inline SVG, a risograph overprint, a halftone field, a plotted line chart and a duotone monogram, so there is nothing to source. That makes it usable as a marketing site for an internal tool that has no shippable screenshots yet.

Does the page jump when a tile expands?

No. A tile morphs into a full-width panel while its neighbours reflow, with the grid height held through the absolute phase so nothing below shifts. Escape closes it and focus is moved into the panel and returned on close.

How do I add or move tiles?

Tile spans are set by class, so adding, removing or rearranging is a CSS edit rather than a markup rewrite. The two bento clusters are tuned to different rhythms on purpose, a 2x2 cover with tall tiles up top and more, smaller tiles below, so keep that contrast when you extend.

Paid template

Purchase to unlock the code.

Buying Draggable Dashboard Template opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects.

£10 Standard license, unlimited projects

Browse free effects

Documentation

What's Included

Code snippet omitted: it ships with the download.

No build step, and no images to source. Open index.html and it runs.

Quick Start

  1. Open index.html and replace Daymark with your product: the brand, hero dashboard, project-room widgets, metrics, product details and conversion copy.
  2. Change the core colours and optional spot colours at the top of assets/style.css. Keep the RGB triples in step. See Brand directions.
  3. Rearrange the grid by changing tile spans in style.css (search for Board tile spans). Tiles are placed by span, not by fixed grid lines, so there is no markup to rewrite. See The grid.
  4. Update the <title> and <meta name="description">, and remove <meta name="robots" content="noindex, nofollow"> when you go live.
  5. Swap the fonts if you want to: change the Google Fonts <link> in index.html and the three --font-* tokens in style.css.
  6. Deploy the folder anywhere that serves static files.

Optional: minify before you go live

assets/script.js is the readable source and is what index.html loads. It is around 43KB, which is fine to ship as-is. If you would rather serve it minified, produce it yourself once your edits are done:

Code snippet omitted: it ships with the download.

Then point the last <script> tag in index.html at assets/script.min.js. Keep script.js as the file you edit and re-run the command after each change, otherwise the two quietly drift apart.

The grid

Two bento clusters, each a plain CSS grid. Tiles carry a span, never a fixed grid line, so the browser places them and re-places them when one of them takes the full row:

Code snippet omitted: it ships with the download.

Two things are worth knowing before you rearrange them:

  • The cells should add up. A four-column grid wants its spans to fill whole rows, or the last row ends with a visible gap of ground. The markup order matters here too, because the tiles auto-place in document order; the amber tile sits before the halftone plate in index.html for exactly that reason.
  • Give neighbours genuinely different spans. A 2x2 next to a 1x1 next to a 3x1 is what makes a bento read as a bento. Six identical tiles read as a card grid, and no amount of colour fixes that.

The seams are per-tile: every tile draws its own 1.5px rule and the grid holds them apart with a 3px gutter of bare ground. That is why the seam weight is identical between tiles and at the outer edge, and why a tile that opens elsewhere leaves ground behind rather than a stray filled panel.

The draggable boards (the signature)

The hero carries data-reorder-board; the practical builder carries data-workspace-board. With JavaScript available, the script adds a handle button to every direct widget and attaches Draggable to that handle only, so links, checklist buttons and selectable copy retain their native behaviour.

Raw pointer coordinates and elementsFromPoint() identify the widget under the handle, including on touch. On release the real DOM node moves before or after that target, then Flip.from() animates the full CSS Grid into its new order. There is no duplicate visual layer and the changed reading order is real.

Both boards lock min-height before Flip's absolute phase, tween it to the new measured height and clear it only after Flip completes. This prevents the board collapsing and the following section sliding underneath during a reorder. The project room also has a reset control that restores the authored widget order.

Focus any handle and press an arrow key to move its widget one place. An aria-live region announces every move. Under reduced motion all controls still work, but settle durations become zero.

The tile expansion

An expandable tile is a data-tile name, a matching data-tile-detail panel inside it, and a real <button>:

Code snippet omitted: it ships with the download.

To add one, copy the whole article and change four things together: data-tile, data-tile-detail, the panel's id, and the button's aria-controls. The pairing is by name, not by position, so deleting a tile cannot shift the rest out of step. Any tile without a data-tile attribute is simply not expandable, which is how the art, quote and monogram tiles work.

Attribute Goes on What it does
data-tile-grid The grid container Marks a grid whose tiles can expand. Flip runs per grid.
data-tile="name" A tile Makes it expandable, under that name
data-tile-detail="name" A panel inside that tile The content revealed. Must match the tile's name.
data-tile-toggle A <button> inside that tile The open/close control
data-btn-open / data-btn-close Spans inside the button Swapped by CSS on open, so one button carries both labels

Inside the panel, the script staggers whatever direct children it finds, so the markup is free: detail-head, detail-copy, detail-figs and detail-list are styles, not requirements.

One tile is open at a time, across both grids. Closing happens on the control, on a click anywhere outside the tile, or on Escape.

Two things the script handles that are easy to get wrong if you rebuild it:

  • The grid's height. Flip's absolute: true is what lets a tile travel across rows, and it lifts the animating tiles out of the grid's normal flow, so the grid's height would collapse toward zero mid-tween and everything below the grid would jump, then snap back. The script locks the grid's min-height to its pre-tween height, tweens that to the post-layout height over the same duration, and clears it on complete.
  • The detail content waits. It fades and staggers in after the morph lands. Run it during the tween and the text reflows inside a box that is still changing width, which reads as a wobble.

The stat board

Each figure ships as plain text in the markup. The script splits it into per-character cells:

Code snippet omitted: it ships with the download.

Attribute Goes on What it does
data-flap-board The section Marks the board. Also scopes the replay button.
data-flap Each stat Marks a figure to split into cells
data-flap-value The figure element The characters to roll to. Falls back to the element's text.
data-flap-replay A <button> Replays the whole board

Values are uppercased, and any character in 0-9 A-Z % + - . , rolls. Anything else is set once and left alone rather than rolled to something wrong.

The figure in the markup is the accessible one. Once the cells exist they are aria-hidden, and the authored figure becomes visually hidden but stays in the DOM, so a screen reader reads "86%, of work from returning clients" rather than a stream of rolling characters. It is also why the board is correct with JavaScript off, with a blocked CDN, and under reduced motion: the number on the page was never generated.

Keep the total number of cells to roughly forty. FLAP_MAX_CELLS at the top of script.js caps the animated ones; past that the per-frame text writes cost more than they read.

Reveals

Attribute Goes on What it does
data-intro-group A container Its children land tile by tile on load
data-reveal Any element Fades and rises when it scrolls into view
data-reveal-group A container Its children fade and rise, staggered, when they scroll into view
data-hero-fade Any element Fades in late in the load-in sequence
data-line A line inside a .mask Rides up from below, for the masked headline

Every one of these has a start state pre-set in CSS under .has-js, which is added synchronously in the <head>. That ordering is what stops the flash where an element paints visible and then snaps to invisible as it crosses its trigger. When a reveal finishes the script adds is-shown, which is what makes the start state one-way: if the media conditions ever change mid-visit, GSAP reverts the inline styles it wrote and without that class the page would hide itself again.

If you add a reveal hook of your own, add it to the pre-hide block near the top of style.css and to the prefers-reduced-motion block at the bottom that restores it.

Brand directions

Four complete directions ship in style.css. They change colour, typography, corner treatment, grid spacing, border weight and depth—not only the accent:

Direction Attribute Character Display face
Daymark no attribute Balanced four-column board, restrained stone and navy, compact radii and subtle offset depth Manrope 700, a geometric-humanist sans
Ledger data-palette="ledger" Dense twelve-column operations sheet, square cells, green-led and shadowless Zilla Slab 700, a slab serif
Signal data-palette="signal" Full-width console headline above live modules, dark grid ground and monospaced display type IBM Plex Mono 600, the mono
Editorial data-palette="editorial" Asymmetric eight-column feature layout, borderless lead story, serif headlines and generous section rhythm Newsreader 600, a news serif

The face and the colours are independent tokens (--font-display and --font-display-weight sit in each block next to the colours), so keep the direction and swap the face, or the other way round. All four faces are in the Google Fonts <link> in index.html; a browser only downloads the ones the page uses, but once you have settled, trim the link to the families you kept. The body face is the same in every direction except Ledger, which sets Manrope for reading text; the mono face never changes.

Choose one on the root element:

Code snippet omitted: it ships with the download.

These are different compositions, not skins: each direction changes the hero grid hierarchy, workspace columns, navigation treatment and statement layout in addition to its type, shape and colour system. Reordering remains real in every direction because widgets still use spans and auto-placement rather than fixed grid areas.

The picker visible on the GSAP Vault preview is demo-only and is not included in the download. The four CSS directions do ship. Once you choose one, either keep the attribute or copy that block's values into :root and remove the unused alternatives.

Core palette tokens

Each direction restates the core roles and RGB triples below. Translucent values resolve from those triples, so no switched brand inherits a stray colour from Daymark.

Code snippet omitted: it ships with the download.

Keep the triples in step with the hexes above them; every translucent value in the stylesheet resolves from them, so there is no rgba() literal anywhere that a reskin could leave behind.

The warm-white tile and stone ground are deliberately close; depth comes from the solid ink edge and offset shadow rather than from a murky surface step. The spot colours are objects in the board, not general-purpose text colours.

Measured, composited, at the sizes used:

Pair Ratio
ink on stone ground 13.25:1
ink on warm-white tile 14.60:1
warm white on navy 8.00:1
ink on rust 4.66:1
ink on ochre 6.95:1
ink on sage 5.22:1
ink on lavender 7.62:1
ink at .72 on warm-white tile 6.13:1

Rust carries solid ink and sage secondary copy uses .80 ink; do not reuse the default .72 dim token on those surfaces without re-measuring it. Navy always carries warm-white text. The solid ink borders and navy focus ring clear the non-text 3:1 requirement.

Accessibility

  • Every toggle is a real <button> with aria-expanded and aria-controls, so Enter and Space work without any key handling. Opening moves focus into the panel; closing returns it to the trigger it came from. Escape closes from anywhere on the page.
  • On a coarse pointer the toggle stretches over the whole tile, so a tap anywhere opens it. On a fine pointer it stays a corner control, so the tile's copy remains selectable.
  • The flap cells are aria-hidden and the authored figure stays in the DOM as a visually hidden element, so a screen reader gets the value and its label, never a stream of rolling characters.
  • prefers-reduced-motion gets the same layout with no tweens, via both a CSS block and a gsap.matchMedia branch. Tiles still open and close, because that is function rather than decoration; they just switch instantly. The replay button on the stat board is hidden, since there is nothing for it to replay, and the figures are already correct.
  • Without JavaScript every detail panel is simply the next part of its tile and every figure is plain text, so the page reads as one complete document with nothing behind a control that cannot work.
  • The has-js class that hides reveal targets is added in the <head> before first paint and removed again by the script if GSAP did not load, so a blocked CDN degrades to that same complete document.
  • Focus is always visible: a solid amber ring, which clears 3:1 on both surfaces.

Smooth Scrolling

Lenis is wired in and optional. Remove the CDN tag in index.html and the lenis block at the top of script.js to drop it. If you keep it, note the lenis.on('scroll', ScrollTrigger.update) line: without it the tile morph and the reveals run a frame behind the smoothed scroll position.

Customisation Notes

  • Brand direction: choose Daymark, Ledger, Signal or Editorial; see Brand directions.
  • Type: Daymark uses Manrope, DM Sans and IBM Plex Mono. Each direction carries its own display face (Zilla Slab, IBM Plex Mono, Newsreader; see Brand directions), and Ledger also moves Manrope to the body. Update the Google Fonts <link> when you swap them. The hero display is capped well under 6rem because the cover tile is only two columns wide; a bigger face starts breaking words.
  • The art plates are inline SVG in index.html: a risograph overprint, a halftone field, a plotted line chart, and a duotone monogram. Colours come from the same tokens. Note that on the two pattern plates the fill lives on the <circle> inside <pattern>, because a CSS fill rule on the rect would beat its fill="url(...)" attribute.
  • Sections are independent: the script guards every lookup and skips any section it cannot find, so delete what you do not need.

Dependencies

  • GSAP 3.15.0 (core)
  • ScrollTrigger
  • Flip
  • Draggable
  • Lenis 1.3.17 (optional)

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.

Your cart

Your cart is empty

The Vault £99

Everything in the catalogue, plus everything we release next.