Hvorfor din «perfekte» knapp egentlig skjuler en bommert
Div-en som ville være en knapp
Alle som har jobbet med komponentbiblioteker har opplevd det. Du trenger en knapp med spesiell styling, et unikt hover-effekt, kanskje en gradient som forandrer seg når brukeren klikker. Så du griper tak i en <div>, kaster på litt CSS, og tenker at du er ferdig.
I Figma ser det perfekt ut. Det fungerer i demoen din. Men så prøver en ekte bruker å navigere med tab-tasten, sender inn et skjema med tastaturet, eller surfer med skjermleser – og alt faller fra hverandre.
Problemet er ikke CSS-en din. Problemet er at du ba en <div> om å utføre et arbeid den aldri var designet for.
Renten på dårlige avgjørelser
Her er hva som typisk skjer: du trenger en knapp med et spesifikt utseende. Du lager en <div>, legger til class="btn", og styler den til den matcher designet. Det ser flott ut. Men så trenger du at den faktisk oppfører seg som en knapp.
Så du legger til en click-handler. Deretter hover-state. Deretter focus-ring for tastaturbrukere. Så innser du at Space og Enter ikke fungerer, så du legger til keydown-lyttere. Knappen må kunne være deaktivert, så du legger til en .disabled-klasse som forhåpentligvis blokkerer alle de riktige interaksjonene. Og et sted derimellom legger du til role="button" og tabindex="0" for å sørge for at tilgjengelighetsverktøy i det minste ikke fullstendig ignorerer det du har laget.
Gratulerer. Du har bygget et knapp-formet objekt som krever omtrent 200 linjer med JavaScript for å approximere det nettleseren ville gitt deg gratis.
Dette er det vi mener når vi snakker om "å betale husleie" på dårlige arkitektoniske avgjørelser. Hver linje med workaround-kode er renter på det opprinnelige valget om å bruke feil element.
Den usynlige kontrakten
Det er én ting med native HTML-elementer: de kommer med en hel interaksjonskontrakt som de fleste utviklere aldri tenker på før den mangler.
Når du bruker en ekte <button>, får du:
- Automatisk tastaturhåndtering — Enter og Space fungerer akkurat som brukerne forventer
- Skikkelig focus-håndtering — Den kommer naturlig inn i tab-rekkefølgen, kan fokuseres programmatorisk
- Deaktivert tilstand — Blokkerer all interaksjon, blir ufokusérbar, blir annonsert som deaktivert
- Skjemadeltakelse — Sender inn skjemaer, respekterer skjemavalidering, deltar i form.reset()
- Tilgjengelighetssemantikk — Skjermlesere annonserer den som en knapp uten ekstra ARIA
- Plattformkonvensjoner — Brukerne vet allerede hvordan knapper oppfører seg fordi knapper oppfører seg konsekvent overalt
Med en <div> kledd som en knapp får du... CSS-en. Alt annet er opp til deg å implementere. Og her er den smutsige hemmeligheten: uansett hvor grundig du er, vil din implementasjon være dårligere enn det nettleserne tilbyr. Nettlesere har team av ingeniører som optimaliserer disse atferdene på tvers av plattformer, edge cases, og hjelpeteknologier. Din egendefinerte knapp har bare deg.
Det egentlige spørsmålet er ikke "kan jeg style den?"
Dette er der design-ingeniør-samarbeid enten skinner eller skaper teknisk gjeld. Utviklere tolker ofte "semantisk HTML" som "å akseptere nettleserens stygge standardutseende". Det er ikke det vi snakker om i det hele tatt.
Spørsmålet er ikke "kan jeg få dette til å se egendefinert ut?" Det kan det absolutt bli. Spørsmålet er: "hvilke native oppførsel bør overleve stylingen?"
En <button> kan ha hvilken visuell behandling som helst. Du kan fjerne all standard styling med appearance: none. Du kan legge til gradients, skygger, animasjoner, egendefinerte fonter – hva som helst designen krever. Nettleserens interaksjonskontrakt bryr seg ikke om hvordan knappen din ser ut.
Det du derimot ikke enkelt kan gjøre med en <div> er kopiere det nettleseren gir deg automatisk. Så velg dine kamper: bruk ingeniørarbeidet ditt på det som gjør produktet ditt unikt, ikke på å oppfinne knappen på nytt.
Bygge for det virkelige nettet
Brukerne dine bruker ikke produktet ditt i et vakuum. De taber mellom felter mens hendene er på tastaturet. De bruker talestyring til å navigere. De forstørrer skjermen til 300% fordi det er det som fungerer for dem. De har forskjellige nettlesere, forskjellige operativsystemer, forskjellige hjelpeteknologier.
Nettplattformen gir deg et massivt forsprang med semantisk HTML. Native elementer er tilgjengelige som standard, tastaturnavigérbare som standard, tvers av plattformer som standard. Når du kjemper mot den infrastrukturen, lager du ikke bare mer arbeid for deg selv – du skaper komponenter som vil feile på subtile måter for virkelige brukere.
Neste gang du er i ferd med å strekke deg etter en <div> med role="button", spør deg selv: bygger jeg noe som genuint trenger en egendefinert implementasjon, eller er jeg bare redd for <button>-taggen? For den kjedelige løsningen er vanligvis den riktige. Og "nettleseren håndterer det korrekt" er en funksjon, ikke en begrensning.
Det semantiske nettet handler ikke om å følge regler. Det handler om å bruke verktøyene som ble bygget for jobben – og bruke energien din der den faktisk utgjør en forskjell.