Webbutveckling · område 2
Guide – HTML: innehåll och struktur
Här står allt som prov 1 kan fråga om, och allt du behöver för Projekt 1. Guiden fungerar utan att du varit på lektionen.
Exemplen är hämtade ur referensprojektet Fyrar längs Bohuskusten – samma kod som visas på lektionerna, och samma kod provet utgår från.
Vad du kan efter guiden
- Skriva ett komplett HTML-dokument från minnet
- Välja rätt element utifrån vad innehållet betyder, inte hur det ser ut
- Bygga en navigering mellan flera sidor med relativa sökvägar som håller
- Skriva
alt-texter som fungerar för den som inte ser bilden - Bygga en datatabell som går att följa med skärmläsare
- Bygga ett formulär där varje fält är kopplat till sin etikett
- Validera din kod och tolka felmeddelandena
- Förklara varför standarder finns och vad en användaragent är
1. Dokumentets grund
Varje HTML-fil har samma skelett. Lär dig det utantill – du kommer att skriva det hundra gånger.
<!doctype html>
<html lang="sv">
<head>
<meta charset="utf-8">
<title>Sidans namn</title>
</head>
<body>
</body>
</html>
| Del | Vad den gör |
|---|---|
<!doctype html> | Säger att det är modern HTML. Måste stå allra först |
<html lang="sv"> | Omsluter allt. lang säger vilket språk sidan är på |
<head> | Information om sidan. Syns inte i fönstret |
<body> | Sidans innehåll. Det man ser |
Element, taggar och attribut
Tre ord som ofta blandas ihop:
<a href="vinga.html">Läs mer om Vinga</a>
- Elementet är hela saken: starttagg, innehåll och sluttagg.
- Taggarna är
<a>och</a>. - Attributet är
href="vinga.html"– extra information som styr elementet. Attribut står alltid i starttaggen.
Några element har inget innehåll och därför ingen sluttagg: <img>,
<br>, <meta>, <input>. De kallas
tomma element.
Skriv grundskelettet från minnet i en ny fil. Öppna den i webbläsaren. Sidan är tom
och vit – det är rätt. Lägg till en <title> och se att flikens namn
ändras.
2. Teckenkodning och språk
Varför å ä ö går sönder
En dator lagrar text som tal. A är 65. Men vilket tal är ä?
Det beror på vilken teckenkodning som används, och det finns flera. Skriver du filen i
en kodning och läser den i en annan blir ä till ä.
UTF-8 är den kodning som klarar alla språk, och det är den webben använder. Två saker måste stämma:
- Filen måste sparas som UTF-8. VS Code gör det som standard – det står nere till höger i statusraden.
- Sidan måste säga att den är UTF-8.
<meta charset="utf-8">
charset-raden ska stå först i <head>. Står den
längre ned har webbläsaren redan hunnit börja gissa, och gissar den fel blir de första
raderna trasiga.
lang
lang talar om vilket språk sidan är skriven på. Det påverkar tre saker: hur
en skärmläsare uttalar orden, hur webbläsaren avstavar, och vad stavningskontrollen
rättar mot. En svensk sida med lang="en" läses upp med engelskt uttal,
vilket blir obegripligt.
Byter språket mitt i sätter du lang på det elementet i stället:
<p>Från engelskans <i lang="en">flash</i>.</p>
Skriv en sida med å ä ö i texten men utan
<meta charset="utf-8">. Ser det rätt ut gissade webbläsaren rätt –
lägg till raden ändå, för nästa webbläsare gissar kanske annat.
3. Semantik: vad ett element betyder
Det här är områdets viktigaste avsnitt.
Ett element väljs efter vad innehållet betyder, inte efter hur det ser ut.
<h1> är inte "stor fet text" – det är "sidans huvudrubrik". Att den
råkar visas stor är webbläsarens förvalda utseende, och det byter du i CSS i november.
Skillnaden märks inte när du tittar på sidan. Den märks för allt annat som läser den: skärmläsare, sökmotorer, läsläget i webbläsaren, och du själv om sex månader.
Sidans landmärken
<body>
<header>
<p>Fyrar längs Bohuskusten</p>
<nav>...</nav>
</header>
<main>
<h1>Alla fyrar</h1>
</main>
<footer>...</footer>
</body>
| Element | Betyder |
|---|---|
header | Sidhuvud – hör till sidan som helhet |
nav | Den huvudsakliga navigeringen |
main | Sidans egna innehåll. Exakt ett per sida |
footer | Sidfot – hör till sidan som helhet |
En skärmläsare kan hoppa direkt mellan landmärken. Utan dem måste användaren lyssna sig
igenom navigeringen på varje sida, varje gång. header, nav och
footer ligger utanför main, inte inuti.
Inuti main
| Element | Använd när |
|---|---|
section | En del av sidan som hör ihop och har en egen rubrik |
article | Något som är begripligt lösryckt – skulle fungera i en tidning |
aside | Hör till, men går att hoppa över |
div | Ingenting av ovanstående passar. Sista utvägen |
div betyder ingenting alls. Den finns för när du behöver en behållare utan
mening, och i det här projektet ska du nästan aldrig behöva den.
Realistiskt exempel
Ur vinga.html:
<main>
<h1>Vinga</h1>
<article>
<section>
<h2 id="historien">Historien</h2>
<p>Vinga ligger längst ut i Göteborgs skärgård...</p>
</section>
</article>
<aside>
<h2>Visste du</h2>
<p>Evert Taube växte upp på Vinga.</p>
</aside>
</main>
Texten om Vinga är en article – den skulle fungera lika bra i en tidning.
Rutan om Taube är en aside – trevlig, men sidan står utan den.
Ta en sida du besöker ofta. Rita av den på papper och sätt ut var
header, nav, main och footer går.
Öppna sedan webbläsarens verktyg och se om du gissade rätt.
4. Rubriker, stycken och listor
Rubriknivåer
<h1> till <h6>. Reglerna är två:
- En
<h1>per sida. Den säger vad just den sidan handlar om. - Hoppa inte över nivåer. Efter
h2kommerh3, aldrigh4.
Rubrikerna bildar sidans innehållsförteckning. En skärmläsare kan lista dem och hoppa
mellan dem, precis som du bläddrar i en bok. En sida som hoppar från h2 till
h4 ser för den användaren ut som en bok där ett kapitel saknas.
Välj aldrig rubriknivå efter storlek. Behöver du en mindre rubrik är det CSS som ska ändras, inte nivån.
Listor
<ul>
<li>Vinga</li>
<li>Hållö</li>
</ul>
<ol>
<li>Blink</li>
<li>Kort mörker</li>
<li>Blink</li>
</ol>
<dl>
<dt>M</dt>
<dd>Nautisk mil, 1 852 meter.</dd>
</dl>
Frågan att ställa: spelar ordningen roll? Blinkmönstret i en fyr måste komma i
rätt följd – ol. Fyrarna i en meny kan stå hur som helst – ul.
dl är för begrepp med förklaring.
En navigering är alltid en lista. Det är den som gör att skärmläsaren kan säga "meny med fyra alternativ" i stället för att bara läsa fyra länkar i rad.
Skriv om den här meningen till HTML: "Recept: hacka löken, fräs den, häll på buljong. Du behöver lök, buljong och en kastrull." Två listor, och de ska inte vara av samma sort.
5. Länkar och sökvägar
<a href="vinga.html">Läs mer om Vinga</a>
href säger vart länken går. Det finns tre sorter, och skillnaden mellan dem
är det som går sönder oftast.
Relativa sökvägar
Utgår från var den nuvarande filen ligger.
| Sökväg | Betyder |
|---|---|
vinga.html | Samma mapp som den här filen |
bilder/fyr-vinga.svg | Mappen bilder inuti den här mappen |
../index.html | Upp en mapp, sedan index.html |
Relativa sökvägar är det du ska använda. De fungerar när du flyttar mappen, när du publicerar, och på din kompis dator.
Absoluta sökvägar
Börjar med / och utgår från serverns rot, inte från din fil.
<img src="/bilder/fyr.svg"> fungerar på din dator men ger 404 på
GitHub Pages, eftersom sajten där ligger i en undermapp. Låt bli det inledande
snedstrecket.
Ankarlänkar
Hoppar till en plats på samma sida. href="#historien" letar upp elementet
med id="historien":
<a href="#historien">Historien</a>
<h2 id="historien">Historien</h2>
Ett id får bara förekomma en gång per sida.
Länktexter som fungerar lösryckta
En skärmläsare kan lista alla länkar på sidan. Då hörs bara länktexten, inte meningen omkring. En lista med sex stycken läs mer är oanvändbar.
<a href="vinga.html">läs mer</a>
<a href="vinga.html">Läs mer om Vinga</a>
Bygg fyra tomma sidor med samma navigering på alla fyra, innan du skriver någon text. Klicka runt. Hittar du ett fel nu tar det tio sekunder att laga; hittar du det i oktober har du fyrtio länkar att gå igenom.
6. Bilder och media
Vilket format en bild ska ha, hur den komprimeras och vem som äger den togs den 31 augusti. Här handlar det om uppmärkningen – hur bilden läggs in på sidan.
<img src="bilder/fyr-vinga.svg" width="240" height="360"
alt="Vinga fyr: ett fyrkantigt stentorn med glasat lanternin.">
alt-texten
alt är obligatoriskt. Det finns tre fall:
| Fallet | Vad du skriver |
|---|---|
| Bilden bär information | Beskriv vad den visar, för den som inte ser den |
| Bilden är ren dekoration | alt="" – tom, så att skärmläsaren hoppar över den |
| Bilden är en länk | Beskriv vart länken går, inte hur bilden ser ut |
Skriv inte "bild på" – att det är en bild vet användaren redan. Skriv inte filnamnet. Fråga dig: om jag läste upp sidan i telefon för någon, vad skulle jag säga här?
width och height
Ange bildens verkliga pixelmått. Då vet webbläsaren hur mycket plats den ska spara innan bilden hämtats, och sidan hoppar inte till när den dyker upp.
figure och figcaption
<figure>
<img src="bilder/kustkarta.svg" width="420" height="300"
alt="Karta över Bohuskusten med fyra fyrar utmärkta.">
<figcaption>De fyra fyrarna, söderifrån räknat.</figcaption>
</figure>
Skillnaden mot en <img> med ett <p> under är att
kopplingen blir maskinläsbar – bildtexten hör bevisligen till bilden, i stället för att
bara råka stå nära. alt och figcaption ska inte säga
samma sak: alt beskriver bilden, figcaption kommenterar den.
Ljud och video
<video controls width="640">
<source src="film.mp4" type="video/mp4">
<track kind="captions" src="undertext.vtt" srclang="sv" label="Svenska">
Din webbläsare kan inte visa video.
</video>
Undertext eller transkript är inte extra. Video utan undertext utestänger den som inte hör, och ljud utan transkript den som inte kan lyssna just då.
Skriv alt-texter till dina egna bildpaketsbilder. Läs dem sedan högt för
någon som inte sett bilderna och fråga vad de föreställer sig.
7. Tabeller
En tabell är till för data som hör ihop i rader och kolumner. Aldrig för att placera saker på sidan – det gör CSS.
<table>
<caption>Fyrarna längs Bohuskusten</caption>
<thead>
<tr>
<th scope="col">Fyr</th>
<th scope="col">Byggår</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Vinga</th>
<td>1841</td>
</tr>
</tbody>
</table>
| Del | Vad den gör |
|---|---|
caption | Tabellens rubrik. Första elementet inuti table |
thead | Raden med kolumnrubriker |
tbody | Själva datat |
th | En rubrikcell |
td | En datacell |
scope | Säger åt vilket håll rubriken gäller |
scope är det som gör tabellen läsbar
När en skärmläsare läser cellen 1841 säger den "Vinga, Byggår, 1841"
– den plockar ihop radrubriken och kolumnrubriken. Utan scope säger den bara
"1841", och tabellen blir en hög lösryckta tal.
Första cellen i varje rad är oftast en th scope="row", inte en
td. Det är den som säger vilken rad man är på.
Bygg tabellen ovan färdig med alla fyra fyrarna. Stäng sedan ögonen och låt någon läsa upp en enskild cell för dig. Kan du säga vilken fyr och vilken kolumn det gällde? Då är tabellen rätt byggd.
8. Formulär
<form action="tack.html" method="get">
<label for="namn">Fyrens namn</label>
<input type="text" id="namn" name="namn" required>
<button type="submit">Skicka</button>
</form>
label och for – kopplingen som allt hänger på
for på <label> måste vara exakt samma sträng som
id på fältet. Kopplingen gör två saker: man kan klicka på texten för att
hamna i fältet, och en skärmläsare vet vad fältet heter.
Ett fält utan label är ett fält utan namn. Ser du bara en ruta vet du inte vad som ska i den.
Input-typerna
| type | Ger |
|---|---|
text | Vanlig textrad |
email | Kontroll av adressens form, och @-tangent på telefon |
number | Sifferknappsats, och min/max |
date | Datumväljare |
tel | Sifferknappsats för telefonnummer |
checkbox | Kryssruta, flera val |
radio | Rundel, ett val i gruppen |
Rätt type är gratis tillgänglighet och gratis validering.
type="email" gör att webbläsaren själv säger till om adressen ser fel ut –
utan en rad JavaScript. För längre text används <textarea>, för kända
alternativ <select> med <option>.
fieldset och legend
<fieldset>
<legend>Om dig</legend>
<label for="epost">Din e-post</label>
<input type="email" id="epost" name="epost" required>
</fieldset>
En skärmläsare läser upp legend före varje fält i gruppen, så användaren vet
i vilket sammanhang fältet står. Det är särskilt viktigt för radioknappar – utan
legend hör man bara "Ja" och "Nej" utan att veta vad frågan
var.
name, required och method
nameär vad fältet heter när svaren skickas. Utannameskickas fältet inte alls.requiredgör fältet obligatoriskt. Webbläsaren stoppar inskickningen själv.method="get"lägger svaren i adressfältet.method="post"skickar dem dolt.
Använd get när ingenting ändras hos mottagaren, post när något
sparas. I det här området finns ingen server – därför går referensprojektets formulär till
en vanlig sida med get, så att du ser svaren dyka upp i adressen.
Bygg ett formulär med fyra fält av olika type. Fyll i det med avsiktligt
felaktiga värden – bokstäver i sifferfältet, en e-postadress utan @ – och se vad
webbläsaren säger utan att du skrivit en rad kod för det.
9. Validering och kvalitetssäkring
W3C-validatorn läser din kod och säger vad som är fel. Den finns på
validator.w3.org, och den kan läsa en publicerad adress, en uppladdad fil
eller inklistrad kod.
Validering är sista steget i varje uppgift, resten av kursen.
Att läsa ett felmeddelande
Meddelandena är på engelska och låter värre än de är. Tre du kommer att se:
| Meddelande | Betyder |
|---|---|
End tag for element X which is not open |
Du stängde något som inte var öppet – oftast en sluttagg för mycket |
Element X not allowed as child of element Y |
Elementet får inte ligga där. Till exempel en li utan ul omkring |
An img element must have an alt attribute |
Precis vad det står |
Börja alltid uppifrån. Ett fel orsakar ofta tio. En sluttagg som saknas gör att allt efter den hamnar fel, och validatorn klagar på varenda del – men det är ett fel, inte tio.
Varje rad säger From line X, column Y och visar kodutdraget. Radnumret är
hur du hittar tillbaka: i VS Code hoppar du dit med Ctrl+G.
Error, Warning och Info
Validatorn märker sina rader i tre sorter, och de betyder olika saker:
| Sort | Vad det är | Vad du gör |
|---|---|---|
| Error | Koden bryter mot standarden | Rätta. Alltid |
| Warning | Tillåtet, men förmodligen inte det du menade | Läs och bestäm dig |
| Info | En upplysning | Ingenting |
Kravet i kursen är noll Error. Warnings tittar du på och tar ställning till.
Varför det spelar roll
En webbläsare försöker rädda trasig HTML i stället för att vägra visa sidan. Det låter snällt, men betyder att felen inte syns – förrän någon öppnar sidan i en annan webbläsare som gissar annorlunda. Validatorn är det enda som säger till innan.
Granskningschecklistan
Validatorn hittar det som bryter mot standarden. Den kan inte se om koden betyder
rätt sak – en alt-text som lyder bild validerar utan anmärkning
och hjälper ingen.
Den här listan är resten. Använd den när du granskar en kamrats sajt, och på din egen innan du lämnar in. En rad i taget, en sida i taget.
Granskning
Granskar du någon annans sajt skriver du ned vad du hittade och var – sida, radnummer, vad som är fel. Den som byggde sajten rättar själv. Annars lär sig ingen av er något, och den som byggde vet inte vad som ändrades.
Validera en sida du redan tycker är klar. Nästan alla får fel första gången. Laga det översta felet, validera om, och se hur många av de andra som försvann på köpet.
10. Interoperabilitet och användaragenter
Varför standarder finns
På 1990-talet uppfann webbläsartillverkarna egna element. En sida byggd för den ena fungerade inte i den andra, och sajter skrev "fungerar bäst i…" i stället för att fungera. Det kallas webbläsarkriget, och det var användarna som förlorade.
W3C och WHATWG skriver standarden som alla webbläsare följer. Det är därför din sida fungerar i webbläsare du aldrig testat, och i webbläsare som inte fanns när du skrev den.
Användaragent
Allt som hämtar och tolkar din sida. Det är fler än du tror:
- Webbläsare på dator, telefon och surfplatta
- Skärmläsare – läser upp sidan för den som inte ser
- Sökrobotar – läser sidan för att indexera den
- Läsläget i webbläsaren, som plockar ut brödtexten
- Uppläsningsfunktioner i telefoner och bilar
Ingen av dem ser din sida. De läser den. Det är därför semantik är viktigare än utseende: utseendet finns bara för en av användaragenterna.
Testa i två webbläsare
| Vad | Varför |
|---|---|
| Formulärfält ser olika ut | Varje webbläsare ritar dem på sitt sätt |
| Rubrikstorlekar skiljer något | Förvalda stilar skiljer sig |
| Datumväljaren ser helt olika ut | type="date" ritas av operativsystemet |
Det är förväntat och rätt. Din sida ska inte se identisk ut överallt – den ska fungera överallt.
Avvikelselistan
När du korstestar skriver du ned varje skillnad du ser och avgör vilken sort den är. Det är sorteringen som är själva arbetet – en lista utan den kolumnen går inte att göra något med.
| Sida | Var jag såg det | Vad som skiljer | Förväntad eller fel |
|---|---|---|---|
rapportera.html | Firefox mot Chrome | Fälten har olika rundade hörn | Förväntad |
index.html | Telefon | Bilden laddar inte, 404 | Fel |
fyrarna.html | Telefon | Tabellen är bredare än skärmen | Fel |
Förväntad – webbläsaren ritar något på sitt eget sätt. Formulärfältens form, knapparnas utseende, rubrikstorlekar som skiljer några pixlar, datumväljaren som ritas av operativsystemet.
Fel – något fungerar inte. En bild som inte laddar, en länk som ger 404, text som ligger utanför skärmen, ett fält det inte går att skriva i.
Felen blir din arbetslista. De förväntade skillnaderna lämnar du i fred.
Filnamn med versaler ger 404 på telefonen
En bild eller en länk som fungerar på din dator men ger 404 på den publicerade sajten
beror nästan alltid på stora och små bokstäver i filnamn. Windows ser
Bilder/Vinga.jpg och bilder/vinga.jpg som samma fil. GitHub
Pages gör det inte.
Skriv allt med gemener, både filnamn och sökvägar.
Öppna din sajt i två webbläsare bredvid varandra. Skriv ned tre skillnader och en mening om varför var och en är ofarlig.
11. Ta det längre
För dig som siktar mot C och A.
- Tangentbordsnavigering. Tryck Tab genom din sajt utan att röra musen. Kommer du åt varje länk och varje fält? Ordningen följer koden, så en sida som är byggd i fel ordning känns fel att navigera.
- Läsläget. De flesta webbläsare har ett läsläge som plockar ut artikeltexten och
kastar resten. Fungerar det på din sida är semantiken rätt. Blir läsläget tomt ligger
texten i
div-ar som ingen förstår. - Skärmläsare. Windows har Skärmläsaren inbyggd, Mac har VoiceOver. Slå på den
och blunda i två minuter på din egen sajt. Det är den snabbaste vägen till att förstå
varför
alt,labelochscopefinns. - Två nav på samma sida – huvudmenyn och en innehållsförteckning – kan skiljas åt
med
<nav aria-label="Innehåll på sidan">. - Sidbeskrivning.
<meta name="description" content="…">iheadär den text som ofta visas i sökresultat.
12. Felsökning
11 rader
| Symptom | Trolig orsak | Åtgärd |
|---|---|---|
Å ä ö visas som ä | meta charset saknas eller står för långt ned | Lägg den först i head |
| Bilden syns inte lokalt | Fel sökväg eller fel skiftläge i filnamnet | Jämför filnamnet tecken för tecken |
| Bilden syns lokalt men inte publicerad | Sökvägen börjar med / | Ta bort snedstrecket |
| Länken ger 404 efter publicering | Vinga.html mot vinga.html | Servern skiljer på stora och små bokstäver, din dator gör det inte |
| Ankarlänken hoppar ingenstans | Inget element har det id:t | Kontrollera stavningen på båda ställena |
| Halva sidan blev fet eller kursiv | En sluttagg saknas | Validera – felet står vid första trasiga taggen |
| Tabellen läses som lösryckta tal | scope saknas på rubrikcellerna | Sätt scope="col" och scope="row" |
| Klick på etiketten gör ingenting | for och id stämmer inte överens | De ska vara exakt lika, tecken för tecken |
| Fältet kommer inte med när formuläret skickas | Fältet saknar name | Lägg till name |
| Sidan ser konstig ut i en webbläsare | Trasig HTML som webbläsarna räddar olika | Validera |
| Validatorn ger trettio fel | Ett fel har orsakat de andra | Laga det översta och validera om |
13. Snabbreferens: taggarna
Alla element här kan komma på prov 1, utom video, audio,
source och track. Provet ställer frågor om
referensprojektets kod, och det projektet innehåller ingen media. Media är utmaningsnivå i
Projekt 1 – lär dig det ändå, men plugga inte på det inför provet.
Träna på taggarna
47 rader
| Element | Betyder | Grupp |
|---|---|---|
| <!doctype html> | Modern HTML. Först i filen | Dokumentet |
| html lang | Omsluter allt. Anger språk | Dokumentet |
| head | Information om sidan | Dokumentet |
| meta charset | Teckenkodning. Först i head | Dokumentet |
| title | Sidans namn. Flik, bokmärke, sökresultat | Dokumentet |
| body | Innehållet | Dokumentet |
| header | Sidhuvud | Struktur |
| nav | Navigering | Struktur |
| main | Sidans egna innehåll. Ett per sida | Struktur |
| section | Avsnitt med egen rubrik | Struktur |
| article | Begripligt lösryckt | Struktur |
| aside | Hör till, går att hoppa över | Struktur |
| footer | Sidfot | Struktur |
| div | Behållare utan betydelse. Sista utvägen | Struktur |
| h1–h6 | Rubriknivåer. En h1 per sida | Text |
| p | Stycke | Text |
| ul | Lista utan ordning | Text |
| ol | Lista med ordning | Text |
| li | Listpunkt | Text |
| dl | Beskrivningslista | Text |
| dt | Term i en beskrivningslista | Text |
| dd | Förklaring i en beskrivningslista | Text |
| strong | Viktigt | Text |
| em | Betonat | Text |
| code | Kod | Text |
| br | Radbrytning inuti ett stycke | Text |
| a href | Länk | Länkar och media |
| img src alt | Bild. alt är obligatoriskt | Länkar och media |
| figure | Bild med bildtext | Länkar och media |
| figcaption | Bildtexten i en figure | Länkar och media |
| table | Tabellen | Tabell |
| caption | Tabellens rubrik. Först inuti table | Tabell |
| thead | Tabellens rubrikdel | Tabell |
| tbody | Tabellens datadel | Tabell |
| tr | Rad i en tabell | Tabell |
| th scope | Rubrikcell. scope säger åt vilket håll den gäller | Tabell |
| td | Datacell | Tabell |
| form action method | Formuläret | Formulär |
| label for | Etikett. for är fältets id | Formulär |
| input type name | Fält | Formulär |
| textarea | Flerradigt fält | Formulär |
| select | Rullgardin | Formulär |
| option | Alternativ i en select | Formulär |
| fieldset | Fältgrupp | Formulär |
| legend | Fältgruppens rubrik | Formulär |
| button | Knapp. type submit skickar formuläret | Formulär |
| required | Obligatoriskt fält | Formulär |