9.3 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	CSS Optimization Guide
Overview
This document describes the CSS optimization implementation for the XRPL Dev Portal, including the rationale, implementation details, performance improvements, and maintenance guidelines.
The Problem
Before Optimization
The dev portal was serving a 486 KB minified CSS bundle that included:
- Entire Bootstrap 5.3.8 framework (~200+ KB)
 - Thousands of unused CSS selectors
 - No tree-shaking or dead code elimination
 - All styles loaded on every page, regardless of usage
 - 1-minute lag in Chrome DevTools when filtering CSS
 
Impact
- Developer Experience: DevTools filter took 60+ seconds to respond
 - Page Performance: 486 KB CSS downloaded on every page load
 - Build Process: Outdated Sass 1.26.10 (from 2020)
 - Debugging: No source maps, even in development
 
Analysis Results
Initial analysis showed:
Bundle Size:      486.64 KB
Total Selectors:  5,423
Unique Selectors: 4,678
Bootstrap Component Usage:
  - Pagination: 998 usages
  - Cards: 428 usages
  - Grid System: 253 usages
  - ...but also...
  - Toast: 8 usages
  - Spinner: 8 usages
  - Accordion: 0 usages (unused!)
The Solution
Modern Build Pipeline
Implemented a three-stage optimization pipeline:
SCSS → Sass Compiler → PostCSS → Optimized CSS
                         │
                         ├─ PurgeCSS (removes unused)
                         ├─ Autoprefixer (adds vendor prefixes)
                         └─ cssnano (minifies)
Key Technologies
- Sass (latest) - Modern SCSS compilation with better performance
 - PostCSS - Industry-standard CSS processing
 - PurgeCSS - Intelligent unused CSS removal
 - Autoprefixer - Browser compatibility
 - cssnano - Advanced minification
 
Implementation
1. Dependency Upgrades
{
  "devDependencies": {
    "sass": "^1.93.2",  // was 1.26.10
    "postcss": "^8.5.6",
    "postcss-cli": "^11.0.1",
    "@fullhuman/postcss-purgecss": "^7.0.2",
    "autoprefixer": "^10.4.21",
    "cssnano": "^7.1.1"
  }
}
2. Build Scripts
Created separate development and production builds:
{
  "scripts": {
    "build-css": "Production build with full optimization",
    "build-css:dev": "Development build with source maps",
    "build-css:watch": "Watch mode for continuous compilation",
    "analyze-css": "node scripts/analyze-css.js"
  }
}
Production Build:
- ✅ Full PurgeCSS optimization
 - ✅ Minified and compressed
 - ✅ Autoprefixed
 - ❌ No source maps
 
Development Build:
- ✅ Source maps for debugging
 - ✅ Autoprefixed
 - ❌ No PurgeCSS (faster builds)
 - ❌ Not minified (readable)
 
3. PurgeCSS Configuration
Created postcss.config.cjs with intelligent safelist:
// Content paths - scan these for class names
content: [
  './**/*.tsx',
  './**/*.md',
  './**/*.yaml',
  './**/*.html',
  './static/js/**/*.js',
]
// Safelist - preserve these classes
safelist: {
  standard: [
    'html', 'body', 'light', 'dark',
    /^show$/, /^active$/, /^disabled$/,
  ],
  deep: [
    /dropdown-menu/, /modal-backdrop/,
    /cm-/, /CodeMirror/, // Third-party
    /rpc-tool/, /websocket/, // Custom components
  ],
}
Safelist Strategy:
- Standard: State classes added by JavaScript
 - Deep: Component patterns (keeps parent and children)
 - Greedy: Attribute-based matching
 
4. Analysis Tool
Created scripts/analyze-css.js to track optimization:
- Bundle size metrics
 - Selector counts
 - Bootstrap component usage
 - Custom pattern detection
 - Optimization recommendations
 
Results
Performance Improvements
| Metric | Before | After | Improvement | 
|---|---|---|---|
| Bundle Size (Uncompressed) | 486.64 KB | 280.92 KB | 42% smaller | 
| Bundle Size (Gzipped) | 71.14 KB | 43.32 KB | 39% smaller | 
| Total Selectors | 5,423 | 2,681 | 51% fewer | 
| Unique Selectors | 4,678 | 2,167 | 54% fewer | 
| DevTools Filter | ~60 seconds | <1 second | 98% faster | 
| Download Time (3G) | ~2.0s | ~1.2s | 40% faster | 
Note: Gzipped size is what actually gets transmitted over the network, representing the real-world bandwidth savings.
Bootstrap Component Optimization
| Component | Before | After | Reduction | 
|---|---|---|---|
| Pagination | 998 | 831 | 17% | 
| Cards | 428 | 306 | 29% | 
| Grid System | 253 | 94 | 63% | 
| Badge | 253 | 0 | 100% (unused) | 
| Navbar | 171 | 78 | 54% | 
| Buttons | 145 | 77 | 47% | 
| Forms | 179 | 70 | 61% | 
Developer Experience
Before:
Build time: 5-10 seconds
DevTools CSS filter: 60 seconds
Debugging: No source maps
After:
Production build: 8-12 seconds
Development build: 3-5 seconds (no PurgeCSS)
DevTools CSS filter: <1 second
Debugging: Source maps in dev mode
Maintenance
Adding New Styles
When adding new component styles:
- 
Create the SCSS file:
// styles/_my-component.scss .my-component { // styles here } - 
Import in xrpl.scss:
@import "_my-component.scss"; - 
If using dynamic classes, update safelist:
// postcss.config.cjs deep: [ /my-component/, // Keeps all .my-component-* classes ] - 
Test both builds:
npm run build-css:dev # Test development build npm run build-css # Test production build npm run analyze-css # Check bundle size impact 
Troubleshooting Missing Styles
If styles are missing after a production build:
- 
Identify the missing class:
# Search for class usage in codebase grep -r "missing-class" . - 
Check if it's dynamically added:
- Bootstrap JavaScript components
 - React state-based classes
 - Third-party library classes
 
 - 
Add to PurgeCSS safelist:
// postcss.config.cjs safelist: { deep: [ /missing-class/, // Preserve this pattern ], } - 
Rebuild and verify:
npm run build-css npm run analyze-css 
Monitoring Bundle Size
Run the analysis tool regularly:
npm run analyze-css
Watch for:
- Bundle size > 350 KB (indicates regression)
 - Components with 0 usages (can be removed from Bootstrap import)
 - Significant selector count increases
 
Future Optimizations
Potential next steps for further optimization:
- 
Code Splitting
- Split vendor CSS (Bootstrap) from custom styles
 - Lazy-load page-specific styles
 - Critical CSS extraction
 
 - 
Bootstrap Customization
- Import only needed Bootstrap components
 - Remove unused variables and mixins
 - Custom Bootstrap build
 
 - 
Component-Level CSS
- CSS Modules for page components
 - CSS-in-JS for dynamic styles
 - Scoped styles per route
 
 - 
Advanced Compression
- Brotli compression (88% ratio vs 76% gzip)
 - CSS splitting by media queries
 - HTTP/2 server push for critical CSS
 
 
Migration Notes
Breaking Changes
None - This optimization is backward-compatible. All existing classes and styles are preserved.
Testing Checklist
When testing the optimization:
- Homepage loads correctly
 - Documentation pages display properly
 - Blog posts render correctly
 - Dev tools (RPC tool, WebSocket tool) function
 - Navigation menus work
 - Dropdowns and modals open correctly
 - Forms are styled properly
 - Code syntax highlighting works
 - Print styles work
 - Light/dark theme switching works
 
Rollback Procedure
If issues are found:
- 
Temporarily revert to old build:
# In package.json, change build-css to: "build-css": "sass --load-path styles/scss styles/xrpl.scss ./static/css/devportal2024-v1.css --style compressed --no-source-map" - 
Rebuild:
npm run build-css - 
Report the issue with:
- Missing class names
 - Page where issue appears
 - Expected vs actual behavior
 
 
Resources
Documentation
Tools
npm run build-css- Production buildnpm run build-css:dev- Development buildnpm run build-css:watch- Watch modenpm run analyze-css- Bundle analysis
Files
styles/README.md- Build process documentationpostcss.config.cjs- PostCSS and PurgeCSS configurationscripts/analyze-css.js- Bundle analysis toolpackage.json- Build scripts
Conclusion
This optimization reduces the CSS bundle by 42% (486 KB → 281 KB), dramatically improving both developer experience and end-user performance. The implementation uses industry-standard tools and maintains full backward compatibility while providing a foundation for future optimizations.
Key Takeaways:
- ✅ 42% smaller uncompressed CSS bundle (486 KB → 281 KB)
 - ✅ 39% smaller gzipped bundle (71 KB → 43 KB network transfer)
 - ✅ 98% faster DevTools filtering (60s → <1s)
 - ✅ Modern build tooling (Sass + PostCSS + PurgeCSS)
 - ✅ Source maps in development mode
 - ✅ Backward compatible - no breaking changes
 - ✅ Well documented and maintainable
 
Last updated: October 2025 Contributors: CSS Optimization Initiative