# CSS Sprites - Image Request Optimization ## Overview The CV website uses CSS sprites to dramatically reduce HTTP requests for company, project, and course logos. Instead of loading 44+ individual image files, we load only 3 sprite sheets (6 files total including retina versions). ## Performance Impact | Metric | Before | After | Improvement | |--------|--------|-------|-------------| | Image Requests | 44+ | 3-6 | ~93% reduction | | Cache Invalidation | Per image | Per sprite | Simplified | | HTTP Overhead | 44 round-trips | 3-6 round-trips | Dramatic reduction | ## Architecture ### File Structure ``` static/ ├── images/ │ ├── companies/ # Source images (any size) │ ├── projects/ # Source images (any size) │ ├── courses/ # Source images (any size) │ └── sprites/ # Generated sprites │ ├── sprite-companies.png │ ├── sprite-companies@2x.png │ ├── sprite-projects.png │ ├── sprite-projects@2x.png │ ├── sprite-courses.png │ ├── sprite-courses@2x.png │ └── sprite-map.json ├── sprite-showcase.html # Visual QA page └── css/ └── 04-interactive/ └── _sprites.css # Sprite CSS classes ``` ### Go Sprite Generator Tool Located at `cmd/sprites/main.go`, this tool: 1. **Scans source directories** for PNG images 2. **Normalizes images** to standard sizes (60x60px for 1x, 120x120px for 2x) 3. **Maintains aspect ratio** and centers on transparent background 4. **Combines into horizontal strips** for each category 5. **Generates sprite-map.json** for documentation 6. **Creates sprite-showcase.html** for visual QA ### Image Size Standards - **Base size**: 60x60px (optimal for 80px display box with 10px padding) - **Retina size**: 120x120px (@2x for high-DPI displays) - **Section display**: 80x80px box (60px icon + 10px padding each side) ## Usage ### Makefile Targets ```bash # Generate sprites from source images make sprites # Clean generated sprite files make sprites-clean ``` ### JSON Data Structure Add `logoIndex` to entries in cv-en.json and cv-es.json: ```json { "company": "Olympic Broadcasting Services", "companyLogo": "olympic-broadcasting.png", "logoIndex": 15 } ``` **Important**: Only add `logoIndex` when there's an actual PNG file. Entries without a logo file should not have `logoIndex`. ### Template Integration Templates automatically use sprites when `logoIndex` is present: ```html {{if .LogoIndex}} {{else if .CompanyLogo}} {{.Company}} logo {{else}} {{end}} ``` ### CSS Classes ```css /* Base sprite class */ .icon-sprite { display: inline-block; width: 50px; height: 50px; background-repeat: no-repeat; background-size: auto 50px; } /* Category-specific classes */ .icon-company { background-image: url('/static/images/sprites/sprite-companies.png'); } .icon-project { background-image: url('/static/images/sprites/sprite-projects.png'); } .icon-course { background-image: url('/static/images/sprites/sprite-courses.png'); } /* Size variants */ .icon-sprite.icon-section { width: 80px; height: 80px; padding: 10px; background-size: auto 60px; background-origin: content-box; background-clip: content-box; } .icon-sprite.icon-small { width: 32px; height: 32px; } .icon-sprite.icon-large { width: 64px; height: 64px; } ``` ## Adding New Icons 1. **Drop source image** into appropriate directory: - `static/images/companies/` for company logos - `static/images/projects/` for project logos - `static/images/courses/` for course logos 2. **Run sprite generation**: ```bash make sprites ``` 3. **Update JSON files** with new `logoIndex` based on sprite-map.json 4. **Verify** in showcase page at `/static/sprite-showcase.html` ## Retina Display Support The CSS automatically loads @2x sprites on retina displays: ```css @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .icon-company { background-image: url('/static/images/sprites/sprite-companies@2x.png'); background-size: auto 60px; /* Display at 1x size */ } } ``` ## Sprite Map JSON The `sprite-map.json` file documents icon positions: ```json { "companies": [ {"index": 0, "name": "accenture.png"}, {"index": 1, "name": "aena-long.png"}, ... ], "projects": [...], "courses": [...] } ``` This file is for documentation/debugging only - CSS calculates offset from index using `calc(var(--icon-index) * -60px)`. ## Verification ### Showcase Page Visit `/static/sprite-showcase.html` to: - View full sprite sheets - See all individual icons with index labels - Test zoom levels (100%, 200%, 300%) - Verify retina rendering ### Network Verification In browser DevTools (Network tab, filter Images): - **Should see**: sprite-companies.png, sprite-projects.png, sprite-courses.png - **Should NOT see**: individual logo files (unless fallback triggers) ## Troubleshooting ### Invalid PNG Warning If you see "png: invalid format: not a PNG file", the source file is not a valid PNG. Check the file with `file ` to verify format. ### Icon Not Displaying 1. Verify `logoIndex` is present in JSON 2. Check sprite-map.json for correct index 3. Verify CSS is loaded 4. Check browser console for errors ### Wrong Icon Displayed Verify the `logoIndex` value matches the icon's position in sprite-map.json (0-indexed).