Skip to main content

Custom CSS Integration

warning

CSS bugs often look like "GeneratePress is broken" but are really cache or specificity. Change one thing at a time and test logged-out.

Custom CSS Integration Explained

LocationBest forProsCons
Customizer -> Additional CSSsmall tweaksfaststored in DB, harder to version
Child theme style.cssminimal overrides + headeralways loadedcan become a dumping ground
Child theme assets/css/*.csscomponent CSSmodular, versionedrequires enqueue
GenerateBlocks presetsconsistent block stylingUI-drivenstill needs discipline

Why It Matters

  • CSS is the fastest way to create long-term maintenance debt.
  • A good file structure prevents "random overrides".
  • Cache-aware versioning prevents stale styles under OLS + LSCache.

How It Works

CSS follows the cascade: source order + specificity + importance. In WordPress, enqueue order decides source order. Caches decide whether you even see the newest file.

Practical Walkthrough

Step 1: Create a Modular CSS Folder

create-css-folder.sh
cd /var/www/html
mkdir -p wp-content/themes/generatepress-child/assets/css
ls -lah wp-content/themes/generatepress-child/assets/css

Step 2: Create a Tokens File and a Component File

create-css-files.sh
cat > wp-content/themes/generatepress-child/assets/css/tokens.css <<'EOF'
:root {
--brand-primary: #1e3a8a;
--brand-surface: #f8fafc;
}
EOF

cat > wp-content/themes/generatepress-child/assets/css/components.css <<'EOF'
.gp-card {
background: var(--brand-surface);
border: 1px solid #e2e8f0;
padding: 16px;
}
EOF

Step 3: Enqueue the CSS Files

wp-content/themes/generatepress-child/inc/enqueue.php
<?php

add_action( 'wp_enqueue_scripts', function() {
foreach ( array( 'tokens.css', 'components.css' ) as $file ) {
$path = get_stylesheet_directory() . '/assets/css/' . $file;
if ( file_exists( $path ) ) {
wp_enqueue_style(
'gp-child-' . $file,
get_stylesheet_directory_uri() . '/assets/css/' . $file,
array(),
filemtime( $path )
);
}
}
} );

Step 4: Verify Files Exist

verify-css-files.sh
cd /var/www/html
ls -lah wp-content/themes/generatepress-child/assets/css

Practical Examples

Example 1: Scope CSS with a Body Class

wp-content/themes/generatepress-child/inc/filters.php
<?php

add_filter( 'body_class', function( $classes ) {
$classes[] = 'gp-child-theme';
return $classes;
} );

Then scope CSS:

assets/css/components.css
.gp-child-theme .gp-card { border-radius: 12px; }

Example 2: Avoid !important by Fixing Source Order

If you are adding !important, you are usually fighting enqueue order or selector design.

Example 3: Cache Hygiene

After CSS changes:

  • purge LSCache
  • test logged-out
  • confirm versions changed (filemtime)

Best Practices

PracticeWhy
Split CSS by intent (tokens/components/pages)Easier maintenance
Keep overrides smallFewer regressions
Prefer tokens over hard-coded valuesEasier redesign
Use filemtime() for versionsCache-friendly

Troubleshooting

SymptomCauseFix
CSS not appliedWrong selector or missing enqueueVerify enqueue and inspect DOM
CSS applies for admins onlyCache varianceTest logged-out and purge LSCache
Styles revert after deployStale cachePurge cache and verify file timestamps

Hands-On

  1. Create tokens.css and components.css.
  2. Enqueue both with filemtime().
  3. Create one scoped component style using a body class.
  4. Purge cache and verify output.

Quick Reference

css-cheatsheet.sh
cd /var/www/html
ls wp-content/themes/generatepress-child/assets/css

What's Next