Creación de tarjetas animadas en las que se puede hacer clic con :has() Relational Pseudo Class PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Creación de tarjetas animadas en las que se puede hacer clic con la pseudoclase relacional :has()

El CSS :has() pseudo clase se está implementando en muchos navegadores con Chrome y Safari ya lo apoya plenamente. A menudo se lo conoce como "el selector principal", ya que podemos seleccionar el estilo de un elemento principal desde un selector secundario, pero hay mucho más que :has() puede ayudarnos a resolver. Una de esas cosas es reinventar el patrón de tarjeta en el que se puede hacer clic que a muchos de nosotros nos encanta usar de vez en cuando.

Echaremos un vistazo a cómo :has() puede ayudarnos a manejar las tarjetas vinculadas, pero primero...

Que es esto :has() pseudo clase?

Ya hay un manojo of maravillosa mensajes flotando alrededor que hacen un excelente trabajo explicando lo que :has() es y para qué se usa, pero aún es lo suficientemente nuevo como para que también debamos decir algunas palabras al respecto aquí.

:has() es una pseudoclase relacional que forma parte de la Borrador de trabajo de nivel 3 de selectores W4C. De eso se tratan los paréntesis: elementos coincidentes que están relacionados con, o, más exactamente, contienen, ciertos elementos secundarios.

/* Matches an article element that contains an image element */
article:has(img) { }

/* Matches an article element with an image contained immediately within it */
article:has(> img) { }

Entonces, puede ver por qué querríamos llamarlo selector "principal". Pero también podemos combinarlo con otras pseudoclases funcionales para ser más específicos. Digamos que queremos diseñar artículos que no no contener ninguna imagen. Podemos combinar los poderes relacionales de :has() con los poderes de negación de :not() Para hacer eso:

/* Matches an article without images  */
article:not(:has(img)) { }

Pero eso es solo el comienzo de cómo podemos combinar poderes para hacer más con :has(). Antes de pasar específicamente a resolver el enigma de la tarjeta en la que se puede hacer clic, veamos algunas formas en que actualmente las abordamos sin usar :has().

Cómo manejamos actualmente las tarjetas en las que se puede hacer clic

Hay tres enfoques principales sobre cómo las personas crean una tarjeta en la que se puede hacer clic en estos días y para comprender completamente el poder de esta pseudoclase, es bueno tener un poco de resumen.

Este enfoque es algo que se usa con bastante frecuencia. Nunca uso este enfoque, pero creé una demostración rápida para demostrarlo:

Hay muchas preocupaciones aquí, especialmente cuando se trata de accesibilidad. Cuando los usuarios navegan por su sitio web utilizando la función del rotor, escucharán el texto completo dentro de ese elemento: el encabezado, el texto y el enlace. Alguien podría no querer sentarse a través de todo eso. Podemos hacerlo mejor. Desde HTML5, podemos anidar elementos de bloque dentro de un elemento. Pero nunca se siente bien para mí, especialmente por esta razón.

Pros:

  • Rápido de implementar
  • semánticamente correcto

Contras:

  • Problemas de accesibilidad
  • Texto no seleccionable
  • Muchas molestias para sobrescribir los estilos que usó en sus enlaces predeterminados

El método JavaScript

Usando JavaScript, podemos adjuntar un enlace a nuestra tarjeta en lugar de escribirlo en el marcado. Encontré esta gran demostración de CodePen por costodesv quien también hizo que el texto de la tarjeta fuera seleccionable en el proceso:

Este enfoque tiene muchos beneficios. Nuestros enlaces son accesibles en foco e incluso podemos seleccionar texto. Pero hay algunos inconvenientes cuando se trata de estilo. Si queremos animar esas tarjetas, por ejemplo, tendríamos que agregar :hover estilos en nuestro principal .card envoltorio en lugar del enlace en sí. Tampoco nos beneficiaríamos de las animaciones cuando los enlaces están enfocados desde el teclado.

Pros:

  • Se puede hacer perfectamente accesible
  • Posibilidad de seleccionar texto

Contras:

  • Requiere JavaScript
  • No es posible hacer clic con el botón derecho (aunque podría solucionarse con algunas secuencias de comandos adicionales)
  • Requerirá mucho estilo en la tarjeta en sí, lo que no funcionaría al enfocar el enlace

La ::after enfoque selector

Este método requiere que configuremos la tarjeta con un posicionamiento relativo, luego configuremos un posicionamiento absoluto en el enlace ::after pseudoselector de un enlace. Esto no requiere JavaScript y es bastante fácil de implementar:

Aquí hay algunos inconvenientes, especialmente cuando se trata de seleccionar texto. A menos que proporcione un índice z más alto en el cuerpo de su tarjeta, no podrá seleccionar texto, pero si lo hace, tenga en cuenta que hacer clic en el texto no activará su enlace. Depende de usted si desea o no texto seleccionable. Creo que puede ser un problema de UX, pero depende del caso de uso. El texto aún es accesible para los lectores de pantalla, pero mi principal problema con el método es la falta de posibilidades de animación.

Pros:

  • Fácil de implementar
  • Enlace accesible sin texto inflado
  • Funciona en hover y focus

Contras:

  • El texto no es seleccionable
  • Solo puede animar el enlace ya que este es el elemento que está desplazando.

Un nuevo enfoque: usar ::after :has()

Ahora que hemos establecido los enfoques existentes para las tarjetas en las que se puede hacer clic, quiero mostrar cómo introducir :has() a la mezcla resuelve la mayoría de esas deficiencias.

De hecho, vamos a basar este enfoque en el último que vimos usando ::after en el elemento de enlace. En realidad podemos usar :has() allí para superar las limitaciones de animación de ese enfoque.

Comencemos con el marcado:

Fluffy gray and white tabby kitten snuggled up in a ball.

Some Heading

Curabitur convallis ac quam vitae laoreet. Nulla mauris ante, euismod sed lacus sit amet, congue bibendum eros. Etiam mattis lobortis porta. Vestibulum ultrices iaculis enim imperdiet egestas.

Mantendré las cosas lo más simples posible apuntando a elementos en el CSS en lugar de clases.

Para esta demostración, agregaremos un zoom de imagen y una sombra a la tarjeta al pasar el mouse por encima, y ​​animaremos el enlace con una flecha que aparece y cambiaremos el color del texto del enlace. Para facilitar esto, vamos a agregar algunas propiedades personalizadas en el ámbito de nuestra tarjeta. Aquí está el estilo básico:

/* The card element */
article {
  --img-scale: 1.001;
  --title-color: black;
  --link-icon-translate: -20px;
  --link-icon-opacity: 0;

  position: relative;
  border-radius: 16px;
  box-shadow: none;
  background: #fff;
  transform-origin: center;
  transition: all 0.4s ease-in-out;
  overflow: hidden;
}
/* The link's ::after pseudo */
article a::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline: 0;
  cursor: pointer;
}

¡Excelente! Agregamos una escala inicial para la imagen (--img-scale: 1.001), el color inicial del encabezado de la tarjeta (--title-color: black) y algunas propiedades adicionales que usaremos para hacer que nuestra flecha salga del enlace. También hemos establecido un estado vacío del box-shadow declaración para animarla más tarde. Esto configura lo que necesitamos para la tarjeta en la que se puede hacer clic en este momento, así que agreguemos algunos reinicios y estilos agregando esas propiedades personalizadas a los elementos que queremos animar:

article h2 {
  margin: 0 0 18px 0;
  font-family: "Bebas Neue", cursive;
  font-size: 1.9rem;
  letter-spacing: 0.06em;
  color: var(--title-color);
  transition: color 0.3s ease-out;
}
article figure {
  margin: 0;
  padding: 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
article img {
  max-width: 100%;
  transform-origin: center;
  transform: scale(var(--img-scale));
  transition: transform 0.4s ease-in-out;
}
article a {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: #28666e;
}
article a:focus {
  outline: 1px dotted #28666e;
}
article a .icon {
  min-width: 24px;
  width: 24px;
  height: 24px;
  margin-left: 5px;
  transform: translateX(var(--link-icon-translate));
  opacity: var(--link-icon-opacity);
  transition: all 0.3s;
}

.article-body {
  padding: 24px;
}

Seamos amables con la gente y también agreguemos un clase de lector de pantalla escondido detrás del enlace:

.sr-only:not(:focus):not(:active) {
  clip: rect(0 0 0 0); 
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap; 
  width: 1px;
}

Nuestra tarjeta está empezando a verse bastante dulce. Es hora de agregarle un poco de magia. Con el :has() pseudo clase, ahora podemos verificar si nuestro enlace está sobrevolado o enfocado, luego actualice nuestras propiedades personalizadas y agregue un box-shadow. Con esta pequeña porción de CSS, nuestra tarjeta realmente cobra vida:

/* Matches an article element that contains a hover or focus state */
article:has(:hover, :focus) {
  --img-scale: 1.1;
  --title-color: #28666e;
  --link-icon-translate: 0;
  --link-icon-opacity: 1;

  box-shadow: rgba(0, 0, 0, 0.16) 0px 10px 36px 0px, rgba(0, 0, 0, 0.06) 0px 0px 0px 1px;
}

¿Ves lo que hay ahí arriba? Ahora tenemos los estilos actualizados si cualquier elemento secundario en la tarjeta se desplaza o se enfoca. Y aunque el elemento de enlace es lo único que puede contener un estado de desplazamiento o enfoque en el ::after enfoque de tarjeta en la que se puede hacer clic, podemos usarlo para hacer coincidir el elemento principal y aplicar las transiciones.

Y ahí lo tienes. Solo otro poderoso caso de uso para el :has() selector. No solo podemos hacer coincidir un elemento padre al declarar otros elementos como argumentos, sino que también podemos hacer coincidir usando pseudos para hacer coincidir y dar estilo a los padres también.

Pros:

  • LA EXCELENCIA
  • Animables
  • No se necesita JavaScript
  • Usos :hover en el elemento correcto

Contras:

  • El texto no es fácilmente seleccionable.
  • El soporte del navegador está limitado a Chrome y Safari (es compatible con Firefox detrás de una bandera).

Aquí hay una demostración usando esta técnica. Es posible que notes un envoltorio adicional alrededor de la tarjeta, pero solo soy yo jugando con consultas de contenedor, que es solo una de esas otras cosas fantásticas que se implementan en todos los principales navegadores.

Tengo algunos Otros ejemplos deseas compartir? Otras soluciones o ideas son más que bienvenidas en la sección de comentarios.

Sello de tiempo:

Mas de Trucos CSS