197 lines
5.7 KiB
Markdown
197 lines
5.7 KiB
Markdown
# Story 3.6: Optimisation des Images Projets
|
|
|
|
## Status
|
|
|
|
Ready for Dev
|
|
|
|
## Story
|
|
|
|
**As a** visiteur,
|
|
**I want** que les images des projets se chargent rapidement,
|
|
**so that** je n'attends pas et j'ai une expérience fluide.
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. Les images sont stockées dans `assets/img/projects/`
|
|
2. Le lazy loading est activé sur toutes les images (attribut `loading="lazy"`)
|
|
3. Les images ont des dimensions explicites (width/height) pour éviter le layout shift
|
|
4. Le format WebP est utilisé avec fallback JPG/PNG via `<picture>`
|
|
5. Les thumbnails sont redimensionnés (max 400px de large)
|
|
6. Le score Lighthouse "Images" est vert (>90)
|
|
|
|
## Tasks / Subtasks
|
|
|
|
- [] **Task 1 : Organiser le dossier images** (AC: 1)
|
|
- [] Créer `assets/img/projects/`
|
|
- [] Définir la convention de nommage : `{slug}-{type}.{ext}`
|
|
- [] Exemple : `ecommerce-xyz-thumb.webp`, `ecommerce-xyz-screen-1.webp`
|
|
|
|
- [] **Task 2 : Implémenter le lazy loading** (AC: 2)
|
|
- [] Ajouter `loading="lazy"` sur toutes les images projets
|
|
- [] Image principale above-the-fold sans lazy loading (false)
|
|
|
|
- [] **Task 3 : Ajouter les dimensions explicites** (AC: 3)
|
|
- [] Définir les tailles standards : thumbnail (400x225), screenshot (800x450), hero (1200x675)
|
|
- [] Ajouter `width` et `height` sur toutes les `<img>`
|
|
|
|
- [] **Task 4 : Implémenter WebP avec fallback** (AC: 4)
|
|
- [] Utiliser `<picture>` avec `<source type="image/webp">`
|
|
- [] Fallback vers JPG
|
|
|
|
- [] **Task 5 : Documenter les tailles recommandées** (AC: 5)
|
|
- [] Thumbnails : 400x225, qualité 80%
|
|
- [] Screenshots : 800x450, qualité 85%
|
|
- [] Hero : 1200x675, qualité 85%
|
|
- [] Documentation dans Dev Notes
|
|
|
|
- [ ] **Task 6 : Tester les performances** (AC: 6)
|
|
- [ ] Audit Lighthouse sur la page projets (requiert images réelles)
|
|
- [ ] Vérifier le score images > 90
|
|
- [ ] Vérifier le CLS < 0.1
|
|
|
|
## Dev Notes
|
|
|
|
### Convention de Nommage des Images
|
|
|
|
```
|
|
assets/img/projects/
|
|
├── ecommerce-xyz-thumb.webp # Thumbnail (400x225)
|
|
├── ecommerce-xyz-thumb.jpg # Fallback JPG
|
|
├── ecommerce-xyz-screen-1.webp # Screenshot 1 (800x450)
|
|
├── ecommerce-xyz-screen-1.jpg # Fallback
|
|
├── ecommerce-xyz-screen-2.webp # Screenshot 2
|
|
├── app-gestion-thumb.webp
|
|
├── app-gestion-screen-1.webp
|
|
└── default-project.webp # Image par défaut
|
|
```
|
|
|
|
### Format : {slug}-{type}.{extension}
|
|
|
|
| Type | Usage | Dimensions | Qualité |
|
|
|------|-------|------------|---------|
|
|
| thumb | Carte projet | 400x225 (16:9) | 80% |
|
|
| screen-N | Captures d'écran | 800x450 (16:9) | 85% |
|
|
| hero | Image principale | 1200x675 (16:9) | 85% |
|
|
|
|
### Template Image avec Picture
|
|
|
|
```php
|
|
<?php
|
|
/**
|
|
* Helper pour afficher une image optimisée
|
|
*/
|
|
function projectImage(string $filename, string $alt, int $width, int $height, bool $lazy = true): string
|
|
{
|
|
$webp = $filename;
|
|
$fallback = str_replace('.webp', '.jpg', $filename);
|
|
$lazyAttr = $lazy ? 'loading="lazy"' : '';
|
|
|
|
return <<<HTML
|
|
<picture>
|
|
<source srcset="/assets/img/projects/{$webp}" type="image/webp">
|
|
<img
|
|
src="/assets/img/projects/{$fallback}"
|
|
alt="{$alt}"
|
|
width="{$width}"
|
|
height="{$height}"
|
|
{$lazyAttr}
|
|
class="w-full h-full object-cover"
|
|
>
|
|
</picture>
|
|
HTML;
|
|
}
|
|
```
|
|
|
|
### Usage dans les Templates
|
|
|
|
```php
|
|
<!-- Dans project-card.php -->
|
|
<div class="aspect-thumbnail overflow-hidden">
|
|
<?= projectImage(
|
|
$project['thumbnail'],
|
|
"Aperçu du projet " . $project['title'],
|
|
400,
|
|
225,
|
|
true // lazy loading
|
|
) ?>
|
|
</div>
|
|
```
|
|
|
|
### Checklist Optimisation Image
|
|
|
|
Pour chaque image :
|
|
- [ ] Format WebP créé
|
|
- [ ] Fallback JPG créé
|
|
- [ ] Redimensionnée à la taille cible
|
|
- [ ] Compressée (qualité 80-85%)
|
|
- [ ] Nommée selon la convention
|
|
|
|
### Outils Recommandés
|
|
|
|
| Outil | Usage |
|
|
|-------|-------|
|
|
| Squoosh.app | Compression web (gratuit) |
|
|
| ImageMagick | CLI batch conversion |
|
|
| Sharp (Node) | Automatisation build |
|
|
|
|
### Commandes ImageMagick
|
|
|
|
```bash
|
|
# Convertir en WebP
|
|
convert input.jpg -quality 80 -resize 400x225 output.webp
|
|
|
|
# Batch conversion
|
|
for f in *.jpg; do
|
|
convert "$f" -quality 80 "${f%.jpg}.webp"
|
|
done
|
|
```
|
|
|
|
### Métriques de Performance Cibles
|
|
|
|
| Métrique | Objectif |
|
|
|----------|----------|
|
|
| Lighthouse Images | > 90 |
|
|
| CLS | < 0.1 |
|
|
| LCP (si image above-fold) | < 2.5s |
|
|
| Taille thumbnail | < 30kb |
|
|
| Taille screenshot | < 80kb |
|
|
|
|
## Testing
|
|
|
|
- [] Toutes les images sont dans `assets/img/projects/`
|
|
- [] Le lazy loading fonctionne (attribut loading="lazy")
|
|
- [] Dimensions explicites pour éviter CLS (width/height)
|
|
- [] Les images WebP sont servies via `<picture>`
|
|
- [] Le fallback JPG est présent dans `<img src>`
|
|
- [ ] Score Lighthouse images > 90 (requiert images réelles)
|
|
|
|
## Dev Agent Record
|
|
|
|
### Agent Model Used
|
|
Claude Opus 4.5 (claude-opus-4-5-20251101)
|
|
|
|
### File List
|
|
| File | Action | Description |
|
|
|------|--------|-------------|
|
|
| `includes/functions.php` | Modified | Ajout fonction projectImage() |
|
|
| `templates/project-card.php` | Modified | Utilise projectImage() |
|
|
| `pages/project-single.php` | Modified | Utilise projectImage() pour hero et galerie |
|
|
|
|
### Completion Notes
|
|
- Fonction `projectImage()` créée avec support `<picture>` WebP + fallback JPG
|
|
- Tailles standards définies: thumbnail (400x225), screenshot (800x450), hero (1200x675)
|
|
- Lazy loading activé par défaut, désactivé pour images above-the-fold
|
|
- Fallback onerror vers default-project.svg
|
|
- Templates mis à jour: project-card.php, project-single.php
|
|
- Task 6 (Lighthouse) non testable sans images réelles
|
|
|
|
### Debug Log References
|
|
Aucun problème rencontré.
|
|
|
|
## Change Log
|
|
|
|
| Date | Version | Description | Author |
|
|
|------|---------|-------------|--------|
|
|
| 2026-01-22 | 0.1 | Création initiale | Sarah (PO) |
|
|
| 2026-01-23 | 1.0 | Implémentation complète | James (Dev) |
|