28. února 2026

Hledání: getElement*, querySelector*

Navigační vlastnosti DOMu jsou skvělé, když jsou elementy navzájem u sebe. Ale co když nejsou? Jak získáme libovolný element stránky?

K tomu slouží další vyhledávací metody.

document.getElementById nebo jen id

Jestliže element má atribut id, můžeme tento element získat pomocí metody document.getElementById(id), ať se nachází kdekoli.

Příklad:

<div id="elem">
  <div id="elem-obsah">Element</div>
</div>

<script>
  // získáme element
  let elem = document.getElementById('elem');

  // obarvíme jeho pozadí červeně
  elem.style.background = 'red';
</script>

Existuje i globální proměnná pojmenovaná podle id, která se na element odkazuje:

<div id="elem">
  <div id="elem-obsah">Element</div>
</div>

<script>
  // elem je odkaz na DOM element s id="elem"
  elem.style.background = 'red';

  // id="elem-obsah" obsahuje pomlčku, takže to nemůže být název proměnné
  // ...můžeme však k němu přistupovat pomocí hranatých závorek: window['elem-obsah']
</script>

…To funguje, dokud v JavaScriptu nedeklarujeme proměnnou se stejným názvem, ta má pak přednost:

<div id="elem"></div>

<script>
  let elem = 5; // elem je nyní 5, ne odkaz na <div id="elem">

  alert(elem); // 5
</script>
Prosíme nepřistupujte k elementům přes globální proměnné nazvané podle id

Toto chování je popsáno ve specifikaci, ale je podporováno zejména kvůli kompatibilitě.

Prohlížeč se nám snaží pomoci tak, že míchá dohromady jmenné prostory JS a DOMu. To se hodí pro jednoduché skripty, vložené přímo do HTML kódu, ale obecně to není dobrá věc. Mohou nastat konflikty názvů. Navíc když si někdo čte JS kód a nemá zobrazen HTML kód, není mu zřejmé, odkud ona proměnná pochází.

V tomto tutoriálu používáme přímý odkaz na element pomocí id pro stručnost, když je zřejmé, odkud element pochází.

V reálném životě je preferována metoda document.getElementById.

id musí být unikátní

id musí být unikátní. V dokumentu může být pouze jeden element s daným id.

Pokud v něm je více elementů se stejným id, pak chování metod, které je využívají, bude nepředvídatelné, např. document.getElementById může vrátit náhodně kterýkoli z těchto elementů. Prosíme tedy, dodržujte toto pravidlo a zachovávejte id unikátní.

Jen document.getElementById, ne jakýkoliElement.getElementById

Metoda getElementById může být volána jedině na objektu document. Hledá zadané id v celém dokumentu.

querySelectorAll

Zdaleka nejpřizpůsobivější metodou je elem.querySelectorAll(css), která vrací všechny elementy uvnitř elem, které odpovídají zadanému CSS selektoru.

Zde najdeme všechny elementy <li>, které jsou posledními dětmi:

<ul>
  <li>Tento</li>
  <li>test</li>
</ul>
<ul>
  <li>prošel</li>
  <li>úspěšně</li>
</ul>
<script>
  let elementy = document.querySelectorAll('ul > li:last-child');

  for (let elem of elementy) {
    alert(elem.innerHTML); // "test", "úspěšně"
  }
</script>

Je to opravdu silná metoda, protože můžeme použít jakýkoli CSS selektor.

Můžeme použít i pseudotřídy

V CSS selektoru jsou podporovány i pseudotřídy, např. :hover nebo :active. Například document.querySelectorAll(':hover') vrátí kolekci elementů, nad nimiž se právě nachází ukazatel (v pořadí vnoření: od vrchního <html> k nejvnořenějšímu elementu).

querySelector

Volání elem.querySelector(css) vrátí první element pro zadaný CSS selektor.

Jinými slovy, výsledek je stejný jako elem.querySelectorAll(css)[0], ale tímto postupem najdeme všechny elementy a pak vezmeme jeden z nich, zatímco elem.querySelector najde pouze jeden. Je tedy rychlejší a navíc kratší na napsání.

matches

Předchozí metody prohledávaly DOM.

Metoda elem.matches(css) nic nehledá, ale jen prověří, zda elem odpovídá zadanému CSS selektoru. Vrací true nebo false.

Tato metoda se hodí, když iterujeme nad elementy (třeba v poli nebo v něčem podobném) a snažíme se vyfiltrovat ty, které nás zajímají.

Příklad:

<a href="http://example.com/file.zip">...</a>
<a href="http://ya.ru">...</a>

<script>
  // místo document.body.children zde může být libovolná kolekce
  for (let elem of document.body.children) {
    if (elem.matches('a[href$="zip"]')) {
      alert("Odkaz na archív: " + elem.href );
    }
  }
</script>

closest

Předkové elementu jsou: rodič, jeho rodič, rodič jeho rodiče a tak dále. Předkové společně tvoří řetěz rodičů od elementu až k vrcholu.

Metoda elem.closest(css) najde nejbližšího předka, který odpovídá zadanému CSS selektoru. Do hledání je zahrnut i samotný element elem.

Jinými slovy, metoda closest postupuje od elementu nahoru a prověří každého z rodičů. Jestliže odpovídá selektoru, hledání se zastaví a onen předek je vrácen.

Příklad:

<h1>Obsah</h1>

<div class="obsah">
  <ul class="kniha">
    <li class="kapitola">Kapitola 1</li>
    <li class="kapitola">Kapitola 2</li>
  </ul>
</div>

<script>
  let kapitola = document.querySelector('.kapitola'); // LI

  alert(kapitola.closest('.kniha')); // UL
  alert(kapitola.closest('.obsah')); // DIV

  alert(kapitola.closest('h1')); // null (protože h1 není předek)
</script>

getElementsBy*

Existují i jiné metody, které hledají uzly podle značky, třídy a podobně.

V dnešní době jsou již převážně historií, neboť querySelector je silnější a kratší na napsání.

Uvedeme je tedy zejména pro úplnost, protože ve starších skriptech je stále můžete najít.

  • elem.getElementsByTagName(značka) najde elementy se zadanou značkou a vrátí jejich kolekci. Parametr značka může být i hvězdička "*", což znamená „libovolná značka“.
  • elem.getElementsByClassName(názevTřídy) vrátí elementy, které mají zadanou CSS třídu.
  • document.getElementsByName(název) vrátí všechny elementy z celého dokumentu, jejichž atribut name má zadanou hodnotu. Používá se velmi zřídka.

Příklad:

// získáme všechny elementy <div> v dokumentu
let divy = document.getElementsByTagName('div');

Najděme všechny značky input uvnitř tabulky:

<table id="tabulka">
  <tr>
    <td>Váš věk:</td>

    <td>
      <label>
        <input type="radio" name="věk" value="mladý" checked> méně než 18 let
      </label>
      <label>
        <input type="radio" name="věk" value="dospělý"> od 18 do 50 let
      </label>
      <label>
        <input type="radio" name="věk" value="senior"> více než 50 let
      </label>
    </td>
  </tr>
</table>

<script>
  let vstupy = tabulka.getElementsByTagName('input');

  for (let vstup of vstupy) {
    alert( vstup.value + ': ' + vstup.checked );
  }
</script>
Nezapomínejte na písmeno "s"!

Začínající vývojáři někdy zapomínají na písmeno "s". Snaží se tedy volat getElementByTagName místo getElementsByTagName.

Písmeno "s" chybí v názvu getElementById, protože tato metoda vrací jediný element (písmeno „s“ je v angličtině přípona množného čísla podstatných jmen – pozn. překl.). Avšak getElementsByTagName vrací kolekci elementů, takže "s" v názvu je.

Metoda vrací kolekci, ne jediný element!

Další rozšířenou začátečnickou chybou je napsat:

// to nefunguje
document.getElementsByTagName('input').value = 5;

To nefunguje, protože tento kód vezme kolekci vstupů a přiřadí hodnotu přímo jí, ne elementům uvnitř.

Měli bychom buď iterovat nad kolekcí, nebo získat element podle jeho indexu a pak přiřazovat, například takto:

// to by mělo fungovat (pokud existuje <input>)
document.getElementsByTagName('input')[0].value = 5;

Najděme elementy třídy .článek:

<form name="můj-formulář">
  <div class="článek">Článek</div>
  <div class="dlouhý článek">Dlouhý článek</div>
</form>

<script>
  // hledání podle atributu name
  let form = document.getElementsByName('můj-formulář')[0];

  // hledání uvnitř formuláře podle třídy
  let články = form.getElementsByClassName('článek');
  alert(články.length); // 2, našly se dva elementy třídy "článek"
</script>

Živé kolekce

Všechny metody "getElementsBy*" vracejí živou kolekci. Taková kolekce vždy odráží aktuální stav dokumentu a „automaticky se aktualizuje“, když se dokument změní.

Následující příklad obsahuje dva skripty.

  1. První vytvoří odkaz na kolekci elementů <div>. Její délka je prozatím 1.
  2. Druhý se spustí až poté, co prohlížeč narazí na další <div>, takže délka kolekce bude 2.
<div>První div</div>

<script>
  let divy = document.getElementsByTagName('div');
  alert(divy.length); // 1
</script>

<div>Druhý div</div>

<script>
  alert(divy.length); // 2
</script>

Naproti tomu querySelectorAll vrací statickou kolekci, podobnou pevnému poli elementů.

Použijeme-li v uvedeném příkladu tuto metodu, oba skripty vypíší 1:

<div>První div</div>

<script>
  let divy = document.querySelectorAll('div');
  alert(divy.length); // 1
</script>

<div>Druhý div</div>

<script>
  alert(divy.length); // 1
</script>

Nyní jasně vidíme rozdíl. Statická kolekce se po přidání nového div do dokumentu nezvětšila.

Shrnutí

Pro hledání uzlů v DOMu existuje 6 hlavních metod:

Metoda Hledá podle... Může být volána na elementu? Vrací živou kolekci?
querySelector CSS selektoru ✔ -
querySelectorAll CSS selektoru ✔ -
getElementById id - -
getElementsByName name - ✔
getElementsByTagName značky nebo '*' ✔ ✔
getElementsByClassName třídy ✔ ✔

Zdaleka nejpoužívanější jsou querySelector a querySelectorAll, ale občas nám mohou pomoci nebo můžeme najít ve starších skriptech i getElement(s)By*.

Kromě toho:

  • Metoda elem.matches(css) prověří, zda elem odpovídá zadanému CSS selektoru.
  • Metoda elem.closest(css) najde nejbližšího předka, který odpovídá zadanému CSS selektoru. Prověří i samotný elem.

A zmiňme ještě jednu metodu, která prověřuje vztah dítě-rodič, protože i ta je někdy užitečná:

  • elemA.contains(elemB) vrátí true, jestliže elemB leží uvnitř elemA (je potomkem elemA) nebo jestliže elemA==elemB.

Úlohy

důležitost: 4

Zde je dokument s tabulkou a formulářem.

Jak najdeme?…

  1. Tabulku s id="tabulka-věků".
  2. Všechny elementy label uvnitř této tabulky (měly by tam být 3).
  3. První td v této tabulce (se slovem „Věk“).
  4. form s name="hledání".
  5. První input v tomto formuláři.
  6. Poslední input v tomto formuláři.

Otevřete si stránku table.html v samostatném okně a využijte k tomu prohlížečové nástroje.

Je mnoho způsobů, jak toho dosáhnout.

Zde jsou některé z nich:

// 1. Tabulka s `id="tabulka-věků"`.
let tabulka = document.getElementById('tabulka-věků')

// 2. Všechny elementy <label> uvnitř této tabulky
tabulka.getElementsByTagName('label')
// nebo
document.querySelectorAll('#tabulka-věků label')

// 3. První element <td> v této tabulce (se slovem „Věk“)
tabulka.rows[0].cells[0]
// nebo
tabulka.getElementsByTagName('td')[0]
// nebo
tabulka.querySelector('td')

// 4. Formulář s názvem "hledání"
// předpokládáme, že v dokumentu je jen jeden element s name="hledání"
let form = document.getElementsByName('hledání')[0]
// nebo specificky formulář
document.querySelector('form[name="hledání"]')

// 5. První <input> v tomto formuláři
form.getElementsByTagName('input')[0]
// nebo
form.querySelector('input')

// 6. Poslední <input> v tomto formuláři
let vstupy = form.querySelectorAll('input') // najdeme všechny vstupy
vstupy[vstupy.length-1] // vezmeme poslední
Mapa tutoriálu

Komentáře

přečtěte si před komentováním…
  • Máte-li návrhy na zlepšení, vytvořte prosím issue na GitHubu nebo pull request místo komentáře.
  • Pokud v článku něčemu nerozumíte, napište prosím, čemu přesně a na kterém místě.
  • Pro vložení několika slov kódu použijte značku <code>, pro několik řádků je obalte značkou <pre>, pro více než 10 řádků vložte odkaz na pískoviště (plnkr, jsbin, codepen…)