From frontend-design
Audit and improve the functional quality of an existing website or web application: interactive states, structural accessibility, responsive layout, form UX, CSS performance, and motion/animation. Use this skill when the user wants to fix interactivity, accessibility, responsive behavior, or animation issues — or says things like "fix the hover states", "it's not accessible", "broken on mobile", "the layout shifts", "forms feel wrong", "focus is invisible", "add transitions", "too many repaints", "prefers-reduced-motion", "fix the tab order", "ARIA is wrong", "the animation is janky", "breakpoints are off", "touch targets too small", "my form has no validation", "skip to content link", "screen reader issues". Also use when the user shares code and asks what's broken functionally, or wants a UX/accessibility review. For visual issues (colors, typography, hierarchy, whitespace, font loading), use frontend-audit-visual instead. Both skills share the same token system and can run sequentially.
How this skill is triggered — by the user, by Claude, or both
Slash command
/frontend-design:frontend-audit-functionalThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Structured, dimension-by-dimension audit of the functional and interactive
Structured, dimension-by-dimension audit of the functional and interactive layer of a web frontend. Produces verifiable reports before any code changes.
This skill assumes a token system exists (from frontend-audit-visual or
the project's own design system). If no tokens exist, note it in the report
but don't block — reference raw values and flag them for tokenization.
Before auditing, establish:
## Contexte fonctionnel
- Framework CSS : [aucun / Tailwind / Bootstrap / autre]
- Framework JS : [vanilla / React / Vue / Svelte / autre]
- Cibles navigateurs : [modernes uniquement / IE11 / mobile-first]
- Cibles appareils : [desktop seulement / desktop+mobile / mobile-first]
- Breakpoints existants: [ex. 768px, 1024px, 1280px — ou non définis]
- Accessibilité cible : [WCAG AA / WCAG AAA / non défini]
- Formulaires présents : [oui/non — si oui, lesquels]
Si non fourni : inférer du code (media queries présentes, structure HTML, <form> tags), proposer le bloc rempli, attendre validation.
Effectuer chaque audit séparément. Rapport de violations d'abord, corrections ensuite.
Objectif : chaque élément cliquable ou focusable a tous ses états visuels définis.
Inventorier tous les éléments interactifs : a, button, input, select, textarea, [role="button"], [tabindex], éléments avec onclick ou event listeners JS.
Pour chacun, vérifier :
| État | Propriétés à vérifier |
|---|---|
:hover | color, background, border, transform, box-shadow |
:focus-visible | outline visible ≥ 2px, ou focus-ring custom |
:active | feedback visuel immédiat (scale, background) |
:disabled | opacity réduite, cursor: not-allowed, pointer-events: none |
transition | présent sur les propriétés qui changent |
:focus défini mais :focus-visible absent → l'outline apparaît au clic souris (mauvaise UX)outline: none / outline: 0 sans remplacement → violation WCAG 2.4.7## Rapport Interactivité
| Élément | :hover | :focus-visible | :active | :disabled | transition |
|-----------------|--------|----------------|---------|-----------|------------|
| .btn-primary | ✅ | ❌ | ❌ | n/a | ✅ |
| .nav-link | ✅ | ❌ | n/a | n/a | ❌ |
| input[type=text]| n/a | ❌ | n/a | ✅ | ❌ |
### Template de correction
```css
:focus-visible {
outline: 2px solid var(--color-focus-ring);
outline-offset: 2px;
}
.btn {
transition: background var(--duration-base) var(--ease-default),
transform var(--duration-fast) var(--ease-default);
}
.btn:hover { background: var(--color-primary-hover); }
.btn:active { transform: scale(0.98); }
---
### Audit B — Accessibilité Structurelle
**Objectif :** le document est navigable et compréhensible pour les technologies d'assistance.
#### Protocole
**1. Landmarks & Structure**
- `<header>`, `<nav>`, `<main>`, `<aside>`, `<footer>` présents et correctement imbriqués ?
- Un seul `<main>` par page ?
- `<nav>` a-t-il un `aria-label` quand il y en a plusieurs ?
- Skip link présent (`<a href="#main">Skip to content</a>`) et visible au focus ?
**2. Headings**
- Hiérarchie h1–h6 sans saut de niveau (h1 → h3 sans h2 = violation)
- Un seul `<h1>` par page ?
- Les titres décrivent-ils le contenu de leur section ?
**3. Images & Médias**
- Toute `<img>` a un `alt` (vide `alt=""` pour les images décoratives)
- Les images informatives ont un `alt` descriptif (pas `alt="image"` ou `alt="photo"`)
- `<svg>` inline : `role="img"` + `aria-label` ou `<title>` ?
- `<video>` / `<audio>` : sous-titres, transcription ?
**4. ARIA**
- Pas d'ARIA redondant (`<nav role="navigation">` → redondant)
- Pas d'ARIA inventé (`aria-description` n'existe pas → `aria-describedby`)
- `aria-hidden="true"` n'est pas sur un élément focusable ou son parent
- Les widgets custom (`[role="dialog"]`, `[role="tablist"]`, etc.) ont les attributs requis
**5. Ordre de tabulation**
- `tabindex` > 0 présent ? → quasi toujours une erreur
- L'ordre DOM correspond-il à l'ordre visuel ?
- Les éléments cachés visuellement (`display:none`, `visibility:hidden`) sont-ils aussi retirés du flux tab ?
#### Format du rapport
```markdown
## Rapport Accessibilité Structurelle
### Landmarks
| Landmark | Présent | Problème |
|----------|---------|-------------------------------------|
| <main> | ✅ | |
| <nav> | ✅ | 2 <nav> sans aria-label ❌ |
| skip link| ❌ | absent |
### Headings
- h1 → h3 à ligne 87 (saut de h2) ❌
- 2 × <h1> sur la même page ❌
### Images
- 3 <img> sans attribut alt ❌
- 1 <img alt="image"> → non descriptif ⚠️
### ARIA
- <nav role="navigation"> ligne 12 → redondant, retirer role ⚠️
- <div role="dialog"> sans aria-labelledby ❌
### Tab order
- <div tabindex="5"> ligne 204 → tabindex positif ❌
Objectif : le site fonctionne correctement sur toutes les largeurs cibles, sans débordement ni perte de contenu.
1. Inventaire des breakpoints
2. Comportement de layout
width fixes en pixels sur des conteneurs qui devraient s'adapter ?overflow-x: hidden sur body ou html → cache-t-il un débordement réel ?3. Contenu à petits écrans
max-width: 100% ?4. Tailles de cibles tactiles
5. Viewport
<meta name="viewport" content="width=device-width, initial-scale=1"> présent ?maximum-scale=1 ou user-scalable=no (empêche le zoom = violation d'accessibilité)## Rapport Responsive
### Breakpoints
| Breakpoint | Occurrences | Cohérent | Notes |
|------------|-------------|----------|--------------------|
| 768px | 12 | ✅ | tablette |
| 1024px | 8 | ✅ | desktop |
| 847px | 1 | ❌ | orphelin, ligne 302|
### Problèmes de layout
- .sidebar { width: 300px } → fixe, pas responsive ❌
- overflow-x: hidden sur body → masque un débordement ⚠️
- <table> non scrollable sous 768px ❌
### Cibles tactiles
- .nav-link : 32×20px → sous le minimum 44×44px ❌
- Boutons de pagination espacés de 4px → trop proche ⚠️
### Viewport
- user-scalable=no → empêche le zoom, violation WCAG ❌
Objectif : les formulaires sont utilisables, accessibles, et fournissent un feedback clair.
1. Labels & Association
<input> a un <label> associé (via for/id ou imbrication) ?radio, checkbox) sont dans un <fieldset> avec <legend> ?2. Feedback de validation
aria-invalid="true" + aria-describedby vers le message d'erreur ?aria-required="true" ou required) ?3. UX de saisie
type correct sur les inputs (email, tel, url, number, search) ?autocomplete défini sur les champs d'identité (name, email, address, cc-*) ?inputmode pour les claviers mobiles adaptés ?4. Taille et espacement
5. États visuels des champs
:focus avec bordure ou outline visible ?## Rapport Formulaires
### Labels
| Champ | Label | Placeholder-as-label | Problème |
|-----------------|--------|---------------------|---------------------|
| input#email | ✅ | non | |
| input#search | ❌ | oui ❌ | placeholder = label |
| radio group | n/a | n/a | pas de <fieldset> ❌ |
### Validation
- Messages d'erreur en haut seulement → pas de feedback inline ❌
- Erreurs signalées uniquement par couleur rouge → pas d'icône/texte ❌
- aria-invalid absent sur les champs en erreur ❌
### Types & Autocomplete
- input#phone : type="text" → devrait être type="tel" ⚠️
- input#email : autocomplete absent ⚠️
### Taille
- Inputs : height 32px → sous le minimum 44px sur mobile ❌
Objectif : le CSS ne cause pas de problèmes de rendu, de surcharge réseau, ou de jank visuel.
1. Sélecteurs
div.container ul li a span) → fragiles et lentsdiv *) → coûteux!important : compter les occurrences → > 5 = signal d'architecture CSS cassée2. Propriétés coûteuses animées Les propriétés suivantes déclenchent du layout/repaint si animées — les signaler :
width, height, margin, padding, top/left/right/bottom, font-sizecolor, background, border, box-shadow, text-shadowtransform, opacity, filter (composited, pas de repaint)3. Volume et duplication
4. Propriétés problématiques
backdrop-filter sans fallback → invisible sur navigateurs non supportésposition: fixed + backdrop-filter → jank sur iOS Safariwill-change utilisé de façon permanente (pas seulement avant animation) → gaspillage mémoire GPU## Rapport Performance CSS
### Sélecteurs profonds (> 3 niveaux)
- `.page .content .sidebar .widget ul li a` (ligne 287) → 7 niveaux ❌
### !important
- 12 occurrences → architecture CSS à revoir ⚠️
### Propriétés coûteuses animées
| Sélecteur | Propriété animée | Coût | Alternative |
|-------------|------------------|----------|----------------------|
| .card:hover | box-shadow | repaint | filter: drop-shadow |
| .menu | height | layout | transform: scaleY |
### Volume
- 3 fichiers CSS, total 78KB → consolider et purger le CSS mort ⚠️
Objectif : les animations sont fluides, intentionnelles, et respectent les préférences utilisateur.
1. Inventaire des animations
transition, animation, @keyframes dans le CSS2. prefers-reduced-motion
@media (prefers-reduced-motion: reduce) est-il présent ?3. Qualité des animations
ease, ease-in-out, ou cubic-bezier personnalisé (jamais linear sauf pour des rotations infinies)scroll-timeline ou IntersectionObserver (performant) vs événement scroll + manipulation de style (janky) ?4. Cohérence
## Rapport Motion & Animation
### Inventaire
| Sélecteur | Type | Propriété | Duration | Easing |
|--------------|------------|------------|----------|------------|
| .btn | transition | background | 200ms | ease ✅ |
| .modal | animation | opacity+y | 500ms | linear ❌ |
| .card:hover | transition | transform | 150ms | ease-out ✅ |
### prefers-reduced-motion
- ❌ Absent → toutes les animations jouent même si l'utilisateur les a désactivées
### Recommandation prefers-reduced-motion
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
---
## Pipeline de Correction
Après les rapports, corriger dans cet ordre :
**Si l'utilisateur cible un audit précis**, commencer par celui-là.
---
## Validation Post-Correction
```markdown
## Checklist de validation fonctionnelle
### Interactivité
- [ ] Tout élément focusable a un :focus-visible
- [ ] Tous les boutons ont :hover + :active + transition
- [ ] Les inputs ont :focus avec border ou outline visible
### Accessibilité
- [ ] Landmarks corrects (header, nav, main, footer)
- [ ] Skip link présent et fonctionnel
- [ ] Hiérarchie h1–h6 sans saut de niveau
- [ ] Toutes les images ont un alt approprié
- [ ] Aucun tabindex > 0
- [ ] ARIA correct et non redondant
### Responsive
- [ ] Breakpoints cohérents dans tout le CSS
- [ ] Pas de width fixe en px sur conteneurs adaptatifs
- [ ] Images max-width: 100%
- [ ] Cibles tactiles ≥ 44×44px
- [ ] Viewport sans user-scalable=no
### Formulaires
- [ ] Chaque input a un label associé (pas placeholder-as-label)
- [ ] Validation inline avec aria-invalid + aria-describedby
- [ ] Types d'input corrects (email, tel, url)
- [ ] Hauteur ≥ 44px sur mobile
### Motion
- [ ] @media (prefers-reduced-motion: reduce) présent
- [ ] Durées entre 100-500ms
- [ ] Pas de linear sauf rotations infinies
### Performance CSS
- [ ] Pas de sélecteur > 3 niveaux
- [ ] < 5 !important
- [ ] Pas de layout properties animées
:focus et :focus-visible. Le premier s'active aussi au clic souris — privilégier systématiquement :focus-visible pour les outlines.html-semantics : l'Audit B (Accessibilité Structurelle) couvre les landmarks, headings, ARIA et images. Pour un audit sémantique HTML plus approfondi (microdata, rôles implicites, sectioning algorithm complet), utiliser la skill html-semantics.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub camauger/dev-skills --plugin frontend-design