Lage animerte, klikkbare kort med :has() Relational Pseudo Class PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Lage animerte, klikkbare kort med :has() Relational Pseudo Class

CSS :has() pseudo-klassen rulles ut i mange nettlesere med Chrome og Safari støtter det allerede fullt ut. Det blir ofte referert til som "foreldrevelgeren" - som i, vi kan velge stil et overordnet element fra en barnevelger - men det er så mye mer som :has() kan hjelpe oss med å løse. En av disse tingene er å gjenoppfinne det klikkbare kortmønsteret mange av oss elsker å bruke fra tid til annen.

Vi skal se på hvordan :has() kan hjelpe oss med å håndtere koblede kort, men først...

Hva er dette :has() pseudo klasse?

Det er allerede en bunt of flott innlegg flyter rundt som gjør en utmerket jobb med å forklare hva :has() er og hva det brukes til, men det er fortsatt nytt nok til at vi burde si noen ord om det her også.

:has() er en relasjonell pseudoklasse som er en del av W3C Selectors Level 4 arbeidsutkast. Det er det parentesene handler om: samsvarende elementer som er relatert til - eller, mer nøyaktig, inneholder - visse underordnede elementer.

/* 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) { }

Så du kan se hvorfor vi kanskje vil kalle det en "foreldre"-velger. Men vi kan også kombinere det med andre funksjonelle pseudoklasser for å bli mer spesifikke. Si at vi vil style artikler som gjør det ikke inneholde noen bilder. Vi kan kombinere relasjonskreftene til :has() med negasjonskreftene til :not() å gjøre det:

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

Men det er bare starten på hvordan vi kan kombinere krefter til å gjøre mer med :has(). Før vi spesifikt tar for oss å løse problem med klikkbare kort, la oss se på noen måter vi for øyeblikket nærmer oss dem uten å bruke :has().

Hvordan vi for tiden håndterer klikkbare kort

Det er tre hovedtilnærminger til hvordan folk lager et fullt klikkbart kort i disse dager, og for å fullt ut forstå kraften i denne pseudoklassen, er det fint å ha en liten oppsummering.

Denne tilnærmingen er noe som brukes ganske ofte. Jeg bruker aldri denne tilnærmingen, men jeg laget en rask demo for å demonstrere det:

Det er mange bekymringer her, spesielt når det gjelder tilgjengelighet. Når brukere navigerer på nettstedet ditt ved hjelp av rotorfunksjonen, vil de høre hele teksten i den element — overskriften, teksten og lenken. Noen vil kanskje ikke sitte gjennom alt det. Vi kan gjøre det bedre. Siden HTML5 kan vi neste blokkelementer inne i en element. Men det føles aldri riktig for meg, spesielt av denne grunn.

Pros:

  • Rask å implementere
  • Semantisk korrekt

Cons:

  • Bekymringer om tilgjengelighet
  • Tekst kan ikke velges
  • Mye problemer med å overskrive stiler du brukte på standardlenkene dine

JavaScript-metoden

Ved å bruke JavaScript kan vi legge ved en lenke til kortet vårt i stedet for å skrive det i markeringen. Jeg fant denne flotte CodePen-demoen av kostnadsdev som også gjorde kortteksten valgbar i prosessen:

Denne tilnærmingen har mange fordeler. Lenkene våre er tilgjengelige på fokus, og vi kan til og med velge tekst. Men det er noen ulemper når det kommer til styling. Hvis vi ønsker å animere disse kortene, for eksempel, må vi legge til :hover stiler på vår hoved .card wrapper i stedet for selve lenken. Vi vil heller ikke ha nytte av animasjonene når lenkene er i fokus fra tabbing på tastaturet.

Pros:

  • Kan gjøres perfekt tilgjengelig
  • Evne til å velge tekst

Cons:

  • Krever JavaScript
  • Høyreklikk ikke mulig (selv om det kan fikses med litt ekstra skripting)
  • Vil kreve mye styling på selve kortet som ikke ville fungere når du fokuserer lenken

De ::after velgertilnærming

Denne metoden krever at vi setter kortet med relativ posisjonering, og deretter setter absolutt posisjonering på lenkene ::after pseudovelger for en lenke. Dette krever ikke noe JavaScript og er ganske enkelt å implementere:

Det er noen ulemper her, spesielt når det gjelder å velge tekst. Med mindre du oppgir en høyere z-indeks på kortet ditt, vil du ikke kunne velge tekst, men hvis du gjør det, vær advart om at å klikke på teksten vil ikke aktivere lenken din. Hvorvidt du vil ha valgbar tekst eller ikke, er opp til deg. Jeg tror det kan være et UX-problem, men det avhenger av brukssaken. Teksten er fortsatt tilgjengelig for skjermlesere, men mitt hovedproblem med metoden er mangelen på animasjonsmuligheter.

Pros:

  • Enkel å implementere
  • Tilgjengelig lenke uten oppblåst tekst
  • Jobber med sveving og fokus

Cons:

  • Tekst kan ikke velges
  • Du kan bare animere koblingen siden dette er elementet du holder på.

En ny tilnærming: Bruke ::after med :has()

Nå som vi har etablert de eksisterende tilnærmingene for klikkbare kort, vil jeg vise hvordan introduksjon :has() til blandingen løser de fleste av disse manglene.

Faktisk, la oss basere denne tilnærmingen på den siste vi så på å bruke ::after på lenkeelementet. Vi kan faktisk bruke :has() der for å overvinne den tilnærmingens animasjonsbegrensninger.

La oss starte med markeringen:

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.

Jeg vil holde ting så enkelt som mulig ved å målrette elementer i CSS i stedet for klasser.

For denne demoen kommer vi til å legge til en bildezoom og skygge på kortet når du svever, og animere lenken med en pil som dukker opp og mens vi endrer lenkens tekstfarge. For å gjøre dette enkelt, kommer vi til å legge til noen tilpassede egenskaper på kortet vårt. Her er den grunnleggende stylingen:

/* 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;
}

Flott! Vi la til en innledende skala for bildet (--img-scale: 1.001), den opprinnelige fargen på kortoverskriften (--title-color: black) og noen ekstra egenskaper vi vil bruke for å få pilen vår til å sprette ut av lenken. Vi har også satt en tom tilstand av box-shadow erklæring for å animere den senere. Dette setter opp det vi trenger for det klikkbare kortet akkurat nå, så la oss legge til noen tilbakestillinger og styling til det ved å legge til de egendefinerte egenskapene til elementene vi vil animere:

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;
}

La oss være snille mot folk og også legge til en skjermleserklasse skjult bak linken:

.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;
}

Kortet vårt begynner å se ganske søtt ut. Det er på tide å legge til litt magi til det. Med :has() pseudo-klasse, kan vi nå sjekke om lenken vår er svevet eller fokusert, og deretter oppdatere våre egendefinerte egenskaper og legge til en box-shadow. Med denne lille biten av CSS blir kortet vårt virkelig levende:

/* 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;
}

Ser du hva som er der oppe? Nå får vi de oppdaterte stilene if noen underordnet element i kortet er svevet eller fokusert. Og selv om lenkeelementet er det eneste som kan inneholde en hover- eller fokustilstand i ::after klikkbare korttilnærming, kan vi bruke den til å matche det overordnede elementet og bruke overgangene.

Og der har du det. Bare nok et kraftig bruksområde for :has() velger. Ikke bare kan vi matche et overordnet element ved å erklære andre elementer som argumenter, men vi kan også matche bruke pseudoer for å matche og style foreldre også.

Pros:

  • Tilgjengelig
  • Animerbar
  • Ingen JavaScript nødvendig
  • Bruker :hover på riktig element

Cons:

  • Tekst er ikke lett å velge.
  • Nettleserstøtte er begrenset til Chrome og Safari (det støttes i Firefox bak et flagg).

Her er en demo som bruker denne teknikken. Du legger kanskje merke til en ekstra omslag rundt kortet, men det er bare meg som leker med containerspørsmål, som bare er en av de andre fantastiske tingene som rulles ut i alle store nettlesere.

Har noe andre eksempler ønsker du å dele? Andre løsninger eller ideer er mer enn velkomne i kommentarfeltet.

Tidstempel:

Mer fra CSS triks