← Område 5 Guide · Responsiv design och tillgänglighet Felsökning

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.

Här handlar allt om koden

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

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">
DelBetyder
width=device-widthRita sidan lika bred som skärmen, inte 980 px
initial-scale=1Bö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.

Skriv den exakt så

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 pxVarförLäs om det
Navigeringen bryter till nya raderflex-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ärmenmax-width: 100% Avsnitt 3
Tabellen spräcker inte sidan .tabellsvep med overflow-x: auto Referensprojektets stil.css, avsnitt 9
Textstorleken följer användarenrem 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:

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.

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.

Prova själv

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);
  }
}
DelVad den gör
@mediaInleder 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ättLäsesPassar
min-widthFrån den här bredden och uppåt Mobile first: grundstilen är smal, bredd läggs till
max-widthUpp 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:

  1. Öppna sidan i device mode på 320 px.
  2. Dra långsamt bredare och titta på innehållet, inte på siffran.
  3. Stanna där något ser fel ut, eller där det finns plats för något bättre.
  4. Läs av bredden. Det är brytpunkten.

Frågor att ställa medan du drar:

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.

Fråga vad som går sönder vid 767

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 breddUträkningBrytpunkt
448 px448 / 1628em
640 px640 / 1640em
896 px896 / 1656em

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.

  1. Fasta bredder bort. width: 900px blir max-width. Många fel försvinner här.
  2. Grundstilen smal. Det som bara ska gälla bredare fönster flyttas in i en media query med min-width.
  3. Dra i fönstret och hitta var layouten behöver byta. Läs av, dela med 16.
  4. Skriv kommentaren ovanför varje media query: vad som går sönder utan den.
  5. Dra från 320 till 1600 igen. Ingen vågrät rullning, ingen text som klipps.
Prova själv

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;
}
DeklarationGör
max-width: 100%Bilden blir aldrig bredare än sin behållare
height: autoHöjden räknas om så att proportionerna behålls
display: blockTar 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.">
DelBetyder
480wDen här filen är 480 pixlar bred. w står för bredd
sizesFrån 40em och uppåt visas bilden 36rem bred, annars hela fönstrets bredd
100vw100 procent av fönstrets bredd. vw står för viewport width
srcReserv 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:

  1. Device mode, telefonbredd. Öppna fliken Network (nätverk) i DevTools.
  2. Kryssa i Disable cache. Utan den hämtas ingenting andra gången, och siffran ser bättre ut än den är.
  3. Ladda om och läs av summan för överförd data längst ned. Det är före.
  4. Exportera din tyngsta bild i två eller tre bredder och skriv srcset och sizes.
  5. 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

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.

Prova själv

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

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

RegelExempelVarför
2 mellanslag indenteringtvå mellanslag före display: flex; Samma i alla filer, oavsett redigerare
Gemener i filnamnvinga.html, inte Vinga.html Pages skiljer på stora och små bokstäver, Windows gör det inte
Bindestreck, inga mellanslagalla-fyrar.html, inte alla fyrar.html Mellanslag blir %20 i adressen
index.html som startsidaindex.html i roten Det är filen servern visar när ingen fil anges
Relativa sökvägarbilder/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örigtKonsekvent
.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:

AvsnittInnehåll
1. VariablernaFärger, typsnitt och avstånd i :root
2. Grundenbox-sizing, body, bilderna
3. Typografi och färgRubriker, stycken, kod
4. Selektorer och kaskadLänkar, fokus, skip-länken
5. Boxmodellen i praktikenSidhuvud, sidfot, figurer
6. FlexboxNavigeringen och dess brytpunkt
7. GridKortlistan och sidlayouten med dess brytpunkt
8. Komponenter med tillståndKnappen och faktarutan
9. TabellenSvepet och cellerna
10. FormuläretFä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ödigAnvä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:

  1. 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.
  2. Regler. Samma fem deklarationer på tre selektorer. Slå ihop selektorerna med komma, eller gör en klass.
  3. 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ågaJa / 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.

Städning får inte ändra vad sidan gör

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

  1. Alla fynd på nivå A först, sedan kamratens tre högst prioriterade punkter. Det är E-kravet. Resten därefter, i listans prioritering.
  2. 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.
  3. Status i dokumentation.md direkt 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.

FyndKoden som rättar detLäs om det
1.1.1 Bild utan fungerande altalt på img, alt="" på dekor Avsnitt 3
1.3.1, 2.4.6 Rubrik hoppar nivåNivån efter strukturen, storleken i CSSNedan
3.3.2 Fält utan etikettlabel 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: noneNedan
1.4.3, 1.4.11 För låg kontrastRätta värdet i :root, inte på varje ställeNedan
2.1.1 Går inte med tangentbordbutton eller a, aldrig divNedan
2.4.3 Tabbordningen hopparÄndra ordningen i HTML:en, aldrig positivt tabindexNedan
2.5.8 För liten klickytapadding och min-heightNedan

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

  1. Välj översta öppna punkten i ordningen ovan.
  2. Rätta den i koden. Hitta regeln eller elementet först, ändra sedan.
  3. Testa med tangentbordet på sidan du ändrat. Det tar en minut.
  4. Commit med punktens nummer, till exempel Åtgärd 4: synlig fokusmarkering på länkarna (2.4.7).
  5. Status i dokumentation.md, med fil och selektor under var.
Prova själv

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:

KolumnVad som står där
TestVilket test: validering, webbläsare och bredder, telefon, tangentbord, automatiskt verktyg
Med vadWebbläsare och version, telefonmodell, verktygets namn
SidaVilken fil, eller alla sidor om resultatet var detsamma överallt
ResultatVad du såg. Inte om det var bra
ÅtgärdVad du ändrade och var, eller ingen

En rad som går att göra om

Jämför två rader om samma test:

TestMed vadSidaResultatÅtgärd
TelefonMin mobilAllaFunkar–
TelefonPixel 7, Chrome och versionsnumretvinga.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.

Tangentbordet

Det test som oftast fäller. Lägg undan musen och gå igenom varje sida:

TangentGör
TabbNästa sak som går att använda
Skift + TabbFöregående
EnterFöljer en länk, skickar ett formulär
MellanslagTrycker på en knapp, kryssar i en ruta
PiltangenternaVäljer i en lista, till exempel en select

Fyra frågor per sida:

  1. Ser du hela tiden var du är?
  2. Kommer du fram till allt som går att klicka på?
  3. Följer ordningen sidan, uppifrån och ned?
  4. 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.

  1. Öppna den publicerade adressen i ett inkognitofönster, så att tillägg i webbläsaren inte stör.
  2. DevTools, fliken Lighthouse. Kryssa bara i Accessibility.
  3. Kör. Skriv ned vilka fel den namnger, sida för sida.
  4. 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

  1. Validera. Allt annat förutsätter att koden är hel.
  2. Tangentbordet, varje sida.
  3. Lighthouse på minst två sidor, varav formulärsidan om det finns en.
  4. Två webbläsare och bredderna.
  5. 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.
Testprotokoll är inte testrapport

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:

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:

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:

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

SymptomTrolig orsakÅtgärd
Sidan ser ut som en förminskad datorsida på telefonenViewport-taggen saknas på den sidanLägg in viewport-raden i head på varje sida
Det går inte att förstora med två fingraruser-scalable=no eller maximum-scale i viewport-taggenSkriv raden exakt som i avsnitt 1. Sök igenom hela repot
Sidan har vågrät rullningslist på telefonNågot har en fast bredd, till exempel width: 900pxByt till max-width. Hitta elementet genom att inspektera det som sticker ut
En lång adress skjuter ut sidan i sidledOrdet saknar mellanslag att bryta vidoverflow-wrap: break-word på text
Regeln i media queryn slår inte igenomMedia queryn står före regeln den ska ändra, och grundregeln vinner för att den står sistFlytta media queryn direkt efter regeln den ändrar
Resten av stilmallen slutar fungera efter en media queryDen sista klammern saknasRäkna klamrarna: en för media queryn, en per regel. Kör CSS-validatorn
Layouten byter inte när texten förstorasBrytpunkten är skriven i pxSkriv den i em: dela pixlarna med 16
I en viss bredd gäller två regler som krockarmin-width och max-width blandadeVälj min-width och skriv om de andra
Bilden är hoptryckt i smala fönsterheight: auto saknasLägg till den bredvid max-width: 100%
En liten bild blir utdragen och suddigwidth: 100% i stället för max-widthByt till max-width: 100%
Datorn hämtar den största filen fast bilden visas litensizes saknas, och webbläsaren antar full fönsterbreddSkriv sizes så att det stämmer med CSS:en
Sidvikten blev nästan noll andra gången jag mätteFilerna kom ur cacheminnetKryssa i Disable cache och mät om
Telefonen hämtar en större fil än bilden visasSkärmens pixeltäthetNormalt, inte ett fel. Därför högst dubbla visningsbredden
Validatorn klagar på alt i picturealt står på sourceFlytta den till img
Övergången syns fast minskad rörelse är påslagenRegeln med prefers-reduced-motion står före övergången, eller träffar en annan selektorSamma selektor, och media queryn efter regeln den ändrar
Jag ser inte var fokus är när jag tabbaroutline: none någonstans i stilmallenSök i hela stil.css. Sätt en egen :focus-visible
Knappen går inte att tabba tillDen är en div med knappens klassByt till button
Tabbordningen hoppar runt på sidanPositivt tabindex, eller HTML:en står i en annan ordning än sidan ser utTa bort tabindex. Flytta elementen i HTML:en
Skip-länken syns aldrig, inte ens när jag tabbarRegeln med :focus saknas, eller länken är gömd med display: noneFlytta den utanför skärmen med top, och tillbaka vid :focus
Fälten i formuläret syns knapptFältkanten har för låg kontrastEgen 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-heightByt till min-height
Telefonen visar den gamla versionenInte pushat, eller Pages har inte hunnit uppdateraPusha, 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

BegreppBetyder
responsiv designSamma sida fungerar i alla bredder, från telefon till datorskärm
viewportYtan sidan ritas på. På en telefon utan viewport-tagg ungefär 980 px
width=device-widthRita sidan lika bred som skärmen
initial-scale=1Börja utan förstoring eller förminskning
user-scalable=noStänger av förstoring. Skrivs aldrig
mobile firstGrundstilen är telefonens, bredare skärmar lägger till
device modeLäge i DevTools som ritar sidan som på en telefon. Ctrl + Shift + M
media queryEn fråga om omgivningen. Är svaret ja gäller reglerna inuti
brytpunktBredden där en media query börjar gälla. Sätts där innehållet går sönder
min-widthFrån den här bredden och uppåt. Används med mobile first
max-width i en media queryUpp till den här bredden. Tar bort i stället för att lägga till
em i en media queryRäknas mot webbläsarens grundstorlek, 16 px. Följer med när texten förstoras
overflow-wrap: break-wordLå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: autoHöjden räknas om så att proportionerna behålls
srcsetSamma bild i flera bredder. Webbläsaren väljer fil
w i srcsetFilens bredd i pixlar, till exempel 480w
sizesHur bred bilden visas. Ska stämma med CSS:en
vwProcent av fönstrets bredd. 100vw är hela bredden
pixeltäthetHur tätt pixlarna sitter. Tät skärm hämtar större fil
pictureByter bild efter bredd, till exempel en beskuren för telefonen
sourceEtt alternativ i picture, med villkor. Har ingen alt
alt=""Tom alt-text. Bilden är dekor och hoppas över
transkriptLjudets innehåll som vanlig text på sidan
transitionMjuk övergång mellan två lägen
prefers-reduced-motionMedia query: användaren har bett om mindre rörelse
kodstandard2 mellanslag, gemener, bindestreck, index.html, relativa sökvägar
dubblettSamma selektor två gånger i filen. Den tidigare är död kod
:focus-visibleFokus för tangentbordet. Får aldrig tas bort utan ersättning
tabindexAldrig positivt. Ordningen ändras i HTML:en
min-heightMinsta höjd. Ger klickyta och låter texten växa
landmärkeheader, nav, main, footer. Skärmläsaren hoppar mellan dem
skip-länkLänk till innehållet som syns när den får fokus
testprotokollTest, med vad, sida, resultat, åtgärd. Varje rad går att göra om
omtestNy rad med samma test efter åtgärden, och det nya resultatet
webbläsarmotorDen del som tolkar HTML och CSS. Chrome och Edge har samma