HTML документът
Накратко: HTML документът е текст с тагове и атрибути, от който браузърът строи дърво от елементи; семантичните елементи header, nav, main и footer казват ролята на всяка част.
Проблем
Цената е връзка
Колега е направил страницата на продукт. Отваряш я и цената е синя и подчертана, а клик на „Добави в кошницата“ те води към други хлябове. В кода няма връзка около цената.
Конзола
Браузърът не показва грешка и конзолата е празна. Натисни „Добави в кошницата“: конзолата казва, че това е връзка към /bread. Грешката е на ред 9: <a> е отворена, но не е затворена. Браузърът не показва текста ред по ред, а първо строи от него нещо друго. Това нещо е причината цената да е връзка.
Идеята
Елементи, тагове, атрибути
HTML е текст, който казва какво има на страницата. Всяко парче е елемент: заглавие, абзац, връзка, бутон. Елементът започва с отварящ таг и свършва със затварящ:
<a href="/cart">Кошница</a><a …>е отварящият таг, а</a>е затварящият: същото име с/.href="/cart"е атрибут: име и стойност в отварящия таг. Той казва нещо за елемента: тук е къде води връзката.- „Кошница“ е съдържанието: текстът между двата тага.
Елементите са едни в други. Абзацът <p> може да съдържа връзка, а <body> съдържа всичко видимо. Някои елементи нямат съдържание и затова нямат затварящ таг: <meta>, <img>, <input>, <br>.
Целият документ има една и съща рамка:
<!doctype html><html lang="bg"> <head> <meta charset="utf-8"> <title>Хляб „Добруджа“</title> </head> <body> … </body></html><!doctype html> казва, че това е модерен HTML. lang="bg" казва езика: по него екранният четец избира гласа, а браузърът пренася думите. В <head> е информацията за страницата: кодировката и заглавието в раздела на браузъра. В <body> е това, което виждаш.
Идеята
От текст към дърво
Браузърът не рисува текста. Той го чете с парсер и строи дърво: всеки елемент е възел, а елементите в него са децата му. Всеки елемент има точно един родител. Това дърво се казва DOM (Document Object Model). CSS и JavaScript работят с него, а не с текста.
Парсерът помни кои елементи са отворени в момента. Отварящ таг прави нов възел, дете на последния отворен елемент. Затварящият таг затваря елемента и парсерът се връща при родителя.
Ако затварящ таг липсва, парсерът не спира. HTML има правило за всяка грешка, и браузърът решава сам къде да затвори. Понякога решава различно от това, което си мислил.
Виж го
Виж как се строи дървото
Кодът е проблемът от началото, на кратко. Гледай кои елементи са отворени вдясно.
<body> <h1>Хляб</h1> <p>Виж и <a href="/bread">другите</p> <p>Цена: 1,80 €</p> <button>Добави</button></body>Стъпка по стъпка, с думи
- Парсерът чете кода отгоре. <body> отваря елемент: тук той е коренът на дървото. Вдясно са елементите, които в момента са отворени.
- <h1> става дете на отворения елемент, <body>. </h1> го затваря на същия ред и парсерът се връща при <body>.
- <p> е дете на <body>, а <a> е дете на <p>. Сега са отворени три елемента: body, p, a.
- </a> няма. </p> затваря абзаца, а <a> не може да остане извън него и се затваря с него. Но парсерът я запомня: в кода връзката не е затворена.
- Преди следващото съдържание парсерът отваря запомнената <a> наново, вече като дете на <body>. Тази връзка я няма в кода. Новият <p> влиза в нея.
- Бутонът също влиза във връзката.
- Пътят от бутона нагоре: button, a, body. Цената и бутонът са във връзка и клик върху тях води към /bread. Поправката е едно </a> на ред 3.
Втората <a> я няма в кода, но я има в дървото. Браузърът показва дървото, а не текста. Затова при странна страница гледаш дървото: в браузъра това е панелът Elements на инструментите за разработчици (F12). Там се вижда втората <a>, а в изходния код (View Source) я няма.
Пробвай
Поправи връзката
Поправи кода така, че на страницата да има точно една връзка: „другите хлябове“. Натисни „Провери“: проверката брои връзките на страницата.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Хляб „Добруджа“</title>
</head>
<body>
<h1>Хляб „Добруджа“</h1>
<p>Виж и <a href="/bread">другите хлябове</a></p>
<p>Цена: 1,80 €</p>
<button type="button">Добави в кошницата</button>
</body>
</html>
Липсваше </a> на ред 9. С нея връзката свършва преди </p> и парсерът няма какво да отваря наново. Цената и бутонът вече са деца на <body>.
Пробвай
Намери грешката
Защо „Доставка до 2 работни дни“ е удебелено?
Избери реда с грешката.
<strong> на ред 3 не е затворен. </p> го затваря заедно с абзаца, но парсерът го помни и го отваря наново около следващия абзац. Трябва <strong>1,80 €</strong></p>.
Пробвай
Попълни
Кой атрибут казва къде води връзката?
<nav>
<a ="/cart">Кошница</a>
</nav>href (hypertext reference): адресът, към който води връзката.
Идеята
Елементи със смисъл
Страницата може да се направи само от <div>. Тогава браузърът знае, че има кутии, но не знае какво е всяка. Човек вижда менюто по мястото и вида му. Екранният четец, търсачката и клавиатурата виждат само дървото.
Затова HTML има семантични елементи: елементи, чието име казва какво е съдържанието.
<header>: горната част на страницата: логото и менюто.<nav>: навигацията, групата от връзки към другите страници.<main>: главното съдържание. Един на страница.<article>: нещо цяло, което има смисъл и само: продукт, поръчка, статия.<footer>: долната част: доставка, контакти, условия.<h1>…<h6>: заглавията.<h1>е заглавието на страницата.
На вид са като <div>. Разликата е, че екранният четец обявява „навигация“ и „главно съдържание“, а човек с клавиатура скача до тях с един клавиш. <div> и <span> остават за кутии без смисъл: група, която CSS трябва да нареди.
Виж го
Страницата със смисъл
Същият продукт със семантични елементи. Във втория файл е малко CSS, за да се виждат частите. За него е следващият модул.
Конзола
Проверката на примера търси частите по роля: <header> е „banner“, <nav> е „navigation“, <main> е „main“, <footer> е „contentinfo“. Така ги вижда и екранният четец.
Пробвай
Сложи смисъл
Страницата е само от <div>. Смени ги със семантични елементи: горната част, менюто, главното съдържание, продуктът и долната част. Името на продукта е заглавието на страницата.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Прясно мляко 3% · Магазинът</title>
</head>
<body>
<header>
<a href="/">Магазинът</a>
<nav>
<a href="/bread">Хляб</a>
<a href="/milk">Мляко</a>
<a href="/cart">Кошница</a>
</nav>
</header>
<main>
<article>
<h1>Прясно мляко 3%</h1>
<p>Цена: 2,40 €</p>
<button type="button">Добави в кошницата</button>
</article>
</main>
<footer>Доставка до 2 работни дни</footer>
</body>
</html>
top става <header>, menu става <nav>, content става <main>, product става <article>, а bottom става <footer>. Името на продукта става <h1>: то е заглавието на страницата. Проверката търси бутона вътре в article, менюто по ролята „navigation“ и заглавието по ниво 1. Класовете вече не трябват.
По-точно, за любопитните
Парсерът и грешките. Правилата за грешките са част от стандарта (HTML Living Standard), затова всички браузъри строят едно и също дърво от един и същ сгрешен HTML. Незатворените <a>, <strong>, <em>, <b> и <i> парсерът помни в списък (list of active formatting elements) и ги отваря наново. Затова такава грешка се „разлива“ надолу по страницата.
Сам се затваря. Някои тагове затварят други без грешка: <p> затваря отворен <p>, а <li> затваря отворен <li>. Затова <li>Хляб<li>Мляко е два елемента от списъка. Пишем затварящите тагове, защото така кодът казва същото като дървото.
Атрибутите. Имената на таговете и атрибутите не зависят от главни и малки букви (<A HREF> е <a href>), но пишем малки. Някои атрибути нямат стойност: <input required>. Кавичките около стойността могат да липсват, но с тях е по-сигурно.
<section> и <aside>. <section> е раздел със заглавие, част от нещо по-голямо. <aside> е съдържание встрани от главното: свързани продукти, реклама.
Упражнение
Моята поръчка
Направи страницата на поръчка 1042 от празно. Горе: връзка „Магазинът“ и меню с две връзки: „Моите поръчки“ и „Кошница“. Главното съдържание: заглавие „Поръчка 1042“, статус „изпратена“ и два продукта, всеки с името си като заглавие от второ ниво и количеството с цената под него (хляб: 2 × 1,80 €, мляко: 1 × 2,40 €), после „Общо: 6,00 €“. Долу: „Връщане до 14 дни от доставката“.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Поръчка 1042 · Магазинът</title>
</head>
<body>
<header>
<a href="/">Магазинът</a>
<nav>
<a href="/orders">Моите поръчки</a>
<a href="/cart">Кошница</a>
</nav>
</header>
<main>
<h1>Поръчка 1042</h1>
<p>Статус: <strong>изпратена</strong></p>
<article>
<h2>Хляб „Добруджа“</h2>
<p>2 × 1,80 €</p>
</article>
<article>
<h2>Прясно мляко 3%</h2>
<p>1 × 2,40 €</p>
</article>
<p>Общо: <strong>6,00 €</strong></p>
</main>
<footer>Връщане до 14 дни от доставката</footer>
</body>
</html>
Всеки продукт е <article> със свое заглавие <h2>: той е цял и сам по себе си. Заглавието на страницата е едно, <h1>. Сумата е абзац в <main>, а условието за връщане е във <footer>. Проверката търси по роля и ниво на заглавието, затова <div class="title"> не минава, колкото и да прилича на заглавие.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Продължава в: Текст, връзки, картинки, таблици · Формуляри · Достъпност · Селектори и каскада
- Задачи по темата: HTML: структурата на страницата