DOM: Modificare Elementi
Impara a modificare contenuto, stile, classi e attributi degli elementi HTML
🔧 Manipolazione DOM
Ora che sai selezionare elementi, impariamo a modificarli!
Puoi cambiare contenuto, stile, classi, attributi e persino creare/eliminare elementi.
- ✅ textContent & innerHTML – Modificare contenuto
- ✅ style – Modificare CSS inline
- ✅ classList – Gestire classi CSS
- ✅ Attributi – Get/Set/Remove attributi
- ✅ createElement() – Creare elementi
- ✅ append/remove – Aggiungere/Rimuovere dal DOM
📝 textContent vs innerHTML
Due modi principali per modificare il contenuto di un elemento.
Legge/scrive solo il testo, senza HTML.
<h1 id="titolo">Benvenuto</h1> <p id="descrizione">Questo è un <strong>paragrafo</strong></p>
const titolo = document.querySelector('#titolo');
const descrizione = document.querySelector('#descrizione');
// Leggere textContent
console.log(titolo.textContent); // "Benvenuto"
console.log(descrizione.textContent); // "Questo è un paragrafo"
// Nota: rimuove i tag HTML!
// Scrivere textContent
titolo.textContent = "Ciao Mondo!";
// Risultato: <h1 id="titolo">Ciao Mondo!</h1>
descrizione.textContent = "Nuovo testo semplice";
// Risultato: <p id="descrizione">Nuovo testo semplice</p>
// I tag <strong> sono stati rimossi!
// Se provi a inserire HTML, viene trattato come testo
titolo.textContent = "Testo con <strong>grassetto</strong>";
// Risultato: Testo con <strong>grassetto</strong> (visibile come testo!)
Legge/scrive HTML completo, inclusi tag.
const descrizione = document.querySelector('#descrizione');
// Leggere innerHTML
console.log(descrizione.innerHTML);
// "Questo è un <strong>paragrafo</strong>"
// Scrivere innerHTML con HTML
descrizione.innerHTML = "Testo con <strong>grassetto</strong>";
// Risultato: HTML viene interpretato!
// <p>Testo con <strong>grassetto</strong></p>
// Creare strutture complesse
const container = document.querySelector('#container');
container.innerHTML = `
<h2>Titolo</h2>
<p>Paragrafo 1</p>
<p>Paragrafo 2</p>
<button>Clicca</button>
`;
// Aggiungere in append (+=)
const lista = document.querySelector('#lista');
lista.innerHTML += "<li>Nuovo elemento</li>";
// Svuotare elemento
container.innerHTML = ""; // Rimuove tutto il contenuto
| Caratteristica | textContent | innerHTML |
|---|---|---|
| Contenuto | Solo testo | HTML completo |
| Tag HTML | ❌ Rimossi/Ignorati | ✅ Interpretati |
| Performance | ⚡ Più veloce | 🐢 Più lento |
| Sicurezza | ✅ Sicuro (no XSS) | ⚠️ Rischio XSS |
| Quando usare | Solo testo semplice | Strutture HTML |
innerHTML può essere pericoloso con input utente non sanitizzato!
// ❌ PERICOLOSO - Input utente diretto
const userInput = prompt("Inserisci nome:");
elemento.innerHTML = `<p>Ciao ${userInput}</p>`;
// Se utente inserisce: <script>alert('XSS')</script>
// Lo script viene eseguito! 😱
// ✅ SICURO - Usa textContent per input utente
elemento.textContent = userInput;
// Script viene mostrato come testo, non eseguito
// ✅ SICURO - Sanitizza con libreria (es: DOMPurify)
const pulito = DOMPurify.sanitize(userInput);
elemento.innerHTML = pulito;
🎨 Modificare Stile (style)
La proprietà style permette di modificare gli stili inline CSS
di un elemento.
<div id="box">Box</div>
const box = document.querySelector('#box');
// Modificare singole proprietà
box.style.color = "red";
box.style.backgroundColor = "yellow"; // Nota: camelCase!
box.style.fontSize = "20px";
box.style.padding = "10px";
box.style.border = "2px solid black";
box.style.borderRadius = "5px";
// Proprietà con più parole → camelCase
box.style.marginTop = "20px"; // margin-top
box.style.textAlign = "center"; // text-align
box.style.fontWeight = "bold"; // font-weight
// Con unità di misura
box.style.width = "200px";
box.style.height = "100px";
// Leggere stile
console.log(box.style.color); // "red"
console.log(box.style.backgroundColor); // "yellow"
// Rimuovere stile
box.style.color = ""; // Rimuove lo stile inline
// Risultato HTML:
// <div id="box" style="background-color: yellow; font-size: 20px; ...">
const box = document.querySelector('#box');
// Impostare più stili insieme
box.style.cssText = `
color: white;
background-color: blue;
padding: 20px;
border-radius: 10px;
font-size: 18px;
`;
// Oppure inline
box.style.cssText = "color: red; font-size: 24px; padding: 10px;";
// ⚠️ cssText SOVRASCRIVE tutti gli stili precedenti!
Legge TUTTI gli stili applicati (CSS + inline).
<style>
.box {
width: 200px;
height: 100px;
background: blue;
}
</style>
<div class="box" style="color: red;"></div>
// JavaScript
const box = document.querySelector('.box');
// style legge SOLO inline
console.log(box.style.width); // "" (vuoto!)
console.log(box.style.color); // "red" (inline)
// getComputedStyle legge TUTTO
const styles = window.getComputedStyle(box);
console.log(styles.width); // "200px"
console.log(styles.height); // "100px"
console.log(styles.backgroundColor); // "rgb(0, 0, 255)"
console.log(styles.color); // "rgb(255, 0, 0)"
// Proprietà specifiche
console.log(styles.getPropertyValue('width')); // "200px"
🌟 BEST PRACTICE: Preferisci modificare classi CSS invece di stili inline!
// ❌ NON IDEALE - Stili inline
elemento.style.color = "red";
elemento.style.fontSize = "20px";
elemento.style.fontWeight = "bold";
// ✅ MEGLIO - Usa classi CSS
/* CSS */
.highlight {
color: red;
font-size: 20px;
font-weight: bold;
}
// JavaScript
elemento.classList.add('highlight');
// Vantaggi:
// - Separazione stile/logica
// - Riutilizzabile
// - Più facile da mantenere
// - Migliore performance
📚 Gestire Classi CSS (classList)
classList è l’API moderna per gestire le classi CSS di un elemento.
Molto più comoda di className!
<div id="box" class="container highlight">Box</div>
const box = document.querySelector('#box');
// add() - Aggiungi classe
box.classList.add('active');
// Risultato: class="container highlight active"
// Aggiungi più classi insieme
box.classList.add('visible', 'important');
// Risultato: class="container highlight active visible important"
// remove() - Rimuovi classe
box.classList.remove('highlight');
// Risultato: class="container active visible important"
// Rimuovi più classi
box.classList.remove('visible', 'important');
// toggle() - Aggiungi se non c'è, rimuovi se c'è
box.classList.toggle('active'); // Rimuove (c'era)
box.classList.toggle('active'); // Aggiunge (non c'era)
// toggle() con condizione (opzionale)
const isLoggedIn = true;
box.classList.toggle('logged-in', isLoggedIn); // Aggiunge
box.classList.toggle('logged-in', !isLoggedIn); // Rimuove
// contains() - Verifica se ha classe
if (box.classList.contains('container')) {
console.log("Ha la classe container");
}
// replace() - Sostituisci classe
box.classList.replace('container', 'wrapper');
// Da: class="container ..."
// A: class="wrapper ..."
// Numero di classi
console.log(box.classList.length); // 2
// Lista classi (iterabile)
box.classList.forEach(classe => {
console.log(classe);
});
const elemento = document.querySelector('#elemento');
// ❌ VECCHIO MODO - className (stringa)
console.log(elemento.className); // "container highlight active"
// Aggiungere classe (scomodo!)
elemento.className += " nuova-classe"; // Spazio importante!
// Rimuovere classe (difficile!)
elemento.className = elemento.className.replace('highlight', '');
// ✅ NUOVO MODO - classList (API moderna)
console.log(elemento.classList); // DOMTokenList
elemento.classList.add('nuova-classe'); // Facile!
elemento.classList.remove('highlight'); // Facile!
elemento.classList.toggle('active'); // Facile!
// classList è MOLTO più comodo! 🌟
// Toggle menu mobile
const menuBtn = document.querySelector('#menu-btn');
const nav = document.querySelector('nav');
menuBtn.addEventListener('click', () => {
nav.classList.toggle('open');
});
// Tema dark/light
const themeBtn = document.querySelector('#theme-btn');
const body = document.body;
themeBtn.addEventListener('click', () => {
body.classList.toggle('dark-theme');
// Salva preferenza
const isDark = body.classList.contains('dark-theme');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
});
// Tabs attivi
const tabs = document.querySelectorAll('.tab');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
// Rimuovi active da tutti
tabs.forEach(t => t.classList.remove('active'));
// Aggiungi active al cliccato
tab.classList.add('active');
});
});
// Animazioni on scroll
const cards = document.querySelectorAll('.card');
window.addEventListener('scroll', () => {
cards.forEach(card => {
const rect = card.getBoundingClientRect();
if (rect.top < window.innerHeight) {
card.classList.add('visible');
} else {
card.classList.remove('visible');
}
});
});
🏷️ Gestire Attributi
Modifica attributi HTML come src, href, alt,
data-*, ecc.
<img id="foto" src="old.jpg" alt="Vecchia foto"> <a id="link" href="https://example.com">Link</a> <button id="btn" disabled>Bottone</button> <div id="box" data-id="123" data-category="tech"></div>
const foto = document.querySelector('#foto');
const link = document.querySelector('#link');
const btn = document.querySelector('#btn');
const box = document.querySelector('#box');
// getAttribute() - Leggi attributo
console.log(foto.getAttribute('src')); // "old.jpg"
console.log(foto.getAttribute('alt')); // "Vecchia foto"
console.log(link.getAttribute('href')); // "https://example.com"
// setAttribute() - Imposta attributo
foto.setAttribute('src', 'new.jpg');
foto.setAttribute('alt', 'Nuova foto');
link.setAttribute('href', 'https://google.com');
link.setAttribute('target', '_blank');
// removeAttribute() - Rimuovi attributo
btn.removeAttribute('disabled'); // Ora cliccabile!
// hasAttribute() - Verifica esistenza
if (foto.hasAttribute('alt')) {
console.log("Ha attributo alt");
}
// Attributi booleani (disabled, checked, required...)
btn.disabled = true; // Aggiungi disabled
btn.disabled = false; // Rimuovi disabled
const checkbox = document.querySelector('#check');
checkbox.checked = true; // Seleziona checkbox
Attributi personalizzati con prefisso data-.
// HTML
<div id="prodotto"
data-id="123"
data-price="99.99"
data-category="electronics"
data-in-stock="true">
</div>
// JavaScript - Metodo 1: getAttribute
const prodotto = document.querySelector('#prodotto');
console.log(prodotto.getAttribute('data-id')); // "123"
console.log(prodotto.getAttribute('data-price')); // "99.99"
// JavaScript - Metodo 2: dataset (CONSIGLIATO! 🌟)
console.log(prodotto.dataset.id); // "123"
console.log(prodotto.dataset.price); // "99.99"
console.log(prodotto.dataset.category); // "electronics"
console.log(prodotto.dataset.inStock); // "true" (camelCase!)
// Impostare data attribute
prodotto.dataset.id = "456";
prodotto.dataset.newAttribute = "valore";
// Risultato: data-new-attribute="valore"
// Rimuovere data attribute
delete prodotto.dataset.category;
// Uso pratico: associare dati agli elementi
const cards = document.querySelectorAll('.product-card');
cards.forEach(card => {
card.addEventListener('click', () => {
const productId = card.dataset.id;
const price = parseFloat(card.dataset.price);
console.log(`Prodotto ${productId} costa €${price}`);
// Chiamata API, aggiungi al carrello, ecc.
});
});
Differenza importante tra attributi HTML e proprietà DOM.
<input id="nome" type="text" value="Mario">
const input = document.querySelector('#nome');
// ATTRIBUTO (HTML) - valore iniziale
console.log(input.getAttribute('value')); // "Mario"
// PROPRIETÀ (DOM) - valore corrente
console.log(input.value); // "Mario"
// Utente cambia input in "Luigi"
console.log(input.getAttribute('value')); // "Mario" (non cambia!)
console.log(input.value); // "Luigi" (aggiornato!)
// Attributo = stato iniziale
// Proprietà = stato corrente
// Per questo SPESSO usi proprietà:
input.value = "Anna"; // Cambia valore
input.checked = true; // Checkbox
input.disabled = true; // Disabilita
// Invece di:
input.setAttribute('value', 'Anna'); // Meno usato
➕ Creare e Aggiungere Elementi
Crea nuovi elementi DOM da zero e aggiungili alla pagina!
// Crea nuovo elemento
const nuovoDiv = document.createElement('div');
const nuovoP = document.createElement('p');
const nuovoBtn = document.createElement('button');
// Imposta contenuto
nuovoDiv.textContent = "Sono un div nuovo!";
nuovoP.textContent = "Paragrafo creato dinamicamente";
nuovoBtn.textContent = "Clicca";
// Imposta attributi
nuovoDiv.id = "nuovo-div";
nuovoDiv.className = "box highlight";
nuovoBtn.type = "button";
// Imposta stile
nuovoDiv.style.color = "blue";
nuovoDiv.style.padding = "10px";
// Aggiungi classi
nuovoP.classList.add('testo', 'importante');
// Data attributes
nuovoBtn.dataset.action = "submit";
// L'elemento è creato MA non ancora visibile!
// Devi aggiungerlo al DOM...
const container = document.querySelector('#container');
const nuovoElemento = document.createElement('div');
nuovoElemento.textContent = "Nuovo!";
// append() - Aggiunge ALLA FINE (moderno) 🌟
container.append(nuovoElemento);
// prepend() - Aggiunge ALL'INIZIO (moderno) 🌟
container.prepend(nuovoElemento);
// appendChild() - Aggiunge alla fine (classico)
container.appendChild(nuovoElemento);
// Differenza append vs appendChild:
// append() può aggiungere più elementi e anche stringhe
container.append(elemento1, elemento2, "testo");
// appendChild() solo UN elemento DOM
container.appendChild(elemento1);
// before() - Inserisci PRIMA dell'elemento
const riferimento = document.querySelector('#rif');
nuovoElemento.before(riferimento);
// after() - Inserisci DOPO l'elemento
riferimento.after(nuovoElemento);
// insertBefore() - Classico (più complicato)
const parent = riferimento.parentElement;
parent.insertBefore(nuovoElemento, riferimento);
function creaCardProdotto(prodotto) {
// Crea elementi
const card = document.createElement('div');
const img = document.createElement('img');
const titolo = document.createElement('h3');
const descrizione = document.createElement('p');
const prezzo = document.createElement('div');
const button = document.createElement('button');
// Imposta classi
card.className = 'product-card';
prezzo.className = 'price';
button.className = 'btn btn-primary';
// Imposta contenuto
img.src = prodotto.immagine;
img.alt = prodotto.nome;
titolo.textContent = prodotto.nome;
descrizione.textContent = prodotto.descrizione;
prezzo.textContent = `€${prodotto.prezzo.toFixed(2)}`;
button.textContent = "Aggiungi al carrello";
// Data attributes
card.dataset.id = prodotto.id;
card.dataset.category = prodotto.categoria;
// Aggiungi event listener
button.addEventListener('click', () => {
console.log(`Aggiunto: ${prodotto.nome}`);
});
// Assembla card
card.append(img, titolo, descrizione, prezzo, button);
return card;
}
// Uso
const prodotto = {
id: 1,
nome: "Laptop",
descrizione: "Laptop potente",
prezzo: 999,
immagine: "laptop.jpg",
categoria: "elettronica"
};
const card = creaCardProdotto(prodotto);
document.querySelector('#prodotti').append(card);
➖ Rimuovere Elementi
Elimina elementi dal DOM quando non servono più.
const elemento = document.querySelector('#da-rimuovere');
// remove() - Rimuove l'elemento (moderno) 🌟
elemento.remove();
// removeChild() - Rimuove figlio (classico)
const parent = elemento.parentElement;
parent.removeChild(elemento);
// Svuotare contenitore (rimuove tutti i figli)
const container = document.querySelector('#container');
// Metodo 1: innerHTML
container.innerHTML = "";
// Metodo 2: Loop children
while (container.firstChild) {
container.removeChild(container.firstChild);
}
// Metodo 3: replaceChildren (moderno)
container.replaceChildren();
// Rimuovere elementi che matchano selettore
const daRimuovere = document.querySelectorAll('.temporary');
daRimuovere.forEach(el => el.remove());
// Rimuovere con conferma
const btn = document.querySelector('#delete-btn');
btn.addEventListener('click', () => {
if (confirm('Sicuro di voler eliminare?')) {
elemento.remove();
}
});
📋 Clonare Elementi
Duplica elementi esistenti invece di crearli da zero.
const originale = document.querySelector('#template');
// cloneNode(false) - Clona solo elemento (shallow)
const cloneSuperficiale = originale.cloneNode(false);
// cloneNode(true) - Clona elemento + figli (deep) 🌟
const cloneProfondo = originale.cloneNode(true);
// Modifica clone
cloneProfondo.id = "nuovo-id";
cloneProfondo.textContent = "Elemento clonato";
// Aggiungi al DOM
document.body.append(cloneProfondo);
// Esempio: Template system
const templateCard = document.querySelector('#card-template');
function creaCardDaTemplate(dati) {
const card = templateCard.cloneNode(true);
card.style.display = 'block'; // Template nascosto
card.id = `card-${dati.id}`;
card.querySelector('.title').textContent = dati.titolo;
card.querySelector('.description').textContent = dati.descrizione;
return card;
}
const nuovaCard = creaCardDaTemplate({
id: 1,
titolo: "Titolo",
descrizione: "Descrizione"
});
document.querySelector('#cards-container').append(nuovaCard);
🚀 Esempio Completo: Todo List Dinamica
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Todo List</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: Arial; padding: 20px; background: #f5f5f5; }
.container { max-width: 600px; margin: 0 auto; background: white; padding: 20px; border-radius: 10px; }
h1 { color: #333; margin-bottom: 20px; }
.input-group { display: flex; gap: 10px; margin-bottom: 20px; }
input { flex: 1; padding: 10px; border: 2px solid #ddd; border-radius: 5px; font-size: 16px; }
button { padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; }
.btn-add { background: #4CAF50; color: white; }
.btn-add:hover { background: #45a049; }
.todo-item { display: flex; align-items: center; padding: 15px; margin-bottom: 10px; background: #f9f9f9; border-radius: 5px; transition: all 0.3s; }
.todo-item:hover { background: #f0f0f0; transform: translateX(5px); }
.todo-item.completed { opacity: 0.6; }
.todo-item.completed .todo-text { text-decoration: line-through; color: #888; }
.todo-text { flex: 1; font-size: 16px; }
.todo-checkbox { margin-right: 15px; width: 20px; height: 20px; cursor: pointer; }
.btn-delete { background: #f44336; color: white; padding: 5px 10px; font-size: 14px; }
.btn-delete:hover { background: #da190b; }
.stats { margin-top: 20px; padding: 15px; background: #e3f2fd; border-radius: 5px; }
.stats p { margin: 5px 0; color: #1976d2; }
</style>
</head>
<body>
<div class="container">
<h1>📝 Todo List</h1>
<div class="input-group">
<input type="text" id="todo-input" placeholder="Aggiungi un todo...">
<button class="btn-add" id="add-btn">Aggiungi</button>
</div>
<div id="todos-container"></div>
<div class="stats" id="stats"></div>
</div>
<script src="script.js"></script>
</body>
</html>
// === SELEZIONE ELEMENTI ===
const todoInput = document.querySelector('#todo-input');
const addBtn = document.querySelector('#add-btn');
const todosContainer = document.querySelector('#todos-container');
const statsDiv = document.querySelector('#stats');
// Array per memorizzare todos
let todos = [];
let nextId = 1;
// === FUNZIONI ===
// Crea elemento todo
function creaTodoElement(todo) {
// Crea elementi
const todoItem = document.createElement('div');
const checkbox = document.createElement('input');
const todoText = document.createElement('span');
const deleteBtn = document.createElement('button');
// Imposta classi
todoItem.className = 'todo-item';
if (todo.completed) {
todoItem.classList.add('completed');
}
todoText.className = 'todo-text';
checkbox.className = 'todo-checkbox';
deleteBtn.className = 'btn-delete';
// Imposta attributi
checkbox.type = 'checkbox';
checkbox.checked = todo.completed;
todoItem.dataset.id = todo.id;
// Imposta contenuto
todoText.textContent = todo.testo;
deleteBtn.textContent = "Elimina";
// Event listeners
checkbox.addEventListener('change', () => {
toggleTodo(todo.id);
});
deleteBtn.addEventListener('click', () => {
eliminaTodo(todo.id);
});
// Assembla elemento
todoItem.append(checkbox, todoText, deleteBtn);
return todoItem;
}
// Aggiungi todo
function aggiungiTodo() {
const testo = todoInput.value.trim();
if (testo === "") {
alert("Inserisci un todo!");
return;
}
// Crea oggetto todo
const nuovoTodo = {
id: nextId++,
testo: testo,
completed: false
};
// Aggiungi a array
todos.push(nuovoTodo);
// Crea elemento DOM
const todoElement = creaTodoElement(nuovoTodo);
// Aggiungi al container
todosContainer.append(todoElement);
// Reset input
todoInput.value = "";
todoInput.focus();
// Aggiorna stats
aggiornaStats();
}
// Toggle completed
function toggleTodo(id) {
// Trova todo in array
const todo = todos.find(t => t.id === id);
if (!todo) return;
// Toggle completed
todo.completed = !todo.completed;
// Aggiorna DOM
const todoElement = document.querySelector(`[data-id="${id}"]`);
todoElement.classList.toggle('completed');
// Aggiorna stats
aggiornaStats();
}
// Elimina todo
function eliminaTodo(id) {
// Rimuovi da array
todos = todos.filter(t => t.id !== id);
// Rimuovi da DOM
const todoElement = document.querySelector(`[data-id="${id}"]`);
// Animazione fade out
todoElement.style.opacity = "0";
todoElement.style.transform = "translateX(-100%)";
setTimeout(() => {
todoElement.remove();
aggiornaStats();
}, 300);
}
// Aggiorna statistiche
function aggiornaStats() {
const totale = todos.length;
const completati = todos.filter(t => t.completed).length;
const pendenti = totale - completati;
const percentuale = totale > 0 ? ((completati / totale) * 100).toFixed(0) : 0;
statsDiv.innerHTML = `
<p><strong>📊 Statistiche</strong></p>
<p>Totale: ${totale} | Completati: ${completati} | Pendenti: ${pendenti}</p>
<p>Progresso: ${percentuale}%</p>
`;
}
// === EVENT LISTENERS ===
addBtn.addEventListener('click', aggiungiTodo);
todoInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
aggiungiTodo();
}
});
// === INIZIALIZZAZIONE ===
aggiornaStats();
todoInput.focus();
console.log("Todo List inizializzata! ✅");
createElement()- Crea tutti gli elementitextContent- Imposta testo sicuroclassList- Gestisce classi CSSdataset- Memorizza ID elementoappend()- Aggiunge elementiremove()- Elimina elementiquerySelector()con data attribute- Event listeners dinamici
- Animazioni CSS con JavaScript
| Operazione | Metodo | Esempio |
|---|---|---|
| Modificare testo | textContent |
el.textContent = "Ciao" |
| Modificare HTML | innerHTML |
el.innerHTML = "<b>Ciao</b>" |
| Modificare stile | style |
el.style.color = "red" |
| Aggiungere classe | classList.add() |
el.classList.add('active') |
| Toggle classe | classList.toggle() |
el.classList.toggle('open') |
| Impostare attributo | setAttribute() |
el.setAttribute('src', 'img.jpg') |
| Data attribute | dataset |
el.dataset.id = "123" |
| Creare elemento | createElement() |
document.createElement('div') |
| Aggiungere elemento | append() |
parent.append(child) |
| Rimuovere elemento | remove() |
el.remove() |