Input Color Feedback — README on npm Input Color Feedback — the entire CSS source Input Color Feedback — MIT license

Overview

Input Color Feedback is a small open-source package I wrote and published on npm. It does one thing well: it makes form inputs feel alive. The moment a field is focused it glows; as the user types, the border shifts colour to tell them — without a word of copy — whether what they've entered is valid yet.

It started as a snippet I kept rewriting on every form I built. Rather than copy-paste it forever, I distilled it into a single stylesheet, documented it, gave it an MIT licence and shipped it to npm so anyone (including future me) can add it with one import.

The idea: a traffic light for forms

The whole thing leans on a visual language everyone already speaks — traffic lights. Green means good, amber means not yet, red means there's a problem. That's all the package really is: native form validation, mapped onto colours nobody has to learn.

For developers it's a small, shareable standard — drop it in and every form across a project (or across projects) speaks the same dialect, instead of everyone reinventing their own validation styling. For users it's a consistent, wordless way to read the status of the field they're filling in. That was the entire goal here: take a pattern I kept rebuilding and share the part I think genuinely helps both sides.

How it works

Every <input> transitions its border colour and glow (box-shadow) according to its focus and validation state. There are six states, and each one tells the user something different:

  • Unfocused and empty (the resting default) — a neutral grey border, no glow: the calm starting point before the field has been touched.
  • Focused and empty (placeholder still showing) — the border glows blue: "you're here, go ahead".
  • Focused but invalid — the border glows amber: "keep going, not quite right yet".
  • Focused and valid — the border glows green: "that works".
  • Unfocused and invalid — the border turns solid red, no glow: a calm error marker once you've moved on.
  • Unfocused and valid — the border stays green, no glow: quietly confirmed.

The glow only ever appears on the focused field, so a long form never lights up like a Christmas tree — your eye is drawn to exactly the input you're working on.

Pure CSS, zero JavaScript

The whole library is one short stylesheet and not a single line of JavaScript. All the logic lives in modern CSS selectors that the browser already evaluates for free: :focus, :placeholder-shown, :valid/:invalid and the user-driven :user-valid/:user-invalid — the last two are what keep the page from yelling "invalid" at an empty field the user hasn't even reached yet.

Because there's no script, there's nothing to initialise, nothing to bundle, no runtime cost and nothing that can break a form's existing behaviour. The transitions on border-color and box-shadow are eased over 0.3s so every state change feels smooth rather than abrupt.

Themeable by design

Every colour is a CSS custom property declared on :root, so theming is a matter of overriding a handful of variables — no Sass, no build step, no forking:

  • --default-color — the resting border.
  • --focus-color — the blue focus glow.
  • --valid-color — the green "valid" state.
  • --warning-color — the amber "focused but invalid" state.
  • --invalid-color — the red "left invalid" state.
  • --shadow-strength — how intense the glow is, mixed into the shadow with color-mix().

Point those at your brand palette and the feedback inherits your design language automatically.

Installation & usage

Install it with npm install input-color-feedback (or yarn add input-color-feedback), then pull in the stylesheet — either from CSS with @import "input-color-feedback/styles.css"; or, with a bundler like Vite or Webpack, from JavaScript with import 'input-color-feedback/styles.css';.

That's the entire setup. No components to wire up and no classes to add — the styling keys off native HTML validation, so it activates as soon as an input has a placeholder and a validation rule such as required, pattern or minlength. Inputs without those won't react, which is by design.

Light and dark, out of the box

The default palette is tuned for dark interfaces — like this site, and like Biglo, the app it was born in. As of v2.1.0 it no longer stops there: on a light background the two colours that wouldn't otherwise meet the WCAG contrast threshold — the valid green and the focused-but-invalid amber — are swapped automatically via prefers-color-scheme, the green darkening and the amber shifting to orange so both clear 3:1 on white. No configuration required.

And because every colour is still a CSS variable, you can re-theme it for any design — which is exactly what I did on the Abogada de la Tierra site: I scoped the library's variables to the contact form, kept the page's own resting border colour, and adjusted the palette so it sits comfortably on a cream background.

Limitations & what's next

I'd rather be upfront about where it stops short:

  • It needs constrained fields. Because it keys off native validation, an input only reacts if it actually has a rule — a placeholder plus something like required, pattern or minlength. An unconstrained input is always :valid, so it would sit green from the very first paint.
  • But you can work around it. On Abogada de la Tierra I paired the package with a novalidate form and a small JS validator that toggles an .is-invalid class for submit-time errors, plus an --optional modifier so empty optional fields stay neutral instead of going green. The CSS handles the live feel; a few lines of JS handle the cases native validation can't express.
  • Colour alone isn't fully accessible. Hue on its own can fail colour-blind users, who may not separate green from amber or red. This started as my personal implementation for Biglo, and I shared it because I think it helps — not because it's the final word. I'm already looking at ways to improve it: pairing the colour with icons, text or ARIA state so the meaning never rests on hue alone.

Status

Published and live on npm as input-color-feedback, with the source on GitHub under an MIT licence. It's currently on version 2.1.0 — small, stable and free for anyone to use.