Que fait surfaces ?
Ce skill détermine la composition de chaque élément : son remplissage, son bord, son ombre, son rayon, ses états et ses icônes. Il sélectionne parmi une courte liste de recettes, si bien que deux écrans n'auront jamais deux cartes différentes.
Avant toute décision, appliquez product-ui §1 (le journal des goûts et la préséance) et §5 (quel skill possède quoi).
Décider dans cet ordre
- Une surface est-elle nécessaire ? Supprimez avant d'ajouter. Un titre avec de l'espace autour n'a pas besoin de carte. Ne nichez jamais une carte dans une carte. Pourquoi : chaque conteneur ajoute un bord que l'œil doit lire.
- Quel niveau ? Page, raised (surélevé), floating (flottant) ou overlay (superposé). Un niveau par élément, choisi pour ce qu'il fait, non pour son impact visuel. elevation.md.
- Qu'est-ce qui dessine le bord ? L'élévation utilise un anneau d'ombre. La structure utilise une bordure. Jamais les deux sur un même bord. elevation.md.
- Quel rayon ? Prenez le jeton correspondant au rôle de l'élément, puis rendez les rayons imbriqués concentriques. elevation.md.
- Quels états ? Concevez les états hover, pressed, selected, disabled et focus-visible comme des modifications de la surface, avant de peaufiner l'état par défaut. states-and-icons.md.
- Quel traitement des icônes ? Un seul ensemble,
currentColor, un trait adapté au texte. states-and-icons.md. - Un matériau est-il autorisé ? Uniquement un chrome flottant au-dessus du contenu défilant. materials-and-edges.md.
- Bords du défilement. Séparateurs, dégradés, overscroll. materials-and-edges.md.
Les quatre niveaux
| Niveau | Pour | Lumineux | Sombre |
|---|---|---|---|
| Page | Le fond | Remplissage de fond, pas d'ombre | Remplissage le plus foncé, pas d'ombre |
| Raised | Cartes, contrôles, option choisie | Blanc, anneau + 1px drop + 3px tight drop | Un cran plus clair, anneau blanc, tight black drop |
| Floating | Menus, popovers, info-bulles, toasts | Blanc, anneau + 1px drop + 4px tight drop | Deux crans plus clair, anneau blanc, tight black drop |
| Overlay | Boîtes de dialogue, panneaux, palette de commandes (avec un scrim) | Blanc, anneau + 1px drop + 6px tight drop | Trois crans plus clair, anneau blanc, tight black drop |
Les jetons exacts se trouvent dans elevation.md. Les règles qui les sous-tendent :
- Un anneau plus un tight drop. Flou ≤ 8px, décalage ≤ 6px, drops avec un spread négatif. Pourquoi : les grands flous doux sont lus comme une lueur, salissent la page et semblent générés.
- Le mode sombre s'élève en s'éclaircissant. Les ombres sont à peine visibles sur fond sombre, donc la clarté porte la hauteur et un anneau blanc à faible alpha porte le bord.
- Les ombres sont translucides et monochromes. Les gris opaques laissent un halo. Les drops sombres restent noirs.
- Les éléments frères partagent un même niveau. Les cartes d'une rangée ont une ombre, un rayon, un espacement identiques.
- Le survol modifie le remplissage, pas l'ombre.
Règles sans référence nécessaire
- Les bordures montrent la structure, les ombres montrent l'élévation. Les séparateurs, les champs de saisie, les cellules de tableau et les états sélectionnés conservent des bordures. Une carte dont la bordure n'existe que pour la soulever reçoit un anneau à la place.
- Gardez
border: 1px solid transparentsous un anneau d'ombre. Pourquoi : le mode forced-colours supprime les ombres, et la bordure dessine quand même un bord. - Les images reçoivent un contour interne de 1px :
outline: 1px solidnoir à 10 % (blanc à 10 % en mode sombre),outline-offset: -1px. Jamais de couleur teintée, qui apparaît comme une frange. Ignorez les logos et les œuvres transparentes. - Rayon concentrique. Extérieur = intérieur + espacement (+ bordure), jusqu'à 24 px d'espacement. Au-delà, ce sont des surfaces distinctes.
- Le focus est un anneau, jamais rien.
:focus-visibleaffiche un contour de 2 px de couleur d'accent avec un décalage de 2 px ; les champs le reçoivent à fleur, comme un bord d'accent de 2 px sans espace.outline: nonesans remplacement est un bogue. L'anneau ne prend pas d'espace de disposition. - Les contrôles désactivés n'ont pas de survol, d'enfoncement ni de mise à l'échelle.
- Icônes : un seul ensemble par surface,
currentColor, contour par défaut et rempli lorsqu'actif. Le trait suit le poids de la police voisine, 1,5 px pour 400 jusqu'à 2 px pour 600. - Flou d'arrière-plan uniquement sur le chrome flottant. Jamais sur le contenu, les cartes ou les tableaux.
- Les superpositions défilables (boîtes de dialogue, tiroirs, menus) reçoivent
overscroll-behavior: contain.
Paires
| Cassé | Corrigé | Pourquoi |
|---|---|---|
border: 1px solid #e5e5e5 sur une carte | box-shadow: var(--elev-raised); border: 1px solid transparent | Une bordure de profondeur devient un anneau ; les couleurs forcées dessinent toujours un bord |
box-shadow: 0 10px 40px rgba(0,0,0,.2) | 0 0 0 1px a.08, 0 1px 2px a.12, 0 4px 8px -4px a.16 | Précis et net vaut mieux que grand et flou |
Carte sombre avec 0 8px 24px #000 | Remplissage plus clair plus 0 0 0 1px oklch(1 0 0 / .08) | Les ombres disparaissent sur fond sombre ; la clarté montre la hauteur |
| Rayon de carte 8, rayon d'image intérieure 8, espacement 8 | Intérieur 8, extérieur 16 | Les coins concentriques conservent un espacement uniforme |
<img> fondue dans une carte blanche | outline: 1px solid oklch(0 0 0 / .1); outline-offset: -1px | Le bord se lit sans bordure |
button:focus { outline: none } | button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px } | Les utilisateurs de clavier gardent leur repère |
| Trait d'icône 1,5 px à côté d'une étiquette en poids 600 | Trait de 2 px | L'épaisseur du trait correspond au poids de la tige |
| Icônes remplies dans chaque emplacement de barre d'outils | Contour par défaut, rempli pour l'élément actif | Le remplissage est le signal d'état |
backdrop-filter: blur(20px) sur une carte | Une surface opaque | Le flou appartient au chrome flottant au-dessus du contenu défilant |
Avant de terminer
| Motif | Correction |
|---|---|
box-shadow avec flou > 8 px ou alpha > .2 sur une interface claire | Utilisez un jeton de niveau |
border et box-shadow faisant le même travail | Anneau plus bordure transparente uniquement |
Anneau d'ombre sans border: 1px solid transparent | Ajoutez-le |
Même border-radius sur un parent et son enfant avec espacement | interne + espacement pour le parent |
outline: none ou outline: 0 sans remplacement par :focus-visible | Ajoutez l'anneau |
:focus (pas :focus-visible) stylisant un anneau | Passez à :focus-visible |
border-width changeant dans un état | Couleur, remplissage ou bordure transparente de même largeur |
fill="#…" ou stroke="#…" codé en dur dans une icône | currentColor |
| Deux bibliothèques d'icônes importées sur un même écran | Une seule |
backdrop-filter en dehors d'une barre collante, d'une barre latérale ou d'un menu flottant | Supprimez-le |
Liste superposée sans overscroll-behavior: contain | Ajoutez-le |
Coupure franche au bord d'un défileur, ou ombre coupée par overflow: hidden | Dégradé du bord ; ajoutez un espacement au défileur |
Vérifiez en rendant les modes clair et sombre à 2× et en recadrant un bord de chaque niveau. Survolez, appuyez, tabulez pour le focus, sélectionnez et désactivez chaque contrôle et comparez la taille de la boîte avant et après. Activez les couleurs forcées (devtools de Chrome, émulation de rendu) et confirmez que chaque carte a toujours un bord.