JavaScript DOM Manipulation
DOM (Document Object Model) ist die Schnittstelle zwischen JavaScript und HTML. Damit kannst du Webseiten dynamisch ändern!
Was ist das DOM?
Das DOM ist eine Baum-Struktur deiner HTML-Seite:
<!-- HTML -->
<!DOCTYPE html>
<html>
<head>
<title>Meine Seite</title>
</head>
<body>
<h1>Titel</h1>
<p>Text</p>
</body>
</html>
// DOM Baum:
// document
// └─ html
// ├─ head
// │ └─ title
// └─ body
// ├─ h1
// └─ pMit JavaScript kannst du:
- ✅ Elemente auswählen
- ✅ Content ändern
- ✅ Styles ändern
- ✅ Elemente erstellen/löschen
- ✅ Auf Events reagieren
Elemente auswählen
querySelector() - Ein Element
<!-- HTML -->
<h1 id="title">Hallo Welt</h1>
<p class="text">Ein Absatz</p>
<div class="container">
<p>Noch ein Absatz</p>
</div>
<script>
// Nach ID
const title = document.querySelector('#title');
console.log(title); // <h1 id="title">Hallo Welt</h1>
// Nach Class (erstes Element)
const text = document.querySelector('.text');
console.log(text); // <p class="text">Ein Absatz</p>
// Nach Tag
const paragraph = document.querySelector('p');
console.log(paragraph); // Erstes <p>
// Kombiniert
const containerP = document.querySelector('.container p');
console.log(containerP); // <p> innerhalb von .container
</script>CSS-Selektoren verwenden!
querySelectorAll() - Mehrere Elemente
<!-- HTML -->
<p class="text">Absatz 1</p>
<p class="text">Absatz 2</p>
<p class="text">Absatz 3</p>
<script>
// Alle Elemente mit .text
const texts = document.querySelectorAll('.text');
console.log(texts); // NodeList(3)
// Über alle iterieren
texts.forEach(text => {
console.log(text.textContent);
});
// Absatz 1
// Absatz 2
// Absatz 3
// Mit Index zugreifen
console.log(texts[0]); // Erster Absatz
console.log(texts[1]); // Zweiter Absatz
</script>Alte Methoden (weniger nutzen)
// getElementById
const el = document.getElementById('title'); // Ohne #!
// getElementsByClassName
const elements = document.getElementsByClassName('text'); // Ohne .!
// getElementsByTagName
const paragraphs = document.getElementsByTagName('p');
// ✅ BESSER: querySelector/All
const el2 = document.querySelector('#title');
const elements2 = document.querySelectorAll('.text');Content ändern
textContent - Text ändern
<!-- HTML -->
<h1 id="title">Alter Titel</h1>
<p id="text">Alter Text</p>
<script>
const title = document.querySelector('#title');
const text = document.querySelector('#text');
// Text lesen
console.log(title.textContent); // Alter Titel
// Text ändern
title.textContent = 'Neuer Titel';
text.textContent = 'Neuer Text mit <b>HTML</b>'; // HTML wird als Text angezeigt!
// Anhängen
text.textContent += ' Mehr Text';
</script>innerHTML - HTML ändern
<!-- HTML -->
<div id="content">
<p>Alter Content</p>
</div>
<script>
const content = document.querySelector('#content');
// HTML lesen
console.log(content.innerHTML); // <p>Alter Content</p>
// HTML ändern
content.innerHTML = '<h2>Neuer Titel</h2><p>Neuer Text</p>';
// HTML hinzufügen
content.innerHTML += '<p>Noch mehr</p>';
// ⚠️ Vorsicht: XSS-Gefahr bei User-Input!
const userInput = '<script>alert("XSS")</script>';
content.innerHTML = userInput; // ❌ Gefährlich!
// ✅ BESSER: textContent oder sanitize
content.textContent = userInput; // Wird als Text angezeigt
</script>Attribute ändern
<!-- HTML -->
<img id="image" src="old.jpg" alt="Altes Bild">
<input id="input" type="text" value="Alt">
<a id="link" href="https://old.com">Link</a>
<script>
const img = document.querySelector('#image');
const input = document.querySelector('#input');
const link = document.querySelector('#link');
// Attribute lesen
console.log(img.src); // https://domain.com/old.jpg
console.log(img.alt); // Altes Bild
console.log(input.value); // Alt
console.log(link.href); // https://old.com
// Attribute ändern
img.src = 'new.jpg';
img.alt = 'Neues Bild';
input.value = 'Neu';
link.href = 'https://new.com';
// Attribute mit getAttribute/setAttribute
console.log(img.getAttribute('src'));
img.setAttribute('src', 'another.jpg');
// data-* Attribute
// <div id="user" data-id="123" data-role="admin"></div>
const user = document.querySelector('#user');
console.log(user.dataset.id); // 123
console.log(user.dataset.role); // admin
user.dataset.id = '456';
</script>Styles ändern
<!-- HTML -->
<div id="box">Box</div>
<script>
const box = document.querySelector('#box');
// Style ändern (camelCase!)
box.style.color = 'white';
box.style.backgroundColor = 'blue';
box.style.padding = '20px';
box.style.borderRadius = '10px';
box.style.fontSize = '24px';
// Mehrere Styles auf einmal
Object.assign(box.style, {
color: 'white',
backgroundColor: 'blue',
padding: '20px',
borderRadius: '10px'
});
// Style lesen
console.log(box.style.color); // white
// Computed Style (inkl. CSS)
const computed = window.getComputedStyle(box);
console.log(computed.color); // rgb(255, 255, 255)
console.log(computed.backgroundColor); // rgb(0, 0, 255)
</script>Classes ändern - classList
Besser als inline styles!
<!-- CSS -->
<style>
.active { background-color: blue; color: white; }
.large { font-size: 24px; }
.hidden { display: none; }
</style>
<!-- HTML -->
<div id="box" class="box">Box</div>
<script>
const box = document.querySelector('#box');
// Class hinzufügen
box.classList.add('active');
console.log(box.className); // box active
// Mehrere Classes
box.classList.add('large', 'rounded');
// Class entfernen
box.classList.remove('active');
// Class togglen (an/aus)
box.classList.toggle('hidden'); // Fügt hinzu
box.classList.toggle('hidden'); // Entfernt wieder
// Prüfen ob Class vorhanden
if (box.classList.contains('active')) {
console.log('Box ist active');
}
// Class ersetzen
box.classList.replace('active', 'inactive');
// Alle Classes
console.log(box.classList); // DOMTokenList
</script>Events - Auf Benutzer reagieren
addEventListener() - Event Listener
<!-- HTML -->
<button id="btn">Klick mich</button>
<input id="input" type="text">
<script>
const button = document.querySelector('#btn');
const input = document.querySelector('#input');
// Click Event
button.addEventListener('click', function() {
console.log('Button geklickt!');
});
// Mit Arrow Function
button.addEventListener('click', () => {
console.log('Button geklickt!');
});
// Input Event
input.addEventListener('input', (event) => {
console.log('Eingabe:', event.target.value);
});
// Mehrere Listener
button.addEventListener('click', () => {
console.log('Handler 1');
});
button.addEventListener('click', () => {
console.log('Handler 2');
});
// Beide werden ausgeführt!
</script>Event Object
button.addEventListener('click', (event) => {
// Event Object
console.log(event.type); // 'click'
console.log(event.target); // Das geklickte Element
console.log(event.currentTarget); // Element mit Listener
// Maus-Position
console.log(event.clientX, event.clientY);
// Verhindern Default-Verhalten
event.preventDefault();
// Verhindern Event-Bubbling
event.stopPropagation();
});
// Link verhindert zu folgen
const link = document.querySelector('a');
link.addEventListener('click', (e) => {
e.preventDefault();
console.log('Link Klick verhindert');
});
// Form Submit verhindern
const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault();
console.log('Submit verhindert');
});Häufige Events
const element = document.querySelector('#element');
// Maus Events
element.addEventListener('click', () => {}); // Klick
element.addEventListener('dblclick', () => {}); // Doppelklick
element.addEventListener('mouseenter', () => {}); // Maus drüber
element.addEventListener('mouseleave', () => {}); // Maus weg
element.addEventListener('mousemove', () => {}); // Maus bewegt
// Keyboard Events
element.addEventListener('keydown', () => {}); // Taste gedrückt
element.addEventListener('keyup', () => {}); // Taste losgelassen
element.addEventListener('keypress', () => {}); // Taste gedrückt (veraltet)
// Form Events
element.addEventListener('submit', () => {}); // Form abgeschickt
element.addEventListener('input', () => {}); // Input geändert
element.addEventListener('change', () => {}); // Wert geändert
element.addEventListener('focus', () => {}); // Fokus erhalten
element.addEventListener('blur', () => {}); // Fokus verloren
// Scroll & Resize
window.addEventListener('scroll', () => {}); // Seite gescrollt
window.addEventListener('resize', () => {}); // Fenster resized
// Load
window.addEventListener('load', () => {}); // Seite geladen
document.addEventListener('DOMContentLoaded', () => {}); // DOM bereitElemente erstellen
<!-- HTML -->
<div id="container"></div>
<script>
const container = document.querySelector('#container');
// Element erstellen
const paragraph = document.createElement('p');
// Text hinzufügen
paragraph.textContent = 'Neuer Absatz';
// Attribute setzen
paragraph.className = 'text';
paragraph.id = 'myParagraph';
// Zum DOM hinzufügen
container.appendChild(paragraph);
// Mehrere Elemente
const heading = document.createElement('h2');
heading.textContent = 'Überschrift';
const text = document.createElement('p');
text.textContent = 'Text';
const button = document.createElement('button');
button.textContent = 'Klick mich';
button.addEventListener('click', () => {
alert('Geklickt!');
});
// Alle hinzufügen
container.appendChild(heading);
container.appendChild(text);
container.appendChild(button);
// An bestimmter Position einfügen
container.insertBefore(heading, container.firstChild);
// prepend/append (modern)
container.prepend(heading); // Am Anfang
container.append(button); // Am Ende
</script>Elemente löschen
<!-- HTML -->
<div id="container">
<p id="p1">Absatz 1</p>
<p id="p2">Absatz 2</p>
<p id="p3">Absatz 3</p>
</div>
<script>
const p1 = document.querySelector('#p1');
const p2 = document.querySelector('#p2');
const container = document.querySelector('#container');
// Element entfernen (modern)
p1.remove();
// Parent entfernen (alt)
container.removeChild(p2);
// Alle Kinder entfernen
container.innerHTML = '';
// Oder mit while
while (container.firstChild) {
container.removeChild(container.firstChild);
}
</script>Praktische Beispiele
Beispiel 1: Counter
<!-- HTML -->
<div id="counter">
<h2 id="count">0</h2>
<button id="increment">+</button>
<button id="decrement">-</button>
<button id="reset">Reset</button>
</div>
<script>
let count = 0;
const countElement = document.querySelector('#count');
const incrementBtn = document.querySelector('#increment');
const decrementBtn = document.querySelector('#decrement');
const resetBtn = document.querySelector('#reset');
// Update Display
function updateDisplay() {
countElement.textContent = count;
countElement.style.color = count > 0 ? 'green' : count < 0 ? 'red' : 'black';
}
// Event Listeners
incrementBtn.addEventListener('click', () => {
count++;
updateDisplay();
});
decrementBtn.addEventListener('click', () => {
count--;
updateDisplay();
});
resetBtn.addEventListener('click', () => {
count = 0;
updateDisplay();
});
</script>Beispiel 2: Todo Liste
<!-- HTML -->
<div id="todoApp">
<input id="todoInput" type="text" placeholder="Neue Aufgabe">
<button id="addBtn">Hinzufügen</button>
<ul id="todoList"></ul>
</div>
<script>
const input = document.querySelector('#todoInput');
const addBtn = document.querySelector('#addBtn');
const list = document.querySelector('#todoList');
function addTodo() {
const text = input.value.trim();
if (text === '') return;
// Li erstellen
const li = document.createElement('li');
li.textContent = text;
// Delete Button
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Löschen';
deleteBtn.addEventListener('click', () => {
li.remove();
});
// Toggle Done
li.addEventListener('click', () => {
li.style.textDecoration = li.style.textDecoration === 'line-through'
? 'none'
: 'line-through';
});
li.appendChild(deleteBtn);
list.appendChild(li);
input.value = '';
input.focus();
}
addBtn.addEventListener('click', addTodo);
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addTodo();
}
});
</script>Beispiel 3: Theme Switcher
<!-- HTML -->
<button id="themeToggle">Toggle Theme</button>
<!-- CSS -->
<style>
body.dark {
background-color: #1a1a1a;
color: white;
}
</style>
<script>
const toggle = document.querySelector('#themeToggle');
toggle.addEventListener('click', () => {
document.body.classList.toggle('dark');
// Text ändern
if (document.body.classList.contains('dark')) {
toggle.textContent = 'Light Mode';
} else {
toggle.textContent = 'Dark Mode';
}
// In localStorage speichern
const theme = document.body.classList.contains('dark') ? 'dark' : 'light';
localStorage.setItem('theme', theme);
});
// Beim Laden wiederherstellen
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
document.body.classList.add('dark');
toggle.textContent = 'Light Mode';
}
</script>Beispiel 4: Modal/Popup
<!-- HTML -->
<button id="openModal">Modal öffnen</button>
<div id="modal" class="modal hidden">
<div class="modal-content">
<span id="closeModal" class="close">×</span>
<h2>Modal Titel</h2>
<p>Modal Content hier...</p>
</div>
</div>
<!-- CSS -->
<style>
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal.hidden {
display: none;
}
.modal-content {
background-color: white;
padding: 20px;
border-radius: 10px;
max-width: 500px;
}
</style>
<script>
const openBtn = document.querySelector('#openModal');
const closeBtn = document.querySelector('#closeModal');
const modal = document.querySelector('#modal');
openBtn.addEventListener('click', () => {
modal.classList.remove('hidden');
});
closeBtn.addEventListener('click', () => {
modal.classList.add('hidden');
});
// Schließen bei Klick außerhalb
modal.addEventListener('click', (e) => {
if (e.target === modal) {
modal.classList.add('hidden');
}
});
// Schließen mit Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
modal.classList.add('hidden');
}
});
</script>Beispiel 5: Form Validation
<!-- HTML -->
<form id="form">
<input id="name" type="text" placeholder="Name" required>
<span id="nameError" class="error"></span>
<input id="email" type="email" placeholder="Email" required>
<span id="emailError" class="error"></span>
<button type="submit">Absenden</button>
</form>
<script>
const form = document.querySelector('#form');
const nameInput = document.querySelector('#name');
const emailInput = document.querySelector('#email');
const nameError = document.querySelector('#nameError');
const emailError = document.querySelector('#emailError');
// Live Validation
nameInput.addEventListener('input', () => {
if (nameInput.value.length < 3) {
nameError.textContent = 'Name zu kurz (min. 3 Zeichen)';
nameError.style.color = 'red';
} else {
nameError.textContent = '';
}
});
emailInput.addEventListener('input', () => {
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(emailInput.value)) {
emailError.textContent = 'Ungültige Email';
emailError.style.color = 'red';
} else {
emailError.textContent = '';
}
});
// Submit
form.addEventListener('submit', (e) => {
e.preventDefault();
if (nameInput.value.length >= 3 && emailInput.value.includes('@')) {
console.log('Form valid!');
console.log({
name: nameInput.value,
email: emailInput.value
});
// Form zurücksetzen
form.reset();
}
});
</script>Event Delegation
Effizienter für viele Elemente:
<!-- HTML -->
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<button id="addItem">Item hinzufügen</button>
<script>
const list = document.querySelector('#list');
const addBtn = document.querySelector('#addItem');
// ❌ SCHLECHT: Listener für jedes Li
// list.querySelectorAll('li').forEach(li => {
// li.addEventListener('click', () => {
// li.style.textDecoration = 'line-through';
// });
// });
// ✅ BESSER: Ein Listener auf Parent
list.addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
e.target.style.textDecoration = 'line-through';
}
});
// Dynamische Elemente funktionieren auch!
addBtn.addEventListener('click', () => {
const li = document.createElement('li');
li.textContent = `Item ${list.children.length + 1}`;
list.appendChild(li);
// Klick funktioniert automatisch!
});
</script>Best Practices
✅ DO:
- DOMContentLoaded nutzen für Scripts im Head
- classList statt inline styles
- textContent statt innerHTML (wenn möglich)
- Event Delegation für viele Elemente
- Template Literals für HTML-Strings
// ✅ DOMContentLoaded
document.addEventListener('DOMContentLoaded', () => {
// Code hier
});
// ✅ classList
element.classList.add('active');
// ✅ textContent (sicher)
element.textContent = userInput;
// ✅ Event Delegation
list.addEventListener('click', (e) => {
if (e.target.matches('.item')) {
// Handle click
}
});
// ✅ Template Literal
const html = `
<div class="card">
<h3>${title}</h3>
<p>${text}</p>
</div>
`;❌ DON'T:
- Nicht innerHTML mit User-Input (XSS!)
- Nicht zu viele Event Listener
- Nicht inline Event Handlers (onclick="...")
- Nicht document.write() (veraltet)
// ❌ SCHLECHT: XSS-Gefahr
element.innerHTML = userInput;
// ✅ BESSER: textContent
element.textContent = userInput;
// ❌ SCHLECHT: Inline Handler
<button onclick="handleClick()">Click</button>
// ✅ BESSER: addEventListener
button.addEventListener('click', handleClick);
// ❌ SCHLECHT: Zu viele Listener
items.forEach(item => {
item.addEventListener('click', handler);
});
// ✅ BESSER: Event Delegation
parent.addEventListener('click', (e) => {
if (e.target.matches('.item')) handler(e);
});TipsAndTricks
Tipps & Tricks
Event Delegation für bessere Performance
Nutze einen Listener statt vieler:
// ❌ Schlecht: Listener für jedes Element
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
// ✅ Gut: Ein Listener auf Parent
document.getElementById('list').addEventListener('click', (e) => {
if (e.target.classList.contains('item')) {
handleClick(e);
}
});
// Funktioniert auch mit dynamisch hinzugefügten Elementen!
classList statt className
Manipuliere Classes elegant:
const element = document.querySelector('.box');
// ❌ Alt: String manipulation
element.className += ' active';
element.className = element.className.replace('active', '');
// ✅ Neu: classList API
element.classList.add('active');
element.classList.remove('inactive');
element.classList.toggle('visible');
element.classList.contains('active'); // true/false
// Mehrere auf einmal
element.classList.add('class1', 'class2', 'class3');
Template Literals für HTML-Generierung
Erstelle dynamischen HTML-Content:
const users = [
{ name: 'Max', age: 25 },
{ name: 'Anna', age: 30 }
];
// Mit Template Literals
const html = users.map(user => `
<div class="user-card">
<h3>${user.name}</h3>
<p>Alter: ${user.age}</p>
</div>
`).join('');
document.getElementById('container').innerHTML = html;
dataset für Custom Data Attributes
Nutze data-* Attribute für Metadaten:
// HTML: <button data-user-id="123" data-action="delete">
const button = document.querySelector('button');
// Zugriff auf data-*
console.log(button.dataset.userId); // '123'
console.log(button.dataset.action); // 'delete'
// Setzen
button.dataset.status = 'active';
// HTML wird: data-status="active"
// CamelCase wird zu kebab-case
button.dataset.userRole = 'admin';
// HTML wird: data-user-role="admin"
📝 Quiz
Was ist der Unterschied zwischen textContent und innerHTML?
📝 Quiz
Warum Event Delegation nutzen?
Übungsaufgaben
Zeit deine DOM-Skills zu testen! Diese Challenges sind etwas anspruchsvoller:
Aufgabe 1: Element auswählen und ändern
Nutze querySelector() um ein Element zu finden und seinen Text zu ändern wenn der Button geklickt wird.
Aufgabe 2: classList toggle
Erstelle einen Button der eine CSS-Klasse 'active' an/aus schaltet (toggle). Die Klasse macht den Text rot und bold.
Aufgabe 3: Live Input Anzeige
Zeige in einem <p> Tag live an was der User in das Input-Feld tippt. Nutze das 'input' Event.
Aufgabe 4: Element erstellen und hinzufügen
Erstelle bei jedem Button-Klick ein neues <li> Element mit Text 'Item X' und füge es zur Liste hinzu.
Nächste Schritte
Du kennst jetzt:
- ✅ DOM Struktur & Selectors
- ✅ Content & Attribute ändern
- ✅ Styles & Classes
- ✅ Events & addEventListener
- ✅ Elemente erstellen/löschen
- ✅ Praktische Projekte
- ✅ Event Delegation
- ✅ Best Practices
Gratulation! Du hast die JavaScript-Grundlagen gemeistert!
Was kommt als Nächstes?
- Async JavaScript (Promises, async/await)
- Fetch API (Daten von Server laden)
- JavaScript Modules
- Moderne Frameworks (React, Vue, Svelte)
Weiter so! 🚀
Gut gemacht! 🎉
Du hast "JavaScript DOM Manipulation - HTML mit JS ändern" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
JavaScript Grundlagen: Deine erste Programmierung
Lerne JavaScript von Null! Variablen, Funktionen, Events - alles was du brauchst um interaktive Webseiten zu erstellen.
JavaScript Arrays - Listen & Array Methods
Lerne JavaScript Arrays: Erstellung, Zugriff, push, pop, map, filter, reduce, forEach, find, spread, destructuring und Best Practices.
JavaScript Conditionals - if, else, switch
Lerne JavaScript Conditionals: if, else, else if, switch - Vergleiche, Logische Operatoren, Truthy/Falsy und Best Practices für Bedingungen.