Formulär i HTML: En nybörjarguide till interaktiva webbformulär
Lär dig skapa HTML-formulär från grunden med denna omfattande guide som täcker form-elementet, inputtyper, etiketter, tillgänglighet och validering.
Lär dig skapa HTML-formulär från grunden med denna omfattande guide som täcker form-elementet, inputtyper, etiketter, tillgänglighet och validering.
<form>
-elementet och hur det fungerar<form>
-elementet fungerar som en behållare för alla formulärkontroller och definierar hur data ska skickas till servern. Det är det grundläggande elementet som gör användarinmatning möjlig på webben.
<form action="/submit" method="POST">
<!-- Formulärinnehåll går här -->
<input type="text" name="username" />
<input type="submit" value="Skicka" />
</form>
action
-attributet:
Anger var formulärdata ska skickas när det skickas in.
<!-- Skicka till en specifik URL -->
<form action="/process-form" method="POST">
<!-- Skicka till samma sida -->
<form action="" method="POST">
<!-- Skicka till en extern tjänst -->
<form action="https://formspree.io/f/your-form-id" method="POST">
method
-attributet:
Definierar HTTP-metoden för att skicka data.
<!-- GET: Data visas i URL:en (standard) -->
<form action="/search" method="GET">
<input type="text" name="query" />
<input type="submit" value="Sök" />
</form>
<!-- POST: Data skickas i förfrågans body -->
<form action="/contact" method="POST">
<input type="email" name="email" />
<input type="submit" value="Skicka" />
</form>
Andra användbara attribut:
<form
action="/submit"
method="POST"
enctype="multipart/form-data" <!-- För filuppladdningar -->
target="_blank" <!-- Öppna resultat i nytt fönster -->
novalidate <!-- Inaktivera webbläsarvalidering -->
autocomplete="on" <!-- Aktivera automatisk komplettering -->
>
<form action="/register" method="POST" class="registration-form">
<h2>Skapa konto</h2>
<div class="form-group">
<label for="fullname">Fullständigt namn:</label>
<input type="text" id="fullname" name="fullname" required />
</div>
<div class="form-group">
<label for="email">E-postadress:</label>
<input type="email" id="email" name="email" required />
</div>
<div class="form-group">
<label for="password">Lösenord:</label>
<input type="password" id="password" name="password" required />
</div>
<button type="submit">Registrera</button>
</form>
HTML5 introducerade många nya inputtyper som ger bättre användarupplevelse och inbyggd validering. Här är de viktigaste typerna du behöver känna till.
type="text"
- Grundläggande textinmatning:
<label for="firstname">Förnamn:</label>
<input type="text" id="firstname" name="firstname" placeholder="Ange ditt förnamn" />
type="email"
- E-postadresser:
<label for="email">E-post:</label>
<input type="email" id="email" name="email" placeholder="din@email.com" required />
type="password"
- Lösenordsfält:
<label for="password">Lösenord:</label>
<input type="password" id="password" name="password" minlength="8" required />
type="tel"
- Telefonnummer:
<label for="phone">Telefon:</label>
<input type="tel" id="phone" name="phone" placeholder="+46 70 123 45 67" />
type="url"
- Webbadresser:
<label for="website">Webbplats:</label>
<input type="url" id="website" name="website" placeholder="https://example.com" />
type="search"
- Sökfält:
<label for="search">Sök:</label>
<input type="search" id="search" name="search" placeholder="Sök på webbplatsen..." />
type="number"
- Numerisk inmatning:
<label for="age">Ålder:</label>
<input type="number" id="age" name="age" min="18" max="100" step="1" />
type="range"
- Skjutreglage:
<label for="volume">Volym:</label>
<input type="range" id="volume" name="volume" min="0" max="100" value="50" />
<output for="volume">50</output>
type="date"
- Datumväljare:
<label for="birthdate">Födelsedatum:</label>
<input type="date" id="birthdate" name="birthdate" />
type="time"
- Tidsväljare:
<label for="appointment">Tid för möte:</label>
<input type="time" id="appointment" name="appointment" />
type="datetime-local"
- Datum och tid:
<label for="event">Eventtid:</label>
<input type="datetime-local" id="event" name="event" />
type="month"
- Månadsväljare:
<label for="start-month">Startmånad:</label>
<input type="month" id="start-month" name="start-month" />
type="week"
- Veckoväljare:
<label for="project-week">Projektvecka:</label>
<input type="week" id="project-week" name="project-week" />
type="file"
- Filuppladdning:
<label for="avatar">Profilbild:</label>
<input type="file" id="avatar" name="avatar" accept="image/*" />
<!-- Flera filer -->
<label for="documents">Dokument:</label>
<input type="file" id="documents" name="documents" multiple accept=".pdf,.doc,.docx" />
type="color"
- Färgväljare:
<label for="theme-color">Temafärg:</label>
<input type="color" id="theme-color" name="theme-color" value="#007bff" />
type="checkbox"
- Kryssrutor:
<input type="checkbox" id="newsletter" name="newsletter" value="yes" />
<label for="newsletter">Prenumerera på nyhetsbrev</label>
<!-- Flera alternativ -->
<fieldset>
<legend>Intressen:</legend>
<input type="checkbox" id="tech" name="interests" value="technology" />
<label for="tech">Teknik</label>
<input type="checkbox" id="design" name="interests" value="design" />
<label for="design">Design</label>
<input type="checkbox" id="business" name="interests" value="business" />
<label for="business">Affärer</label>
</fieldset>
type="radio"
- Radioknappar:
<fieldset>
<legend>Kön:</legend>
<input type="radio" id="male" name="gender" value="male" />
<label for="male">Man</label>
<input type="radio" id="female" name="gender" value="female" />
<label for="female">Kvinna</label>
<input type="radio" id="other" name="gender" value="other" />
<label for="other">Annat</label>
</fieldset>
type="hidden"
- Dolda fält:
<input type="hidden" name="csrf_token" value="abc123xyz" />
<input type="hidden" name="form_id" value="contact_form" />
Etiketter är avgörande för formulärtillgänglighet och användarupplevelse. De hjälper användare att förstå vad varje fält förväntar sig och gör formulär navigerbara med tangentbord och skärmläsare.
Explicit etikettering (rekommenderat):
<label for="username">Användarnamn:</label>
<input type="text" id="username" name="username" />
Implicit etikettering:
<label>
E-postadress:
<input type="email" name="email" />
</label>
Flera etiketter för ett fält:
<label for="phone-main">Telefonnummer</label>
<label for="phone-main">(Huvudnummer)</label>
<input type="tel" id="phone-main" name="phone" />
Gruppering med fieldset och legend:
<fieldset>
<legend>Kontaktinformation</legend>
<div class="form-row">
<label for="first-name">Förnamn:</label>
<input type="text" id="first-name" name="firstName" required />
</div>
<div class="form-row">
<label for="last-name">Efternamn:</label>
<input type="text" id="last-name" name="lastName" required />
</div>
<div class="form-row">
<label for="contact-email">E-post:</label>
<input type="email" id="contact-email" name="email" required />
</div>
</fieldset>
aria-describedby
för hjälptext:
<label for="password">Lösenord:</label>
<input type="password" id="password" name="password" aria-describedby="pwd-help" required />
<div id="pwd-help">Lösenordet måste vara minst 8 tecken långt och innehålla både bokstäver och siffror.</div>
aria-invalid
för felindikering:
<label for="email">E-postadress:</label>
<input type="email" id="email" name="email" aria-invalid="true" aria-describedby="email-error" />
<div id="email-error" role="alert">Ange en giltig e-postadress.</div>
aria-required
för obligatoriska fält:
<label for="full-name">Fullständigt namn:</label>
<input type="text" id="full-name" name="fullName" aria-required="true" />
<form action="/contact" method="POST" novalidate>
<h2>Kontakta oss</h2>
<fieldset>
<legend>Personlig information</legend>
<div class="form-group">
<label for="name">Fullständigt namn: <span aria-label="obligatoriskt">*</span></label>
<input
type="text"
id="name"
name="name"
required
aria-required="true"
aria-describedby="name-help"
/>
<div id="name-help" class="help-text">Ange ditt för- och efternamn</div>
</div>
<div class="form-group">
<label for="email">E-postadress: <span aria-label="obligatoriskt">*</span></label>
<input
type="email"
id="email"
name="email"
required
aria-required="true"
aria-describedby="email-help"
/>
<div id="email-help" class="help-text">Vi kommer aldrig att dela din e-postadress</div>
</div>
</fieldset>
<fieldset>
<legend>Meddelande</legend>
<div class="form-group">
<label for="subject">Ämne:</label>
<select id="subject" name="subject" aria-describedby="subject-help">
<option value="">Välj ett ämne</option>
<option value="general">Allmän förfrågan</option>
<option value="support">Teknisk support</option>
<option value="billing">Fakturering</option>
</select>
<div id="subject-help" class="help-text">Välj det ämne som bäst beskriver din förfrågan</div>
</div>
<div class="form-group">
<label for="message">Meddelande: <span aria-label="obligatoriskt">*</span></label>
<textarea
id="message"
name="message"
rows="5"
required
aria-required="true"
aria-describedby="message-help"
></textarea>
<div id="message-help" class="help-text">Beskriv din förfrågan i detalj</div>
</div>
</fieldset>
<button type="submit">Skicka meddelande</button>
</form>
Knappar är avgörande för formulärfunktionalitet och ger användare sätt att interagera med och skicka formulärdata.
type="submit"
- Skicka formulär:
<button type="submit">Skicka formulär</button>
<input type="submit" value="Skicka formulär" />
type="reset"
- Återställ formulär:
<button type="reset">Rensa formulär</button>
<input type="reset" value="Rensa formulär" />
type="button"
- Allmän knapp:
<button type="button" onclick="validateForm()">Validera</button>
<input type="button" value="Validera" onclick="validateForm()" />
Flera submit-knappar:
<form action="/process" method="POST">
<input type="text" name="document" placeholder="Dokumentnamn" />
<button type="submit" name="action" value="save">Spara utkast</button>
<button type="submit" name="action" value="publish">Publicera</button>
<button type="submit" name="action" value="preview">Förhandsgranska</button>
</form>
Knappar med ikoner:
<button type="submit" class="btn-primary">
<svg class="icon" viewBox="0 0 24 24">
<path d="M2 21l21-9L2 3v7l15 2-15 2v7z"/>
</svg>
Skicka meddelande
</button>
Inaktiverade knappar:
<button type="submit" disabled id="submit-btn">Skicka</button>
<script>
// Aktivera knappen när formuläret är giltigt
document.getElementById('email').addEventListener('input', function() {
const submitBtn = document.getElementById('submit-btn');
submitBtn.disabled = !this.value.includes('@');
});
</script>
<select>
-element för rullgardinsmenyer:
<label for="country">Land:</label>
<select id="country" name="country" required>
<option value="">Välj land</option>
<option value="se">Sverige</option>
<option value="no">Norge</option>
<option value="dk">Danmark</option>
<option value="fi">Finland</option>
</select>
Grupperade alternativ:
<label for="city">Stad:</label>
<select id="city" name="city">
<optgroup label="Sverige">
<option value="stockholm">Stockholm</option>
<option value="gothenburg">Göteborg</option>
<option value="malmo">Malmö</option>
</optgroup>
<optgroup label="Norge">
<option value="oslo">Oslo</option>
<option value="bergen">Bergen</option>
<option value="trondheim">Trondheim</option>
</optgroup>
</select>
<textarea>
för längre text:
<label for="feedback">Feedback:</label>
<textarea
id="feedback"
name="feedback"
rows="4"
cols="50"
placeholder="Dela dina tankar med oss..."
maxlength="500"
></textarea>
<datalist>
för autokomplettering:
<label for="browser">Välj webbläsare:</label>
<input list="browsers" id="browser" name="browser" />
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
<option value="Opera">
</datalist>
HTML5 tillhandahåller inbyggd validering som hjälper till att säkerställa att användare anger korrekt data innan formuläret skickas.
required
- Obligatoriska fält:
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<select name="category" required>
<option value="">Välj kategori</option>
<option value="general">Allmänt</option>
</select>
minlength
och maxlength
- Textlängd:
<input type="text" name="username" minlength="3" maxlength="20" />
<textarea name="bio" maxlength="500"></textarea>
min
och max
- Numeriska värden:
<input type="number" name="age" min="18" max="100" />
<input type="date" name="start-date" min="2024-01-01" max="2024-12-31" />
<input type="range" name="rating" min="1" max="10" />
step
- Numeriska steg:
<input type="number" name="price" step="0.01" min="0" />
<input type="range" name="volume" step="5" min="0" max="100" />
pattern
- Reguljära uttryck:
<!-- Svenskt telefonnummer -->
<input
type="tel"
name="phone"
pattern="^(\+46|0)[1-9]\d{8,9}$"
title="Ange ett giltigt svenskt telefonnummer"
/>
<!-- Postnummer -->
<input
type="text"
name="postal-code"
pattern="^\d{3}\s?\d{2}$"
title="Ange postnummer i format 123 45"
/>
<!-- Användarnamn -->
<input
type="text"
name="username"
pattern="^[a-zA-Z0-9_]{3,20}$"
title="3-20 tecken, endast bokstäver, siffror och understreck"
/>
<form id="registration-form">
<div class="form-group">
<label for="email">E-postadress:</label>
<input
type="email"
id="email"
name="email"
required
data-error="Ange en giltig e-postadress"
/>
<div class="error-message" id="email-error"></div>
</div>
<div class="form-group">
<label for="password">Lösenord:</label>
<input
type="password"
id="password"
name="password"
minlength="8"
required
data-error="Lösenordet måste vara minst 8 tecken långt"
/>
<div class="error-message" id="password-error"></div>
</div>
<button type="submit">Registrera</button>
</form>
<script>
document.getElementById('registration-form').addEventListener('submit', function(e) {
e.preventDefault();
const email = document.getElementById('email');
const password = document.getElementById('password');
// Rensa tidigare felmeddelanden
document.querySelectorAll('.error-message').forEach(el => el.textContent = '');
let isValid = true;
// Validera e-post
if (!email.validity.valid) {
document.getElementById('email-error').textContent = email.dataset.error;
isValid = false;
}
// Validera lösenord
if (!password.validity.valid) {
document.getElementById('password-error').textContent = password.dataset.error;
isValid = false;
}
if (isValid) {
// Skicka formulär
this.submit();
}
});
</script>
<form class="live-validation">
<div class="form-group">
<label for="username">Användarnamn:</label>
<input
type="text"
id="username"
name="username"
minlength="3"
maxlength="20"
required
/>
<div class="validation-feedback" id="username-feedback"></div>
</div>
<div class="form-group">
<label for="email">E-postadress:</label>
<input
type="email"
id="email"
name="email"
required
/>
<div class="validation-feedback" id="email-feedback"></div>
</div>
<button type="submit">Skicka</button>
</form>
<script>
function validateField(field, feedbackElement) {
if (field.validity.valid) {
feedbackElement.textContent = '✓ Ser bra ut';
feedbackElement.className = 'validation-feedback valid';
} else {
if (field.validity.valueMissing) {
feedbackElement.textContent = 'Detta fält är obligatoriskt';
} else if (field.validity.tooShort) {
feedbackElement.textContent = `Minst ${field.minLength} tecken krävs`;
} else if (field.validity.typeMismatch) {
feedbackElement.textContent = 'Ange en giltig e-postadress';
}
feedbackElement.className = 'validation-feedback invalid';
}
}
document.getElementById('username').addEventListener('input', function() {
validateField(this, document.getElementById('username-feedback'));
});
document.getElementById('email').addEventListener('input', function() {
validateField(this, document.getElementById('email-feedback'));
});
</script>
/* Grundläggande formulärstyling */
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input, textarea, select {
width: 100%;
padding: 10px;
border: 2px solid #ddd;
border-radius: 4px;
font-size: 16px;
transition: border-color 0.3s;
}
/* Valideringsstatus */
input:valid {
border-color: #28a745;
}
input:invalid {
border-color: #dc3545;
}
input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
/* Felmeddelanden */
.error-message {
color: #dc3545;
font-size: 14px;
margin-top: 5px;
}
.validation-feedback {
font-size: 14px;
margin-top: 5px;
}
.validation-feedback.valid {
color: #28a745;
}
.validation-feedback.invalid {
color: #dc3545;
}
/* Knappstyling */
button {
background-color: #007bff;
color: white;
padding: 12px 24px;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}
<form id="multi-step-form" class="multi-step">
<!-- Steg 1: Personlig information -->
<div class="step active" data-step="1">
<h3>Steg 1: Personlig information</h3>
<div class="form-group">
<label for="first-name">Förnamn:</label>
<input type="text" id="first-name" name="firstName" required />
</div>
<div class="form-group">
<label for="last-name">Efternamn:</label>
<input type="text" id="last-name" name="lastName" required />
</div>
<button type="button" class="next-step">Nästa</button>
</div>
<!-- Steg 2: Kontaktinformation -->
<div class="step" data-step="2">
<h3>Steg 2: Kontaktinformation</h3>
<div class="form-group">
<label for="email">E-postadress:</label>
<input type="email" id="email" name="email" required />
</div>
<div class="form-group">
<label for="phone">Telefonnummer:</label>
<input type="tel" id="phone" name="phone" />
</div>
<button type="button" class="prev-step">Föregående</button>
<button type="button" class="next-step">Nästa</button>
</div>
<!-- Steg 3: Bekräftelse -->
<div class="step" data-step="3">
<h3>Steg 3: Bekräfta dina uppgifter</h3>
<div id="summary"></div>
<button type="button" class="prev-step">Föregående</button>
<button type="submit">Skicka</button>
</div>
</form>
<form id="dynamic-form">
<fieldset>
<legend>Kontaktpersoner</legend>
<div id="contacts-container">
<div class="contact-group">
<input type="text" name="contacts[0][name]" placeholder="Namn" required />
<input type="email" name="contacts[0][email]" placeholder="E-post" required />
<button type="button" class="remove-contact">Ta bort</button>
</div>
</div>
<button type="button" id="add-contact">Lägg till kontakt</button>
</fieldset>
<button type="submit">Skicka</button>
</form>
<script>
let contactIndex = 1;
document.getElementById('add-contact').addEventListener('click', function() {
const container = document.getElementById('contacts-container');
const newContact = document.createElement('div');
newContact.className = 'contact-group';
newContact.innerHTML = `
<input type="text" name="contacts[${contactIndex}][name]" placeholder="Namn" required />
<input type="email" name="contacts[${contactIndex}][email]" placeholder="E-post" required />
<button type="button" class="remove-contact">Ta bort</button>
`;
container.appendChild(newContact);
contactIndex++;
});
document.addEventListener('click', function(e) {
if (e.target.classList.contains('remove-contact')) {
e.target.parentElement.remove();
}
});
</script>
<!-- Fel: Ingen etikett -->
<input type="text" name="name" placeholder="Namn" />
<!-- Korrekt: Tydlig etikett -->
<label for="name">Namn:</label>
<input type="text" id="name" name="name" placeholder="Ange ditt namn" />
<!-- Fel: Text för e-post -->
<input type="text" name="email" />
<!-- Korrekt: E-posttyp -->
<input type="email" name="email" />
<!-- Fel: Ingen validering -->
<input type="email" name="email" />
<!-- Korrekt: Med validering -->
<input type="email" name="email" required aria-describedby="email-help" />
<div id="email-help">Ange en giltig e-postadress</div>
<!-- Fel: Ostrukturerat -->
<form>
Namn: <input type="text" name="name" />
E-post: <input type="email" name="email" />
<input type="submit" value="Skicka" />
</form>
<!-- Korrekt: Välstrukturerat -->
<form>
<div class="form-group">
<label for="name">Namn:</label>
<input type="text" id="name" name="name" required />
</div>
<div class="form-group">
<label for="email">E-postadress:</label>
<input type="email" id="email" name="email" required />
</div>
<button type="submit">Skicka</button>
</form>
HTML-formulär är kraftfulla verktyg för att samla in användardata och skapa interaktiva webbupplevelser. Genom att förstå <form>
-elementet, olika inputtyper, korrekt etikettering, tillgänglighetsprinciper och valideringstekniker kan du skapa formulär som är både funktionella och användarvänliga.
Kom ihåg att ett bra formulär är mer än bara HTML - det kräver genomtänkt design, tydlig kommunikation och noggrann testning. Börja med grunderna och bygg gradvis upp mer avancerade funktioner när du blir bekväm med de grundläggande koncepten.
Genom att följa bästa praxis och fokusera på användarupplevelse och tillgänglighet kommer dina formulär att tjäna både dina användare och dina affärsmål effektivt.
Fortsätt läsa med dessa relaterade artiklar
Bemästra HTML-bilder med denna omfattande guide som täcker img-taggen, alt-text, filformat, responsiva bilder, srcset och webbprestandaoptimering.
Bemästra HTML-listor med denna kompletta guide som täcker ul-, ol- och dl-element, nästlingstekniker, CSS-styling och bästa praxis för tillgänglighet.
Lär dig HTML-tabeller från grunder till avancerade tekniker. Bemästra table-, tr-, td-, th-element, tillgänglighet, responsiv design och när tabeller ska användas korrekt.
Upptäck kraften i semantisk HTML med denna omfattande guide som täcker header, footer, article, section och varför semantisk kod förbättrar SEO och tillgänglighet.