Taming Chrome's Autofill

If you've ever styled a beautiful input field only to watch Chrome slap an ugly blue background and border on it the moment autofill kicks in — you're not alone. Here's why it happens and the bulletproof CSS fix.

When Chrome autofills a form field (emails, passwords, addresses), it applies internal user-agent styles via the :-webkit-autofill pseudo-class. These styles use !important at the browser engine level, which means your Tailwind classes, inline styles, and even your own !important declarations often lose the specificity battle.

The result? Your carefully chosen border color gets replaced with Chrome's default blue, your background turns a pale lavender, and your custom font might even change like in the example below.

Loading demo...

Why Tailwind's autofill: Variant Isn't Enough

You might try something like this:

<input className="autofill:border-input! autofill:bg-background!" />

This generates valid CSS targeting :-webkit-autofill, but Chrome's internal styles still win because they operate at a deeper level of the cascade than author stylesheets.

The Fix

The solution is a global CSS rule that combines two tricks:

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0px 1000px var(--background) inset !important;
  -webkit-text-fill-color: var(--foreground) !important;
  border-color: var(--input) !important;
  transition: background-color 5000s ease-in-out 0s;
  caret-color: var(--foreground);
  font-family: var(--font-mono) !important;
}

How each line works

PropertyWhat it does
-webkit-box-shadowPaints a massive inset shadow in your background color, visually covering Chrome's blue background
-webkit-text-fill-colorForces the text color, since color alone gets overridden
border-colorRestores your border — the actual fix for the "blue border" problem
transition: background-color 5000sDelays Chrome's background-color change by ~83 minutes, effectively preventing it
caret-colorEnsures the blinking cursor matches your theme

Why we target all four states

Covering :hover, :focus, and :active in addition to the base :-webkit-autofill prevents Chrome from re-applying its styles during user interaction.

What You Can't Control

There are things that live outside the DOM entirely — the browser controls them, and no amount of CSS can fix them:

  1. The autofill suggestion popup — that popup listing your saved emails/passwords is native browser UI. Its theme follows your operating system theme, not your website's theme. If your OS is in light mode, the dropdown will be white regardless of your site being dark.

  2. The font in the suggestion dropdown — same deal. The hovering text in the dropdown uses the browser's own font, not yours.

⚠️ The Big Caveat: This Approach Is for Single-Theme Sites

CAUTION

If your site supports both light and dark mode, this approach has a significant drawback.

Toggling theme from light/dark mode

The culprit is transition: background-color 5000s. It delays all background-color transitions on the input for ~83 minutes. This means: if a user has autofilled an input and then toggles the theme, the autofill background color stays stuck on the previous theme's colors. The CSS variable values change, but the transition prevents them from visually taking effect.

Can it be solved?

The only reliable solution found so far is a full page refresh when switching themes — which defeats the purpose of a smooth theme toggle.

Approaches that were tried and did not work:

  • Temporarily disabling the transition via a .theme-switching class toggled with requestAnimationFrame — Chrome still holds onto the old computed values
  • Setting color-scheme on the root element — doesn't affect the autofill dropdown or override the transition lock

Who is this for?

  • Single-theme sites (either light or dark, not both) — works perfectly
  • Multi-theme sites with a light/dark toggle — autofill colors will be stale after switching until the user refreshes

TL;DR

Don't fight Chrome's autofill with utility classes. Drop a single global CSS rule targeting :-webkit-autofill with the box-shadow trick, explicit border-color, and the transition delay. It stays out of your component code and handles background, text, border, caret, and font in one place.