Présentation des principes de base pour créer des composants de bouton d'action flottant adaptatifs aux couleurs, responsifs et accessibles.
Dans cet article, je vais vous expliquer comment créer des composants de bouton d'action flottant adaptatifs aux couleurs, responsifs et accessibles. Essayez la démonstration et consultez le code source.
Si vous préférez regarder une vidéo, voici une version YouTube de cet article:
Présentation
Les boutons d'action flottants sont plus courants sur mobile que sur ordinateur, mais ils sont présents dans les deux cas. Ils gardent les actions principales à l'écran, ce qui les rend pratiques et omniprésents. Ce style d'expérience utilisateur a été rendu célèbre par l'interface utilisateur Material. Vous trouverez les suggestions d'utilisation et de placement sur cette page.
Éléments et styles
Le code HTML de ces commandes comprend un élément de conteneur et un ensemble d'un ou plusieurs boutons. Le conteneur positionne les boutons d'action flottants dans la fenêtre d'affichage et gère un espace entre les boutons. Les boutons peuvent être mini ou par défaut, ce qui offre une belle variété entre les actions principales et secondaires.
Conteneur du bouton d'action flottant
Cet élément peut être un <div>
standard, mais faisons un geste pour nos utilisateurs non voyants et ajoutons-lui des attributs utiles pour expliquer l'objectif et le contenu de ce conteneur.
Balisage des boutons d'action flottants
Commencez par une classe .fabs
pour que le CSS puisse s'y associer pour le style, puis ajoutez role="group"
et aria-label
pour qu'il ne s'agisse pas simplement d'un conteneur générique, mais d'un conteneur nommé et à des fins spécifiques.
<div class="fabs" role="group" aria-label="Floating action buttons">
<!-- buttons will go here -->
</div>
Style des boutons d'action flottants
Pour que les boutons d'action flottants soient pratiques, ils restent toujours dans la fenêtre d'affichage.
Il s'agit d'un excellent cas d'utilisation pour la position fixed
. Dans cette position de vue, j'ai choisi d'utiliser inset-block
et inset-inline
afin que la position complète le mode de document de l'utilisateur, comme de droite à gauche ou de gauche à droite. Les propriétés personnalisées permettent également d'éviter les répétitions et de garantir une distance égale par rapport aux bords inférieur et latéral du viewport:
.fabs {
--_viewport-margin: 2.5vmin;
position: fixed;
z-index: var(--layer-1);
inset-block: auto var(--_viewport-margin);
inset-inline: auto var(--_viewport-margin);
}
Je donne ensuite à l'affichage du conteneur flex
et je modifie son orientation de mise en page en column-reverse
.
Les enfants sont alors empilés les uns sur les autres (colonne) et leur ordre visuel est inversé. Cela a pour effet de faire du premier élément sélectionnable l'élément du bas au lieu du haut, qui est l'endroit où le focus se trouve normalement dans le document HTML. Inverser l'ordre visuel unifie l'expérience pour les utilisateurs voyants et les utilisateurs de clavier, car le style de l'action principale est plus grand que les mini-boutons, ce qui indique aux utilisateurs voyants qu'il s'agit d'une action principale, et les utilisateurs de clavier la mettront en surbrillance en tant que premier élément de la source.
.fabs {
…
display: flex;
flex-direction: column-reverse;
place-items: center;
gap: var(--_viewport-margin);
}
Le centrage est géré avec place-items
, et gap
ajoute de l'espace entre les boutons FAB placés dans le conteneur.
Boutons d'action flottants
Il est temps de styliser certains boutons pour qu'ils semblent flotter au-dessus de tout.
Bouton d'action flottant par défaut
Le premier bouton à styliser est le bouton par défaut. Il servira de base à tous les boutons de type appui long. Nous créerons plus tard une variante qui offre une apparence alternative tout en modifiant le moins possible ces styles de base.
Balisage du bouton d'action flottant
L'élément <button>
est la bonne réponse. Nous allons commencer par cela comme base, car il offre une excellente expérience utilisateur avec la souris, l'écran tactile et le clavier. L'aspect le plus crucial de ce balisage consiste à masquer l'icône aux utilisateurs de lecteurs d'écran avec aria-hidden="true"
et à ajouter le texte de libellé nécessaire au balisage <button>
lui-même. Dans ces cas, j'aime également ajouter un title
afin que les utilisateurs de la souris puissent obtenir des informations sur ce que l'icône tente de communiquer.
<button data-icon="plus" class="fab" title="Add new action" aria-label="Add new action">
<svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>
Style du bouton d'action flottant
Commençons par transformer le bouton en bouton rond avec une bordure et une ombre prononcée, car ce sont les premières caractéristiques qui le définissent:
.fab {
--_size: 2rem;
padding: calc(var(--_size) / 2);
border-radius: var(--radius-round);
aspect-ratio: 1;
box-shadow: var(--shadow-4);
}
Ensuite, ajoutons de la couleur. Nous allons utiliser une stratégie que nous avons déjà utilisée dans les défis d'interface utilisateur. Créez un ensemble de propriétés personnalisées clairement nommées qui contiennent de manière statique les couleurs claires et sombres, puis une propriété personnalisée adaptative qui sera définie sur les variables claires ou sombres en fonction des préférences système de l'utilisateur pour les couleurs:
.fab {
…
/* light button and button hover */
--_light-bg: var(--pink-6);
--_light-bg-hover: var(--pink-7);
/* dark button and button hover */
--_dark-bg: var(--pink-4);
--_dark-bg-hover: var(--pink-3);
/* adaptive variables set to light by default */
--_bg: var(--_light-bg);
/* static icon colors set to the adaptive foreground variable */
--_light-fg: white;
--_dark-fg: black;
--_fg: var(--_light-fg);
/* use the adaptive properties on some styles */
background: var(--_bg);
color: var(--_fg);
&:is(:active, :hover, :focus-visible) {
--_bg: var(--_light-bg-hover);
@media (prefers-color-scheme: dark) {
--_bg: var(--_dark-bg-hover);
}
}
/* if users prefers dark, set adaptive props to dark */
@media (prefers-color-scheme: dark) {
--_bg: var(--_dark-bg);
--_fg: var(--_dark-fg);
}
}
Ajoutez ensuite des styles pour que les icônes SVG s'adaptent à l'espace.
.fab {
…
& > svg {
inline-size: var(--_size);
block-size: var(--_size);
stroke-width: 3px;
}
}
Enfin, supprimez la mise en surbrillance du bouton, car nous avons ajouté nos propres commentaires visuels pour l'interaction:
.fab {
-webkit-tap-highlight-color: transparent;
}
Mini FAB
L'objectif de cette section est de créer une variante pour le bouton de type appui long. En réduisant la taille de certains boutons d'action flottants par rapport à l'action par défaut, nous pouvons mettre en avant l'action que l'utilisateur effectue le plus souvent.
Balisage du mini-bouton d'action flottant
Le code HTML est le même que celui d'un bouton d'action flottant, mais nous ajoutons une classe ".mini" pour donner au CSS un crochet dans la variante.
<button data-icon="heart" class="fab mini" title="Like action" aria-label="Like action">
<svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>
Style du bouton d'action flottant mini
Grâce à l'utilisation de propriétés personnalisées, le seul changement nécessaire est un ajustement de la variable --_size
.
.fab.mini {
--_size: 1.25rem;
}
Accessibilité
L'élément le plus important à retenir pour l'accessibilité avec les boutons d'action flottants est leur emplacement dans le flux de clavier de la page. Cette démonstration ne comporte que des boutons d'action flottants. Il n'y a donc rien à comparer en termes d'ordre et de flux du clavier, ce qui signifie qu'il n'a pas la possibilité de démontrer un flux de clavier pertinent. Dans un scénario où des éléments se disputent l'attention, je vous suggère de réfléchir attentivement à l'endroit où l'utilisateur doit entrer dans le flux du bouton FAB.
Une fois que l'utilisateur a sélectionné le conteneur du bouton d'action flottant, nous avons déjà ajouté role="group"
et aria-label="floating action buttons"
, qui informent les utilisateurs du lecteur d'écran sur le contenu de ce qu'ils ont sélectionné. J'ai placé le bouton d'action flottant par défaut en premier pour que les utilisateurs trouvent d'abord l'action principale. J'utilise ensuite flex-direction: column-reverse;
pour organiser visuellement le bouton principal en bas, près des doigts des utilisateurs pour un accès facile. C'est un bon point, car le bouton par défaut est visuellement proéminent et est également le premier pour les utilisateurs de clavier, ce qui leur offre des expériences très similaires.
Enfin, n'oubliez pas de masquer vos icônes aux utilisateurs de lecteurs d'écran et assurez-vous de leur fournir un libellé pour le bouton afin qu'il ne soit pas un mystère. Cela a déjà été fait dans le code HTML avec aria-hidden="true"
sur <svg>
et aria-label="Some action"
sur les <button>
.
Animation
Vous pouvez ajouter différents types d'animations pour améliorer l'expérience utilisateur. Comme dans d'autres défis d'interface utilisateur graphique, nous allons configurer quelques propriétés personnalisées pour contenir l'intention d'une expérience de mouvement réduite et d'une expérience de mouvement complète. Par défaut, les styles supposent que l'utilisateur souhaite réduire le mouvement, puis, à l'aide de la requête multimédia prefers-reduced-motion
, remplacent la valeur de transition par un mouvement complet.
Une stratégie de mouvements réduits avec des propriétés personnalisées
Trois propriétés personnalisées sont créées dans le code CSS suivant: --_motion-reduced
, --_motion-ok
et --_transition
. Les deux premières contiennent les transitions appropriées en fonction des préférences de l'utilisateur, et la dernière variable --_transition
sera définie sur --_motion-reduced
ou --_motion-ok
, respectivement.
.fab {
/* box-shadow and background-color can safely be transitioned for reduced motion users */
--_motion-reduced:
box-shadow .2s var(--ease-3),
background-color .3s var(--ease-3);
/* add transform and outline-offset for users ok with motion */
--_motion-ok:
var(--_motion-reduced),
transform .2s var(--ease-3),
outline-offset 145ms var(--ease-2);
/* default the transition styles to reduced motion */
--_transition: var(--_motion-reduced);
/* set the transition to our adaptive transition custom property*/
transition: var(--_transition);
/* if motion is ok, update the adaptive prop to the respective transition prop */
@media (prefers-reduced-motion: no-preference) {
--_transition: var(--_motion-ok);
}
}
Une fois les éléments ci-dessus en place, les modifications apportées à box-shadow
, background-color
, transform
et outline-offset
peuvent être effectuées, ce qui permet à l'utilisateur de recevoir un retour sur l'interface utilisateur indiquant que son interaction a été reçue.
Ajoutez ensuite un peu plus de style à l'état :active
en ajustant légèrement translateY
. Cela donne au bouton un bel effet de pression:
.fab {
…
&:active {
@media (prefers-reduced-motion: no-preference) {
transform: translateY(2%);
}
}
}
Enfin, apportez les modifications nécessaires aux icônes SVG des boutons:
.fab {
…
&[data-icon="plus"]:hover > svg {
transform: rotateZ(.25turn);
}
& > svg {
@media (prefers-reduced-motion: no-preference) {
will-change: transform;
transition: transform .5s var(--ease-squish-3);
}
}
}
Conclusion
Maintenant que vous savez comment j'ai fait, comment procéderiez-vous ? 🙂
Diversifions nos approches et découvrons toutes les façons de créer sur le Web.
Créez une démo, tweetez-moi des liens et je les ajouterai à la section "Remix de la communauté" ci-dessous.
Remix de la communauté
Aucun élément à afficher pour le moment.
Ressources
- Code source sur GitHub