How to change background color of my site header in WordPress
Changing a header’s background color sounds like a five-minute job, and for a lot of themes it is. The Customizer has a color picker, you click it, you’re done. The problem shows up when the color doesn’t stick, or it changes on desktop but not mobile, or it looks right until a page builder overrides it two levels down in the CSS cascade. This covers the reliable methods, plus the specificity and caching issues that cause “I changed it but nothing happened” tickets.
Start With the Customizer, But Know Its Limits
Go to Appearance > Customize and look for Header, Site Identity, or Colors, the exact label depends on the theme. If your theme built its header color option properly, this writes an inline style or a small block of CSS directly to the page, which usually wins against the theme’s own stylesheet without any extra work.
The limit: not every theme exposes header background as a distinct option. Some only expose a single “accent color” that touches buttons and links along with the header all at once, which isn’t what you want if you’re trying to change just the header. If the Customizer doesn’t have a dedicated header background field, move to custom CSS.
Custom CSS: Where Most People Land
Appearance > Customize > Additional CSS is the safest place for a CSS-only fix, since it survives theme updates (a child theme’s style.css works too and is arguably the more correct home for anything beyond a few lines).
The step people skip is identifying the actual selector. Right-click the header in your browser and choose Inspect. Look for the element that wraps the whole header, not just the logo or the nav, since the wrong target only colors part of it. Common patterns: .site-header, header#masthead.elementor-location-header. Then:
.site-header {
background-color: #0073e6;
}
If this doesn’t visibly change anything, the issue is almost always specificity, not a typo. Themes frequently apply header background through a more specific selector than a plain class, something like #masthead.site-header or a selector carrying an ID, which beats a single class in CSS’s cascade regardless of source order. Open dev tools, find the actual rule currently controlling the background, and match or exceed its specificity rather than reaching for !important as a first move. !important works, but it also makes the next override (yours, six months from now) harder to write cleanly, since it forces every subsequent change to also use !important just to compete.
Page Builders Complicate the Selector, Not the Concept
Elementor and Divi, plus similar builders that manage the header through a template, add their own wrapper classes and often their own inline styles generated from the builder’s color controls, which sit even higher in specificity than a normal stylesheet rule.
Elementor
If the header is built as an Elementor Theme Builder template, edit that template directly rather than fighting it with custom CSS. Select the outermost section, open the Style tab, and set Background there. This changes the value at its actual source instead of trying to override an inline style with a stylesheet rule, which is a fight the stylesheet usually loses without !important.
If the header background is controlled by Elementor’s Global Colors (Site Settings > Global Colors), changing the underlying global swatch cascades everywhere that color is referenced, which might be more sweeping than intended if that same swatch is used elsewhere on the site. Check what else references the color before changing it globally.
WPBakery
Open the header row in the front-end editor, click the pencil icon, and look under Design Options for a background color field. Same principle: edit at the source rather than layering a CSS override on top of an inline style.
Sticky and Transparent Headers Need a Second Rule
A lot of modern themes ship a header that’s transparent over the hero image and then switches to a solid background once the visitor scrolls past a certain point, usually toggled with a JavaScript-added class like .scrolled or .is-sticky.
Changing .site-header’s background alone often only affects one of those two states. If the header still looks transparent at the top of the page after your change, check whether the theme applies a separate, more specific rule for the non-scrolled state, frequently through a modifier class or an inline style set by JavaScript on load. You may need two rules:
.site-header { background-color: #0073e6; }
.site-header.scrolled { background-color: #0073e6; }
Inspect both states directly, at the top of the page and after scrolling, rather than assuming a single selector covers both. This is one of the most common reasons a header color change “half works.”
Using a CSS Custom Property Instead of a Hardcoded Hex
If a theme defines its colors through CSS custom properties (variables), changing the header color at the variable level is often cleaner and more maintainable than overriding a specific selector, since it also updates anywhere else that variable is referenced consistently.
:root {
–header-bg: #0073e6;
}
Inspect the theme’s existing CSS for something like var(–header-background) or similar already in use on the header rule. If it’s there, redefining the variable in Additional CSS is a one-line fix that respects the theme’s existing architecture rather than fighting it with a competing selector. Not every theme uses custom properties for this (older, simpler themes especially), but it’s worth checking before writing a full override.
Dark Mode Needs Its Own Value, Not an Assumption
If the site (or the visitor’s browser) supports a dark color scheme, a header color chosen purely for light mode can look wrong, or fail contrast entirely, once dark mode kicks in. Test with prefers-color-scheme: dark in dev tools’ rendering emulation before considering the change finished.
@media (prefers-color-scheme: dark) {
.site-header { background-color: #101828; }
}
A header color that reads fine in light mode can put white text on a background that’s suddenly too close in luminance once dark mode swaps other page elements, producing a header that technically has a background color set but doesn’t contrast against its own nav text anymore.
Gradient and Image Headers Aren’t a Simple Color Swap
Some themes set the header’s visual look through a background-image (a gradient, a texture, a photo) rather than a flat background-color, and setting background-color alone won’t override that, since background-image paints on top of it by default.
.site-header {
background-image: none;
background-color: #0073e6;
}
The background-image: none line matters here. Without it, your new background-color sits underneath the existing image and never becomes visible. This is a common reason someone sets a color, sees zero change, and assumes their selector was wrong when the real issue was an image layer still painting over it.
If the header uses a gradient defined with background: linear-gradient(…), the same principle applies; a background-color rule alone won’t remove it, since the shorthand background-image portion of that gradient declaration needs its own explicit override.
Working With WooCommerce and Membership Headers
Sites running WooCommerce or a membership plugin sometimes render a different header state for logged-in users (a cart icon, an account menu, a different notification bar) that can carry its own background styling separate from the logged-out header. If the color change looks correct while logged out but wrong while logged in, check for a body class like .logged-in or a plugin-specific wrapper that’s applying a competing background.
.logged-in .site-header {
background-color: #0073e6;
}
This is easy to miss during testing since most people check the change while logged into wp-admin (which counts as logged in) but forget to also verify the fully logged-out visitor view, or vice versa.
Contrast Is Not Optional
WCAG AA requires a 4.5:1 contrast ratio for normal text and 3:1 for large text and UI components. A striking header color that looks great in a mockup can fail this outright against your existing nav text color, particularly with mid-tone blues and purples, or muted greens, that sit in an awkward luminance range against both black and white text.
Run the exact hex values, header background against nav link color, through WebAIM’s contrast checker before shipping the change. This takes under a minute and catches a real accessibility failure before a site audit does.
Why the Change Sometimes Doesn’t Show Up At All
Caching plugins serve a stored HTML/CSS snapshot to visitors, so a CSS change in the Customizer or Additional CSS can be saved correctly and still not appear until the cache clears. Clear the page cache explicitly (most caching plugins have a “clear all cache” button) rather than assuming autosave triggers it.
Browser caching on your own machine can hide a successful change too. A hard refresh (Cmd+Shift+R or Ctrl+Shift+R) or testing in a private browsing window rules this out before you start second-guessing a CSS rule that was actually correct.
Testing Across Breakpoints Properly
A header color change deserves the same 390px check as any other visual update, not just a glance at desktop. Open dev tools’ responsive mode and step through mobile and tablet widths, then desktop, rather than resizing the browser window loosely and eyeballing it.
Two things commonly break at narrow widths that don’t show up at desktop size. First, the mobile menu toggle (hamburger icon) sometimes lives in a different DOM element with its own background, so the header bar changes color but the menu button’s background stays whatever it was. Second, some themes swap in an entirely different header template below a certain breakpoint (rather than just collapsing the desktop one via CSS), meaning your selector might not even exist in the mobile markup and needs a parallel rule targeting the mobile-specific header class instead.
Inspect the mobile header directly in dev tools rather than assuming the desktop fix inherited down cleanly. It often doesn’t, and it’s a five-minute check against a much longer debugging session later when a support ticket says “the header looks wrong on my phone” with no other detail.
Using the Theme’s Own Customizer Hooks Instead of Fighting It
If you’re comfortable with a bit of PHP and the theme exposes a customizer setting for header color that just isn’t wired up to change the actual background (a real gap in some lightweight themes), hooking into wp_head to output a small inline style block tied to that setting’s saved value is often cleaner long-term than a hardcoded CSS override, since it keeps the color editable through the Customizer for whoever manages the site after you.
add_action(‘wp_head’, function() {
$color = get_theme_mod(‘header_bg_color’, ‘#ffffff’);
echo ‘<style>.site-header{background-color:’ . esc_attr($color) . ‘;}</style>’;
});
This is more setup than pasting a static rule into Additional CSS, and it’s not necessary for a one-time change. It’s worth the extra effort specifically when the color needs to stay adjustable by a non-technical site owner going forward.
Multiple Header Templates on the Same Site Need Separate Rules
A single site rarely has just one header. A dedicated landing page template or a stripped-down checkout template often carries its own header markup, separate from the default header the rest of the site shares.
Change .site-header’s background and the main blog updates correctly, along with most other pages. Then a marketing landing page keeps its old color. That page was built with a different template that never inherited the default header markup at all; it has its own header block, or its own header.php variant entirely.
Check Appearance > Theme File Editor, or the Site Editor’s template list on a block theme, for anything named landing-page.php or a custom template slug assigned through a page’s Template dropdown in the block editor sidebar. If a page uses a non-default template, inspect that specific page’s header markup separately rather than assuming the sitewide rule reached it. Elementor and other builders add their own wrinkle here too. A page built with a builder-managed header template overrides the theme’s default header entirely for that page, so the sitewide CSS rule can be technically correct and still invisible there, since a different element is rendering.
The fix is usually one extra selector, not a rewrite. Find the template-specific wrapper class (inspect the actual landing page, not the homepage) and add a second rule targeting it alongside the main one. Skipping this check is how a header color update that looked complete in QA shows up wrong on the one page that actually mattered most, the campaign landing page a paid ad is currently sending traffic to.
Common Mistakes Worth Naming Directly
Targeting the wrong element, coloring the nav wrapper instead of the full header, so only part of the bar changes.
Reaching for !important on the first attempt instead of checking actual specificity in dev tools, which usually reveals a cleaner fix.
Forgetting the sticky or scrolled state has its own selector, so the change only applies to one scroll position.
Setting a header color without checking contrast against the existing nav text, shipping an accessibility failure alongside the visual update.
Assuming a cache clear happened automatically after a CSS save, and troubleshooting a “broken” change that was actually just cached.
FAQ
Does the header color affect my browser tab’s theme color?
Not automatically. Chrome and some mobile browsers read a separate meta theme-color tag to color the browser chrome around the tab, and that value doesn’t update just because the header’s CSS background changed. If matching those two matters for a branded feel, update the theme-color meta tag in the site’s head separately, most SEO plugins expose a field for this, or it can be set manually through a small snippet.
Why does my header color change work in the Customizer preview but not on the live site?
Almost always caching. Clear your page cache plugin’s cache and do a hard refresh before assuming the change failed to save.
Can I set different header colors for different pages?
Yes, with a body class targeted selector. WordPress adds page-specific classes to the body tag automatically (page-id-123, for instance), so a rule like .page-id-123 .site-header { background-color: #000; } applies only to that page without touching the sitewide header style.
My header color looks right on desktop but wrong on mobile. Why?
Mobile menus are frequently a separate markup structure, not just a responsive collapse of the same header, especially with page builders. Inspect the mobile menu specifically; it may need its own selector entirely rather than inheriting from .site-header.
My header background looks fine in the editor but wrong on the published page. Why?
Page builder editors often preview content inside an iframe that loads a slightly different stylesheet order than the live page, or caches an older version of the style while you’re actively editing. Save, then check the actual published URL in a private browsing window rather than trusting the in-editor preview as the final word.
Is it safe to use !important for a header background?
It’ll work, but it’s a last resort, not a first move. Check specificity first. If nothing else fixes it and the theme’s own CSS is unusually aggressive, !important is acceptable, just isolate it to this one rule rather than spreading it through every future override too.
Should I use a child theme or Additional CSS for a permanent change?
Either survives theme updates. Additional CSS is faster for a handful of rules and lives inside the Customizer where it’s easy to find later. A child theme’s style.css makes more sense once the custom CSS grows past a page or two, or when other structural changes (template overrides, functions.php additions) are happening alongside it.
Where This Leaves You
Start in the Customizer if your theme supports it directly. Move to Additional CSS or a child theme when it doesn’t, and check actual specificity in dev tools before adding !important out of frustration.
Test both the resting and scrolled states. Test both light and dark mode if the site supports it. Run the final contrast ratio before calling it done.
The color itself is the easy part. Everything downstream of it, specificity, breakpoints, logged-in states, dark mode, is where a five-minute task quietly turns into an hour if you skip the verification pass.