È noto che in CSS non esiste un modo per selezionare direttamente un elemento principale in base ai suoi elementi secondari. Questa è da molti anni una delle richieste principali degli sviluppatori. Il selettore:has()
, ora supportato da tutti i principali browser, risolve questo problema. Prima di
:has()
, spesso si mettevano in catena selettori lunghi o si aggiungevano classi per gli hook di stile. Ora puoi applicare uno stile in base alla relazione di un elemento con i suoi discendenti. Scopri di più sul selettore :has()
in CSS Wrapped 2023 e 5 snippet CSS che ogni sviluppatore frontend dovrebbe conoscere.
Sebbene questo selettore sembri piccolo, può consentire un numero enorme di casi d'uso.
Questo articolo mostra alcuni casi d'uso che le aziende di e-commerce hanno sbloccato con il
selettore :has()
.
:has()
fa parte di Elementi di base di nuovo disponibili.
Dai un'occhiata alla serie completa di cui fa parte questo articolo, che illustra in che modo le aziende di e-commerce hanno migliorato il proprio sito web utilizzando nuove funzionalità CSS e UI.
Bazar criteri
Con il selettore
:has()
, siamo riusciti a eliminare la convalida basata su JavaScript della selezione dell'utente e a sostituirla con una soluzione CSS che funziona perfettamente per noi con la stessa esperienza di prima. - Aman Soni, Tech Lead, Policybazaar
Il team di investimento di Policybazaar ha applicato abilmente il selettore :has()
per fornire un'indicazione visiva chiara agli utenti che confrontano i piani. L'immagine seguente mostra due tipi di piani nell'interfaccia utente di confronto (giallo e blu). Ogni piano
può essere confrontato solo con il proprio tipo. Se utilizzi :has()
, quando un utente seleziona un tipo di piano, l'altro tipo di piano non può essere selezionato.
Codice
:has()
ti consente di applicare stili agli elementi principali e ai relativi elementi secondari. Il seguente codice verifica se un contenitore principale ha una classe .disabled-group
impostata.
In questo caso, la scheda non è selezionabile e il pulsante "Aggiungi" non reagisce ai clic impostando pointer-events
su 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);
}
Il team dedicato alla salute di Policybazaar ha implementato un caso d'uso leggermente diverso. Hanno un quiz in linea per l'utente e usano :has()
per selezionare lo stato della casella di controllo della domanda e vedere se la domanda ha ricevuto una risposta. In questo caso, viene applicata un'animazione per passare alla domanda successiva.
Codice
Nell'esempio di confronto dei piani, :has()
è stato utilizzato per verificare la presenza di una
classe. Puoi anche controllare lo stato di un elemento di input, ad esempio una casella di controllo, utilizzando
:has(input:checked)
. Nell'immagine che mostra il quiz, ogni domanda nel banner viola è una casella di controllo. Policybazaar controlla se la domanda ha ricevuto
risposta utilizzando :has(input:checked)
e, in caso affermativo, attiva un'animazione utilizzando
animation: quesSlideOut 0.3s 0.3s linear forwards
per passare alla domanda
successiva. Scopri come funziona nel codice seguente.
.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 ha utilizzato :has()
per creare un'immagine in overlay se la miniatura del prodotto contiene un video. Se la miniatura del prodotto contiene una classe .playIcon
, viene aggiunto un overlay CSS. In questo caso, il selettore :has() viene utilizzato insieme al selettore di nidificazione &
all'interno della classe .thumbnailWrapper
generale che si applica a tutte le miniature. In questo modo, il CSS è più modulare e leggibile.
Codice
Il seguente codice utilizza i
selettori e i combinatori CSS
(&
e >
) e il nidificazione con :has()
per applicare uno stile alla miniatura.
Per i browser che non supportano la funzionalità, viene utilizzata come alternativa la regola della classe CSS aggiuntiva standard. La regola @supports selector(:has(*))
viene utilizzata anche per verificare il supporto del browser.
Di conseguenza, l'esperienza complessiva è la stessa nelle varie versioni del browser.
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;
}
}
`;
Aspetti da considerare quando si utilizza :has()
Combina :has()
con altri selettori per creare una condizione più complessa. Dai un'occhiata ad alcuni esempi in has() sul selettore della famiglia.
Risorse:
- CSS Wrapped 2023
- :has(): il selettore di famiglie
- Demo :has()
- Vuoi segnalare un bug o richiedere una nuova funzionalità? Vogliamo conoscere la tua opinione.
Consulta gli altri articoli di questa serie per scoprire in che modo le aziende di e-commerce hanno tratto vantaggio dall'utilizzo di nuove funzionalità CSS e UI, come animazioni basate sullo scorrimento, transizioni di visualizzazione, popover e query dei contenitori.