Å bygge bro over Gapet Mellom CSS og JavaScript: CSS-i-JS

0
5

I denne artikkelen kommer vi til å grave i begrepet CSS-i-JS. Hvis du allerede er kjent med dette konseptet, kan du fortsatt nyte en spasertur gjennom den filosofi at tilnærmingen, og du kan være enda mer interessert i den neste artikkelen (kommer i morgen!).

Web-utvikling er veldig tverrfaglig. Vi er vant til å jobbe tett med flere språk. Og, som å utvikle web-applikasjoner blir mer og mer vanlig og nyansert, vi ofte ser etter kreative måter å brobygger mellom disse språkene for å gjøre våre utviklingsmiljøer og arbeidsflyter for enklere og mer effektiv.

De vanligste eksemplene er vanligvis når du bruker templating språk. For eksempel, ett språk kan brukes til å generere kode for en mer utførlig språk (ofte HTML). Dette er en av de viktigste aspektene av front end rammer — hva gjør manipulere HTML-ser ut som? De siste vri på dette området var JSX fordi det er egentlig ikke en templating språk; det er en syntaks utvidelse til JavaScript, og det gjør arbeidet med HTML veldig tydelige.

Web-applikasjoner, gå gjennom mange statlige kombinasjoner, og det er ofte utfordrende å administrere innhold alene. Dette er grunnen til at CSS noen ganger faller av veikant — selv om administrerende styling gjennom ulike stater og media queries er like viktig og like utfordrende. I denne to-del-serien, jeg ønsker å plassere CSS i søkelyset og utforske bygge bro over gapet mellom det og JavaScript. Hele denne serien, jeg vil anta at du bruker en modul bundler som webpack. Som sådan, jeg vil bruke Reagere i mine eksempler, men den samme eller en lignende prinsipper som gjelder for andre JavaScript-rammeverk, inkludert Vue.

CSS landskapet utvikler seg i mange retninger fordi det er mange utfordringer å løse, og det er ingen “riktig” vei. Jeg har brukt betydelig innsats for å eksperimentere med ulike tilnærminger, for det meste på personlige prosjekter, slik intensjonen bak denne serien er bare å informere, ikke for å foreskrive.

Utfordringer av CSS

Før dykking i koden, er det verdt å forklare de mest kjente utfordringer av styling web-applikasjoner. De jeg vil snakke om i denne serien er scoping, betinget og dynamisk stiler, og reusability.

Scoping

Omfang er en velkjent CSS utfordring, det er ideen om å skrive stiler som ikke lekkasje utenfor komponenten, og dermed unngå utilsiktede bivirkninger. Vi ønsker å oppnå det ideelt uten at det går på bekostning authoring opplevelse.

Betinget og dynamisk stiler

Mens staten i front-end applikasjoner begynte å bli mer og mer avanserte, CSS fortsatt var statisk. Vi var bare i stand til å anvende sett med stiler betinget — hvis en knapp som var det primære, ville vi sannsynligvis søke klassen “primær” og definere sine stiler i en egen CSS-fil til å gjelde hvordan det kommer til å se ut som på skjermen. Å ha et par av forhåndsdefinerte knappen variasjoner var overkommelig, men hva hvis vi ønsker å ha et utvalg av knapper, som spesifikt de som er skreddersydd for , , Pinterest og hvem vet hva annet? Hva vi virkelig ønsker å gjøre er bare passere en farge og definerer stater med CSS som holder, fokus, disabled etc. Dette kalles dynamisk styling fordi vi ikke lenger å bytte mellom forhåndsdefinerte stiler — vi vet ikke hva som kommer neste. Innebygde stiler kan komme til sinn for å håndtere dette problemet, men de støtter ikke pseudo-klasser, attributter velgere, media queries, eller lignende.

Reusability

Gjenbruk rulesets, media spørringer etc. er et tema som jeg sjelden ser er nevnt i det siste fordi det er blitt løst ved preprocessors som Sass og Mindre. Men jeg vil fortsatt liker å se det i denne serien.

Jeg vil liste opp noen teknikker for å håndtere disse utfordringene sammen med sine begrensninger i begge deler av denne serien. Ingen teknikk er bedre enn den andre, og de selv ikke er gjensidig utelukkende; du kan velge ett eller kombinere dem, avhengig av hva du velger vil forbedre kvaliteten på prosjektet.

Oppsett

Vi vil demonstrere forskjellige styling teknikker ved hjelp av et eksempel komponent kalt Bildet. Vi vil gjengi en forståelsesfull bilde som kan ha avrundede hjørner og viser alternative teksten som en bildetekst. Det vil bli brukt som dette:

<Bilde publicId=”ballonger” alt=”Varm luft ballonger!” avrundet />

Før du bygger den faktiske komponent, vil vi abstraherer bort srcSet-attributtet til å holde eksempel kode kort. Så, la oss lage en utils.js filen med to verktøy for å generere bilder av forskjellige bredder ved hjelp av Cloudinary:

import { Cloudinary } fra ‘cloudinary-core’

const cl = Cloudinary.nye({ cloud_name: ‘demo’, sikker: true })

eksport const getSrc = ({ publicId, bredde }) =>
cl.url(publicId, { crop: ‘skalaen’, bredde })

eksport const getSrcSet = ({ publicId, bredder }) => bredder
.kart(bredde => `${getSrc({ publicId, bredde })} ${bredde}w`)
.bli med(‘, ‘)

Vi setter opp våre Cloudinary eksempel å bruke navnet på Cloudinary ‘ s demo-cloud, så vel som dens url metode for å generere url-adresser for bildet publicId i henhold til det angitte valg. Vi er bare interessert i å endre bredden i denne komponenten.

Vi vil bruke disse verktøyene til src-og srcset attributter, henholdsvis:

getSrc({ publicId: ‘bobler’, bredde: 200 })
// => ‘https://res.cloudinary.com/demo/image/upload/c_scale,w_200/ballonger’

getSrcSet({ publicId: ‘bobler’, bredder: [200, 400] })
// => ‘https://res.cloudinary.com/demo/image/upload/c_scale,w_200/ballonger 200w,
https://res.cloudinary.com/demo/image/upload/c_scale,w_400/ballonger 400w’

Hvis du er ukjent med srcset og størrelser attributter, foreslår jeg at du leser litt om responsive bilder først. På den måten vil du ha en enklere tid å følge eksemplene.

CSS-i-JS

CSS-i-JS er en styling tilnærming som abstracts CSS-modellen til den komponent nivå, snarere enn dokumentet nivå. Denne ideen er at CSS kan knyttes til en bestemt komponent — og bare det-komponent — til den grad at de bestemte stiler er ikke delt med eller lekket til andre komponenter, og videre, kalt bare når det er nødvendig. CSS-i-JS bibliotek opprette stiler ved kjøring ved å sette <style> – kodene i <head>.

En av de første bibliotekene for å sette dette konseptet i bruk er JSS. Her er eksempel og ansette sin syntaks:

import Reagere fra “reagerer’
import injectSheet fra ‘reagere-jss’
import { getSrc, getSrcSet } fra ‘./utils’

const stiler = {
foto: {
bredde: 200,
‘@media (min-width: 30rem)’: {
bredde: 400,
},
borderRadius: rekvisitter => (rekvisitter.avrundet ? ‘1rem’ : 0),
},
}

const Bilde = ({ klasser, publicId, alt }) => (
<figur>
<img
className={klasser.foto}
src={getSrc({ publicId, bredde: 200 })}
srcSet={getSrcSet({ publicId, bredder: [200, 400, 800] })}
størrelser=”(min-width: 30rem) 400px, 200px”
/>
<figcaption>{alt}</figcaption>
</figure>
)
Foto.defaultProps = {
avrundet: false,
}

eksport standard injectSheet(stiler)(Bilde)

Ved første øyekast, stiler objektet ser ut som CSS skrevet i objekt-notasjon med flere funksjoner, som passerer en funksjon for å angi verdien basert på rekvisitter. Den genererte klasser er unike, slik at du aldri trenger å bekymre deg om dem kranglet med andre stiler. Med andre ord, du får scoping gratis! Dette er hvordan de fleste CSS-i-JS bibliotek arbeid — selvfølgelig med noen vendinger i funksjoner og syntaks som vi vil dekke mens vi går.

Du kan se av attributter som bredden av våre gjengitt bilde starter på 200px, så når viewport bredde blir minst 30rem, bredden øker til 400px bredt. Vi generert en ekstra 800 kilde for å dekke enda større skjerm tettheter:

  • 1x skjermer vil bruke 200 og 400
  • 2x skjermer vil bruke 400 og 800

stil-komponenter er en annen CSS-i-JS bibliotek, men med en mye mer kjent syntaks som en smart måte bruker merket mal verdiane i stedet for objekter å se mer ut som CSS:

import Reagere fra “reagerer’
import stylet, { css } fra ‘stylet-komponenter’
import { getSrc, getSrcSet } fra ‘./utils’

const mediaQuery = ‘(min-width: 30rem)’

const roundedStyle = css”
border-radius: 1rem;
`

const Bilde = stylet.img`
width: 200px;
@media ${mediaQuery} {
bredde: 400px;
}
${rekvisitter => rekvisitter.avrundet && roundedStyle};

const Bilde = ({ publicId, alt, avrundet }) => (
<figur>
<Bilde
src={getSrc({ publicId, bredde: 200 })}
srcSet={getSrcSet({ publicId, bredder: [200, 400, 800] })}
størrelser={`${mediaQuery} 400px, 200px`}
avrundet={avrundet}
/>
<figcaption>{alt}</figcaption>
</figure>
)
Foto.defaultProps = {
avrundet: false,
}

eksport standard Bilde

Vi oppretter ofte semantisk-nøytrale elementer som <div> og <span> utelukkende for styling formål. Dette biblioteket, og mange andre, la oss lage og stil dem i en enkel bevegelse.

Min favoritt nytte av denne syntaksen er at det er som vanlig CSS, minus interpolations. Dette betyr at vi kan overføre våre CSS-kode lettere og vi kommer til å bruke våre eksisterende muskel-minne i stedet for å gjøre oss kjent med å skrive CSS i objektet syntaksen.

Legg merke til at vi kan interpolere nesten alt i vår stiler. Dette konkret eksempel viser hvordan vi kan spare media query i variabelen og bruke det på flere steder. Responsive bilder er et utmerket eksempel på bruk for dette, fordi størrelser attributtet inneholder i utgangspunktet CSS, slik at vi kan bruke JavaScript for å gjøre koden mer TØRR.

La oss si at vi bestemte oss for at vi ønsker å visuelt skjule tekst, men likevel gjøre det tilgjengelig for skjermlesere. Jeg vet at en bedre måte å gjøre dette på ville være å bruke et alt-attributt i stedet, men la oss bruke en annen måte for å få til dette eksemplet. Vi kan bruke et bibliotek med stil mixins kalt polert — det fungerer bra med CSS-i-JS-bibliotek som gjør det flott for vårt eksempel. Dette biblioteket inneholder en mixin kalt hideVisually som gjør akkurat hva vi vil og vi kan bruke det ved å interpolere returverdien:

import { hideVisually } fra ‘polert’

const Caption = stylet.figcaption`
${hideVisually()};
`

<Caption>{alt}</Caption>

Selv om hideVisually utganger et objekt, stylet-komponenter library vet hvordan å interpolere det som stiler.

CSS-i-JS bibliotek har mange avanserte funksjoner som tematisere, leverandør prefixing og selv inlining kritisk CSS, noe som gjør det enkelt å slutte å skrive CSS-filer helt. På dette punktet, kan du begynne å se hvorfor CSS-i-JS blir et spennende konsept.

Ulemper og begrensninger

Den åpenbare ulempen med å CSS-i-JS er at den introduserer en runtime: stiler trenger å bli lagt inn, analyseres og utført via JavaScript. Forfatterne av CSS-i-JS bibliotek er å legge til alle typer smart optimalisering, som Babel plugins, men noen runtime kostnader vil likevel eksisterer.

Det er også viktig å merke seg at disse bibliotekene ikke blir lest av PostCSS fordi PostCSS var ikke designet for å bli brakt inn i runtime. Mange bruker stilfulle, i stedet som et resultat, fordi det er mye raskere. Dette betyr at vi dessverre ikke kan bruke PostCSS plugins.

Den siste ulempen jeg vil nevne er verktøy. CSS-i-JS utvikler seg på en virkelig rask hastighet og tekst-editor, extension, linters, kode-formatters etc. trenger å spille catch-up med nye funksjoner for å holde på linje. For eksempel, bruker folk VS Kode extension stylet-komponenter for lignende CSS-i-JS bibliotek som følelser, selv om de ikke alle har de samme funksjonene. Jeg har selv sett API valg av foreslåtte funksjonene blir påvirket av målet om å beholde syntaks utheving!

Fremtiden

Det er to nye CSS-i-JS bibliotek, Linaria og astroturf, som har klart null runtime ved å trekke CSS i filer. Deres Api-er lik stil-komponenter, men de varierer i funksjoner og mål.

Målet med Linaria er å etterligne API for CSS-i-JS bibliotek som stylet-komponenter ved å ha innebygde funksjoner som du ser, hekke-og leverandør prefixing. I motsatt fall, astroturf er bygget på CSS-Moduler, har begrenset interpolering evner, og oppfordrer til å bruke en CSS-økosystem i stedet for å utsette JavaScript.

Jeg bygget Gatsby plugins for både biblioteker hvis du ønsker å spille med dem:

  • gatsby-plugin-linaria
  • gatsby-plugin-astroturf

To ting å ha i bakhodet når du bruker disse bibliotekene:

  1. etter å ha selve CSS-filer, betyr at vi kan behandle dem med kjente verktøy som PostCSS
  2. Linaria bruker egendefinerte egenskaper (en.k.a. CSS-variabler) under panseret, være sikker på å ta sin nettleser støtter hensyn til før du bruker dette biblioteket

Konklusjon

CSS-i-JS er alt-i-ett-styling løsninger for å bygge bro over gapet mellom CSS og JavaScript. De er enkle å bruke og de inneholder nyttige innebygd optimaliseringer — men alle som kommer til en kostnad. Mest merkbart ved hjelp av CSS-i-JS, vi er egentlig ta ut fra CSS økosystem og godtar JavaScript for å løse våre problemer.

Null-runtime løsninger for å redusere noen av ulempene ved å bringe tilbake CSS-verktøy, som stiger CSS-i-JS diskusjonen til en mye mer interessant nivå. Hva er de faktiske begrensninger av preprosessering verktøy i forhold til CSS-i-JS? Dette vil bli omtalt i neste del av denne serien.

Artikkel-Serien:

  1. CSS-i-JS (Dette innlegget)
  2. CSS-Moduler, PostCSS og Fremtiden av CSS (Kommer i morgen!)