El CSS siempre se caracterizó por no tener una forma de seleccionar directamente un elemento superior en función de sus elementos secundarios. Esta fue una de las principales solicitudes de los desarrolladores durante muchos años. El selector :has(), que ahora es compatible con todos los navegadores principales, resuelve este problema. Antes de :has(), solías encadenar selectores largos o agregar clases para los hooks de diseño. Ahora puedes aplicar estilos en función de la relación de un elemento con sus descendientes. Obtén más información
sobre el :has() selector en
CSS Wrapped 2023 y
5 fragmentos de CSS que todo desarrollador de frontend debe conocer.
Aunque este selector parece pequeño, puede habilitar una gran cantidad de casos de uso.
En este artículo, se muestran algunos casos de uso que las empresas de comercio electrónico desbloquearon con el selector :has().
Consulta la serie completa de la que forma parte este artículo, en la que se explica cómo las empresas de comercio electrónico mejoraron su sitio web con nuevas funciones de CSS y de IU.
Policybazaar
Con el
:has()selector, pudimos eliminar la validación basada en JavaScript de la selección del usuario y reemplazarla por una solución de CSS que funciona sin problemas para nosotros con la misma experiencia que antes.—Aman Soni, líder técnico de Policybazaar
El equipo de inversión de Policybazaar aplicó de forma inteligente el selector :has() para proporcionar una indicación visual clara a los usuarios que comparan planes. En la siguiente imagen, se muestran dos tipos de planes en la IU de comparación (amarillo y azul). Cada plan solo se puede comparar con su propio tipo. :has()Cuando un usuario selecciona un
tipo de plan, no se puede seleccionar el otro tipo de plan.
:has() para aplicar estilo al elemento superior y a sus elementos secundarios para crear una funcionalidad de selección vinculada a la categoría.Código
:has() te da acceso a los elementos superiores y sus elementos secundarios. El siguiente código verifica si un contenedor superior tiene establecida una clase .disabled-group.
Si es así, la tarjeta aparece atenuada y se impide que el botón "Agregar" reaccione a los clics estableciendo pointer-events en 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);
}
El equipo de salud de Policybazaar implementó
un caso de uso ligeramente diferente. Tienen un cuestionario intercalado para el usuario y usan :has() para verificar el estado de la casilla de verificación de la pregunta y ver si se respondió. Si es así, se aplica una animación para pasar a la siguiente pregunta.
Código
En el ejemplo de comparación de planes, se usó :has() para verificar la presencia de una clase. También puedes verificar el estado de un elemento de entrada, como una casilla de verificación, con :has(input:checked). En la imagen que muestra el cuestionario, cada pregunta en el banner morado es una casilla de verificación. Policybazaar verifica si se respondió la pregunta con :has(input:checked) y, si es así, activa una animación con animation: quesSlideOut 0.3s 0.3s linear forwards para pasar a la siguiente pregunta. Mira cómo funciona en el siguiente código.
.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 usó :has() para crear una imagen superpuesta si la miniatura del producto contiene un video. Si la miniatura del producto contiene una clase .playIcon, se agrega una superposición de CSS. Aquí, el selector :has() se usa junto con el selector de anidación & dentro de la clase general .thumbnailWrapper, que se aplica a todas las miniaturas. Esto crea un CSS más modular y legible.
:has().Código
En el siguiente código, se usan los
selectores y combinadores de CSS
(& y >) y la anidación con :has() para aplicar estilo a la miniatura.
Para los navegadores no compatibles, se usa la regla de clase CSS adicional normal como resguardo. También se usa la regla @supports selector(:has(*)) para verificar la compatibilidad del navegador.
Por lo tanto, la experiencia general es la misma en todas las versiones del navegador.
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;
}
}
`;
Aspectos que debes tener en cuenta cuando usas :has()
Combina :has() con otros selectores para crear una condición más compleja. Consulta
algunos ejemplos en has() el selector de familia.
Recursos:
- CSS Wrapped 2023
- :has(): el selector de familia
- Demostraciones :has()
- ¿Quieres informar un error o solicitar una función nueva? Queremos conocer tu opinión.
Explora los otros artículos de esta serie en los que se explica cómo las empresas de comercio electrónico se beneficiaron del uso de nuevas funciones de CSS y de IU, como las animaciones controladas por el desplazamiento, las transiciones de vista, las ventanas emergentes y las consultas de contenedores.