Webbutveckling · område 5
Guide – Responsiv design och tillgänglighet
Här står allt som prov 3 kan fråga om, och allt du behöver för Projekt 4. Guiden fungerar utan att du varit på lektionen. Avsnitt 1 till 6 följer områdets sex genomgångar i tur och ordning.
Exemplen är hämtade ur referensprojektet Fyrar längs Bohuskusten – samma sajt
som i område 3, nu responsiv och tillgänglig. Ha referensprojektets stil.css
öppen bredvid guiden. Den är indelad i tio numrerade avsnitt, och varje ändring som hör
till det här området är märkt med passets nummer, Pass 36 till Pass 40.
Vad ett WCAG-kriterium betyder, vem det gäller och vilken nivå det har lär du dig i Gränssnittsdesign. Verktygens gränser och användartestet likaså. Guiden visar raden i koden som uppfyller kravet, och säger i en mening var resten står.
Vad du kan efter guiden
- Förklara vad viewport-taggen gör, och varför den ska stå exakt som den står
- Bygga mobile first: en grundstil för telefonen som bredare skärmar lägger till på
- Skriva en media query med
min-widthiem, och hitta brytpunkten i innehållet i stället för i en lista över telefoner - Göra bilder flexibla, och ge rätt fil till rätt skärm med
srcsetochsizes - Stänga av rörelse för den som bett om det, med
prefers-reduced-motion - Hålla en kodstandard som gör att någon annan hittar i din stilmall
- Peka på raden i koden som rättar ett tillgänglighetsfynd: fokus, kontrast, klickyta, rubriknivå, knapp
- Skriva ett testprotokoll där varje rad går att göra om
1. Viewport och mobile first
Responsiv design betyder att samma sida, med samma HTML, fungerar i alla bredder: från en smal telefon till en bred datorskärm. Du bygger inte en mobilsajt och en datorsajt. Du bygger en sajt som tål att utrymmet ändras.
Viewport-taggen och bredderna 320 till 1600 px är ska-krav, nivå E. Mobile first är ett bör-krav, nivå C.
Viewport-taggen
Viewport är den yta sidan ritas på. På en dator är den fönstret. På en telefon som inte fått några instruktioner är den ungefär 980 pixlar bred, och sidan krymps sedan ihop för att få plats. Det var så de första smarta telefonerna visade en webb som bara var byggd för datorer. Resultatet är en sida du ser i sin helhet men inte kan läsa, med länkar för små för att träffa.
En rad i head talar om för telefonen att låta bli:
<meta name="viewport" content="width=device-width, initial-scale=1">
| Del | Betyder |
|---|---|
width=device-width | Rita sidan lika bred som skärmen, inte 980 px |
initial-scale=1 | Börja utan förstoring eller förminskning |
Den ska stå i head på varje sida, inte bara på startsidan.
Referensprojektet har haft den sedan område 2. Nu är det den som gör skillnaden.
På nätet finns ofta en längre variant med user-scalable=no eller
maximum-scale=1. Båda stänger av förstoring med två fingrar, och den som
behöver förstora mest kan då inte göra det. Det är ett tillgänglighetsfel i en enda
rad, och uppgiften förbjuder det. Varför förstoring är ett krav i WCAG gick
Gränssnittsdesign igenom den 18 januari.
Varför sajten redan nästan fungerar
Mycket av det du byggde i område 3 är responsivt redan, eftersom flexbox och grid är gjorda för att tåla att utrymmet ändras:
| Det som fungerar i 320 px | Varför | Läs om det |
|---|---|---|
| Navigeringen bryter till nya rader | flex-wrap: wrap |
Guide CSS, avsnitt 8 |
| Galleriet blir en spalt | repeat(auto-fit, minmax(16rem, 1fr)) räknar ut antalet |
Guide CSS, avsnitt 9 |
| Bilderna krymper med skärmen | max-width: 100% |
Avsnitt 3 |
| Tabellen spräcker inte sidan | .tabellsvep med overflow-x: auto |
Referensprojektets stil.css, avsnitt 9 |
| Textstorleken följer användaren | rem i stället för
px |
Guide CSS, avsnitt 6 |
Det som går sönder
Det som går sönder i en elevsajt är nästan alltid något som låser en bredd:
width: 900pxpå en behållare. Byt tillmax-width, så får den bli smalare men aldrig bredare.- En bild utan
max-width. Se avsnitt 3. - En rubrik med teckenstorlek i
px. - En lång adress eller ett långt ord utan mellanslag, som inte kan radbrytas.
Det sista lagas med en regel som referensprojektet har i avsnitt 2 av
stil.css:
p, li, dd, td {
overflow-wrap: break-word;
}
Den tillåter webbläsaren att bryta mitt i ett ord när ordet annars inte får plats. Vanliga ord påverkas inte.
Mobile first
Mobile first betyder att grundstilen, alltså reglerna utanför alla media queries, är telefonens. Bredare skärmar lägger till. Motsatsen är att bygga för datorn och sedan ta bort saker för telefonen.
Referensprojektets navigering är staplad som grundstil, en länk per rad:
nav ul {
display: flex;
flex-direction: column;
gap: var(--steg-1);
list-style: none;
margin: 0;
padding: 0;
}
En länk per rad ger stora ytor att träffa med tummen. Hur den blir en rad igen på bredare skärmar står i avsnitt 2.
Det smala fallet är oftast det enkla: en spalt, allt under varandra, i den ordning
HTML:en redan har. Det är när det blir brett som du behöver bestämma något. Hur sajten
ska se ut i olika bredder bestämde du redan i mockupen i Gränssnittsdesign. Visar den
inte något, till exempel menyn på telefon, bestämmer du själv och skriver det i
dokumentation.md.
Device mode och den riktiga telefonen
Device mode är ett läge i webbläsarens utvecklarverktyg, DevTools, som ritar sidan som på en telefon. Öppna med F12 och sedan Ctrl + Shift + M.
- Bredden går att dra i. Handtaget i kanten ger vilken bredd som helst.
- Bredden står i pixlar överst. Den siffran behöver du för brytpunkterna.
- 320 px är den smalaste bredd uppgiften kräver. Varför just 320 är ett WCAG-kriterium som Gränssnittsdesign gick igenom den 18 januari.
Device mode visar bredden. Det visar inte fingret, inte solen i skärmen och inte bilden som laddar över mobilnätet. Därför testar du både i device mode och på en riktig telefon, med sajtens publicerade adress.
Kontrollera att viewport-taggen finns på varje sida. Öppna sajten i device mode, börja
på 320 px och dra långsamt upp till 1600. Öppna sedan den publicerade adressen på din
telefon. Skriv upp allt som går sönder – sida, bredd eller telefon, vad som händer –
innan du lagar något. Listan hör hemma i dokumentation.md; mallen står i
avsnitt 6.
2. Media queries och brytpunkter
Det viktigaste i avsnittet är hur få media queries som behövs. Två eller tre, och var och en med ett skäl. Referensprojektet har två för hela sajten.
Minst en media query med min-width är ett ska-krav, nivå E. Att
varje brytpunkt har ett skäl i innehållet är ett bör-krav, nivå C.
Syntaxen
En media query är en fråga till webbläsaren om omgivningen: hur bred är ytan, vill användaren ha mindre rörelse. Är svaret ja gäller reglerna inuti.
@media (min-width: 56em) {
.sidlayout {
grid-template-columns: minmax(0, 3fr) minmax(0, 1fr);
}
}
| Del | Vad den gör |
|---|---|
@media | Inleder frågan |
(min-width: 56em) | Villkoret: minst så här brett |
{ … } | Vanliga regler, med egna klamrar inuti |
Läs den högt: är fönstret minst 56em brett, gör kolumnerna så här. Under den bredden finns regeln inte. En brytpunkt, på engelska breakpoint, är bredden där en media query börjar gälla.
Lägg märke till de dubbla klamrarna: en för media queryn, en för regeln. Saknas den sista hamnar resten av stilmallen inuti media queryn. CSS-validatorn hittar det. Ögat gör det sällan.
min-width, inte max-width
| Skrivsätt | Läses | Passar |
|---|---|---|
min-width | Från den här bredden och uppåt | Mobile first: grundstilen är smal, bredd läggs till |
max-width | Upp till den här bredden | Desktop först: grundstilen är bred, saker tas bort |
Varje brytpunkt med max-width tar bort något som redan är satt, och du
måste hålla reda på vad det var. Med min-width lägger du bara till, och
grundstilen står orörd. Blanda inte: finns det en bredd där både en
min-width och en max-width gäller samtidigt blir det svårt att
förutse vad som vinner. Välj riktning en gång.
Brytpunkten sitter i innehållet
Brytpunkten ska sitta där innehållet går sönder, inte där en viss telefon eller surfplatta börjar. Sajten vet inte vilken enhet den visas i, bara hur mycket plats den har. Så här hittar du den:
- Öppna sidan i device mode på 320 px.
- Dra långsamt bredare och titta på innehållet, inte på siffran.
- Stanna där något ser fel ut, eller där det finns plats för något bättre.
- Läs av bredden. Det är brytpunkten.
Frågor att ställa medan du drar:
- Blir raderna för långa att läsa? Då får en spalt till plats.
- Bryts orden ett och ett? Då är brytpunkten för låg.
- Rullar sidan i sidled? Då har något en fast bredd, och det lagas utan media query.
I referensprojektet gav metoden två brytpunkter. Navigeringen vid 28em: där ryms alla fyra länkarna på en rad, och staplingen slösar bara höjd. Sidlayouten på Vinga-sidan vid 56em: under den blir faktarutan i en fjärdedels spalt så smal att raderna får några få ord var.
Galleriet behöver ingen brytpunkt. auto-fit räknar ut antalet kolumner i
alla bredder. Varför det håller även i bredder ingen testat står i
avsnitt 7.
Du kommer att vilja skriva 768, för att du sett den siffran. Fråga dig vad som går sönder vid 767 pixlar. Kan du inte svara är det inte en brytpunkt. Mockupens bredder, 360 och 1280, är inte heller brytpunkter – de är bredderna den ritades i.
Brytpunkter i em
Brytpunkter skrivs i em, inte i px. I en media query räknas
em mot webbläsarens grundstorlek, 16 px om användaren inte ändrat den. Dela
bredden du läste av med 16:
| Avläst bredd | Uträkning | Brytpunkt |
|---|---|---|
| 448 px | 448 / 16 | 28em |
| 640 px | 640 / 16 | 40em |
| 896 px | 896 / 16 | 56em |
Skälet: har användaren ställt in större text i webbläsaren flyttar brytpunkten med.
Layouten byter till en spalt när texten inte längre ryms. Med px står
brytpunkten still medan texten växer. Det är samma argument som för rem på
text i område 3, en nivå upp.
Media queryn står i avsnittet den ändrar
Media queryn skrivs direkt efter reglerna den ändrar, i samma avsnitt av
stil.css – inte samlad i slutet av filen. Den som ska ändra navigeringen
letar i avsnittet om navigeringen. Så här står den i referensprojektets avsnitt 6:
nav ul {
display: flex;
flex-direction: column;
gap: var(--steg-1);
list-style: none;
margin: 0;
padding: 0;
}
/* 28em: här ryms alla fyra länkarna på en rad. Staplade tar de fyra rader höjd för
ingenting, och sidans innehåll hamnar under kanten på en liggande telefon. */
@media (min-width: 28em) {
nav ul {
flex-direction: row;
flex-wrap: wrap;
gap: var(--steg-1) var(--steg-3); /* rad, kolumn */
}
}
Kommentaren är halva regeln. Den säger vad som gick sönder utan brytpunkten, och det
är just det bör-kravet frågar efter. flex-wrap står kvar för bredderna
precis över 28em, där länkarna ännu inte ryms på en rad.
Laga utan media query först
Gå igenom listan över det som går sönder uppifrån, och försök laga varje fel utan media query. Bara om det inte går lägger du till en brytpunkt.
- Fasta bredder bort.
width: 900pxblirmax-width. Många fel försvinner här. - Grundstilen smal. Det som bara ska gälla bredare fönster flyttas in i en
media query med
min-width. - Dra i fönstret och hitta var layouten behöver byta. Läs av, dela med 16.
- Skriv kommentaren ovanför varje media query: vad som går sönder utan den.
- Dra från 320 till 1600 igen. Ingen vågrät rullning, ingen text som klipps.
Räkna dina media queries. Är de fler än tre, välj en och ta bort den tillfälligt. Dra i fönstret. Gick något sönder? Om inte behövdes den inte.
3. Flexibla bilder och media
En bild ska vara flexibel i layouten och rätt storlek i nätverket. Det är två olika saker, och de löses med olika kod.
Flexibla bilder med fungerande alt-text är ska-krav, nivå E. Flera
bildstorlekar med srcset, sidvikten mätt före och efter, och
prefers-reduced-motion är bör-krav, nivå C. picture med
olika beskärning är en utmaning, nivå A, och står i
avsnitt 7.
max-width och height: auto
Referensprojektet har regeln på alla bilder, inte bara på bilderna i
figure som i område 3:
img {
display: block;
max-width: 100%;
height: auto;
}
| Deklaration | Gör |
|---|---|
max-width: 100% | Bilden blir aldrig bredare än sin behållare |
height: auto | Höjden räknas om så att proportionerna behålls |
display: block | Tar bort glipan under bilden. En bild står annars på textens baslinje |
Utan height: auto krymper bilden på bredden men behåller höjden från
height-attributet, och blir hoptryckt. Attributen width och
height i HTML:en ska ändå stå kvar: de talar om bildens proportioner innan
den laddats, så att sidan inte hoppar. CSS:en bestämmer hur stor den faktiskt blir.
Skriv max-width, inte width: 100%. Med width
sträcks också små bilder ut till full bredd, och blir suddiga.
srcset och sizes
max-width gör bilden liten på skärmen. Den gör inte filen mindre. En
telefon som visar en bild 360 pixlar bred kan ändå hämta en fil som är 1600 pixlar bred,
och det betalar den som är på mobilnätet för.
srcset är en lista med samma bild i flera bredder.
sizes talar om hur bred bilden kommer att visas. Med de två
uppgifterna väljer webbläsaren själv vilken fil den hämtar. Så här står fotot på
vinga.html:
<img src="bilder/vinga-960.jpg"
srcset="bilder/vinga-480.jpg 480w,
bilder/vinga-960.jpg 960w,
bilder/vinga-1200.jpg 1200w"
sizes="(min-width: 40em) 36rem, 100vw"
width="960" height="640"
alt="Vinga fyr, ett grått stentorn på en kal klippa, med öppet hav bakom.">
| Del | Betyder |
|---|---|
480w | Den här filen är 480 pixlar bred. w
står för bredd |
sizes | Från 40em och uppåt visas bilden 36rem bred, annars hela fönstrets bredd |
100vw | 100 procent av fönstrets bredd.
vw står för viewport width |
src | Reserv för webbläsare som inte kan
srcset |
Filerna ligger i mappen bilder, samma bild i tre bredder:
bilder/
vinga-480.jpg 480 px bred
vinga-960.jpg 960 px bred
vinga-1200.jpg 1600 px bred
vinga-smal.jpg 480 × 600, beskuren kring tornet (till picture)
kustkarta.svg vektorbild, behöver ingen srcset
Kartan är en SVG, en vektorbild. Den skalas utan att bli suddig och finns bara i en
fil. srcset behövs för fotografier och andra rasterbilder.
Pixeltätheten
Det som brukar förvåna: webbläsaren räknar med skärmens pixeltäthet. En telefon med dubbelt så tätt mellan pixlarna hämtar en fil ungefär dubbelt så bred som visningsbredden. Därför säger uppgiften att stora bilder ska finnas i högst dubbla visningsbredden. Vill du se det själv: byt pixeltäthet i device mode, ladda om och titta i nätverksfliken vilken fil som hämtas.
sizes och CSS:en hör ihop
Måttet i sizes ska stämma med CSS:en. I referensprojektet står det i
avsnitt 5:
.foto {
width: auto;
max-width: 36rem;
}
Ändras det ena måste det andra ändras också, annars hämtar webbläsaren fel fil. Saknas
sizes helt antar webbläsaren att bilden är lika bred som fönstret, och
hämtar en för stor fil på datorn.
Mät sidvikten före och efter
Sidvikten är hur mycket data sidan hämtar. Mät den så här:
- Device mode, telefonbredd. Öppna fliken Network (nätverk) i DevTools.
- Kryssa i Disable cache. Utan den hämtas ingenting andra gången, och siffran ser bättre ut än den är.
- Ladda om och läs av summan för överförd data längst ned. Det är före.
- Exportera din tyngsta bild i två eller tre bredder och skriv
srcsetochsizes. - Ladda om och läs av igen. Det är efter. Båda siffrorna förs in i testprotokollet.
I referensprojektets protokoll hämtar telefonen fotot som en fil på 14 kB i stället för 68 kB. Format och komprimering gick Gränssnittsdesign igenom i augusti, och står i din exportlogg från bildpaketet.
alt sitter på img
altsitter alltid påimg, även medsrcsetoch inutipicture.sourcehar ingen.- Samma alt-text gäller alla filer. Webbläsaren väljer fil, inte du. Skriv texten för det alla varianterna visar.
- Dekor får
alt="", som i område 2. Tom alt säger att bilden inte säger något, och skärmläsaren hoppar över den.
Om en alt-text fungerar – säger det bilden säger där den står – prövade du i WCAG-granskningen i Gränssnittsdesign den 18 januari. Ta fynden därifrån.
Video, ljud och transkript
Undertexter läggs in med <track kind="captions"> inuti
video, som i område 2,
avsnitt 6. Ett nytt tillägg är ett transkript: ljudets innehåll utskrivet som
vanlig text på sidan. Det går att läsa utan uppspelning, och det går att söka i.
Har sajten ingen video och inget ljud skriver du det i dokumentation.md,
med status Inte tillämpligt. Då är kravet uppfyllt. Fyrsajten gör så.
prefers-reduced-motion
prefers-reduced-motion är en media query som frågar om användaren bett
sitt system om mindre rörelse. En transition är en mjuk övergång mellan två
lägen, här knappens färg vid hover. Referensprojektets avsnitt 8:
.knapp {
transition: background-color 0.2s;
}
@media (prefers-reduced-motion: reduce) {
.knapp {
transition: none;
}
}
Den som bett om mindre rörelse får ingen övergång alls – bytet sker direkt. En färg som tonar är knappt rörelse; regeln står här för att visa mönstret. Det som verkligen behöver den är sådant som flyttar sig: menyer som glider in, sidor som scrollar mjukt. Vem som behöver det och var inställningen finns går Gränssnittsdesign igenom den 21 januari.
Har sajten inga övergångar eller animationer gäller inte kravet. Har den det, ska varje
en ha sin prefers-reduced-motion.
Mät sidvikten på din startsida innan du ändrar något, och skriv upp siffran. Utan en
före-siffra finns inget efter. Skriv sedan srcset och sizes
för din tyngsta bild och mät igen.
4. God praxis och kodstandard
Avsnittet lär inte ut något nytt i HTML eller CSS. Det handlar om hur koden ser ut för den som ska läsa den. Webbläsaren läser vad som helst så länge det är giltigt; koden skrivs för webbläsaren en gång och för människor varje gång den öppnas igen.
Att stilmallen följer kodstandarden och är kamratgranskad är ett bör-krav, nivå C.
Varför det spelar roll
- I mars börjar slutprojektet. Specifikationen har en rad för filstruktur och namngivning, och det du bestämmer nu skriver du in där.
- Under våren arbetar en del i par. Den andras stilmall blir din att ändra i.
- I juni läses koden vid bedömningen, och kunden kan behöva någon som tar över.
Du kommer att öppna din egen kod i maj och inte känna igen den. Det händer alla. Frågan är om den går att läsa ändå.
Kodstandarden
| Regel | Exempel | Varför |
|---|---|---|
| 2 mellanslag indentering | två mellanslag före
display: flex; |
Samma i alla filer, oavsett redigerare |
| Gemener i filnamn | vinga.html, inte
Vinga.html |
Pages skiljer på stora och små bokstäver, Windows gör det inte |
| Bindestreck, inga mellanslag | alla-fyrar.html, inte
alla fyrar.html |
Mellanslag blir %20 i adressen |
index.html som startsida | index.html i
roten |
Det är filen servern visar när ingen fil anges |
| Relativa sökvägar | bilder/vinga-960.jpg |
Fungerar både på datorn och på Pages |
Regel två känner du igen från område 2: ett filnamn med stor bokstav fungerar på datorn och ger 404 på telefonen. Se guiden till område 2, avsnitt 10.
Filstrukturen
Referensprojektets sidor ligger i roten, bilderna i en egen mapp, och det finns en stilmall:
index.html
fyrarna.html
vinga.html
rapportera.html
tack.html
stil.css
dokumentation.md
bilder/
Inga filer som heter stil2.css, ny.html eller
test.html. Gamla försök som ligger kvar i repot publiceras på Pages, och
kan hittas av vem som helst.
Namngivning
Regeln från område 3 gäller: namnge en klass efter vad den är, inte var den står. Två saker läggs till.
Konsekvens. Välj ett språk och ett skrivsätt, och håll det i hela filen. Gemener och bindestreck gäller klasser och variabler också, av samma skäl som filnamnen.
| Rörigt | Konsekvent |
|---|---|
.knapp, .card, .InfoBox |
.knapp, .kort, .faktaruta |
--mainColor, --text_dov |
--accent, --text-dov |
Namn som går att söka på. .k1 och .ruta2 hittar
ingen. Den som söker efter faktaruta ska hitta regeln. Måste du läsa CSS:en för
att förstå vad en klass gör är namnet fel.
Avsnitt
Dela in stilmallen i numrerade avsnitt, i en ordning som går att förklara. Så här börjar avsnitt 6 i referensprojektet:
/* ---------- 6. Flexbox (pass 23, 36, 37, 40) -------------------------------
Navigeringen. Staplad på telefon, en rad från 28em. */
Hela stilmallen går från det allmänna till det särskilda:
| Avsnitt | Innehåll |
|---|---|
| 1. Variablerna | Färger, typsnitt och avstånd i :root |
| 2. Grunden | box-sizing, body, bilderna |
| 3. Typografi och färg | Rubriker, stycken, kod |
| 4. Selektorer och kaskad | Länkar, fokus, skip-länken |
| 5. Boxmodellen i praktiken | Sidhuvud, sidfot, figurer |
| 6. Flexbox | Navigeringen och dess brytpunkt |
| 7. Grid | Kortlistan och sidlayouten med dess brytpunkt |
| 8. Komponenter med tillstånd | Knappen och faktarutan |
| 9. Tabellen | Svepet och cellerna |
| 10. Formuläret | Fält, etiketter och fältkanter |
Media queries står i avsnittet de ändrar, som i avsnitt 2. Då räcker det att läsa avsnitt 6 för att förstå hela navigeringen.
Kommentarer
En kommentar säger varför, inte vad. Vad står redan i koden. Skriv den till den som undrar om regeln går att ta bort: kan hen avgöra det utan att fråga dig är kommentaren bra.
| Onödig | Användbar, ur referensprojektet |
|---|---|
/* media query */ |
/* 28em: här ryms alla fyra länkarna på en rad */ |
/* kant */ |
/* med --linje syntes fälten inte. Pass 40 */ |
/* minsta höjd */ |
/* min-height i stället för height, så att länken kan växa om texten
förstoras */ |
Bortkommenterad kod tas bort. Gamla regler som ligger kvar mellan
/* och */ för säkerhets skull gör filen svårare att läsa.
Historiken i repot är säkerheten.
Återanvändning
Tre ställen där samma sak brukar skrivas flera gånger:
- Värden. Samma färg som hex-kod på sex ställen. Den hör hemma i
:root, se guiden till område 3, avsnitt 7. - Regler. Samma fem deklarationer på tre selektorer. Slå ihop selektorerna med komma, eller gör en klass.
- Dubbletter. Samma selektor på två ställen i filen, med olika värden. Den senare vinner, och den tidigare är död kod. Sök på selektorn i redigeraren; hittas den två gånger, läs båda.
Varje dubblett är ett ställe där nästa ändring glöms. Du ändrar på det ena stället och förstår inte varför ingenting händer.
Kamratgranskning
Byt stilmall med en klasskamrat som inte sett din förut. Hen går igenom den med listan och skriver svaren. Listan handlar om läsbarhet, inte om utseende: jag hade valt en annan färg hör inte hemma här.
| Fråga | Ja / nej, och var |
|---|---|
| Hittar du navigeringens regler inom en halv minut? | |
| Är indenteringen 2 mellanslag överallt? | |
| Är alla filnamn gemener utan mellanslag? | |
| Är namnen på klasser och variabler i samma språk och skrivsätt? | |
| Finns det ett värde som upprepas och borde vara en variabel? | |
| Står varje media query i avsnittet den ändrar, med en kommentar? | |
| Finns det en kommentar du inte förstår, eller en regel som saknar en? |
Det som ska rättas blir en punkt i dokumentation.md.
Flyttas regler i fel ordning kan kaskaden ändras: två regler som väger lika avgörs av vilken som står sist. Ladda om och titta efter varje avsnitt du flyttat. Gör ett commit, en sparad version i repots historik, per steg i städningen. Blir allt ett enda commit går det inte att ångra bitvis.
5. Tillgänglighet i koden
Du arbetar efter två listor: kamratens åtgärdslista från december och dina egna WCAG-fynd från Gränssnittsdesign den 18 januari. Avsnittet visar koden som rättar de vanligaste fynden. Det som är rättat den 4 februari är det som testas på riktiga personer i Gränssnittsdesign.
Tangentbord, fokus, label, rubriker och kontrast är ska-krav, nivå
E. Ett eget commit per åtgärd, och att koden bär semantiken utan hjälp av CSS, är
nivå C.
Ordningen
- Alla fynd på nivå A först, sedan kamratens tre högst prioriterade punkter. Det är E-kravet. Resten därefter, i listans prioritering.
- Ett commit per åtgärd, med punktens nummer först i meddelandet: Åtgärd 3: label på sökfältet går att hitta i mars, fixar gör det inte.
- Status i
dokumentation.mddirekt efter commit: åtgärdad, delvis eller inte, med skäl. Mallen står i avsnitt 6.
Fynden och koden som rättar dem
Numren är samma som i din WCAG-granskning. Vad kriteriet betyder gick Gränssnittsdesign igenom den 18 januari; här är frågan vilken rad som rättar det.
| Fynd | Koden som rättar det | Läs om det |
|---|---|---|
| 1.1.1 Bild utan fungerande alt | alt på
img, alt="" på dekor |
Avsnitt 3 |
| 1.3.1, 2.4.6 Rubrik hoppar nivå | Nivån efter strukturen, storleken i CSS | Nedan |
| 3.3.2 Fält utan etikett | label med for som
pekar på fältets id |
Guide HTML, avsnitt 8 |
| 2.4.7 Fokus syns inte | :focus-visible med
outline, aldrig bara outline: none | Nedan |
| 1.4.3, 1.4.11 För låg kontrast | Rätta värdet i :root,
inte på varje ställe | Nedan |
| 2.1.1 Går inte med tangentbord | button eller
a, aldrig div | Nedan |
| 2.4.3 Tabbordningen hoppar | Ändra ordningen i HTML:en, aldrig
positivt tabindex | Nedan |
| 2.5.8 För liten klickyta | padding och
min-height | Nedan |
Kontrast rättas i variablerna
I referensprojektet hade fältkanterna samma färg som avdelarna, --linje,
med kontrasten 1,4:1 mot vitt. Fälten syntes knappt. Rättelsen är en ny variabel i
:root, och fälten som använder den:
:root {
--linje: #d4dde6; /* avdelare och kort, bär ingen betydelse */
--linje-falt: #76869a; /* fältkanter: 3,7:1 mot --yta. Pass 40 */
}
input,
select,
textarea {
border: 1px solid var(--linje-falt);
}
Värdet rättas på ett ställe, och alla fält följer med. Mät med WebAIM Contrast Checker,
samma verktyg som i Gränssnittsdesign. Står en textfärg i :root som inte
klarar kravet rättar du den där, inte på varje regel som använder den.
Rubriknivån följer strukturen
Faktarutan på Vinga-sidan har en h2 som ska se mindre ut. Nivån står kvar,
storleken ändras i CSS:
.faktaruta h2 { font-size: 1.15rem; }
Välj aldrig h4 för att den ser lagom stor ut. Nivån är strukturen
skärmläsaren navigerar efter. Hur stor rubriken ser ut är CSS:ens sak.
Synlig fokus
Referensprojektets fokusregel, i avsnitt 4:
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
outline: 3px solid var(--accent);
outline-offset: 2px;
}
Fokusringen i referensprojektet har kontrasten 6,7:1 mot bakgrunden. Mät din egen på
samma sätt; den ska klara minst 3:1. Sök sedan efter outline: none i hela
stil.css, inte bara i komponenterna. Står den kvar någonstans utan en
ersättning är fokus borta där. Mer om :focus-visible står i
guiden till område 3, avsnitt
10.
Knappar som inte är knappar
En div med knappens klass ser likadan ut, men den går inte att tabba till
och inte att trycka på med Enter eller mellanslag:
<!-- Ser ut som en knapp, är det inte -->
<div class="knapp">Skicka rapporten</div>
<!-- Är en knapp -->
<button type="submit" class="knapp">Skicka rapporten</button>
Fyrsajten har ingen sådan div, så exemplet står för sig. Regeln är enkel:
något som gör något på sidan är en button, något som leder till en annan
sida är en a.
Tabbordningen följer HTML:en
Tangentbordet går igenom sidan i den ordning elementen står i HTML:en. Står något i fel
ordning flyttas det i koden. Använd aldrig tabindex med ett positivt tal
för att tvinga fram en ordning; den gäller då bara för de element du numrerat, och
resten hamnar efter.
Samma sak gäller CSS: grid och flexbox kan flytta saker på skärmen utan att flytta dem i HTML:en. Skärmläsaren och tangentbordet följer HTML:en, inte rutnätet.
Klickytor
Stilguiderna i Gränssnittsdesign valde en träffyta på 44 × 44 px. Det är högre än WCAG:s minimum, och det är ett designbeslut. Koden som ger det, ur avsnitt 6:
nav a {
display: inline-flex;
align-items: center;
min-height: 2.75rem;
padding: var(--steg-1) 0;
font-weight: 600;
text-decoration: none;
}
2.75rem är 44 px. min-height i stället för
height, så att länken kan växa om texten förstoras.
inline-flex och align-items: center håller texten mitt i den
högre ytan.
Det skärmläsaren läser
En skärmläsare läser upp HTML:en, inte det du ser. Det den behöver är det du redan
skrivit om det är rätt: landmärkena header, nav och
main, rubriker i rätt nivå, label på varje fält, alt-texter och
länktexter som går att förstå lösryckta. Det är det bör-kravet menar med att koden bär
semantiken utan hjälp av CSS. Hur du startar skärmläsaren gick Gränssnittsdesign igenom
den 21 januari.
En skip-länk, Till innehållet, är en utmaning på nivå A och står i avsnitt 7.
Arbetsgången, en punkt i taget
- Välj översta öppna punkten i ordningen ovan.
- Rätta den i koden. Hitta regeln eller elementet först, ändra sedan.
- Testa med tangentbordet på sidan du ändrat. Det tar en minut.
- Commit med punktens nummer, till exempel Åtgärd 4: synlig fokusmarkering på länkarna (2.4.7).
- Status i
dokumentation.md, med fil och selektor under var.
Ta varje punkt du markerat som åtgärdad och peka på raden i koden som rättar den. Kan du inte peka på raden är punkten inte klar, oavsett vad som står i dokumentationen.
6. Testning och testprotokoll
Inget av testen är nytt. Validatorn kom i område 2, två webbläsare och telefon också,
tangentbordet och :focus-visible i område 3. Det nya är att de görs i en
bestämd form och skrivs ned så att någon annan kan göra om dem.
Ett testprotokoll med alla fem testen är ett ska-krav, nivå E. Att protokollet visar felet, åtgärden och omtestet är nivå C. Att testerna hittat något du inte väntade dig, och att protokollet visar vad du gjorde åt det, är nivå A.
Protokollets form
dokumentation.md har två avsnitt. Åtgärder är listorna från
Gränssnittsdesign. Testprotokoll är dina egna test, med fem kolumner:
| Kolumn | Vad som står där |
|---|---|
| Test | Vilket test: validering, webbläsare och bredder, telefon, tangentbord, automatiskt verktyg |
| Med vad | Webbläsare och version, telefonmodell, verktygets namn |
| Sida | Vilken fil, eller alla sidor om resultatet var detsamma överallt |
| Resultat | Vad du såg. Inte om det var bra |
| Åtgärd | Vad du ändrade och var, eller ingen |
En rad som går att göra om
Jämför två rader om samma test:
| Test | Med vad | Sida | Resultat | Åtgärd |
|---|---|---|---|---|
| Telefon | Min mobil | Alla | Funkar | – |
| Telefon | Pixel 7, Chrome och versionsnumret | vinga.html |
Länkarna i navigeringen ligger så tätt att tummen träffar fel | min-height på nav a, stil.css |
Den första raden säger att någon tittat. Den andra säger vad som hände, var, och vad som gjordes åt det – och den går att testa om. Versionsnumret hittar du i webbläsarens Om-meny.
Omtestet är en ny rad med samma test, samma sida och det nya resultatet. Det är skillnaden mellan E och C. Ett protokoll där varje rad är grön från början har antingen en felfri sajt eller en testare som inte letade.
Skriv protokollet medan du testar, med sajten öppen bredvid. Skrivet i efterhand, ur minnet, står det funkar överallt.
Mallen för dokumentation.md
Lägg filen i repots rot. Den här mallen får du kopiera in som den är och fylla i:
# Dokumentation ## Åtgärder | Nr | Källa | Vad du gjorde | Var | Status | |---|---|---|---|---| | | | | | | ## Testprotokoll | Test | Med vad | Sida | Resultat | Åtgärd | |---|---|---|---|---| | | | | | |
Referensprojektets dokumentation.md är ifylld i samma form, och visar hur
raderna ser ut på riktigt.
Två webbläsare, bredderna och telefonen
Det här är korstestet från område 2, med en skillnad: avvikelselistan blir rader i en tabell. Uppdelningen i förväntad skillnad och fel gäller fortfarande, se avvikelselistan. Ett fält som ritas lite annorlunda i Firefox är ingen rad. En länk som inte går att klicka är det.
- Två webbläsare med olika motor. Motorn är den del av webbläsaren som tolkar HTML och CSS. Chrome och Edge har samma motor, så ett test i båda är nästan samma test två gånger. Välj Firefox som den ena.
- Bredderna. Dra fönstret långsamt från 320 till 1600 pixlar. En rad per sida där något händer: en vågrät rullningslist, text som klipps, en bild som sticker ut.
- Telefonen. Öppna den publicerade adressen på en riktig telefon. Device mode är ett bra verktyg medan du bygger, men det är inte telefonraden i protokollet. Raden ska ha en telefonmodell.
Tangentbordet
Det test som oftast fäller. Lägg undan musen och gå igenom varje sida:
| Tangent | Gör |
|---|---|
| Tabb | Nästa sak som går att använda |
| Skift + Tabb | Föregående |
| Enter | Följer en länk, skickar ett formulär |
| Mellanslag | Trycker på en knapp, kryssar i en ruta |
| Piltangenterna | Väljer i en lista, till exempel en
select |
Fyra frågor per sida:
- Ser du hela tiden var du är?
- Kommer du fram till allt som går att klicka på?
- Följer ordningen sidan, uppifrån och ned?
- Kommer du ut igen ur allt du kommer in i?
Varje nej är en rad, med sida och element. Fokus syns inte på Skicka-knappen går att rätta. Tangentbordet funkar dåligt går inte att rätta. Testa formulärsidan särskilt noga: där finns fälten, knappen och listorna.
Validering
W3C:s validerare för HTML och för CSS, varje sida, noll fel. Se guiden till område 2, avsnitt 9. En rad per validerare räcker om alla sidor gav samma resultat. Skriv alla fem sidor, 0 fel, inte validerar – det säger inte vilka sidor som körts.
Lighthouse
Lighthouse är det automatiska verktyget i protokollet. Det är inbyggt i Chrome, i DevTools under fliken med samma namn.
- Öppna den publicerade adressen i ett inkognitofönster, så att tillägg i webbläsaren inte stör.
- DevTools, fliken Lighthouse. Kryssa bara i Accessibility.
- Kör. Skriv ned vilka fel den namnger, sida för sida.
- Rätta felen och kör igen. Det är omtestet.
Siffran får stå i resultatkolumnen, men siffran är inte resultatet. En hög siffra betyder att verktyget inte hittade något, inte att sajten fungerar – en borttagen fokusring kan passera utan anmärkning. Därför kräver protokollet tangentbordet också. Vilka fel som är äkta och vilka som är falsklarm sorterade du i Gränssnittsdesign den 25 januari; använd den sorteringen här.
Ordningen
- Validera. Allt annat förutsätter att koden är hel.
- Tangentbordet, varje sida.
- Lighthouse på minst två sidor, varav formulärsidan om det finns en.
- Två webbläsare och bredderna.
- Telefonen, på Pages-adressen. Den kräver att sajten är pushad och att Pages hunnit uppdatera, därför sist. Har du pushat för en minut sedan ser du kanske den gamla versionen.
Testprotokollet svarar på om koden klarar en kontroll, rad för rad. Det ligger i repot och följer koden. Hur en person klarar sajten – WCAG-granskningen och användartestet – hör till testrapporten i Gränssnittsdesign, i portföljen. Samma tabell på båda ställena är ett fel för mycket.
7. Ta det längre
Utmaningarna i Projekt 4, nivå A. Ta dem när ska- och bör-kraven sitter, och aldrig före ett öppet fynd på nivå A.
Skip-länken
En skip-länk är en länk överst på sidan som hoppar förbi navigeringen, direkt
till innehållet. Den syns bara när den får fokus, alltså för den som tabbar. Kravet på
att kunna hoppa över navigeringen klaras redan av landmärkena; skip-länken gör det
synligt. I HTML:en står den först i body, och main får ett
id att hoppa till:
<body>
<a class="till-innehallet" href="#innehall">Till innehållet</a>
<header>
<!-- sidnamn och navigering som förut -->
</header>
<main id="innehall">
<h1>Fyrar längs Bohuskusten</h1>
</main>
</body>
CSS:en, ur referensprojektets avsnitt 4:
.till-innehallet {
position: absolute;
top: -4rem;
left: var(--steg-2);
z-index: 1;
padding: var(--steg-1) var(--steg-2);
background: var(--yta);
font-weight: 600;
}
.till-innehallet:focus {
top: var(--steg-2);
}
position: absolute lyfter länken ur flödet, och top flyttar
den uppåt, utanför skärmen, tills den får fokus. Göm den aldrig med
display: none – då går den inte att tabba till, och då finns den inte.
Testa så här: ladda sidan, tryck Tab en gång. Länken ska synas. Tryck Enter. Nästa Tab ska hamna i innehållet, inte i navigeringen.
200 % förstoring
Sajten ska gå att använda när texten är dubbelt så stor, utan att text klipps eller hamnar ovanpå annan text. Förstora med Ctrl och plus tills webbläsaren visar 200 %, och gå igenom varje sida. Det som brukar gå sönder:
heightdär det borde ståmin-height. Texten växer, rutan gör det inte, och texten rinner ut över kanten.- Fasta bredder. En behållare med
widthipxrymmer inte längre sin text. - Teckenstorlek i
px. Den följer inte med när användaren ställer in större text i webbläsarens inställningar.
Brytpunkter i em hjälper här: när texten blir stor staplas navigeringen
igen, eftersom länkarna inte längre ryms på en rad. Vad kriteriet kräver gick
Gränssnittsdesign igenom den 18 januari.
picture med olika beskärning
srcset byter storlek på samma bild. picture kan byta
bild: en beskuren version för telefonen, där motivet annars blir för litet. Så
står fotot på referensprojektets startsida:
<picture>
<source media="(min-width: 40em)"
srcset="bilder/vinga-960.jpg 960w, bilder/vinga-1200.jpg 1200w"
sizes="36rem">
<img src="bilder/vinga-smal.jpg" width="480" height="600"
alt="Vinga fyr, ett grått stentorn på en kal klippa, med öppet hav bakom.">
</picture>
Är fönstret minst 40em brett hämtas en av de breda bilderna i source,
annars den beskurna i img. På telefonen fyller tornet bilden; i den breda
versionen skulle det bli en prick. source har ingen alt – den
sitter på img och gäller vilken fil som än hämtas. Skriv den för det båda
versionerna visar.
Beskärningen ska gå att motivera ur din mockup: vad visar den i mobilbredd, och vad skulle försvinna om hela bilden krympte?
Prova en sida med skärmläsare
Välj en sida, gärna formulärsidan, och gå igenom den med skärmläsaren påslagen. Hur du startar den och tar dig runt står i Gränssnittsdesigns guide, avsnitt 3. Lyssna efter det som är din kod:
- Läses rubrikerna upp i en ordning som går att följa?
- Hittar du landmärkena, och är det bara ett
main? - Säger varje fält vad det heter när du kommer till det?
- Säger bilderna något, och hoppas dekoren över?
- Går länktexterna att förstå utan texten omkring?
Skriv en anteckning i dokumentation.md: vad som lät fel, och vad du ändrade
i koden. Utan anteckningen syns utmaningen inte i bedömningen.
Bredder du inte testat
Sajten ska hålla i bredder ingen provat, utan brytpunkter för specialfall, och du ska kunna förklara varför. Förklaringen finns i de verktyg som räknar själva:
- Galleriet med
repeat(auto-fit, minmax(16rem, 1fr))räknar ut antalet kolumner efter hur mycket plats som finns, i varje bredd. Se guiden till område 3, avsnitt 9. - Navigeringen har
flex-wrap, så den bryter om länkarna inte ryms. - Bilderna och behållarna har
max-widthi stället för fasta bredder. - Brytpunkterna sitter där innehållet går sönder, inte vid en enhet. Mellan dem finns ingen bredd som är särskild.
En brytpunkt för en enda telefonmodell är ett tecken på att något annat är fel: en fast
bredd, en bild utan max-width, ett ord som inte bryts.
8. Felsökning
22 rader
| Symptom | Trolig orsak | Åtgärd |
|---|---|---|
| Sidan ser ut som en förminskad datorsida på telefonen | Viewport-taggen saknas på den sidan | Lägg in viewport-raden i head på varje
sida |
| Det går inte att förstora med två fingrar | user-scalable=no
eller maximum-scale i viewport-taggen | Skriv raden exakt som i avsnitt 1. Sök igenom hela repot |
| Sidan har vågrät rullningslist på telefon | Något har en fast bredd,
till exempel width: 900px | Byt till max-width.
Hitta elementet genom att inspektera det som sticker ut |
| En lång adress skjuter ut sidan i sidled | Ordet saknar mellanslag att bryta vid | overflow-wrap: break-word på text |
| Regeln i media queryn slår inte igenom | Media queryn står före regeln den ska ändra, och grundregeln vinner för att den står sist | Flytta media queryn direkt efter regeln den ändrar |
| Resten av stilmallen slutar fungera efter en media query | Den sista klammern saknas | Räkna klamrarna: en för media queryn, en per regel. Kör CSS-validatorn |
| Layouten byter inte när texten förstoras | Brytpunkten är skriven i
px | Skriv den i em: dela pixlarna med 16 |
| I en viss bredd gäller två regler som krockar | min-width
och max-width blandade | Välj min-width och skriv
om de andra |
| Bilden är hoptryckt i smala fönster | height: auto
saknas | Lägg till den bredvid max-width: 100% |
| En liten bild blir utdragen och suddig | width: 100% i
stället för max-width | Byt till
max-width: 100% |
| Datorn hämtar den största filen fast bilden visas liten | sizes
saknas, och webbläsaren antar full fönsterbredd | Skriv
sizes så att det stämmer med CSS:en |
| Sidvikten blev nästan noll andra gången jag mätte | Filerna kom ur cacheminnet | Kryssa i Disable cache och mät om |
| Telefonen hämtar en större fil än bilden visas | Skärmens pixeltäthet | Normalt, inte ett fel. Därför högst dubbla visningsbredden |
Validatorn klagar på alt i picture | alt
står på source | Flytta den till img |
| Övergången syns fast minskad rörelse är påslagen | Regeln med
prefers-reduced-motion står före övergången, eller träffar en annan
selektor | Samma selektor, och media queryn efter regeln den ändrar |
| Jag ser inte var fokus är när jag tabbar | outline: none
någonstans i stilmallen | Sök i hela stil.css. Sätt en egen
:focus-visible |
| Knappen går inte att tabba till | Den är en div med
knappens klass | Byt till button |
| Tabbordningen hoppar runt på sidan | Positivt tabindex,
eller HTML:en står i en annan ordning än sidan ser ut | Ta bort
tabindex. Flytta elementen i HTML:en |
| Skip-länken syns aldrig, inte ens när jag tabbar | Regeln med
:focus saknas, eller länken är gömd med
display: none | Flytta den utanför skärmen med
top, och tillbaka vid :focus |
| Fälten i formuläret syns knappt | Fältkanten har för låg kontrast | Egen variabel för fältkanter i :root, minst 3:1 |
| Texten rinner ut ur länken vid 200 % | height i stället
för min-height | Byt till min-height |
| Telefonen visar den gamla versionen | Inte pushat, eller Pages har inte hunnit uppdatera | Pusha, vänta en stund, ladda om |
9. Snabbreferens: begreppen
Använd den inför prov 3. Ordträningen nedan drar slumpvis ur tabellen.
Ordträning
36 rader
| Begrepp | Betyder |
|---|---|
| responsiv design | Samma sida fungerar i alla bredder, från telefon till datorskärm |
| viewport | Ytan sidan ritas på. På en telefon utan viewport-tagg ungefär 980 px |
| width=device-width | Rita sidan lika bred som skärmen |
| initial-scale=1 | Börja utan förstoring eller förminskning |
| user-scalable=no | Stänger av förstoring. Skrivs aldrig |
| mobile first | Grundstilen är telefonens, bredare skärmar lägger till |
| device mode | Läge i DevTools som ritar sidan som på en telefon. Ctrl + Shift + M |
| media query | En fråga om omgivningen. Är svaret ja gäller reglerna inuti |
| brytpunkt | Bredden där en media query börjar gälla. Sätts där innehållet går sönder |
| min-width | Från den här bredden och uppåt. Används med mobile first |
| max-width i en media query | Upp till den här bredden. Tar bort i stället för att lägga till |
| em i en media query | Räknas mot webbläsarens grundstorlek, 16 px. Följer med när texten förstoras |
| overflow-wrap: break-word | Låter ett långt ord brytas i stället för att skjuta ut sidan |
| max-width: 100% | Bilden blir aldrig bredare än sin behållare |
| height: auto | Höjden räknas om så att proportionerna behålls |
| srcset | Samma bild i flera bredder. Webbläsaren väljer fil |
| w i srcset | Filens bredd i pixlar, till exempel 480w |
| sizes | Hur bred bilden visas. Ska stämma med CSS:en |
| vw | Procent av fönstrets bredd. 100vw är hela bredden |
| pixeltäthet | Hur tätt pixlarna sitter. Tät skärm hämtar större fil |
| picture | Byter bild efter bredd, till exempel en beskuren för telefonen |
| source | Ett alternativ i picture, med villkor. Har ingen alt |
| alt="" | Tom alt-text. Bilden är dekor och hoppas över |
| transkript | Ljudets innehåll som vanlig text på sidan |
| transition | Mjuk övergång mellan två lägen |
| prefers-reduced-motion | Media query: användaren har bett om mindre rörelse |
| kodstandard | 2 mellanslag, gemener, bindestreck, index.html, relativa sökvägar |
| dubblett | Samma selektor två gånger i filen. Den tidigare är död kod |
| :focus-visible | Fokus för tangentbordet. Får aldrig tas bort utan ersättning |
| tabindex | Aldrig positivt. Ordningen ändras i HTML:en |
| min-height | Minsta höjd. Ger klickyta och låter texten växa |
| landmärke | header, nav, main, footer. Skärmläsaren hoppar mellan dem |
| skip-länk | Länk till innehållet som syns när den får fokus |
| testprotokoll | Test, med vad, sida, resultat, åtgärd. Varje rad går att göra om |
| omtest | Ny rad med samma test efter åtgärden, och det nya resultatet |
| webbläsarmotor | Den del som tolkar HTML och CSS. Chrome och Edge har samma |