Skip to content

Latest commit

 

History

History
101 lines (76 loc) · 5.45 KB

File metadata and controls

101 lines (76 loc) · 5.45 KB

Custom CSS Styling

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.

Why it matters

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.

How to do it

  • 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.css for larger sets.
  • Avoid !important unless 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.

WordPress Customizer showing the Additional CSS panel with a live preview pane

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' )
    );
} );

Example

/* 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.

Security considerations

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_css capability is mapped to unfiltered_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:none as 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.

Troubleshooting

  • 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 @media queries 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'

References

Related