Casos de éxito de :has()

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

Es muy evidente que CSS tiene una forma de seleccionar directamente un elemento superior basado en sus elementos secundarios. Esta ha sido 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(), por lo general, se encadenaban selectores largos o agregabas clases para aplicar estilo a los hooks. Ahora puedes definir el diseño según la relación de un elemento con sus elementos subordinados. Obtén más información sobre el selector :has() 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().

:has() forma parte de Baseline Newly disponible.

Navegadores compatibles

  • 105
  • 105
  • 121
  • 15.4

Origen

Consulta la serie completa de la que forma parte este artículo, en la que se analiza cómo las empresas de comercio electrónico mejoraron su sitio web con nuevas funciones de IU y CSS.

Bazar de políticas

Con el selector :has(), pudimos eliminar la validación basada en JavaScript de la selección del usuario y reemplazarla por una solución de CSS que funciona a la perfección con la misma experiencia de antes.—Aman Soni, líder de Tecnología, Policybazaar

El equipo de inversiones de Policybazaar aplicó de forma inteligente el selector :has() a fin de proporcionar una indicación visual clara para los usuarios que comparan planes. En la siguiente imagen, se muestran dos tipos de planes dentro de la IU de comparación (amarillo y azul). Cada plan solo se puede comparar con su propio tipo. Mediante :has(), cuando un usuario selecciona un tipo de plan, el otro no se puede seleccionar.

Implementa :has() para diseñar el elemento superior y sus elementos secundarios con el fin de crear una funcionalidad de selección vinculada a la categoría.

Código

:has() te da acceso a los elementos superiores de diseño y sus elementos secundarios. Con el siguiente código, se verifica si un contenedor superior tiene configurada una clase .disabled-group. Si es así, la tarjeta estará inhabilitada y el botón "Agregar" no reaccione a los clics si estableces 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 hacer la transición a la siguiente pregunta.

health.policybazaar.com/

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 del banner púrpura 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. Observa 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 anidado & dentro de la clase .thumbnailWrapper general, que se aplica a todas las miniaturas. Esto crea CSS más modulares y legibles.

Captura de pantalla de la página de Tokopedia antes y después de usar el selector has.
Antes y después de usar :has()

Código

En el siguiente código, se usan los selectores y la combinación de CSS (& y >) y la anidación con :has() para aplicar diseño a la miniatura. En los navegadores no compatibles, se usa la regla de clase de CSS adicional normal como resguardo. La regla @supports selector(:has(*)) también se usa 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 uses :has()

Combina :has() con otros selectores para crear una condición más compleja. Consulta algunos ejemplos en has() the family selector.

Recursos:

Explora los otros artículos de esta serie, en los que se explica cómo las empresas de comercio electrónico se beneficiaron con el uso de nuevas funciones de IU y CSS, como las animaciones basadas en desplazamientos, las transiciones de vistas, las ventanas emergentes y las consultas de contenedores.