SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/material-design

7 Material Design CSS Components

4 Pure CSS3 with JSPublished 2026-10-05Free · no sign-up

Seven components in the Material 3 style, written in plain CSS: the button family, an outlined text field with a counter, an elevated card, floating action buttons, filter chips, a bottom navigation bar with an active indicator and a snackbar with an Undo action.

01. Filled, Tonal and Outlined Buttons

MaterialButtons

The Material Design button family: filled for the main action, tonal for secondary, outlined and text buttons for less emphasis. Each has the fully rounded shape, a state layer on hover drawn with a pseudo-element, and visible focus.

View code
<div class="md1"><button class="f">Save</button><button class="t">Duplicate</button><button class="o">Export</button><button class="x">Cancel</button></div>
.md1 { display: flex; flex-wrap: wrap; gap: 8px; font: 500 14px Roboto, Inter, system-ui, sans-serif; }
.md1 button { position: relative; overflow: hidden; height: 40px; padding: 0 24px; border: 0; border-radius: 20px; font: inherit; letter-spacing: .01em; cursor: pointer; }
.md1 button::after { content: ""; position: absolute; inset: 0; background: currentColor; opacity: 0; transition: opacity .15s; }
.md1 button:hover::after { opacity: .08; } .md1 button:active::after { opacity: .12; }
.md1 .f { background: #6750a4; color: #fff; } .md1 .t { background: #e8def8; color: #1d192b; }
.md1 .o { border: 1px solid #79747e; background: transparent; color: #6750a4; } .md1 .x { background: transparent; color: #6750a4; padding: 0 12px; }
.md1 button:focus-visible { outline: 3px solid #6750a4; outline-offset: 2px; }

02. Outlined Text Field with Counter

MaterialInput

A Material outlined text field with the label floating into a notch in the border, helper text below and a character counter. The label is a real label, the helper and counter are linked with aria-describedby, and focus thickens the outline.

View code
<div class="md2"><div class="f"><input id="md2i" placeholder=" " maxlength="40" aria-describedby="md2h"><label for="md2i">Display name</label></div><p id="md2h"><span>Shown on your profile</span><span class="c">0/40</span></p></div>
.md2 { width: 280px; max-width: 100%; font: 16px Roboto, Inter, system-ui, sans-serif; }
.md2 .f { position: relative; }
.md2 input { width: 100%; box-sizing: border-box; padding: 16px; border: 1px solid #79747e; border-radius: 4px; background: transparent; color: #1d1b20; font: inherit; }
.md2 label { position: absolute; left: 12px; top: 16px; padding: 0 4px; background: #f3f5f9; color: #49454f; pointer-events: none; transition: top .15s, font-size .15s, color .15s; }
.md2 input:focus + label, .md2 input:not(:placeholder-shown) + label { top: -9px; font-size: 12px; }
.md2 input:focus { outline: none; border: 2px solid #6750a4; padding: 15px; } .md2 input:focus + label { color: #6750a4; }
.md2 p { display: flex; justify-content: space-between; margin: 4px 16px 0; color: #49454f; font-size: 12px; }
@media (prefers-reduced-motion: reduce) { .md2 label { transition: none; } }
var i = document.getElementById('md2i'), c = document.querySelector('.md2 .c');
i.oninput = function () { c.textContent = i.value.length + '/40'; };

03. Elevated Material Card

MaterialCard

A Material card with media, a headline, supporting text and text-button actions, sitting on a soft elevation shadow with a medium radius. Actions are aligned to the end, the convention for Material cards.

View code
<article class="md3"><div class="m" aria-hidden="true"></div><div class="b"><h3>Mountain cabin</h3><p>Two nights in the Tatras, breakfast included.</p></div><div class="a"><button>Details</button><button>Book</button></div></article>
.md3 { width: 260px; max-width: 100%; border-radius: 12px; background: #fffbfe; box-shadow: 0 1px 2px rgba(0,0,0,.3), 0 1px 3px 1px rgba(0,0,0,.15); overflow: hidden; font: 14px Roboto, Inter, system-ui, sans-serif; }
.md3 .m { height: 130px; background: linear-gradient(#bfdbfe 50%, #15803d 50%); }
.md3 .b { padding: 16px 16px 0; } .md3 h3 { margin: 0 0 4px; color: #1d1b20; font-size: 20px; font-weight: 400; } .md3 p { margin: 0; color: #49454f; }
.md3 .a { display: flex; justify-content: flex-end; gap: 8px; padding: 8px; }
.md3 button { height: 40px; padding: 0 12px; border: 0; border-radius: 20px; background: transparent; color: #6750a4; font: 500 14px Roboto, Inter, system-ui, sans-serif; cursor: pointer; }
.md3 button:hover { background: rgba(103,80,164,.08); }
.md3 button:focus-visible { outline: 3px solid #6750a4; outline-offset: 1px; }

04. Material FAB and Extended FAB

MaterialFAB

The floating action button in its rounded-square Material 3 shape and the extended version with a label. Both use the primary container colour, and the icon-only one has an accessible name.

View code
<div class="md4"><button class="fab" aria-label="Compose">✎</button><button class="ext"><span aria-hidden="true">✎</span>Compose</button></div>
.md4 { display: flex; align-items: center; gap: 16px; font: 500 14px Roboto, Inter, system-ui, sans-serif; }
.md4 button { display: inline-flex; align-items: center; justify-content: center; gap: 12px; height: 56px; border: 0; border-radius: 16px; background: #eaddff; color: #21005d; font: inherit; box-shadow: 0 1px 3px rgba(0,0,0,.3), 0 4px 8px 3px rgba(0,0,0,.15); cursor: pointer; }
.md4 .fab { width: 56px; font-size: 22px; } .md4 .ext { padding: 0 20px 0 16px; } .md4 .ext span { font-size: 20px; }
.md4 button:hover { background: #ddcbfb; }
.md4 button:focus-visible { outline: 3px solid #6750a4; outline-offset: 2px; }

05. Filter Chips

MaterialChips

Material filter chips that toggle on and off, showing a tick when selected. Each chip is a button with aria-pressed, so the selection is announced, and the chips wrap onto new lines on narrow screens.

View code
<div class="md5" role="group" aria-label="Filter recipes"><button aria-pressed="true"><span class="ck" aria-hidden="true">✓</span>Vegetarian</button><button aria-pressed="false"><span class="ck" aria-hidden="true">✓</span>Quick</button><button aria-pressed="false"><span class="ck" aria-hidden="true">✓</span>Budget</button></div>
.md5 { display: flex; flex-wrap: wrap; gap: 8px; font: 500 14px Roboto, Inter, system-ui, sans-serif; }
.md5 button { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 16px; border: 1px solid #79747e; border-radius: 8px; background: transparent; color: #49454f; font: inherit; cursor: pointer; }
.md5 .ck { display: none; }
.md5 [aria-pressed=true] { padding-left: 8px; border-color: transparent; background: #e8def8; color: #1d192b; } .md5 [aria-pressed=true] .ck { display: inline; }
.md5 button:focus-visible { outline: 3px solid #6750a4; outline-offset: 2px; }
document.querySelectorAll('.md5 button').forEach(function (b) { b.onclick = function () { b.setAttribute('aria-pressed', b.getAttribute('aria-pressed') !== 'true'); }; });

06. Navigation Bar with Indicator

MaterialNavigation

The Material 3 bottom navigation bar: icons in a pill-shaped active indicator above always-visible labels. The current destination is marked with aria-current, and the indicator is the icon wrapper's background.

View code
<nav class="md6" aria-label="App"><a href="#home" aria-current="page"><span aria-hidden="true">⌂</span>Home</a><a href="#explore"><span aria-hidden="true">◎</span>Explore</a><a href="#saved"><span aria-hidden="true">♡</span>Saved</a><a href="#profile"><span aria-hidden="true">☺</span>Profile</a></nav>
.md6 { display: grid; grid-template-columns: repeat(4, 1fr); width: 320px; max-width: 100%; padding: 12px 4px 16px; box-sizing: border-box; background: #f3edf7; font: 500 12px Roboto, Inter, system-ui, sans-serif; }
.md6 a { display: grid; justify-items: center; gap: 4px; color: #49454f; text-decoration: none; }
.md6 span { display: grid; place-items: center; width: 56px; max-width: 100%; height: 32px; border-radius: 16px; font-size: 18px; }
.md6 a[aria-current] { color: #1d1b20; font-weight: 700; } .md6 a[aria-current] span { background: #e8def8; }
.md6 a:focus-visible { outline: 3px solid #6750a4; outline-offset: 2px; border-radius: 8px; }

07. Snackbar with Action

MaterialSnackbar

A Material snackbar that appears at the bottom with a short message and one action, then hides after six seconds. It lives in a status region so it is announced, and the Undo action is focusable while it is visible.

View code
<div class="md7"><button class="show">Archive email</button><div class="bar" role="status"></div></div>
.md7 { position: relative; width: 300px; max-width: 100%; height: 200px; font: 14px Roboto, Inter, system-ui, sans-serif; }
.md7 .show { height: 40px; padding: 0 20px; border: 0; border-radius: 20px; background: #6750a4; color: #fff; font: 500 14px Roboto, Inter, system-ui, sans-serif; cursor: pointer; }
.md7 .bar { position: absolute; left: 0; right: 0; bottom: 0; }
.md7 .sn { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px 6px 16px; border-radius: 4px; background: #322f35; color: #f5eff7; box-shadow: 0 2px 6px rgba(0,0,0,.3); animation: md7 .2s ease; }
.md7 .sn button { height: 36px; padding: 0 12px; border: 0; border-radius: 18px; background: transparent; color: #d0bcff; font: 500 14px Roboto, Inter, system-ui, sans-serif; cursor: pointer; }
.md7 button:focus-visible { outline: 3px solid #d0bcff; outline-offset: 1px; }
@keyframes md7 { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: reduce) { .md7 .sn { animation: none; } }
var bar = document.querySelector('.md7 .bar'), t;
document.querySelector('.md7 .show').onclick = function () { bar.innerHTML = '<div class="sn">Email archived<button type="button">Undo</button></div>'; bar.querySelector('button').onclick = function () { bar.innerHTML = '<div class="sn">Archive undone</div>'; }; clearTimeout(t); t = setTimeout(function () { bar.innerHTML = ''; }, 6000); };

About these Material Design CSS Components

State layers

Material shows hover and press with a translucent layer of the content colour over the component. A pseudo-element with background: currentColor and low opacity does it for any colour.

Shape and colour roles

Material 3 uses rounded shapes and colour roles (primary, primary container, surface). Defining them as custom properties keeps a whole interface consistent.

Elevation with soft shadows

Cards and FABs rise with two-layer shadows: a tight one and a soft one. Keep elevation for things that genuinely float above others.

Accessible by default

Chips are toggle buttons with aria-pressed, the navigation marks the current page with aria-current and snackbars live in a status region.

Frequently asked questions

Is this the official Material library?

No. These are original CSS components inspired by Material 3, with no framework.

Which font does Material use?

Roboto by default; the demos fall back to Inter or the system font.

Can I change the colours?

Yes. Swap the purple palette for your own primary and container colours.