Story 1.1: initialisation projet
This commit is contained in:
196
docs/stories/3.6.optimisation-images.md
Normal file
196
docs/stories/3.6.optimisation-images.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# 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) |
|
||||
Reference in New Issue
Block a user