piksler på nært hold, glatt langt unna

8. september 2026 meta designpixelart

Det finnes to typer tegning på denne siden og de får aldri lov til å røre hverandre. Den regelen høres skjør ut når jeg skriver den sånn, men det er det som faktisk fikk headeren og bakgrunnen til å slutte å kjempe om oppmerksomheten.

problemet den løser

Tidlig ble alt på siden tegnet på samme måte: pikselgrid-sprites, harde kanter, én SVG <rect> per celle. Fjellet i headeren, fuglene, alt sammen. Så fint ut på nært hold og helt flatt så snart du la til noe som skulle sitte lenger tilbake, som en bakgrunnssilhuett bak tekstkolonnen. Klumpete piksler som skal lese som "fjernt fjell i disen" fungerer ikke, avstand i faktisk syn er mykt, ikke klosset. Men å gå helt glatt overalt drepte det jeg faktisk likte med pixel arten i utgangspunktet, som er at den leser som bevisst og håndlaget i stedet for en lager-vektorillustrasjon.

Fiksen var ikke å velge én stil. Det var å bestemme, med vilje, hvilke elementer som får være skarpe og hvilke som får være myke, og aldri la et element skreve over begge.

nært hold: alt du ser rett på

Header- og footer-horisontstripene, de bitte små navigasjonsglyfene ved siden av hver seksjonslenke, BMK-monogrammets fjellmerke, 404-lunden, måne/sol-ikonene på temabryteren, og hver fugl og fisk som faktisk flyr eller svømmer over himmelen og strandlinjen. Alt pikselgrid. Alt bygget på samme måte: jeg skisserer formen som et ASCII-grid i en kommentar øverst i komponenten først, ett tegn per celle, før jeg skriver en eneste linje SVG:

//   ......................RRR.MM.....................
//   .....................RRRRRMM.....................
//   .....................RRRRRR.....................
//   ....................RRRRRRRR.....................

Det er den faktiske toppen av den høye header-horisonten, R for stein, . for åpen himmel, M for månen som bare vises i mørk modus. Når grid-et først leser riktig som ASCII, konverterer jeg det til sammenslåtte <rect>-strekk (tilstøtende celler med samme farge i en rad slås sammen til én bredere rect i stedet for én per celle, som holder DOM-en fra å bli oppblåst på et 48-kolonners grid) med preserveAspectRatio="none" slik at hele stripen strekker seg til å fylle beholderen sin fra kant til kant uten noensinne å flyte over på en rar skjermbredde.

Nært hold: den skarpe pikselgrid-horisonten i headeren

langt unna: alt som skal sitte tilbake

Bakgrunnsøysilhuetten er det motsatte av alt det der. Det er én sammenhengende form, sporet med kubiske Bezier-kurver fra et faktisk referansebilde jeg tok av Lovundfjellet, ikke skissert celle for celle:

const MOUNTAIN_PATH =
	'M145,300' +
	'C160,250 175,210 195,180' +
	'C210,158 225,140 240,133' +
	'C258,140 275,155 290,170' +
	'C305,195 320,225 335,260' +
	...

Samme faktiske fjell, samme ekte topunkts-profil (jeg sporet faktisk pikselversjonen først, ved akkurat de samme kolonne- og rad-koordinatene, og konverterte deretter de festepunktene til glatte kurver for denne runden i stedet for å starte helt på nytt) men rendret som én myk masse i stedet for et trappet omriss. Sitter bak innholdskolonnen ved lav opasitet, det leser som atmosfære, slik et ekte fjell gjør når det er en bygd og en strekning vann mellom deg og det. Nattens stjernebildelag fungerer på samme måte, ekte stjerneposisjoner, men tegnet som myke, fylte sirkler i stedet for pikselkvadrater, fordi et "fjernt" stjernefelt laget av harde pikseldotter ville sett ut som en bug, ikke en himmel.

Langt unna: samme fjell som en myk silhuett bak innholdskolonnen

hvorfor linjen betyr noe

Regelen jeg holder meg selv til er at ingenting skrever over begge registrene. En fuglesprite er enten en pikselcelle-fugl som flyr over det nære laget eller en glatt silhuett som sirkler bakgrunnsøya, aldri halvparten av hver. I det øyeblikket du blander dem innenfor ett element klarer ikke øyet ditt å bestemme seg for hvor langt unna tingen skal være, og hele dybdeillusjonen kollapser. Det er et billig triks når du først ser det: skarpe ting leser nært, myke ting leser fjernt, og du trenger ikke faktisk parallakse eller uskarphetsfiltre for å selge "avstand," du trenger bare konsistent behandling per element og å aldri bryte din egen regel halvveis.

Jeg brøt den akkurat én gang, tidlig i redesignet, tegnet en myk bakgrunnsfugl med et par harde pikselaksenter på vingespissen fordi jeg trodde det ville "forankre" silhuetten litt.

<!-- what I tried: smooth silhouette body, pixel-square wingtip accents -->
<path d={SILHOUETTE_PATH} class="soft-fill" />
<rect x="34" y="12" width="2" height="2" class="pixel-accent" />
<rect x="36" y="12" width="2" height="2" class="pixel-accent" />

Det så bare ut som en rendringsbug, som en ressurs som feilet under lasting. Tok aksentene ut igjen i løpet av samme økt da jeg så på det igjen neste morgen med friske øyne, tilbake til én sammenhengende myk-fyll-sti og ingenting annet som rørte den.

delen jeg ikke forventet

Jeg gikk inn i dette og tenkte på det som et rent visuelt triks, nært versus fjernt, forgrunn versus bakgrunn. Det som faktisk overbeviste meg om å holde regelen streng er at den også matcher hvordan oppmerksomhet fungerer på siden. De nære-register-elementene er alle ting jeg vil at en lesers øye faktisk registrerer som innholdsnær detalj, navigasjonsglyfene som forteller deg hvilken seksjon du er i, fuglene som gir siden liv. Det fjerne-register-stoffet er eksplisitt dekorativt, aria-hidden, pointer-events: none, ment å føles i stedet for å ses på. Å holde de to visuelt distinkte viste seg også å holde dem funksjonelt distinkte, som jeg ikke planla for, men er glad skjedde likevel.

kontrast får ikke lov til å ignorere bakgrunnen heller

Å ha en myk silhuett sittende rett bak brødtekst lenger ned på siden skapte et ekte tilgjengelighetsspørsmål jeg ikke hadde tenkt helt gjennom før jeg kom til å sjekke det ordentlig: hva nøyaktig blir tekstkontrasten målt mot. Sidebakgrunnen her er en gradientvask nær toppen som toner mot en flat farge, og øyskyggen selv sitter bak lesbar tekst lenger ned på siden, så å sjekke kontrast mot bare den flate bakgrunnsfargen ville sjekket helt feil ting. Jeg endte opp med å måle mot de faktiske sammensatte tonene tekst kan rendres over, vaskens lyseste punkt og øyskyggefargen spesifikt, ved bruk av den ekte relative-luminans-beregningen i stedet for å eyeballe det, og holde begge til de vanlige WCAG AA-gulvene, 4,5 til 1 for brødtekst, 3 til 1 for stor tekst og interaktive elementer. De rent dekorative tokenene, månedsmarkørene, steinfargen, månen, er eksplisitt unntatt fra det kravet, siden ingen av dem bærer informasjon som ikke allerede sitter i lesbar tekst et annet sted på samme side. Avstand som visuelt triks er én ting. Avstand som unnskyldning for å la en bakgrunnssilhuett ødelegge en lesers evne til faktisk å lese ordene foran seg er noe helt annet, og jeg var ikke villig til å la tosregister-ideen være grunnen til at det skjedde.

0 kommentarer

Logg inn for å kommentere.

Logg inn

Ingen konto?