← Alle guider

Komplet Begynderguide til HTML, CSS og JavaScript

Velkommen! Denne guide er lavet til dig, som aldrig har skrevet en eneste linje kode før. Måske har du set hjemmesider og tænkt "hvordan pokker laver man det?" – nu får du svaret. Trin for trin. Uden stress.

Tag det roligt. Du behøver ikke lære alt på én gang. Bare læs med, prøv det af, og mærk hvor fedt det er at se dine egne ideer blive til virkelighed på skærmen.


Indholdsfortegnelse

  1. Hvad er HTML, CSS og JavaScript?
  2. Hvad skal du bruge?
  3. Dit første website
  4. HTML basics
  5. HTML struktur
  6. CSS basics
  7. CSS layout
  8. CSS frameworks
  9. JavaScript basics
  10. DOM manipulation
  11. Fetch API
  12. Hosting
  13. Domæne
  14. Tips til begyndere
  15. Næste skridt
  16. Eksempel-projekt
  17. HTML & CSS for danske freelancere

1. Hvad er HTML, CSS og JavaScript?

Forestil dig at du bygger et hus.

HTML er skelettet. Det er væggene, taget, dørene og vinduerne. Uden HTML er der ingenting – bare tomhed. HTML bestemmer hvad der er på siden: overskrifter, tekst, billeder, links, knapper.

CSS er tøjet og interiøret. Det er farverne på væggene, møblerne, fonten på skiltene, afstanden mellem rummene. Uden CSS ser dit website ud som et word-dokument fra 1995. CSS gør det pænt.

JavaScript er hjernen. Det er alt der bevæger sig, reagerer og interagerer. Når du klikker en knap og noget sker – det er JavaScript. Når du udfylder en formular og får en fejlmeddelelse – JavaScript. Når et billede skifter automatisk – JavaScript.

Sådan husker du det:

Du behøver ikke mestre det hele på én gang. De fleste starter med HTML, tilføjer lidt CSS, og så JavaScript når de føler sig klar. Netop denne guide hjælper dig med det.


2. Hvad skal du bruge?

Her er den gode nyhed: du skal ikke bruge penge på noget som helst.

Du skal kun bruge to ting:

1. En kodeeditor

Dette er det program hvor du skriver din kode. Den mest populære (og gratis) er Visual Studio Code (ofte bare kaldet VS Code).

Tip: Når du har installeret VS Code, så installer udvidelsen "Live Server". Den gør at din hjemmeside opdaterer sig automatisk når du gemmer dine filer – super fedt til at se ændringer i realtid!

2. En webbrowser

Du har allerede en. Chrome, Firefox, Edge, Safari – de virker alle sammen. Chrome anbefales fordi den har de bedste udviklerværktøjer (DevTools).

Det var det. Ingen server, ingen database, ingen komplicerede opsætninger. Bare en editor og en browser.


3. Dit første website

Lad os komme i gang med det samme! Følg disse trin:

Trin 1: Opret en mappe

Opret en ny mappe på dit skrivebord eller i dine dokumenter. Kald den mit-første-website.

Trin 2: Opret HTML-filen

Åbn VS Code. Gå til File > Open Folder og vælg den mappe du lige oprettede.

Klik på "New File" ikonet (det ligner et dokument med et plus) og navngiv filen index.html.

Trin 3: Skriv din første kode

Skriv følgende i filen:

<!DOCTYPE html>
    <html lang="da">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Mit første website</title>
    </head>
    <body>
        <h1>Hej verden!</h1>
        <p>Dette er mit allerførste website. Jeg er så stolt!</p>
    </body>
    </html>
    

Trin 4: Åbn i browseren

Højreklik på index.html i VS Code og vælg "Open with Live Server" (hvis du installerede udvidelsen). Ellers kan du bare dobbeltklikke på filen i din mappe.

Tillykke! Du har lige lavet dit første website. Det ser måske ikke ud af meget, men du er nu officielt en der kan kode. 🎉

Hvad skete der lige?

Lad os bryde koden ned:


4. HTML basics

HTML bruger "tags" til at definere indhold. De ser sådan her ud: <tag>indhold</tag>

De vigtigste tags

Overskrifter: <h1> til <h6>

<h1>Største overskrift</h1>
    <h2>Underoverskrift</h2>
    <h3>Endnu mindre</h3>
    <h4>og så videre...</h4>
    <h5>...hele vejen ned til...</h5>
    <h6>...den mindste overskrift</h6>
    

Husk: Brug kun ét h1 per side (det er din hovedoverskrift). Brug h2 til hovedafsnit, h3 til underafsnit osv.

Afsnit: <p>

<p>Dette er et tekstafsnit. Browseren sørger automatisk for mellemrum mellem afsnit.</p>
    <p>Dette er et nyt afsnit. Du behøver ikke trykke enter to gange – bare start et nyt p-tag.</p>
    

Links: <a>

<a href="https://google.com">Klik her for at komme til Google</a>
    <a href="om-mig.html">Læs mere om mig</a>
    <a href="mailto:hej@example.com">Send mig en mail</a>
    

Attributten href bestemmer hvor linket fører hen.

Billeder: <img>

<img src="billede.jpg" alt="Et flot billede af min kat">
    

Bemærk: <img> er et "self-closing" tag – det har ikke en lukke-tag. alt-attributten er vigtig – den beskriver billedet for skærmlæsere og vises hvis billedet ikke kan loades.

Divisions: <div>

<div class="container">
        <h2> Overskrift her</h2>
        <p>Indhold her</p>
    </div>
    

<div> er en generisk beholder. Den gør ikke noget specielt i sig selv, men den er fantastisk til at gruppere indhold så du kan style det med CSS.

Navigation: <nav>

<nav>
        <a href="index.html">Forside</a>
        <a href="om.html">Om mig</a>
        <a href="kontakt.html">Kontakt</a>
    </nav>
    

Sektioner: <section>

<section>
        <h2>Om mig</h2>
        <p>Jeg er webudvikler...</p>
    </section>
    

Attributes

Attributes giver ekstra information til tags. De sidder i åbningstagen:

<a href="https://google.com" target="_blank" title="Åbner i nyt faneblad">Google</a>
    

Head vs Body

<!DOCTYPE html>
    <html>
      <head>
        <!-- META-data: ting browseren skal vide -->
        <!-- Title, charset, links til CSS, osv. -->
      </head>
      <body>
        <!-- SYNligt indhold: overskrifter, tekst, billeder, knapper -->
      </body>
    </html>
    

Husk: Alt det pæne (CSS) og kloge (JavaScript) lægger du i <head>. Alt det synlige lægger du i <body>.


5. HTML struktur

Semantisk HTML

"Semantisk HTML" betyder at du bruger de rigtige tags til det rigtige formål. Det gør dit website mere tilgængeligt og lettere at vedligeholde.

I stedet for:

<div class="header">
      <div class="nav">...</div>
    </div>
    <div class="content">...</div>
    <div class="footer">...</div>
    

Så skriv:

<header>
      <nav>...</nav>
    </header>
    <main>...</main>
    <footer>...</footer>
    

Semantiske tags at kende:

Lists

Punktopstilling (unordered):

<ul>
        <li>Æbler</li>
        <li>Bananer</li>
        <li>Cherry</li>
    </ul>
    

Nummereret (ordered):

<ol>
        <li>Først gør du dette</li>
        <li>Så gør du dette</li>
        <li>Til sidst gør du dette</li>
    </ol>
    

Tables

<table>
        <thead>
            <tr>
                <th>Navn</th>
                <th>Alder</th>
                <th>By</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Maria</td>
                <td>28</td>
                <td>København</td>
            </tr>
            <tr>
                <td>Peter</td>
                <td>34</td>
                <td>Aarhus</td>
            </tr>
        </tbody>
    </table>
    

Forms

Forms er super vigtige – de lader brugeren indtaste data.

<form action="/send" method="POST">
        <label for="navn">Dit navn:</label>
        <input type="text" id="navn" name="navn" required>

        <label for="email">Din email:</label>
        <input type="email" id="email" name="email" required>

        <label for="besked">Besked:</label>
        <textarea id="besked" name="besked" rows="4"></textarea>

        <button type="submit">Send</button>
    </form>
    

Vigtige form-elementer:


6. CSS basics

CSS (Cascading Style Sheets) er det der får dit website til at se fantastisk ud.

Sådan tilføjer du CSS

Der er tre måder:

1. Inline (ikke anbefalet):

<p style="color: red; font-size: 20px;">Rød tekst</p>
    

2. Intern (god til små projekter):

<head>
        <style>
            p {
                color: red;
                font-size: 20px;
            }
        </style>
    </head>
    

3. Ekstern fil (bedste praksis):

<head>
        <link rel="stylesheet" href="style.css">
    </head>
    

Opret en fil der hedder style.css i samme mappe som dit HTML.

Selectors

Selectors bestemmer hvilke elementer du vil style.

/* Element-selector: alle p-tags */
    p {
        color: blue;
    }

    /* Class-selector: alle med class="vigtig" */
    .vigtig {
        font-weight: bold;
        color: red;
    }

    /* ID-selector: kun det med id="banner" */
    #banner {
        background-color: yellow;
        padding: 20px;
    }
    

Prioritet: ID > Class > Element. Så #banner slår .vigtig som slår p.

Farver

/* Navne */
    color: red;
    background-color: lightblue;

    /* Hex (mest brugt) */
    color: #ff0000;
    background-color: #00bfff;

    /* RGB */
    color: rgb(255, 0, 0);
    background-color: rgba(0, 191, 255, 0.5); /* med transparency */
    

Tip: Brug colorpicker.com eller coolors.co til at finde flotte farver.

Fonts

body {
        font-family: 'Arial', sans-serif;
        font-size: 16px;
        line-height: 1.6;
    }

    h1 {
        font-size: 2.5em;
        font-weight: bold;
    }
    

Brug Google Fonts for flottere typografi:

  1. Gå til fonts.google.com
  2. Vælg en skrifttype
  3. Kopier link-tagget og sæt det i dit <head>
  4. Brug den i dit CSS
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
    
body {
        font-family: 'Poppins', sans-serif;
    }
    

Margin og Padding (Box Model)

Forestil dig en æske. Indeni æsken er dit indhold (content). Mellem indholdet og kanten er padding. Uden for kanten er margin.

┌───────────────────────────┐ ← Margin (yderrum)
    │ ┌───────────────────────┐ │ ← Padding (indre rum)
    │ │                       │ │
    │ │      DIT INDHOLD     │ │
    │ │                       │ │
    │ └───────────────────────┘ │
    └───────────────────────────┘
    
.boks {
        /* Indvendigt rum (mellem indhold og kant) */
        padding: 20px;           /* alle sider */
        padding-top: 10px;       /* kun top */
        padding: 10px 20px;      /* top/bund, venstre/højre */

        /* Udvendigt rum (mellem denne og andre elementer) */
        margin: 20px;            /* alle sider */
        margin-top: 0;           /* kun top */
        margin: 0 auto;          /* centrerer水平t! */
    }
    

Border

.boks {
        border: 2px solid #333;
        border-radius: 10px;  /* afrundede hjørner */
    }
    

7. CSS layout

Flexbox (det vigtigste at lære!)

Flexbox er en måde at lægge elementer ud på. Det er fantastisk til at centrere ting, lave rækker, og fordele plads.

.container {
        display: flex;
        justify-content: center;    /* vandret centreret */
        align-items: center;        /* lodret centreret */
        gap: 20px;                  /* mellemrum mellem elementer */
        flex-wrap: wrap;            /* hop til ny linje ved behov */
    }
    

De vigtigste Flexbox-værdier:

justify-content (vandret):

align-items (lodret):

Praktisk eksempel – navigation:

nav {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 1rem 2rem;
    }

    nav ul {
        display: flex;
        gap: 1.5rem;
        list-style: none;
    }
    

Centrering af indhold (den klassiske måde):

.hero {
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;  /* fylder hele skærmen */
        text-align: center;
    }
    

CSS Grid

Grid er mere avanceret end Flexbox og perfekt til 2D-layouts (rækker OG kolonner).

.grid-container {
        display: grid;
        grid-template-columns: repeat(3, 1fr); /* 3 lige brede kolonner */
        gap: 20px;
    }

    @media (max-width: 768px) {
        .grid-container {
            grid-template-columns: 1fr; /* 1 kolonne på mobil */
        }
    }
    

Responsivt design

Responsivt design betyder at dit website ser godt ud på alle enheder – mobil, tablet og computer.

Media Queries er nøglen:

/* Mobil først (standard) */
    .container {
        padding: 10px;
    }

    /* Tablet */
    @media (min-width: 768px) {
        .container {
            padding: 20px;
        }
    }

    /* Desktop */
    @media (min-width: 1024px) {
        .container {
            padding: 40px;
            max-width: 1200px;
            margin: 0 auto;
        }
    }
    

Tip: Tænk "mobil først". Skriv CSS til mobil, og tilføj breakpoints til større skærme.

Praktisk eksempel – et responsivt layout

<!DOCTYPE html>
    <html lang="da">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Responsivt layout</title>
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }

            body {
                font-family: Arial, sans-serif;
            }

            header {
                background: #333;
                color: white;
                padding: 1rem;
            }

            nav {
                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .hero {
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
                text-align: center;
                padding: 4rem 1rem;
            }

            .cards {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
                gap: 1.5rem;
                padding: 2rem;
            }

            .card {
                border: 1px solid #ddd;
                border-radius: 8px;
                padding: 1.5rem;
                text-align: center;
            }

            footer {
                background: #333;
                color: white;
                text-align: center;
                padding: 1rem;
            }
        </style>
    </head>
    <body>
        <header>
            <nav>
                <div class="logo">Mit Website</div>
                <ul>
                    <li><a href="#">Hjem</a></li>
                    <li><a href="#">Om</a></li>
                    <li><a href="#">Kontakt</a></li>
                </ul>
            </nav>
        </header>

        <section class="hero">
            <h1>Velkommen til mit website</h1>
            <p>Bygget med ren HTML og CSS</p>
        </section>

        <div class="cards">
            <div class="card">
                <h3>Kort 1</h3>
                <p>Indhold her</p>
            </div>
            <div class="card">
                <h3>Kort 2</h3>
                <p>Indhold her</p>
            </div>
            <div class="card">
                <h3>Kort 3</h3>
                <p>Indhold her</p>
            </div>
        </div>

        <footer>
            <p>&copy; 2026 Mit Website</p>
        </footer>
    </body>
    </html>
    

8. CSS frameworks

Tailwind CSS (Utility-First)

Tailwind er et "utility-first" framework. I stedet for at skrive dine egne klasser, bruger du små utility-klasser direkte i HTML.

<div class="bg-blue-500 text-white p-4 rounded-lg shadow-md">
        <h2 class="text-xl font-bold">Hej med dig</h2>
        <p class="mt-2">Dette er stylet med Tailwind</p>
    </div>
    

Fordele:

Ulemper:

Bootstrap (Component-Based)

Bootstrap er et ældre og mere etableret framework. Det er "component-baseret" – du bruger færdige komponenter.

<div class="container">
        <div class="row">
            <div class="col-md-4">
                <div class="card">
                    <div class="card-body">
                        <h5 class="card-title">Kort titel</h5>
                        <p class="card-text">Kort tekst</p>
                        <a href="#" class="btn btn-primary">Læs mere</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
    

Fordele:

Ulemper:

Hvornår bruger man hvad?

Situation Anbefaling
Lære CSS grundlæggende Ingen framework – skriv det selv
Hurtigt projekt/poc Tailwind eller Bootstrap
Unikt design Ingen framework eller Tailwind
Komponent-tungt site Bootstrap
Moderne, let site Tailwind

Min anbefaling: Lær CSS først. Når du forstår det, så prøv Tailwind. Det vil give dig mere mening.


9. JavaScript basics

JavaScript gør dit website levende.

Variabler

Tænk på variabler som kasser med navne på. I kassen kan du opbevare ting.

// Moderne måde (brug const og let)
    const navn = "Anna";           // Kan ikke ændres
    let alder = 25;                // Kan ændres
    const erStuderende = true;     // Sandt/falsk

    // Ændr en variabel
    alder = 26;

    // Vis i konsollen (brug DevTools)
    console.log("Hej, jeg hedder " + navn);
    console.log(`Jeg er ${alder} år`);  // Template literal (bedre)
    

Regel: Brug const som standard. Brug let når du skal ændre værdien. Undgå var.

Funktioner

Funktioner er genbrugelig kode. Skriv den én gang, brug den mange gange.

// Klassisk funktion
    function hils(navn) {
        return `Hej, ${navn}! Velkommen!`;
    }

    // Arrow function (moderne)
    const hils2 = (navn) => {
        return `Hej, ${navn}! Velkommen!`;
    };

    // Kort arrow function
    const hils3 = (navn) => `Hej, ${navn}! Velkommen!`;

    // Brug funktionen
    console.log(hils("Peter"));  // "Hej, Peter! Velkommen!"
    

If/Else (Betingelser)

const alder = 18;

    if (alder >= 18) {
        console.log("Du er myndig");
    } else {
        console.log("Du er ikke myndig endnu");
    }

    // Flere betingelser
    const karakter = "B";

    if (karakter === "A") {
        console.log("Fremragende!");
    } else if (karakter === "B") {
        console.log("Rigtig godt!");
    } else {
        console.log("Fortsæt med at øve dig");
    }
    

Loops

Loops gentager kode.

// For loop
    for (let i = 0; i < 5; i++) {
        console.log(`Iteration ${i}`);
    }

    // While loop
    let tæller = 0;
    while (tæller < 5) {
        console.log(`Tæller: ${tæller}`);
        tæller++;
    }

    // forEach (til arrays)
    const frugter = ["æble", "banan", "cherry"];
    frugter.forEach((frugt, index) => {
        console.log(`${index}: ${frugt}`);
    });
    

Arrays

Arrays er lister.

const farver = ["rød", "grøn", "blå"];

    console.log(farver[0]);  // "rød" (null-baseret!)
    console.log(farver.length);  // 3

    // Tilføj
    farver.push("gul");

    // Fjern
    farver.pop();

    // Find
    const længde3 = farver.find(f => f.length === 3);
    

Events (Hændelser)

Events er hvordan JavaScript reagerer på brugerens handlinger.

// Klik på en knap
    const knap = document.getElementById("minKnap");

    knap.addEventListener("click", function() {
        alert("Du klikkede på knappen!");
    });

    // Formular indsendelse
    const form = document.getElementById("minForm");

    form.addEventListener("submit", function(event) {
        event.preventDefault(); // Forhindrer default opførsel
        console.log("Formen blev sendt!");
    });

    // Musen bevæger sig
    document.addEventListener("mousemove", function(event) {
        console.log(`Mus: ${event.clientX}, ${event.clientY}`);
    });

    // Tastatur
    document.addEventListener("keydown", function(event) {
        console.log(`Tast: ${event.key}`);
    });
    

10. DOM manipulation

DOM (Document Object Model) er hvordan JavaScript ser og ændrer dit HTML.

Find elementer

// Ved ID
    const overskrift = document.getElementById("overskrift");

    // Ved class (flere elementer)
    const paragraffer = document.getElementsByClassName("tekst");

    // Ved CSS selector (et element)
    const første = document.querySelector(".tekst");

    // Ved CSS selector (flere elementer)
    const alle = document.querySelectorAll(".tekst");
    

Ændr indhold

// Tekst
    overskrift.textContent = "Ny overskrift";

    // HTML (brug med forsigtighed!)
    overskrift.innerHTML = "<em>Ny</em> overskrift";

    // Attributter
    const billede = document.querySelector("img");
    billede.src = "nyt-billede.jpg";
    billede.alt = "Nyt billede";
    

Tilføj/fjern CSS-klasser

const element = document.querySelector(".card");

    // Tilføj klasse
    element.classList.add("aktiv");

    // Fjern klasse
    element.classList.remove("aktiv");

    // Skift klasse (toggle)
    element.classList.toggle("aktiv");
    

Vis/skjul elementer

const popup = document.querySelector(".popup");

    // Vis
    popup.style.display = "block";

    // Skjul
    popup.style.display = "none";

    // Bedre måde med CSS-klasser
    popup.classList.add("skjult");
    popup.classList.remove("skjult");
    

Opret nye elementer

const liste = document.querySelector("ul");

    // Opret nyt element
    const nytElement = document.createElement("li");
    nytElement.textContent = "Nyt punkt";

    // Tilføj til siden
    liste.appendChild(nytElement);
    

Praktisk eksempel: Tema-skifter

<!DOCTYPE html>
    <html lang="da">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Tema-skifter</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                padding: 2rem;
                transition: background 0.3s, color 0.3s;
            }

            body.mørk {
                background-color: #1a1a1a;
                color: white;
            }

            button {
                padding: 0.5rem 1rem;
                font-size: 1rem;
                cursor: pointer;
            }
        </style>
    </head>
    <body>
        <h1>Skift tema</h1>
        <p>Klik på knappen for at skifte mellem lyst og mørkt tema.</p>
        <button id="temaKnap">Skift tema</button>

        <script>
            const temaKnap = document.getElementById("temaKnap");

            temaKnap.addEventListener("click", function() {
                document.body.classList.toggle("mørk");

                if (document.body.classList.contains("mørk")) {
                    temaKnap.textContent = "Skift til lyst tema";
                } else {
                    temaKnap.textContent = "Skift til mørkt tema";
                }
            });
        </script>
    </body>
    </html>
    

Formularvalidering

const form = document.querySelector("form");
    const email = document.querySelector("#email");

    form.addEventListener("submit", function(event) {
        event.preventDefault();

        // Tjek om email er gyldig
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

        if (!emailRegex.test(email.value)) {
            alert("Indtast venligst en gyldig email");
            return;
        }

        // Hvis alt er ok
        alert("Tak for din besked!");
        form.reset();
    });
    

11. Fetch API

Fetch API lader dig hente data fra andre hjemmesider (API'er).

Grundlæggende fetch

fetch("https://jsonplaceholder.typicode.com/users")
        .then(response => response.json())
        .then(data => {
            console.log(data);
            // Vis data på din side
        })
        .catch(error => {
            console.error("Der gik noget galt:", error);
        });
    

Med async/await (moderne)

async function hentBrugere() {
        try {
            const response = await fetch("https://jsonplaceholder.typicode.com/users");
            const data = await response.json();

            const liste = document.querySelector("#brugerListe");

            data.forEach(bruger => {
                const li = document.createElement("li");
                li.textContent = `${bruger.name} - ${bruger.email}`;
                liste.appendChild(li);
            });
        } catch (error) {
            console.error("Fejl:", error);
        }
    }

    hentBrugere();
    

Praktisk eksempel: Vejr-app

<!DOCTYPE html>
    <html lang="da">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vejr-app</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                max-width: 400px;
                margin: 2rem auto;
                padding: 0 1rem;
            }

            .vejr-kort {
                border: 1px solid #ddd;
                border-radius: 10px;
                padding: 1.5rem;
                text-align: center;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
            }

            input, button {
                width: 100%;
                padding: 0.75rem;
                margin-bottom: 0.5rem;
                font-size: 1rem;
                border-radius: 5px;
                border: 1px solid #ddd;
            }

            button {
                background: #667eea;
                color: white;
                border: none;
                cursor: pointer;
            }

            button:hover {
                background: #5a6fd6;
            }
        </style>
    </head>
    <body>
        <h1>Vejr-app</h1>
        <input type="text" id="by" placeholder="Indtast by (f.eks. København)">
        <button onclick="hentVejr()">Hent vejr</button>

        <div id="vejrResultat"></div>

        <script>
            async function hentVejr() {
                const by = document.getElementById("by").value;
                const resultat = document.getElementById("vejrResultat");

                if (!by) {
                    alert("Indtast venligst en by");
                    return;
                }

                try {
                    // Brug Open-Meteo (gratis, ingen API-nøgle)
                    const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${by}&count=1&language=da`;
                    const geoResponse = await fetch(geoUrl);
                    const geoData = await geoResponse.json();

                    if (!geoData.results || geoData.results.length === 0) {
                        resultat.innerHTML = "<p>By ikke fundet</p>";
                        return;
                    }

                    const { latitude, longitude, name } = geoData.results[0];

                    const vejrUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current_weather=true`;
                    const vejrResponse = await fetch(vejrUrl);
                    const vejrData = await vejrResponse.json();

                    const temp = vejrData.current_weather.temperature;
                    const vind = vejrData.current_weather.windspeed;

                    resultat.innerHTML = `
                        <div class="vejr-kort">
                            <h2>${name}</h2>
                            <p style="font-size: 3rem; margin: 1rem 0;">${temp}°C</p>
                            <p>Vind: ${vind} km/t</p>
                        </div>
                    `;
                } catch (error) {
                    resultat.innerHTML = "<p>Der gik noget galt. Prøv igen.</p>";
                }
            }
        </script>
    </body>
    </html>
    

12. Hosting

Hosting er når du lægger dit website online så alle kan se det.

GitHub Pages (gratis)

Bedst til: Statiske sites, porteføljer, dokumentation.

  1. Opret en GitHub-konto på github.com
  2. Installer Git på din computer
  3. Opret et nyt repository kaldet dit-brugernavn.github.io
  4. Upload dine filer
  5. Gå til Settings > Pages
  6. Vælg "main" branch
  7. Dit site er live på https://dit-brugernavn.github.io

Alternativ i Danmark: Du kan også bruge Simply.com eller UnoEuro til at hoste dine statiske sider — begge har dansk support og betaling i DKK.

Netlify (gratis)

Bedst til: Moderne projekter, hurtigere deployment.

  1. Opret konto på netlify.com
  2. Træk og slip din mappe ind
  3. Færdig! Du får et link med det samme

Du kan også forbinde dit GitHub-repository og få automatisk deployment.

Alternativ i Danmark: NordicWay tilbyder statisk webhotel med dansk support og fakturering i DKK.

Vercel (gratis)

Bedst til: React, Next.js, og andre frameworks.

  1. Opret konto på vercel.com
  2. Forbind dit GitHub-repository
  3. Vercel genkender frameworket og bygger automatisk
  4. Dit site er live med det samme

Alternativ i Danmark: Til Next.js-projekter er Vercel stadig bedst, men du kan også hoste på danske servere via Simply.com's Node.js-hosting.

Tip: For et simpelt HTML/CSS/JS-site er Netlify nemmest. Bare træk og slip din mappe.


13. Domæne

Et domæne er dit hjemmenavn på internettet. F.eks. mitwebsite.dk.

Hvor kan du købe domæner?

Tips til valg af domæne

Danske forhold

Sådan sætter du dit domæne op

Når du har købt et domæne, skal du pege det mod din hosting:

  1. Gå til dit domænes DNS-indstillinger
  2. Tilføj en "CNAME"-post der peger mod din hosting (f.eks. your-site.netlify.app)
  3. Vent 24-48 timer på at det udbreder sig

14. Tips til begyndere

1. Giv aldrig op

Alle der kan kode i dag, har engang været completely confused. Det er normalt. Når du sidder fast, så tag en pause, gå en tur, og kom tilbage med friske øjne.

2. Øv dig hver dag

Det behøver ikke være timer hver dag. Bare 15-30 minutters øvelse gør en forskel over tid. Konsistens slår intensitet.

3. Kopier og modificér

Find et website du synes er flot. Prøv at kopiere det. Du lærer enormt meget ved at se hvordan andre har løst problemer. Det er ikke snyd – det er sådan alle lærer.

4. Brug DevTools

Højreklik på ethvert website og vælg "Inspektér" (eller tryk F12). Her kan du se:

Du kan endda ændre ting midlertidigt for at eksperimentere!

5. Byg projekter

Teori er fint, men praksis er bedre. Byg ting:

6. Søg hjælp

7. Læs andres kode

Gå på GitHub og se hvordan andre har bygget projekter. Du vil opdage nye teknikker og mønstre.

8. Vær tålmodig

Det tager tid at blive god. De fleste siger det tager 6-12 måneder at lære det grundlæggende. Men allerede efter et par uger vil du kunne lave simple ting – og det er super motiverende!


15. Næste skridt

Når du har styr på HTML, CSS og JavaScript grundlæggende, er det tid til at udforske mere.

Frontend Frameworks

Disse frameworks gør det nemmere at bygge store, komplekse applikationer:

React (af Facebook)

Vue.js

Svelte

Min anbefaling: Lær React. Det er det mest efterspurgte på jobmarkedet, og der er flest ressourcer til rådighed.

Backend (hvis du vil bygge hele applikationer)

Database


16. Eksempel-projekt: Personlig portfolio

Lad os samle alt du har lært og bygge et komplet portfolio-site.

Struktur

portfolio/
    ├── index.html
    ├── style.css
    └── script.js
    

index.html

<!DOCTYPE html>
    <html lang="da">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Mit Portfolio - [Dit Navn]</title>
        <link rel="stylesheet" href="style.css">
        <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
    </head>
    <body>
        <header>
            <nav>
                <div class="logo">[Dit Navn]</div>
                <ul>
                    <li><a href="#hjem">Hjem</a></li>
                    <li><a href="#om">Om mig</a></li>
                    <li><a href="#projekter">Projekter</a></li>
                    <li><a href="#kontakt">Kontakt</a></li>
                </ul>
                <button id="temaKnap" class="tema-knap">🌙</button>
            </nav>
        </header>

        <section id="hjem" class="hero">
            <div class="hero-indhold">
                <h1>Hej, jeg er <span class="fremhæv">[Dit Navn]</span></h1>
                <p class="hero-tekst">Jeg er [beskriv dig selv f.eks. "webudvikler med passion for pænt design"]</p>
                <a href="#projekter" class="knap">Se mine projekter</a>
            </div>
        </section>

        <section id="om" class="sektion">
            <h2>Om mig</h2>
            <div class="om-grid">
                <div class="om-tekst">
                    <p>Her kan du fortælle om dig selv. Hvad laver du? Hvad er du god til? Hvad brænder du for?</p>
                    <p>Skriv 2-3 afsnit om dig selv. Vær personlig, men professionel.</p>
                </div>
                <div class="om-færdigheder">
                    <h3> Mine færdigheder</h3>
                    <ul class="færdighedsliste">
                        <li>HTML</li>
                        <li>CSS</li>
                        <li>JavaScript</li>
                        <li>[Tilføj flere]</li>
                    </ul>
                </div>
            </div>
        </section>

        <section id="projekter" class="sektion mørk">
            <h2>Projekter</h2>
            <div class="projekt-grid">
                <div class="projekt-kort">
                    <div class="projekt-billede">
                        <span>Projekt 1</span>
                    </div>
                    <div class="projekt-info">
                        <h3>Projektnavn</h3>
                        <p>Kort beskrivelse af projektet</p>
                        <a href="#" class="læs-mere">Læs mere →</a>
                    </div>
                </div>
                <div class="projekt-kort">
                    <div class="projekt-billede">
                        <span>Projekt 2</span>
                    </div>
                    <div class="projekt-info">
                        <h3>Projektnavn</h3>
                        <p>Kort beskrivelse af projektet</p>
                        <a href="#" class="læs-mere">Læs mere →</a>
                    </div>
                </div>
                <div class="projekt-kort">
                    <div class="projekt-billede">
                        <span>Projekt 3</span>
                    </div>
                    <div class="projekt-info">
                        <h3>Projektnavn</h3>
                        <p>Kort beskrivelse af projektet</p>
                        <a href="#" class="læs-mere">Læs mere →</a>
                    </div>
                </div>
            </div>
        </section>

        <section id="kontakt" class="sektion">
            <h2>Kontakt mig</h2>
            <form id="kontaktForm">
                <div class="form-gruppe">
                    <label for="navn">Navn</label>
                    <input type="text" id="navn" name="navn" required>
                </div>
                <div class="form-gruppe">
                    <label for="email">Email</label>
                    <input type="email" id="email" name="email" required>
                </div>
                <div class="form-gruppe">
                    <label for="besked">Besked</label>
                    <textarea id="besked" name="besked" rows="5" required></textarea>
                </div>
                <button type="submit" class="knap">Send besked</button>
            </form>
        </section>

        <footer>
            <p>&copy; 2026 [Dit Navn]. Bygget med ❤️ og meget kaffe.</p>
        </footer>

        <script src="script.js"></script>
    </body>
    </html>
    

style.css

/* Reset og grundlæggende */
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    html {
        scroll-behavior: smooth;
    }

    body {
        font-family: 'Poppins', sans-serif;
        line-height: 1.6;
        color: #333;
        transition: background 0.3s, color 0.3s;
    }

    body.mørk {
        background-color: #1a1a1a;
        color: #f0f0f0;
    }

    /* Navigation */
    header {
        position: fixed;
        top: 0;
        width: 100%;
        background: rgba(255, 255, 255, 0.95);
        backdrop-filter: blur(10px);
        z-index: 1000;
        transition: background 0.3s;
    }

    body.mørk header {
        background: rgba(26, 26, 26, 0.95);
    }

    nav {
        display: flex;
        justify-content: space-between;
        align-items: center;
        max-width: 1200px;
        margin: 0 auto;
        padding: 1rem 2rem;
    }

    .logo {
        font-size: 1.5rem;
        font-weight: 700;
        color: #667eea;
    }

    nav ul {
        display: flex;
        list-style: none;
        gap: 2rem;
    }

    nav a {
        text-decoration: none;
        color: #333;
        font-weight: 500;
        transition: color 0.3s;
    }

    body.mørk nav a {
        color: #f0f0f0;
    }

    nav a:hover {
        color: #667eea;
    }

    .tema-knap {
        background: none;
        border: none;
        font-size: 1.5rem;
        cursor: pointer;
    }

    /* Hero sektion */
    .hero {
        min-height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 2rem;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
    }

    .hero h1 {
        font-size: 3rem;
        margin-bottom: 1rem;
    }

    .fremhæv {
        color: #ffd700;
    }

    .hero-tekst {
        font-size: 1.2rem;
        margin-bottom: 2rem;
        opacity: 0.9;
    }

    /* Knapper */
    .knap {
        display: inline-block;
        padding: 0.75rem 2rem;
        background: white;
        color: #667eea;
        text-decoration: none;
        border-radius: 50px;
        font-weight: 600;
        transition: transform 0.3s, box-shadow 0.3s;
    }

    .knap:hover {
        transform: translateY(-3px);
        box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
    }

    /* Sektioner */
    .sektion {
        padding: 5rem 2rem;
        max-width: 1200px;
        margin: 0 auto;
    }

    .sektion.mørk {
        background: #f8f9fa;
        max-width: 100%;
    }

    body.mørk .sektion.mørk {
        background: #2a2a2a;
    }

    .sektion h2 {
        text-align: center;
        font-size: 2.5rem;
        margin-bottom: 3rem;
    }

    /* Om mig */
    .om-grid {
        display: grid;
        grid-template-columns: 2fr 1fr;
        gap: 3rem;
        align-items: start;
    }

    .om-tekst p {
        margin-bottom: 1rem;
        font-size: 1.1rem;
    }

    .færdighedsliste {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        list-style: none;
    }

    .færdighedsliste li {
        background: #667eea;
        color: white;
        padding: 0.5rem 1rem;
        border-radius: 20px;
        font-size: 0.9rem;
    }

    /* Projekter */
    .projekt-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
        gap: 2rem;
    }

    .projekt-kort {
        background: white;
        border-radius: 10px;
        overflow: hidden;
        box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        transition: transform 0.3s;
    }

    body.mørk .projekt-kort {
        background: #333;
    }

    .projekt-kort:hover {
        transform: translateY(-10px);
    }

    .projekt-billede {
        height: 200px;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
        font-size: 1.5rem;
        font-weight: 600;
    }

    .projekt-info {
        padding: 1.5rem;
    }

    .projekt-info h3 {
        margin-bottom: 0.5rem;
    }

    .projekt-info p {
        color: #666;
        margin-bottom: 1rem;
    }

    body.mørk .projekt-info p {
        color: #aaa;
    }

    .læs-mere {
        color: #667eea;
        text-decoration: none;
        font-weight: 600;
    }

    /* Kontaktformular */
    #kontaktForm {
        max-width: 600px;
        margin: 0 auto;
    }

    .form-gruppe {
        margin-bottom: 1.5rem;
    }

    .form-gruppe label {
        display: block;
        margin-bottom: 0.5rem;
        font-weight: 500;
    }

    .form-gruppe input,
    .form-gruppe textarea {
        width: 100%;
        padding: 0.75rem;
        border: 2px solid #ddd;
        border-radius: 5px;
        font-family: inherit;
        font-size: 1rem;
        transition: border-color 0.3s;
    }

    body.mørk .form-gruppe input,
    body.mørk .form-gruppe textarea {
        background: #444;
        border-color: #555;
        color: white;
    }

    .form-gruppe input:focus,
    .form-gruppe textarea:focus {
        outline: none;
        border-color: #667eea;
    }

    /* Footer */
    footer {
        text-align: center;
        padding: 2rem;
        background: #333;
        color: white;
    }
    

script.js

// Tema-skifter
    const temaKnap = document.getElementById("temaKnap");
    const body = document.body;

    // Tjek for gemt præference
    if (localStorage.getItem("tema") === "mørk") {
        body.classList.add("mørk");
        temaKnap.textContent = "☀️";
    }

    temaKnap.addEventListener("click", function() {
        body.classList.toggle("mørk");

        if (body.classList.contains("mørk")) {
            temaKnap.textContent = "☀️";
            localStorage.setItem("tema", "mørk");
        } else {
            temaKnap.textContent = "🌙";
            localStorage.setItem("tema", "lys");
        }
    });

    // Smooth scroll for navigation links
    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener("click", function(event) {
            event.preventDefault();
            const mål = document.querySelector(this.getAttribute("href"));
            mål.scrollIntoView({ behavior: "smooth" });
        });
    });

    // Kontaktformular
    const form = document.getElementById("kontaktForm");

    form.addEventListener("submit", function(event) {
        event.preventDefault();

        const navn = document.getElementById("navn").value;
        const email = document.getElementById("email").value;
        const besked = document.getElementById("besked").value;

        // Tjek email
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (!emailRegex.test(email)) {
            alert("Indtast venligst en gyldig email-adresse");
            return;
        }

        // Simuler sending (erstat med rigtig backend/API)
        alert(`Tak for din besked, ${navn}! Jeg vender tilbage hurtigst muligt.`);
        form.reset();
    });

    // Fade-in animation ved scroll
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                entry.target.style.opacity = "1";
                entry.target.style.transform = "translateY(0)";
            }
        });
    }, { threshold: 0.1 });

    // Animer sektioner
    document.querySelectorAll(".sektion").forEach(sektion => {
        sektion.style.opacity = "0";
        sektion.style.transform = "translateY(30px)";
        sektion.style.transition = "opacity 0.6s, transform 0.6s";
        observer.observe(sektion);
    });
    

17. HTML & CSS for danske freelancere

Når du bygger hjemmesider til danske kunder, er der nogle særlige forhold du skal være opmærksom på — både juridisk, teknisk og designmæssigt.

Lovkrav for danske hjemmesider

Hvis du driver erhverv, skal dit CVR-nummer fremgå på hjemmesiden. Har du momsregistrering, skal momsbeløb også fremgå. Du skal desuden have et cookie-samtykke (GDPR) på plads — brug et værktøj som Cookiebot eller Cookie Information til at lave en cookie-popup der overholder dansk lovgivning.

Dansk webdesign

Danske hjemmesider er kendt for et rent, minimalistisk design med fokus på brugervenlighed. Mørk tilstand er populært i Danmark, og de fleste nyere sites understøtter det. Hold layoutet enkelt, med god whitespace og tydelig typografi.

Typografi til dansk

Vælg skrifttyper der understøtter danske tegn (æ, ø, å) ordentligt. Gode valg:

Brug Google Fonts eller systemfonts for at undgå forsinkelser.

Hosting og domæner på dansk

Til danske kunder kan du spare penge ved at bruge danske udbydere:

.dk domæner købes hos DK Hostmaster eller hos danske registrarer som DanDomain, One.com, Simply.com eller ScanDomain.

Tilgængelighed (WCAG 2.1)

WCAG 2.1-kravene gælder også i Danmark, især for offentlige hjemmesider. Brug lang="da" på dit HTML-element, sørg for kontrastfyldte farver, og test med skærmlæsere. Danske brugere forventer at din side fungerer med tastaturnavigation.

Værktøjer til danske freelancere


Afsluttende ord

Tillykke! Du har lært det grundlæggende i HTML, CSS og JavaScript. Du ved nu hvordan du:

Husk: Det handler ikke om at lære alt på én gang. Det handler om at blive bedre lidt efter lidt. Hver gang du byder noget nyt, lærer du lidt mere.

De mest succesfulde udviklere er ikke dem der lærte hurtigst – det er dem der aldrig gav op.

Så hvad venter du på? Åbn VS Code og begynd at bygge noget fantastisk!

Du har det her. 💪


Denne guide blev oprettet i 2026. Teknologier udvikler sig, men grundlæggende HTML, CSS og JavaScript forbliver det samme.

Sidst opdateret: Juni 2026