Le CSS ne permet pas de sélectionner directement un élément parent en fonction de ses enfants. C'est une fonctionnalité très demandée par les développeurs depuis de nombreuses années. Le sélecteur :has()
, désormais compatible avec tous les principaux navigateurs, résout ce problème. Avant :has()
, vous enchaîniez souvent des sélecteurs longs ou ajoutiez des classes pour les crochets de style. Vous pouvez désormais appliquer un style en fonction de la relation d'un élément avec ses descendants. Pour en savoir plus sur le sélecteur :has()
, consultez CSS Wrapped 2023 et 5 extraits CSS que tout développeur front-end doit connaître.
Bien que ce sélecteur semble petit, il peut permettre un grand nombre de cas d'utilisation.
Cet article présente quelques cas d'utilisation que les entreprises d'e-commerce ont débloqués avec le sélecteur :has()
.
:has()
fait partie de la section Nouvelle version de référence disponible.
Découvrez la série complète dont cet article fait partie, qui explique comment les entreprises d'e-commerce ont amélioré leur site Web à l'aide de nouvelles fonctionnalités CSS et d'UI.
Policybazaar
Avec le sélecteur
:has()
, nous avons pu éliminer la validation basée sur JavaScript de la sélection de l'utilisateur et la remplacer par une solution CSS qui fonctionne parfaitement pour nous avec la même expérience qu'auparavant.—Aman Soni, Tech Lead, Policybazaar
L'équipe Investment de Policybazaar a intelligemment appliqué le sélecteur :has()
pour fournir une indication visuelle claire aux utilisateurs qui comparent des forfaits. L'image suivante montre deux types de forfaits dans l'UI de comparaison (jaune et bleu). Chaque forfait ne peut être comparé qu'à son propre type. Lorsque vous utilisez :has()
, un utilisateur ne peut pas sélectionner un autre type de forfait lorsqu'il a déjà sélectionné un type de forfait.
Code
:has()
vous permet de styliser les éléments parent et leurs enfants. Le code suivant vérifie si un conteneur parent a une classe .disabled-group
définie.
Si c'est le cas, la fiche est grisée et le bouton "Ajouter" ne réagit pas aux clics en définissant pointer-events
sur none
.
.plan-group-container:has(.disabled-group) {
opacity: 0.5;
filter: grayscale(100%);
}
.plan-group-container:has(.disabled-section) .button {
pointer-events: none;
border-color: #B5B5B5;
color: var(--text-primary-38-color);
background: var(--input-border-color);
}
L'équipe santé de Policybazaar a implémenté un cas d'utilisation légèrement différent. Il propose un quiz intégré à l'utilisateur et utilise :has()
pour vérifier l'état de la case à cocher de la question afin de voir si elle a été répondue. Si c'est le cas, une animation est appliquée pour passer à la question suivante.
Code
Dans l'exemple de comparaison de plans, :has()
a été utilisé pour vérifier la présence d'une classe. Vous pouvez également vérifier l'état d'un élément d'entrée tel qu'une case à cocher à l'aide de :has(input:checked)
. Dans le visuel du quiz, chaque question de la bannière violette est une case à cocher. Policybazaar vérifie si la question a été répondue à l'aide de :has(input:checked)
. Si c'est le cas, il déclenche une animation à l'aide de animation: quesSlideOut 0.3s 0.3s linear forwards
pour passer à la question suivante. Découvrez comment cela fonctionne dans le code suivant.
.segment_banner__wrap__questions {
position: relative;
animation: quesSlideIn 0.3s linear forwards;
}
.segment_banner__wrap__questions:has(input:checked) {
animation: quesSlideOut 0.3s 0.3s linear forwards;
}
@keyframes quesSlideIn {
from {
transform: translateX(50px);
opacity: 0;
}
to {
transform: translateX(0px);
opacity: 1;
}
}
@keyframes quesSlideOut {
from {
transform: translateX(0px);
opacity: 1;
}
to {
transform: translateX(-50px);
opacity: 0;
}
}
Tokopedia
Tokopedia a utilisé :has()
pour créer une image superposée si la miniature du produit contient une vidéo. Si la miniature du produit contient une classe .playIcon
, une superposition CSS est ajoutée. Ici, le sélecteur :has() est utilisé avec le sélecteur d'imbrication &
dans la classe .thumbnailWrapper
globale qui s'applique à toutes les miniatures. Cela crée un code CSS plus modulaire et lisible.
Code
Le code suivant utilise les sélecteurs et combinators CSS (&
et >
) et l'imbrication avec :has()
pour styliser la vignette.
Pour les navigateurs non compatibles, la règle de classe CSS supplémentaire standard est utilisée comme solution de secours. La règle @supports selector(:has(*))
permet également de vérifier la compatibilité avec le navigateur.
Par conséquent, l'expérience globale est la même entre les versions du navigateur.
export const thumbnailWrapper = css`
padding: 0;
margin-right: 7px;
border: none;
outline: none;
background: transparent;
> div {
width: 64px;
height: 64px;
overflow: hidden;
cursor: pointer;
border-color: ;
position: relative;
border: 2px solid ${NN0};
border-radius: 8px;
transition: border-color 0.25s;
&.active {
border-color: ${GN500};
}
@supports selector(:has(*)) {
&:has(.playIcon) {
&::after {
content: '';
display: block;
background: rgba(0, 0, 0, 0.2);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}
}
& > .playIcon {
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
text-align: center;
z-index: 1;
}
}
`;
Éléments à prendre en compte lors de l'utilisation de :has()
Combinez :has()
avec d'autres sélecteurs pour créer une condition plus complexe. Consultez quelques exemples dans has() le sélecteur de famille.
Ressources :
- CSS Wrapped 2023
- :has(): sélecteur de famille
- Démonstrations :has()
- Voulez-vous signaler un bug ou demander une nouvelle fonctionnalité ? Votre avis nous intéresse !
Consultez les autres articles de cette série qui expliquent comment les entreprises d'e-commerce ont tiré parti des nouvelles fonctionnalités CSS et d'UI telles que les animations basées sur le défilement, les transitions de vue, les popovers et les requêtes de conteneur.