La personnalisation des éléments de formulaire HTML standards, tels que les cases à cocher et les cases d'option, a toujours été difficile. Les développeurs devaient souvent choisir entre utiliser les valeurs par défaut du navigateur ou créer des composants personnalisés de toutes pièces. La création de commandes personnalisées prend du temps et peut facilement entraîner des problèmes d'accessibilité ou des états manquants (comme l'état indéterminé pour les cases à cocher).
La propriété CSS accent-color permet d'appliquer facilement la couleur de votre marque aux entrées de formulaire HTML intégrées avec une seule ligne de CSS, sans sacrifier l'accessibilité ni les fonctionnalités intégrées du navigateur.
Implémentation
Pour appliquer la couleur de votre marque aux commandes de formulaire :
- Identifiez la couleur de votre marque : choisissez une couleur qui représente votre marque.
- Appliquez la propriété
accent-color: ajoutezaccent-colorà l'élément ou à un élément conteneur (commebodyou un formulaire spécifique) dans votre CSS. - Prise en charge du mode sombre (facultatif, mais recommandé) : utilisez
color-schemepour indiquer au navigateur que votre site est compatible avec le mode sombre, et ajustezaccent-colorsi nécessaire pour un meilleur contraste.
Exemple de code : commandes de formulaire cohérentes avec la marque
:root {
--brand-color: #6200ee;
}
/* Apply accent-color to the body or a specific container */
body {
accent-color: var(--brand-color);
}
/* Optional: Adjust for dark mode if needed */
@media (prefers-color-scheme: dark) {
:root {
--brand-color: #bb86fc; /* A lighter shade for dark mode */
}
}
<form>
<!-- Checkbox -->
<label for="subscribe">
<input type="checkbox" id="subscribe" checked>
Subscribe to newsletter
</label>
<!-- Radio Buttons -->
<label for="plan-monthly">
<input type="radio" id="plan-monthly" name="plan" value="monthly">
Monthly
</label>
<label for="plan-yearly">
<input type="radio" id="plan-yearly" name="plan" value="yearly" checked>
Yearly
</label>
<!-- Range Slider -->
<label for="volume">Volume:</label>
<input type="range" id="volume" min="0" max="100" value="70">
<!-- Progress Bar -->
<label for="file">Upload Progress:</label>
<progress id="file" max="100" value="70">70%</progress>
</form>
Implémentation stratégique et bonnes pratiques
- À FAIRE : Utilisez
accent-colorpour adapter facilement les éléments de contrôle des formulaires à votre marque. - NE FAITES PAS aveuglément confiance au navigateur pour gérer le contraste. Bien que les navigateurs soient censés déterminer automatiquement une couleur de contraste éligible, des bugs connus dans des implémentations telles que Safari (bug WebKit 244233) et Android Chrome (bug Chromium 343503163) peuvent empêcher l'inversion des couleurs des coches. Cela peut rendre les commandes invisibles ou difficiles à voir lorsque vous utilisez des couleurs qui ne contrastent pas suffisamment avec l'arrière-plan (par exemple, des couleurs claires en mode clair ou des couleurs sombres en mode sombre).
- À FAIRE : Combinez
accent-coloraveccolor-scheme: light darkpour vous assurer que les commandes de formulaire s'affichent correctement dans les thèmes clair et sombre. - À ÉVITER : N'utilisez pas une couleur trop proche de la couleur d'arrière-plan. Même si les navigateurs essaient de garantir le contraste, il est préférable de fournir une couleur avec un bon contraste de base.
- NE PARTEZ PAS DU PRINCIPE que
accent-colorfonctionne sur tous les éléments de formulaire. Actuellement, il ne teinte que les élémentscheckbox,radio,rangeetprogress.
Stratégie de remplacement
Pour les navigateurs qui ne sont pas compatibles avec accent-color, les commandes de formulaire reviennent à l'apparence par défaut du navigateur. Pour garantir une cohérence totale de la marque et une grande fiabilité dans tous les environnements, vous DEVEZ implémenter une stratégie de remplacement personnalisée à l'aide de la technique établie de "saisie visuellement masquée".
Amélioration progressive avec @supports not
Vous DEVEZ utiliser la règle @supports not pour appliquer des styles de remplacement personnalisés uniquement lorsque accent-color n'est pas accepté. Vous pouvez ainsi profiter de la simplicité de accent-color pour les navigateurs récents, tout en garantissant une expérience cohérente avec votre marque pour les navigateurs plus anciens.
1. Structure HTML
Assurez-vous que vos libellés encapsulent le texte dans un <span> pour permettre l'utilisation de sélecteurs frères en CSS :
<label for="subscribe-fallback">
<input type="checkbox" id="subscribe-fallback" class="visually-hidden" checked>
<span>Subscribe to newsletter</span>
</label>
2. CSS de remplacement
Appliquez des styles personnalisés dans un bloc @supports not :
/* Fallback for older browsers without accent-color */
@supports not (accent-color: var(--brand-color)) {
/* Visually hide the native input using the canonical accessible recipe */
form input[type="checkbox"].visually-hidden {
position: absolute !important;
clip-path: inset(50%) !important;
overflow: hidden !important;
width: 1px !important;
height: 1px !important;
margin: -1px !important;
padding: 0 !important;
border: 0 !important;
white-space: nowrap !important;
}
/* Style the wrapper label */
label {
position: relative;
padding-left: 2rem;
cursor: pointer;
display: inline-flex;
align-items: center;
}
/* Custom box for checkbox */
input[type="checkbox"] + span::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 1.2rem;
height: 1.2rem;
border: 2px solid #ccc;
background: white;
border-radius: 4px;
box-sizing: border-box;
transition: all 0.2s ease;
}
/* Ensure custom checkbox shows focus for keyboard users */
input[type="checkbox"]:focus-visible + span::before {
outline: 2px solid #000;
outline-offset: 2px;
}
/* Checked State */
input[type="checkbox"]:checked + span::before {
background-color: var(--brand-color, #6200ee);
border-color: var(--brand-color, #6200ee);
}
/* Checkmark (Unicode) */
input[type="checkbox"]:checked + span::after {
content: "✓";
position: absolute;
left: 0.25rem;
top: 50%;
transform: translateY(-50%);
color: white;
font-weight: bold;
font-size: 0.9rem;
}
/* Fallback for Range Slider */
input[type="range"] {
-webkit-appearance: none;
appearance: none;
background: transparent;
}
/* Webkit (Chrome, Safari, Edge) */
input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
/* Use gradient to show progress for a static value (e.g., 70%) or update with JS */
background: linear-gradient(to right, var(--brand-color, #6200ee) 70%, #ccc 70%);
border-radius: 4px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--brand-color, #6200ee);
cursor: pointer;
margin-top: -4px; /* Center vertically */
}
/* Firefox */
input[type="range"]::-moz-range-track {
width: 100%;
height: 8px;
background: #ccc;
border-radius: 4px;
}
input[type="range"]::-moz-range-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--brand-color, #6200ee);
cursor: pointer;
}
/* Firefox specific progress bar */
input[type="range"]::-moz-range-progress {
background-color: var(--brand-color, #6200ee);
height: 8px;
border-radius: 4px;
}
/* Fallback for Progress Bar */
progress {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
background: #ccc;
height: 8px;
border-radius: 4px;
}
progress::-webkit-progress-bar {
background-color: #ccc;
border-radius: 4px;
}
progress::-webkit-progress-value {
background-color: var(--brand-color, #6200ee);
border-radius: 4px;
}
progress::-moz-progress-bar {
background-color: var(--brand-color, #6200ee);
border-radius: 4px;
}
}
Progression de la plage dynamique dans le remplacement Webkit
Pour que le remplissage de la progression se déplace avec le curseur sur un curseur de plage dans les navigateurs Webkit (sans accent-color), vous pouvez utiliser une variable CSS et une petite quantité de code JavaScript.
Mettez à jour le CSS : utilisez une variable CSS pour le point de dégradé :
input[type="range"]::-webkit-slider-runnable-track { background: linear-gradient(to right, var(--brand-color) var(--progress, 0%), #ccc var(--progress, 0%)); }Ajoutez du code JavaScript : mettez à jour la variable sur l'événement
input:
if (!CSS.supports('accent-color')) {
const slider = document.getElementById('volume');
slider.addEventListener('input', (e) => {
e.target.style.setProperty('--progress', `${e.target.value}%`);
});
}