JavaScript i DOM: zmiana strony z poziomu skryptu

INF.03 · teoria
autor: redakcja · 09.09.2026
Model DOM w JavaScript: jak przeglądarka buduje drzewo dokumentu, jak pobrać z niego element metodami getElementById, getElementsByClassName i querySelector oraz jak zmienić jego treść, atrybuty, styl i klasy, a także dodać i usunąć węzeł. Lekcja 11.6 kursu INF.03.
DOM (Do­cu­ment Object Model, obiek­to­wy model do­ku­men­tu) to drzewo obiek­tów, które prze­glą­dar­ka buduje z kodu HTML strony i oddaje do dys­po­zy­cji skryp­to­wi. Każdy znacz­nik jest w nim osob­nym obiek­tem z wła­sno­ścia­mi, a zmiana wła­sno­ści wi­docz­na jest na ekra­nie od razu, bez prze­ła­do­wa­nia strony. W części pi­sem­nej wra­ca­ją py­ta­nia „do czego służy document.getElementById", „którą in­struk­cją zmie­nić kolor tekstu ele­men­tu", „jak od­wo­łać się do pierw­sze­go aka­pi­tu". W za­da­niu prak­tycz­nym to DOM wsta­wia po­li­czo­ny wynik do wska­za­ne­go ele­men­tu i zmie­nia kolory strony.

Drzewo do­ku­men­tu

Drzewo do­ku­men­tu to hie­rar­chia węzłów, w której każdy ele­ment HTML ma jed­ne­go ro­dzi­ca i do­wol­nie wiele dzieci, a ele­men­ty o wspól­nym ro­dzi­cu są ro­dzeń­stwem. Ko­rze­niem jest html, a całe drzewo re­pre­zen­tu­je obiekt document (do­ku­ment): od niego za­czy­na się każde od­wo­ła­nie do strony. Znacz­ni­ki i za­gnież­dża­nie opi­su­je dział o HTML.
Drzewo dokumentu: korzeń html, pod nim head i body, a w body header, main z nagłówkiem i akapitem oraz footer; skrypt sięga do każdego z tych węzłów
Prze­glą­dar­ka buduje to drzewo w trak­cie czy­ta­nia pliku, od góry do dołu. Skrypt uru­cho­mio­ny w <head> wy­ko­nu­je się, zanim po­wsta­nie co­kol­wiek z <body>, więc szuka ele­men­tów, któ­rych jesz­cze nie ma, i do­sta­je null (nic). Ko­lej­ny wiersz, który pró­bu­je na tym null czegoś zmie­nić, kończy się błędem w kon­so­li i skrypt staje.
1
2
3
4
5
6
<head>
<script src="skrypt.js"></script>
</head>
<body>
<p id="cena1">120 zł</p>
</body>
W takim ukła­dzie document.getElementById("cena1") zwróci null, choć akapit ist­nie­je w pliku. Le­kar­stwo jest jedno: znacz­nik <script> idzie przed za­my­ka­ją­cym </body>, i do­kład­nie tak do­łą­cza się plik skryp­tu w za­da­niu prak­tycz­nym.
Skrypt nie zmie­nia pliku HTML na dysku, tylko drzewo w pa­mię­ci prze­glą­dar­ki. Po od­świe­że­niu strony wszyst­ko wraca do stanu z pliku.

Po­bie­ra­nie ele­men­tów

Po­bra­nie ele­men­tu to od­na­le­zie­nie w drze­wie węzła, na którym skrypt ma pra­co­wać. Metody należą do obiek­tu document i dzielą się na dwie grupy: jedne oddają POJEDYNCZY ele­ment, drugie KOLEKCJĘ, czyli po­nu­me­ro­wa­ny zbiór wszyst­kich pa­su­ją­cych ele­men­tów. Ko­lej­ne przy­kła­dy pra­cu­ją na takim frag­men­cie strony sklepu:
1
2
3
<h1 id="tytul">Sklep komputerowy</h1>
<p class="cena">650 zł</p>
<p class="cena">120 zł</p>
getElementById (POBIERZ ELEMENT PO IDENTYFIKATORZE) oddaje jeden ele­ment o po­da­nym id, bez znaku # w na­wia­sie. getElementsByTagName (POBIERZ ELEMENTY PO NAZWIE ZNACZNIKA) oddaje ko­lek­cję wszyst­kich ele­men­tów danego znacz­ni­ka, a getElementsByClassName (POBIERZ ELEMENTY PO NAZWIE KLASY) ko­lek­cję wszyst­kich ele­men­tów na­le­żą­cych do klasy.
1
2
3
4
5
6
const tytul = document.getElementById("tytul");
const akapity = document.getElementsByTagName("p");
const ceny = document.getElementsByClassName("cena");
console.log(tytul.textContent);
console.log(akapity.length);
console.log(ceny[0].textContent);
1
2
3
Sklep komputerowy
2
650 zł
Ko­lek­cja sama nie jest ele­men­tem: ma wła­sność length (dłu­gość) i nu­me­ra­cję od zera, więc do po­je­dyn­czej po­zy­cji sięga się na­wia­sem kwa­dra­to­wym, a do wszyst­kich pętlą.
1
2
3
4
const ceny = document.getElementsByClassName("cena");
for (let i = 0; i < ceny.length; i++) {
ceny[i].textContent = "wyprzedane";
}
Wynik: oba aka­pi­ty klasy cena mają teraz treść wyprzedane. Ta sama in­struk­cja bez [i], czyli ceny.textContent = "wyprzedane";, nie zmie­ni­ła­by ni­cze­go, bo ko­lek­cja takiej wła­sno­ści nie ma.
querySelector (WYBIERZ PO SELEKTORZE) i querySelectorAll (WYBIERZ WSZYSTKIE PO SELEKTORZE) przyj­mu­ją se­lek­tor CSS, ten sam co w ar­ku­szu stylów: #tytul dla iden­ty­fi­ka­to­ra, .cena dla klasy, p dla znacz­ni­ka. Pierw­sza oddaje pierw­szy pa­su­ją­cy ele­ment, druga ko­lek­cję wszyst­kich. Se­lek­to­ry omawia lekcja o se­lek­to­rach CSS.
1
2
3
4
5
const pierwszaCena = document.querySelector(".cena");
const wszystkieCeny = document.querySelectorAll(".cena");
console.log(pierwszaCena.textContent);
console.log(wszystkieCeny.length);
console.log(document.querySelector("#tytul").textContent);
1
2
3
650 zł
2
Sklep komputerowy
Pu­łap­ka: getElementById ma ELEMENT w licz­bie po­je­dyn­czej, a getElementsByTagName i getElementsByClassName ELEMENTS w mno­giej. Zapisy getElementByID i getElementByTagName nie ist­nie­ją, bo JavaScript roz­róż­nia wiel­kość liter.

Zmiana treści ele­men­tu

Treść ele­men­tu zmie­nia się przez przy­pi­sa­nie do jednej z trzech wła­sno­ści. innerHTML (we­wnętrz­ny HTML) pod­mie­nia za­war­tość razem ze znacz­ni­ka­mi: to, co przy­pi­szesz, prze­glą­dar­ka prze­czy­ta jak kod strony. textContent (treść tek­sto­wa) wsta­wia czysty tekst, więc znacz­ni­ki pokażą się do­słow­nie, ze zna­ka­mi mniej­szo­ści. innerText (tekst we­wnętrz­ny) działa jak textContent, ale pomija tekst ukryty stylem.
1
2
3
4
const koszyk = document.getElementById("koszyk");
koszyk.innerHTML = "Masz <b>3</b> produkty";
const stopka = document.getElementById("stopka");
stopka.textContent = "Masz <b>3</b> produkty";
Wynik: w ko­szy­ku widać Masz 3 produkty z po­gru­bio­ną trójką, a w stopce do­słow­nie Masz <b>3</b> produkty, razem ze znacz­ni­ka­mi.
To samo przy­pi­sa­nie ze zna­kiem plus do­kła­da treść za­miast ją ka­so­wać: koszyk.innerHTML = koszyk.innerHTML + " i mysz";. Do praw­dzi­wej strony innerHTML nadaje się tylko dla treści, którą sam two­rzysz: wsta­wio­ny w ten sposób tekst od użyt­kow­ni­ka wpro­wa­dza na stronę cudzy kod, więc dane z for­mu­la­rza idą przez textContent. Arkusz CKE żąda jednak innerHTML wprost i tego trzeba użyć.
Poza DOM stoi document.write (PISZ), znane z pytań o wy­pi­sy­wa­nie tekstu. Pisze ono wprost do do­ku­men­tu w trak­cie jego wczy­ty­wa­nia, a wy­wo­ła­ne póź­niej czyści całą stronę i za­stę­pu­je ją tym, co do­sta­ło, więc w go­to­wej wi­try­nie się go nie używa.

Atry­bu­ty i war­tość pola for­mu­la­rza

Atry­but to para nazwa i war­tość za­pi­sa­na w znacz­ni­ku, na przy­kład src w ob­ra­zie albo href w od­no­śni­ku. setAttribute (USTAW ATRYBUT) przyj­mu­je nazwę atry­bu­tu i nową war­tość, getAttribute (POBIERZ ATRYBUT) samą nazwę i oddaje war­tość. Naj­częst­sze atry­bu­ty są do­stęp­ne także jako zwykłe wła­sno­ści obiek­tu, więc te same dwa zapisy robią to samo.
1
2
3
4
const foto = document.getElementById("foto");
foto.setAttribute("src", "monitor2.png");
foto.src = "monitor2.png";
console.log(foto.getAttribute("alt"));
Wynik dla obrazu <img id="foto" src="monitor1.png" alt="Monitor 24">: na stro­nie po­ja­wia się monitor2.png w miej­scu po­przed­nie­go zdję­cia, a kon­so­la wy­pi­su­je Monitor 24. Pod­mia­na ob­raz­ka po klik­nię­ciu przy­ci­sku to jedno ze sta­łych pytań w banku.
Pola for­mu­la­rza trzy­ma­ją wpi­sa­ny tekst w osob­nej wła­sno­ści value (war­tość). Zawsze jest to napis, nawet gdy pole ma typ number, więc do ra­chun­ków prze­pusz­cza się go przez Number. Same pola opi­su­je lekcja o for­mu­la­rzach HTML.
1
2
3
4
const pole = document.getElementById("ilosc");
const ile = Number(pole.value);
const suma = ile * 650;
document.getElementById("koszyk").innerHTML = "Do zapłaty: " + suma + " zł";
Wynik: gdy w polu stoi 2, ele­ment o iden­ty­fi­ka­to­rze koszyk po­ka­zu­je Do zapłaty: 1300 zł. Znacz­nik input nie ma treści między na­wia­sa­mi ostry­mi, więc jego innerHTML jest pusty: wpi­sa­ny tekst leży wy­łącz­nie w value.

Styl i klasy

Wygląd ele­men­tu zmie­nia się na dwa spo­so­by: przez wła­sność style (styl), która usta­wia regułę wprost w znacz­ni­ku, albo przez pod­mia­nę klasy, po której gotową regułę znaj­dzie arkusz stylów. Nazwy wła­ści­wo­ści CSS z mi­nu­sem tracą go w JavaScript i do­sta­ją wielką literę: background-color staje się backgroundColor, font-size staje się fontSize.
1
2
3
4
const cena = document.getElementById("cena1");
cena.style.color = "blue";
cena.style.backgroundColor = "yellow";
document.body.style.backgroundColor = "black";
Wynik: akapit cena1 ma nie­bie­ski tekst na żółtym tle, a tło całej strony robi się czarne. Ostat­ni wiersz to do­kład­nie to, o co prosi arkusz w za­da­niu „skrypt zmie­nia kolory tła i czcion­ki całej strony".
Wła­sność display (wy­świe­tla­nie) o war­to­ści none usuwa ele­ment z układu strony: ele­ment znika, a miej­sce po nim się zamyka. War­tość block przy­wra­ca go z po­wro­tem. Klasę całą naraz pod­mie­nia className (nazwa klasy), a po­je­dyn­cze klasy do­kła­da i za­bie­ra classList (lista klas) me­to­da­mi add, remove i toggle.
1
2
3
4
5
6
const promocja = document.getElementById("promocja");
promocja.style.display = "none";
promocja.className = "wyrozniona";
promocja.classList.add("nowosc");
promocja.classList.remove("wyprzedaz");
console.log(promocja.className);
Wynik: wyrozniona nowosc. Ele­ment jest ukryty, className nad­pi­sał wszyst­kie wcze­śniej­sze klasy, add do­ło­żył jedną, a remove nie­obec­nej klasy wyprzedaz nie zrobił nic.
Pu­łap­ka: style.background-color to błąd skład­ni, bo minus czyta się jako odej­mo­wa­nie, a style.font-color nie ist­nie­je w ogóle: ko­lo­rem tekstu jest color.

Two­rze­nie i usu­wa­nie ele­men­tów

Nowy ele­ment po­wsta­je w dwóch kro­kach. createElement (UTWÓRZ ELEMENT) buduje węzeł z po­da­nej nazwy znacz­ni­ka, ale trzyma go poza drze­wem, więc na stro­nie jesz­cze go nie widać. appendChild (DOŁĄCZ DZIECKO) wy­wo­ła­ny na ele­men­cie ro­dzi­ca dopina węzeł jako jego ostat­nie dziec­ko i do­pie­ro wtedy ele­ment po­ja­wia się na ekra­nie.
1
2
3
4
5
6
7
const lista = document.getElementById("produkty");
const nazwy = ["Monitor 24", "Klawiatura", "Mysz"];
for (let i = 0; i < nazwy.length; i++) {
const pozycja = document.createElement("li");
pozycja.textContent = nazwy[i];
lista.appendChild(pozycja);
}
Wynik: lista <ul id="produkty"> do­sta­je trzy ele­men­ty <li> z na­zwa­mi w ko­lej­no­ści z ta­bli­cy. Ta­bli­ce omawia lekcja o ta­bli­cach i obiek­tach.
removeChild (USUŃ DZIECKO) kasuje węzeł, ale wy­wo­łu­je się go na RODZICU i podaje mu dziec­ko do usu­nię­cia, nie od­wrot­nie.
1
2
3
4
const lista = document.getElementById("produkty");
const pierwsza = lista.getElementsByTagName("li")[0];
lista.removeChild(pierwsza);
console.log(lista.getElementsByTagName("li").length);
Wynik: 2, bo pierw­sza po­zy­cja znik­nę­ła. Całą za­war­tość ele­men­tu czyści jeden wiersz lista.innerHTML = "";, i to jest zwykle krót­sza droga niż pętla z removeChild.

Na eg­za­mi­nie

Py­ta­nia pi­sem­ne o DOM mają kilka sta­łych kształ­tów. „Metoda document.getElementById(id) ma za za­da­nie": zwró­cić od­nie­sie­nie do ele­men­tu o po­da­nym iden­ty­fi­ka­to­rze, nie spraw­dzić for­mu­la­rza ani nic wy­pi­sać. „DOM do­star­cza metod i wła­sno­ści po­zwa­la­ją­cych na": po­bie­ra­nie i mo­dy­fi­ko­wa­nie ele­men­tów strony wy­świe­tlo­nej przez prze­glą­dar­kę. Od­wo­ła­nie do pierw­sze­go aka­pi­tu we frag­men­cie bez iden­ty­fi­ka­to­rów to getElementsByTagName("p")[0], a ope­ra­cje na znacz­ni­kach z klasą nomargin to getElementsByClassName("nomargin"). Zmiana koloru tekstu ele­men­tu o iden­ty­fi­ka­to­rze test to document.getElementById("test").style.color = "blue";, a nie style.font-color, nie css.color i nie style.background-color. Za­war­tość ele­men­tu zmie­nia innerHTML, a war­tość atry­bu­tu setAttribute, nie getAttribute.
Kilka od­po­wie­dzi myli się re­gu­lar­nie. Py­ta­nie z ko­mu­ni­ka­tem błędu w kon­so­li i kodem getElementByTagName ma jedną po­praw­ną od­po­wiedź: błęd­nie na­pi­sa­na nazwa metody, po­win­no być getElementsByTagName. Ko­lek­cja nie jest ele­men­tem, więc bez in­dek­su albo pętli przy­pi­sa­nie do niej nic nie da. Skrypt umiesz­czo­ny w <head> bez opóź­nie­nia nie znaj­dzie ele­men­tu z <body>. W kodzie z ar­ku­szy i banku pytań zmien­ne de­kla­ru­je var, star­sze od let i const, ale dzia­ła­ją­ce tu tak samo.
W za­da­niu prak­tycz­nym po­le­ce­nie brzmi zwykle: „skrypt zmie­nia kolor tła i czcion­ki całej strony", „wynik wy­świe­tlo­ny w ele­men­cie o po­da­nym iden­ty­fi­ka­to­rze", „lista wy­ge­ne­ro­wa­na na pod­sta­wie ta­bli­cy". Pierw­sze to document.body.style.backgroundColor i document.body.style.color, drugie document.getElementById("wynik").innerHTML = ..., trze­cie pętla z createElement i appendChild. Plik do­łą­cza się znacz­ni­kiem <script src="skrypt.js"></script> przed za­my­ka­ją­cym </body>, a wy­wo­łu­je klik­nię­ciem przy­ci­sku: zda­rze­nia opi­su­je lekcja o zda­rze­niach i for­mu­la­rzach.

Ściąga

Zapis
Znaczy
document.getElementById("x")
jeden ele­ment o iden­ty­fi­ka­to­rze x, bez znaku #
document.getElementsByTagName("p")
ko­lek­cja wszyst­kich aka­pi­tów
document.getElementsByClassName("c")
ko­lek­cja wszyst­kich ele­men­tów klasy c
document.querySelector("#x")
pierw­szy ele­ment pa­su­ją­cy do se­lek­to­ra CSS
document.querySelectorAll(".c")
ko­lek­cja wszyst­kich pa­su­ją­cych do se­lek­to­ra
kolekcja[0]
pierw­szy ele­ment ko­lek­cji, nu­me­ra­cja od zera
kolekcja.length
liczba ele­men­tów w ko­lek­cji
el.innerHTML = "<b>3</b>"
treść razem ze znacz­ni­ka­mi, znacz­ni­ki dzia­ła­ją
el.textContent = "<b>3</b>"
czysty tekst, znacz­ni­ki wi­docz­ne do­słow­nie
el.setAttribute("src", "a.png")
usta­wie­nie war­to­ści atry­bu­tu
el.getAttribute("alt")
odczyt war­to­ści atry­bu­tu
pole.value
tekst wpi­sa­ny w pole for­mu­la­rza
el.style.color = "blue"
kolor tekstu ele­men­tu
el.style.backgroundColor = "red"
kolor tła, nazwa CSS bez minusa, wielką literą
el.style.display = "none"
ukry­cie ele­men­tu razem z jego miej­scem
el.className = "a b"
pod­mia­na całego atry­bu­tu class
el.classList.add("a")
do­ło­że­nie jednej klasy, bez ru­sza­nia po­zo­sta­łych
document.createElement("li")
nowy węzeł, jesz­cze poza drze­wem
rodzic.appendChild(el)
do­pię­cie węzła jako ostat­nie­go dziec­ka
rodzic.removeChild(el)
usu­nię­cie dziec­ka, wy­wo­ła­ne na ro­dzi­cu
Pobierz ściągę PDF
ZAWODNIK
egzamin zawodowy INF.02 · INF.03 · INF.04
Serwer Discord
Egzaminy zawodowe IT/Matury/Studia
@yastor
© 2026 Zawodnik · by Yastor
Arkusze i zasady oceniania pochodzą z CKE. Serwis nie jest powiązany z Centralną Komisją Egzaminacyjną.