È noto che in CSS non esiste un modo per selezionare direttamente un elemento principale in base ai suoi elementi secondari. Si tratta di una delle richieste più frequenti degli sviluppatori da molti anni. Il selettore:has()
, ora supportato da tutti i principali browser, risolve questo problema. Prima di
:has()
, spesso si collegavano 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.
Anche se questo selettore sembra piccolo, può abilitare un numero enorme di casi d'uso.
Questo articolo mostra alcuni casi d'uso sbloccati dalle aziende di e-commerce 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.
Policybazaar
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 accedere agli elementi principali e ai relativi elementi secondari. Il
seguente codice controlla se un contenitore principale ha impostato una classe .disabled-group
.
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 utilizzano
:has()
per controllare lo stato della casella di controllo della domanda per vedere se la domanda è stata
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 come 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 è stata data una risposta alla domanda utilizzando :has(input:checked)
e, in questo caso, 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. Qui, 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 viene creato un 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() il selettore di famiglie.
Risorse:
- CSS Wrapped 2023
- :has(): il selettore di famiglie
- Demos :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.