Sammenslåing av klassenavn på en god måte
Mange som lager ny nettside bruker Tailwind som rammeverk for styling. Én av utfordringene alle som har skrevet Tailwind har opplevd er å måtte slå sammen klasser dynamisk. Eksempelvis:
Utfordringen med dette kommer når man ikke bare har én variabel å forholde seg til, men mange. Eller når klassene man skal bruke betinget er mer komplekse:
Og kanskje man vil hente inn klassenavn fra en ovenliggende komponent?
Som du kanskje ser er det lagt til tomme mellomrom etter “p-4”
, “block”
og “hidden”
. Dette er for å passe på at den resulterende klassen er noe som: bg-white p-4 block text-yellow-500 leading-5
og ikke bg-white p-4blocktext-yellow-500
.
Etterhvert som bruken blir mer kompleks kan dette være vanskelig å holde styr på. Spesielt om du har veldig lange klassenavn, som er vanlig med Tailwind.
En løsning på dette er classnames biblioteket. Eller dens lettvektige lillebror clsx. La oss ta utgangspunkt i clsx for resten av artikkelen.
Vi kan skrive om koden over på to forskjellige måter med vårt nye verktøy:
clsx (og classnames) fikser automatisk mellomrom for oss, og er meget fleksibel på inputten vi sender inn. Det er f.eks. ikke noe problem om «classNames» er undefined.
Så da er alt bra, eller?
Problemer med sammenslåing konflikterende klassenavn
En utfordring oppstår når vi prøver å slå sammen klasser som gir lignende instruksjoner:
Hva forventer du at paddingen på MyComponent
sin div er? Om du er som meg tenker du at, vel, det resulterende klassenavnet i MyComponent
blir bg-white p-4 hidden text-black p-6
, og da blir paddingen i p-6
(padding: 1.5rem;
) anvendt, ja?
Nei. Slik som HTML og CSS fungerer vil p-4
være den dominerende paddingen, og overskrivingen vår av defaultverdien vil ikke fungere.
Åpenbare løsninger på dette problemet kommer fort til kort når man må håndtere mer kompliserte tilfeller som p-4 px-2 pb-3 p-5 py-3
.
Heldigvis finnes det et bibliotek for dette: tailwind-merge. Tailwind-merge ligner litt på classNames og clsx i måten det tar input på:
Utfordringen med tailwind-merge er derimot at det ikke er like fleksibelt på hva det tar imot av input, og kan f.eks. ikke håndterer javascript objekter som vi brukte over:
Løsningen
Så hva er løsningen på begge våre problemer? Jo, å slå sammen twMerge
og clsx:
Endrer vi nå komponenten vår til:
Er vi i mål. Komponenten vises med p-6
some førende padding, og alle klassenavn blir slått sammen på riktig måte.