Neu Input
46 px input fields carved into the material by two inset shadows, including a search with an inlaid magnifier; on focus, a 3 px violet rim joins the hollow. Pure CSS, label tied to its field.
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 hollow fits in a single rule. .neu-input (100% wide, 46 px tall, border-radius: 12px, no border or outline) has the material's #e0e5ec background and two inset shadows: #b8bec7 3px 3px 6px inset top left, #fff -3px -3px 6px inset bottom right. Light seems to come from the top left and the field reads as a cavity. Typed text is #374151 (14 px, Inter if loaded), placeholder #9ca3af. On focus, a third shadow joins the first two: rgba(139, 92, 246, .2) 0 0 0 3px, a pale violet rim around the hollow, with a 0.3 s transition.
The search places an 18 px SVG magnifier (#9ca3af stroke) in position: absolute 14 px from the left edge, centered with top: 50% and translateY(-50%); the field shifts its text by 40 px to make room. The .neu-input-scene group has 280 px of content, in a column with a 16 px gap.
Two choices make the fields usable without a mouse or a screen. The label wraps its field (<label class="neu-input-group">, text in a span): the link is implicit, a click on “Nom complet” focuses the field and input.labels.length is 1; a <label> placed next to it without for would be linked to nothing. The search, which has no visible label, carries aria-label="Rechercher", and its magnifier aria-hidden. And, as for the whole family, .neu-input-scene declares its surface (background: #e0e5ec, padding: 28px, border-radius: 24px, box-sizing: content-box): over a black background, the light gray hollows would read as flat slabs.
Accessibility
- Nearly invisible focus: the code removes the browser outline (
outline: 0) and replaces it with anrgba(139, 92, 246, .2)rim which, on#e0e5ec, only contrasts at 1.2:1 with the material. A keyboard user can hardly tell which field is active. Replace it with a solid rim:.neu-input:focus-visible { box-shadow: #b8bec7 3px 3px 6px inset, #fff -3px -3px 6px inset, #8b5cf6 0 0 0 2px }(3.3:1) — the hollow stays, the rim becomes readable. - Contrast: typed text
#374151measures 8.1:1, but the#6b7280label (12.5 px, 600) 3.8:1 and the#9ca3afplaceholder 2.0:1, below the 4.5:1 threshold. Switch the label to#374151(as in the scenes) and put nothing essential in the placeholder: it disappears with the first letter. - Field boundaries: the cavity only exists through the
#b8bec7shadow (1.5:1), below the 3:1 required for field boundaries (WCAG 1.4.11). For an important form (payment, admin), add a1px solid #9ca3afborder. - Names: checked in Chromium and Firefox, the first field is named “Nom complet” (wrapping label, clicking the text focuses it) and the search “Rechercher”. If you add fields without a visible label, give them an
aria-label: a placeholder does not replace a name.
Browser compatibility
CSS only: multiple inset box-shadow, ::placeholder, :focus, transition, absolutely positioned SVG, flexbox with gap. Zero JavaScript, zero dependencies. Identical rendering measured in Chromium, Firefox and WebKit (Playwright). Flex gap needs Chrome 84, Firefox 63, Safari 14.1.
Without box-shadow, the fields become borderless rounded gray rectangles, still usable but hard to spot. On iPhone, a font below 16 px makes the page zoom on focus: set .neu-input to 1rem for a mobile form.
The code
HTML structure to paste into your page (the CSS + JS come with Premium):
<div class="neu-input-scene">
<label class="neu-input-group">
<span class="neu-input-label">Full name</span>
<input type="text" class="neu-input" placeholder="…">
</label>
<div class="neu-search-wrap">
<svg viewBox="0 0 24 24" aria-hidden="true">…</svg>
<input type="text" class="neu-input" placeholder="Search..." aria-label="Search">
</div>
</div>
The full HTML + CSS + JS of Neu Input, 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 |
|---|---|---|
Hollow depth (CSS — 3px 3px 6px inset) |
3 px offset, 6 px blur | 5px 5px 10px for a deeper field (main input), 2px 2px 4px for dense forms. Change both shadows together, and the :focus ones too. |
Focus rim (CSS — rgba(139, 92, 246, .2) 0 0 0 3px) |
violet at 20%, 3 px | Measured contrast 1.2:1: switch to #8b5cf6 0 0 0 2px (3.3:1) or #6d28d9 (5.6:1) for a keyboard-readable focus. |
Height and radius (CSS — height: 46px; border-radius: 12px) |
46 × 12 px | Pill-shaped search: border-radius: 23px. Do not go below 40 px tall on touch screens. |
Text size (CSS — font-size: .88rem) |
14 px | Switch to 1rem (16 px) to avoid iOS's automatic zoom on focus. |
Material tint (CSS — #e0e5ec, shadows #b8bec7 / #fff) |
light bluish gray | The field and the .neu-input-scene surface share one tint: change them together, with a shadow pair from the same family. |
FAQ
.neu-input:focus with #8b5cf6 0 0 0 2px: the look stays neumorphic and the focus becomes readable.<label class="neu-input-group"><span class="neu-input-label">Email</span><input class="neu-input" type="email"></label>. The wrapping label ties the text to the field without an id, so no risk of duplicates if the form appears twice.