- Add Lightning CSS integration for CSS bundling and minification - Create Makefile targets: css-dev, css-prod, css-watch, css-clean - Implement conditional CSS loading based on GO_ENV (dev=modular, prod=bundled) - Add IsProduction template variable for environment-aware rendering - Keep print.css separate with media="print" for PDF export - Add static/dist/ to .gitignore (generated bundles) - Fix Go template syntax in _cv-header.css - Remove redundant font @import in _typography.css Performance gains: - 27 HTTP requests → 1 (96% reduction) - 188KB → 86KB CSS (54% reduction) - ~15KB gzip network transfer Documentation: - Update 12-CSS-ARCHITECTURE.md with bundling section - Add Phase 9 to 2-MODERN-WEB-TECHNIQUES.md - Add css-bundling.test.mjs Playwright test (8/8 pass)
16 KiB
CSS Architecture Documentation
Overview
The CV site uses a modular CSS architecture based on ITCSS (Inverted Triangle CSS) principles, organized into layers from generic to specific styles. This approach ensures maintainability, scalability, and reduces specificity conflicts.
Directory Structure
static/css/
├── main.css # Entry point - imports all modules
├── print.css # Print styles (loaded separately with media="print")
├── 01-foundation/ # Base styles, variables, resets
│ ├── _reset.css # CSS reset/normalize
│ ├── _variables.css # CSS custom properties (colors, spacing)
│ ├── _typography.css # Font definitions and text styles
│ └── _themes.css # Theme variables (light/dark modes)
├── 02-layout/ # Page structure and grids
│ ├── _container.css # Container wrapper styles
│ ├── _page.css # Page layout structure
│ ├── _grid.css # Grid system
│ └── _paper.css # CV paper/document styles
├── 03-components/ # UI components
│ ├── _action-bar.css # Top action bar
│ ├── _sidebar.css # Skills sidebar
│ ├── _cv-header.css # CV header section
│ ├── _cv-section.css # Generic CV sections
│ ├── _experience.css # Work experience items
│ ├── _projects.css # Projects section
│ ├── _courses.css # Courses section
│ ├── _education.css # Education section
│ └── _languages.css # Languages section
├── 04-interactive/ # Interactive elements & HTMX patterns
│ ├── _toggles.css # Toggle switches (theme, length, icons)
│ ├── _tooltips.css # Tooltip styles
│ ├── _navigation.css # Hamburger menu & navigation
│ ├── _scroll-behavior.css # Scroll-based interactions
│ ├── _buttons.css # Fixed action buttons
│ ├── _modals.css # Modal dialogs
│ ├── _toasts.css # Toast notifications
│ └── _zoom-control.css # Zoom slider control
├── 05-responsive/ # Responsive breakpoints
│ └── _breakpoints.css # Media queries for all screen sizes
└── 06-effects/ # Visual effects
└── _skeleton.css # Loading skeleton screens
static/dist/ # Generated by Lightning CSS (gitignored)
├── bundle.css # Development bundle
└── bundle.min.css # Production bundle (minified)
Layer Descriptions
01-foundation/ - Base Styles (Most Generic)
Purpose: Fundamental styles that affect the entire application.
- _reset.css: Normalizes browser defaults for consistency
- _variables.css: CSS custom properties (colors, spacing, z-index)
- _typography.css: Font families, sizes, line heights
- _themes.css: Theme-specific variables (light/dark/clean modes)
When to edit: Changing global colors, fonts, or spacing values.
02-layout/ - Structure
Purpose: Page-level layout and positioning systems.
- _container.css: Main wrapper containers
- _page.css: Page layout structure (multi-page CV)
- _grid.css: Grid system for content organization
- _paper.css: CV paper/document styling (cv-short, cv-long classes)
When to edit: Adjusting page structure, paper sizes, or grid systems.
03-components/ - UI Components
Purpose: Reusable UI components specific to CV sections.
Each file contains styles for a specific CV section:
- Visual appearance (colors, borders, spacing)
- Component-specific layouts
- Section-specific icons and imagery
When to edit: Styling individual CV sections or components.
04-interactive/ - Interactive Elements
Purpose: User interactions, HTMX patterns, and dynamic behaviors.
_toggles.css (5.9 KB)
- Theme toggles (light/dark/clean)
- Length toggles (short/long CV)
- Icon visibility toggles
- Toggle switch component styles
_navigation.css (8.2 KB)
- Hamburger button styling
- Slide-out navigation menu
- Menu items and submenus
- Smooth scrolling behavior
- Pure CSS hover-triggered menus
_scroll-behavior.css (5.0 KB)
- Header hide/show on scroll direction
- Back-to-top button
- Info button (bottom-left)
- Scroll-based visual changes
_buttons.css (4.7 KB)
- Fixed action buttons:
- Download button (PDF export)
- Print-friendly button
- Keyboard shortcuts button
- Zoom toggle button
- Mobile horizontal layout
- At-bottom state changes
_modals.css (16 KB)
- Info Modal: Project details dialog
- Keyboard Shortcuts Modal: Shortcut reference
- PDF Download Modal: Interactive thumbnail selection
- Native
<dialog>element styling - Glassmorphism effects
- Accessibility features
_zoom-control.css (6.3 KB)
- Zoom slider (50%-150%)
- Reset button
- Draggable positioning
- Mobile auto-disable
- localStorage persistence
When to edit: Adding new interactive features or HTMX swap patterns.
05-responsive/ - Responsive Design
Purpose: Media queries for different screen sizes.
_breakpoints.css (14 KB)
- Desktop (>1280px): Full layout with sidebars
- Medium (1024-1280px): Compact fonts, collapsible sidebars
- Medium (901-1023px): EN/ES labels, icon-only buttons
- Tablet (≤768px): Centered photo, larger touch targets
- Mobile (≤540px): Single-column, hamburger menu only
- Small Mobile (≤480px): Ultra-compact zoom control
When to edit: Adjusting responsive behavior at specific breakpoints.
06-effects/ - Visual Effects
Purpose: Animations, transitions, and loading states.
- _skeleton.css: Loading skeleton screens for language transitions
When to edit: Adding new animations or loading states.
print.css - Print Styles (Separate File)
Purpose: Print-optimized styles loaded via <link rel="stylesheet" href="print.css" media="print">.
Location: static/css/print.css (at root level, NOT bundled)
Why separate:
- Only loaded when printing (no bundle bloat)
- Uses
media="print"for automatic browser handling - Special PDF export requirements
- Independent of theme system
When to edit: Adjusting print output or PDF export appearance.
Import Order (main.css)
The import order follows the ITCSS inverted triangle - from generic to specific:
/* 01 - Foundation (most generic) */
@import './01-foundation/_reset.css';
@import './01-foundation/_variables.css';
@import './01-foundation/_typography.css';
@import './01-foundation/_themes.css';
/* 02 - Layout */
@import './02-layout/_container.css';
@import './02-layout/_page.css';
@import './02-layout/_grid.css';
@import './02-layout/_paper.css';
/* 03 - Components */
@import './03-components/_action-bar.css';
@import './03-components/_sidebar.css';
@import './03-components/_cv-header.css';
@import './03-components/_cv-section.css';
@import './03-components/_experience.css';
@import './03-components/_projects.css';
@import './03-components/_courses.css';
@import './03-components/_education.css';
@import './03-components/_languages.css';
/* 04 - Interactive */
@import './04-interactive/_toggles.css';
@import './04-interactive/_navigation.css';
@import './04-interactive/_scroll-behavior.css';
@import './04-interactive/_buttons.css';
@import './04-interactive/_modals.css';
@import './04-interactive/_zoom-control.css';
/* 05 - Responsive */
@import './05-responsive/_breakpoints.css';
/* 06 - Effects */
@import './06-effects/_skeleton.css';
/* NOTE: print.css is loaded separately in HTML with media="print" */
⚠️ IMPORTANT: Do not change the import order. Later imports can override earlier ones based on specificity.
CSS Bundling (Lightning CSS)
For production, CSS files are bundled and minified using Lightning CSS for better performance.
Bundle Strategy
| Mode | CSS Loading | HTTP Requests |
|---|---|---|
| Development | Individual files via @import |
~27 requests (waterfall) |
| Production | Single bundled file | 1 request |
Size Comparison
| Metric | Individual Files | Bundle (dev) | Bundle (minified) | Gzip |
|---|---|---|---|---|
| Size | 188 KB | 110 KB | 86 KB | ~15 KB |
| Reduction | - | 43% | 54% | 92% |
Makefile Targets
# Development: Bundle CSS (readable)
make css-dev
# Production: Bundle + minify CSS
make css-prod
# Watch mode (auto-rebuild on changes)
make css-watch
# Clean generated bundles
make css-clean
Environment-Based Loading
The template conditionally loads CSS based on GO_ENV:
<!-- In templates/index.html -->
{{if .IsProduction}}
<link rel="stylesheet" href="/static/dist/bundle.min.css">
{{else}}
<link rel="stylesheet" href="/static/css/main.css">
{{end}}
<!-- Print always separate -->
<link rel="stylesheet" href="/static/css/print.css" media="print">
Build Requirements
# Install Lightning CSS CLI globally
npm install -g lightningcss-cli
# Verify installation
lightningcss --version
CI/CD Integration
Production builds should run make css-prod before deployment:
# Example GitHub Actions
- name: Build CSS
run: make css-prod
File Naming Conventions
- Prefix with underscore:
_filename.cssindicates a partial file (imported by main.css) - Lowercase with hyphens:
_action-bar.css(not_ActionBar.cssor_action_bar.css) - Descriptive names: File name should clearly indicate its purpose
HTMX Integration
Interactive Elements Design
The 04-interactive layer is designed to work seamlessly with HTMX patterns:
- Atomic Swaps: Each component can be swapped independently
- Out-of-Band Updates: Modals and toggles support
hx-swap-oob - Loading States: Skeleton screens for async content transitions
- Progressive Enhancement: CSS-first approach with JavaScript fallbacks
Common HTMX Patterns
<!-- Toggle with out-of-band swap -->
<div hx-post="/toggle/theme"
hx-target=".cv-container"
hx-swap="outerHTML">
<!-- Content updated by server -->
</div>
<!-- Modal trigger -->
<button onclick="document.getElementById('pdf-modal').showModal()">
Download PDF
</button>
<!-- Navigation with smooth scroll -->
<a href="#experience" class="menu-item">
Experience
</a>
Best Practices
1. Single Responsibility Principle
Each CSS file should have one clear purpose. Don't mix concerns.
✅ Good: _buttons.css contains only button styles
❌ Bad: _buttons.css contains buttons + modals + forms
2. Component Isolation
Components should be self-contained and not depend on parent context.
✅ Good:
.modal-close {
position: absolute;
top: 1rem;
right: 1rem;
}
❌ Bad:
.modal .close { /* Requires .modal parent */
position: absolute;
}
3. Mobile-First Responsive Design
Write mobile styles first, then add desktop enhancements.
✅ Good:
.button { padding: 0.5rem; }
@media (min-width: 768px) {
.button { padding: 1rem; }
}
4. CSS Custom Properties for Theming
Use variables for theme-specific values.
✅ Good:
.button { background: var(--primary-color); }
❌ Bad:
.button { background: #27ae60; }
5. Avoid Deep Nesting
Keep specificity low for easier overrides.
✅ Good: .menu-item { }
❌ Bad: .navigation .menu .item { }
Adding New Styles
Adding a New Component
-
Create new file in
03-components/:touch static/css/03-components/_my-component.css -
Add import to
main.cssin the components section:@import './03-components/_my-component.css'; -
Write component styles:
/* My Component - Description */ .my-component { /* Styles here */ }
Adding a New Interactive Pattern
-
Determine if it fits an existing file or needs a new one
-
If new file needed, create in
04-interactive/:touch static/css/04-interactive/_my-feature.css -
Add import to
main.cssafter other interactive files -
Document HTMX integration patterns if applicable
Adding Responsive Styles
- Add media queries to
05-responsive/_breakpoints.css - Group by breakpoint, not by component
- Use min-width for mobile-first approach
Performance Considerations
File Sizes (Production Bundle)
- Production CSS: 86 KB minified (~15 KB gzip)
- Print CSS: 18 KB (loaded only when printing)
- Development CSS: ~188 KB across 27 files
Production Optimizations
- Lightning CSS bundling: Combines all CSS into single file
- Minification: Removes whitespace, comments, shortens values
- Single HTTP request: Eliminates waterfall from @import
- Gzip compression: 92% network transfer reduction
Development Workflow
- Hot reload friendly: Individual files for debugging
- Browser DevTools: Can trace styles to source files
- Faster iteration: No build step required
- Modular organization: Easy to find and edit specific styles
Troubleshooting
Styles Not Applying
- Check import order: Later imports override earlier ones
- Check specificity: Use browser DevTools to see which rule wins
- Check file path: Ensure
@importpath is correct - Clear browser cache: Hard refresh (Cmd+Shift+R / Ctrl+Shift+F5)
Modal Not Showing
- Check if
<dialog>element is in DOM - Verify
.showModal()is called (not.show()) - Check z-index conflicts
- Inspect
::backdropstyling
Responsive Issues
- Check viewport meta tag in HTML:
<meta name="viewport" content="width=device-width, initial-scale=1.0"> - Test at exact breakpoint values
- Use browser DevTools responsive mode
- Check for
!importantoverrides
Migration History
v1.0 → v2.0 (Current)
Before (Monolithic):
- Single
_remaining.cssfile: 2,287 lines - Difficult to navigate and maintain
- High merge conflict risk
After (Modular):
- 6 focused files: 2,042 lines total
- Clear separation of concerns
- Better caching and collaboration
- 245 lines saved through organization
Breaking Changes: None - CSS is backward compatible
Future Enhancements
Planned Improvements
- CSS Modules for component scoping
- CSS Container Queries for responsive components
- View Transitions API for smooth page changes
- CSS Nesting (when browser support improves)
- Tailwind CSS integration (optional)
Considerations
- Keep HTMX-friendly patterns
- Maintain progressive enhancement
- Preserve print stylesheet functionality
- Ensure accessibility standards (WCAG AA)
References
- ITCSS: Harry Roberts' ITCSS
- BEM Naming: getbem.com
- CSS Custom Properties: MDN Web Docs
- HTMX Patterns: htmx.org
Contributing
When adding new styles:
- Follow the established file structure
- Use CSS custom properties for theme values
- Write mobile-first responsive styles
- Test in multiple browsers
- Document complex interactions
- Update this documentation for structural changes
Last Updated: November 30, 2025 Version: 2.1 (Lightning CSS bundling) Maintainer: Development Team