How to Use Navy Blue Colors in CSS and HTML
Named colours, custom properties, gradients, shadows and colour-mix, with copyable snippets.
Getting a navy onto a page is trivial. Managing navy across a codebase so that every button, border and background stays consistent through two years of feature work is not. This guide covers the CSS techniques that make the difference, from the named keyword through custom properties, colour functions, gradients and theming.
The named keyword
CSS has understood navy since the beginning. It resolves to and is available in every browser without qualification:
h1 { color: navy; }
.panel { background-color: navy; }
.rule { border-bottom: 2px solid navy; }It is genuinely useful for prototypes and throwaway pages. It is a poor choice for production, for one reason: you cannot adjust it. The moment a designer asks for a slightly less saturated navy, every occurrence of the keyword has to be found and replaced. Custom properties solve this on day one at almost no cost.
Related keywords in the same family are midnightblue , darkblue and royalblue . Their names are historical rather than systematic, so darkblue is lighter than navy despite what the names suggest.
Custom properties as the foundation
Declare your navies once on the root element and reference them everywhere. This single habit prevents most colour inconsistency:
:root {
/* Core scale */
--navy-900: #080F26;
--navy-800: #0A1128;
--navy-700: #14213D;
--navy-600: #1E3A8A;
--navy-500: #3A5BA0;
--navy-300: #7A8FB8;
--navy-100: #E4E9F2;
/* Semantic aliases: what the colour means, not what it is */
--surface-page: var(--navy-100);
--surface-card: #FFFFFF;
--text-body: var(--navy-800);
--text-link: var(--navy-600);
--border-subtle: #DCE4F0;
--action-primary: var(--navy-600);
}The two-layer structure matters more than the values. The numbered scale describes colours; the semantic aliases describe roles. When a redesign changes the link colour, you edit one alias rather than hunting through components. When you add dark mode, you redefine the aliases and leave every component untouched.
Naming the scale
Use numbers rather than adjectives. A scale of navy-100 through navy-900 stays coherent when someone inserts a new step; a scale of light, medium and dark navy does not survive its first addition. Higher numbers should mean darker, following the convention most design systems already use.
Deriving colours with colour-mix
Modern CSS can compute related colours in the browser, which keeps your entire palette tied to one source value:
:root { --navy: #14213D; }
.tint { background: color-mix(in srgb, var(--navy) 12%, white); }
.shade { background: color-mix(in srgb, var(--navy) 80%, black); }
/* Perceptually even steps */
.tint-even { background: color-mix(in oklab, var(--navy) 12%, white); }
/* Hover states derived from the base colour */
.btn {
background: var(--navy);
color: #FFFFFF;
}
.btn:hover {
background: color-mix(in srgb, var(--navy) 82%, white);
}The in oklab interpolation is worth knowing about. Mixing in sRGB produces steps that look uneven to the eye because sRGB is not perceptually uniform; mixing in oklab corrects for that. For navy specifically, the difference is most visible in the mid-range tints.
Relative colour syntax
Newer still is relative colour syntax, which lets you take an existing colour apart and rebuild it with one channel changed:
:root { --navy: #14213D; }
.lighter {
/* Same hue and saturation, lightness raised by 18 points */
background: hsl(from var(--navy) h s calc(l + 18));
}
.desaturated {
background: hsl(from var(--navy) h calc(s - 20) l);
}Check current browser support before relying on this in production, and provide a static fallback declaration immediately above it. Any browser that does not understand the newer syntax ignores that declaration and keeps the previous one, which is the whole basis of CSS fallbacks.
Navy gradients
A gradient between two navies that share a hue looks like depth. A gradient between navies with different hues usually looks like a mistake, because the intermediate colours pass through territory neither endpoint intended.
/* Subtle depth: one hue, two lightness levels */
.hero {
background: linear-gradient(160deg, #0A1128 0%, #14213D 55%, #0D1B3E 100%);
}
/* Ambient glow layered over a base */
.hero-glow {
background:
radial-gradient(900px 380px at 15% -10%, #1E3A6E 0%, transparent 62%),
linear-gradient(165deg, #0A1128, #14213D);
}
/* Text clipped to a gradient, for display headings only */
.gradient-heading {
background: linear-gradient(100deg, #1E3A8A, #7FA8E8);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}Gradient text has an accessibility cost. Because the text becomes transparent, contrast varies across each character and automated checkers cannot measure it. Restrict it to large display type, never to body copy, and make sure the darkest stop still clears contrast against the background.
Borders, shadows and outlines
Full-strength navy borders are almost always too heavy. Use a tint for structure and save the strong navy for elements that need emphasis:
.card {
border: 1px solid #DCE4F0;
border-radius: 14px;
box-shadow: 0 1px 2px rgba(10, 17, 40, 0.06),
0 12px 32px rgba(10, 17, 40, 0.07);
}
.card--featured {
border-color: #1E3A8A;
box-shadow: 0 0 0 3px rgba(30, 58, 138, 0.12);
}Note that the shadows use navy at low alpha rather than black. A pure black shadow on a cool palette looks slightly dirty; tinting the shadow with your darkest navy keeps everything in the same temperature.
Focus rings
Never remove focus outlines without replacing them. On a navy interface, a navy focus ring disappears against navy elements, so choose something outside the family:
:focus-visible {
outline: 3px solid #C9A227;
outline-offset: 2px;
border-radius: 4px;
}Theming light and dark
With semantic aliases in place, a dark theme becomes a redefinition rather than a rewrite:
:root {
color-scheme: light dark;
--surface-page: #F4F7FC;
--surface-card: #FFFFFF;
--text-body: #131C33;
--border-subtle: #DCE4F0;
}
@media (prefers-color-scheme: dark) {
:root {
--surface-page: #080F26;
--surface-card: #14213D;
--text-body: #E7EDF8;
--border-subtle: #223A5E;
}
}
body {
background: var(--surface-page);
color: var(--text-body);
}The color-scheme declaration is easy to forget and does real work: it tells the browser to render form controls, scrollbars and default backgrounds in the matching theme, which prevents a white flash before your CSS applies.
HTML details worth getting right
<meta name="theme-color" content="#0A1128">
<meta name="theme-color" content="#F4F7FC" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#080F26" media="(prefers-color-scheme: dark)">Mobile browsers tint their address bar to match, which makes a navy site feel considerably more finished on a phone. Inline styles remain acceptable for one specific case: swatch previews, where the colour is data rather than design.
<span class="swatch" style="background: #14213D" aria-hidden="true"></span>
<code>#14213D</code>The aria-hidden attribute matters there. A colour block conveys nothing to a screen reader, so the accessible information has to be the code beside it.
Performance notes
Colour choices rarely affect performance, with two exceptions. Large multi-stop gradients on scrolling elements can cause repaint cost on low-end devices; test on real hardware rather than a desktop emulator. And animating colour properties triggers paint on every frame, so prefer transitioning opacity or using a pre-composited layer when animating large navy surfaces.
For the values themselves, see the shade collection. For choosing which navy to build your system around, read the complete reference and the light navy guide for tint generation in more depth.
Related guides
About the author
navy blue color code Editorial Team researches and maintains the navy shade library at navy blue color code. Every value published here is derived from its source HEX code rather than transcribed, and articles are reviewed whenever the underlying standards change. Published by navy blue color code. Corrections are welcome at [email protected].
Frequently asked questions
Can I write color: navy in CSS?
Yes. navy is one of the sixteen original named colours and resolves to #000080 in every browser. It needs no fallback.
Should I use HEX or custom properties?
Define the HEX once in a custom property and reference the property everywhere else. Hard-coding the same HEX in twenty places is how palettes drift.
What is color-mix used for?
It blends two colours in CSS itself, so you can derive tints, shades and hover states from a single source value without a build step.
How do I set a navy theme colour on mobile browsers?
Use <meta name="theme-color" content="#0A1128"> in the head. Mobile browsers tint their UI chrome to match.
Do I still need vendor prefixes for navy gradients?
No. Unprefixed linear-gradient has been supported across all current browsers for many years.