Custom CSS styling is the practice of writing your own rules to override or extend a WordPress theme's default look — adjusting colors, typography, spacing, and element visibility to match a brand or fix a layout.
Custom styling lets you personalize a site cheaply and reversibly, without forking the theme. Because your rules load after the theme stylesheet, small, well-targeted overrides achieve big visual changes through the CSS cascade and specificity. Keeping custom CSS minimal and in a child theme (not pasted into random plugins) also reduces the attack surface and keeps changes auditable. Overrides applied here survive theme updates when placed correctly, so you avoid the classic mistake of editing the parent theme directly and losing every change on the next update.
- Identify the element's selector using browser DevTools (Inspect).
- Write the most specific selector needed, then override properties.
- Place rules in Appearance → Customize → Additional CSS for quick tweaks, or a child theme
style.cssfor larger sets. - Avoid
!importantunless overriding stubborn inline or plugin styles. - Test in the Customizer preview and across screen sizes before publishing.
The Additional CSS panel lives inside the Customizer and writes to the wp_custom_css_post custom post type — it is theme-scoped, so switching themes hides the rules until you switch back.
For larger or version-controlled rule sets, use a child theme so the CSS lives on disk and survives parent-theme updates:
<?php
// child-theme/functions.php — load the parent stylesheet first,
// then the child stylesheet so child rules win on equal specificity.
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
wp_enqueue_style(
'child-style',
get_stylesheet_directory_uri() . '/style.css',
array( 'parent-style' ),
wp_get_theme()->get( 'Version' )
);
} );/* Restyle the primary button site-wide */
.wp-block-button__link,
button[type="submit"] {
background-color: #146c43;
color: #ffffff;
border-radius: 6px;
padding: 10px 18px;
}
/* Hide a theme element you don't want */
.site-footer .credits {
display: none;
}
/* Respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }
}Tip
Prefer overriding CSS custom properties (variables) exposed by block themes via theme.json and :root instead of hard-coding hex values. Changing --wp--preset--color--primary once recolors every element that references it, keeping your overrides consistent and future-proof.
Custom CSS is not executable code, but it can still be abused and it interacts with the site's trust boundary:
- Only administrators should reach Additional CSS. The
edit_csscapability is mapped tounfiltered_html; on multisite this is restricted, and you should not grant it to untrusted editors. - CSS can leak or exfiltrate data (attribute selectors that trigger background-image requests) and can clickjack UI by repositioning elements. Never paste CSS from an untrusted source.
- Avoid
url()references to third-party hosts — they create tracking vectors and can break under a strict Content-Security-Policy. Self-host fonts and images. - Do not use CSS
display:noneas a security control to "hide" admin functions; the markup is still delivered to the browser and is trivially revealed.
Warning
Anyone with the unfiltered_html capability can inject arbitrary CSS (and, elsewhere, HTML). Treat that capability as high-privilege and audit which roles hold it.
- Rule has no effect: the theme selector is more specific. Increase specificity (add a parent selector) rather than reaching for
!important. Inspect the computed styles in DevTools to see which rule wins. - Change works in preview but not live: you published a different theme, or a caching layer (page cache / CDN / browser) is serving stale CSS. Purge caches and hard-reload.
- Styles vanished after a theme switch: Additional CSS is stored per-theme. Copy the rules to the new theme or move them into a child theme.
- Layout breaks on mobile: wrap responsive tweaks in
@mediaqueries and test the Customizer's device-preview icons.
# Quickly confirm whether a CDN/proxy is serving cached CSS
curl -sI https://example.com/wp-content/themes/mytheme/style.css | grep -i -E 'age|cache|etag'- WordPress Developer — Additional CSS / Customizer: https://developer.wordpress.org/themes/customize-api/
- WordPress Theme Handbook — Child Themes: https://developer.wordpress.org/themes/advanced-topics/child-themes/
- WordPress Theme Handbook — theme.json global styles: https://developer.wordpress.org/themes/global-settings-and-styles/
- MDN — CSS specificity and the cascade: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
- MDN — prefers-reduced-motion: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
- CSS Customization — module MOC
- WordPress-CSS-Editor
- CSS-Best-Practices
- Secure WordPress Administration — course MOC
