Текст, връзки, картинки, таблици
Накратко: Съдържанието на HTML страница е от заглавия h1–h6, абзаци, списъци, връзки с href, картинки с alt и таблици с данни с caption, th и scope.
Проблем
„Мляко“ води в нищото
Купувач пише, че от страницата на хляба връзката „Мляко“ води към „Няма такава страница“. От началната страница същото меню работи. Страницата е на адрес https://shop.example/bread/white/dobrudzha.
Конзола
Натисни „Мляко“. Пясъчникът е една страница и не отваря връзки, но конзолата казва какво пише в href: milk. Другите връзки започват с /, а тази не. Без / браузърът не отива на /milk. Той сглобява адреса от адреса на страницата, на която си, и получава друг.
Идеята
Пълен и относителен адрес
Връзката е <a> с атрибут href: къде води. Адресът в href (URL) е пълен или относителен.
Пълният адрес има всичко: схема (https://), хост (shop.example) и път (/bread/white/dobrudzha). Пътят е от папки, разделени с /, а последната част е страницата.
Относителният адрес е непълен, и браузърът го допълва от адреса на страницата, на която е връзката. Началото решава как:
milk(нищо отпред): от папката на страницата.../milk: една папка нагоре./milk: от корена на сайта, независимо от страницата.#price: място в същата страница, елементът сid="price".
Затова менюто, което е на всяка страница, е с адреси от корена: /milk води на едно място отвсякъде. Пълен адрес слагаш само за друг сайт.
Виж го
Виж как се сглобява адресът
Пет връзки от една и съща страница. Гледай кои части от адреса горе браузърът пази и какво добавя.
<!-- адресът на страницата: https://shop.example/bread/white/dobrudzha --><a href="milk">Мляко</a><a href="../milk">Мляко</a><a href="/milk">Мляко</a><a href="#price">Цената</a><a href="https://recipes.example/bread">Рецепти</a>Стъпка по стъпка, с думи
- Страницата е на https://shop.example/bread/white/dobrudzha. Браузърът дели адреса на части: схема, хост и път. Пътят е от папки, а последната част е самата страница.
- href="milk" няма нищо отпред. Браузърът пази папката на страницата, /bread/white/, и сменя само последната част. Получава /bread/white/milk: страница, която я няма.
- ../ значи „една папка нагоре“. От /bread/white/ браузърът се качва в /bread/ и добавя milk. Пак не е /milk.
- Наклонена черта отпред значи „от корена на сайта“. Браузърът пази само схемата и хоста. Този адрес работи от всяка страница на магазина.
- # е място в същата страница. Браузърът пази целия адрес и добавя #price. Страницата не се зарежда наново, а се превърта до елемента с id="price".
- Адрес със схема е пълен. Браузърът не взима нищо от страницата. Така се води към друг сайт.
- Началото на href решава: нищо или ../ е от папката, / е от корена, # е в същата страница, https:// е пълен адрес.
Браузърът не пита сървъра дали адресът съществува. Той сглобява адреса по правилата и тръгва натам. Затова грешка в href не се вижда в кода, а когато някой натисне връзката. В браузъра виждаш сглобения адрес, ако задържиш мишката над връзката: долу вляво на прозореца.
Пробвай
Поправи връзките
Поправи връзките: „Мляко“ и „Кошница“ трябва да работят от всяка страница на магазина (адрес от корена: /milk и /cart). „Към цената“ трябва да скача до абзаца с цената. „Рецепти с този хляб“ води към друг сайт: нека се отваря в нов раздел, без той да получава достъп до нашата страница.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Хляб „Добруджа“ · Магазинът</title>
</head>
<body>
<!-- Адресът на страницата: https://shop.example/bread/white/dobrudzha -->
<nav>
<a href="/bread">Хляб</a>
<a href="/milk">Мляко</a>
<a href="/cart">Кошница</a>
</nav>
<main>
<h1>Хляб „Добруджа“</h1>
<p><a href="#price">Към цената</a></p>
<p>Бял хляб, 650 г, изпечен тази сутрин.</p>
<p id="price">Цена: 1,80 €</p>
<p><a href="https://recipes.example/bread" target="_blank" rel="noopener">Рецепти с този хляб</a></p>
</main>
</body>
</html>
href="/milk" и href="/cart" започват от корена и не зависят от страницата. ../milk тук води до /bread/milk: една папка нагоре от /bread/white/ е /bread/.
#price търси елемент с id="price", затова id-то отива на абзаца с цената. Решетката е само във връзката, не в id.
target="_blank" отваря връзката в нов раздел. Тогава новата страница може да стигне до нашата през window.opener и да я подмени, докато купувачът гледа рецептите. rel="noopener" спира това. Новите браузъри го правят сами за target="_blank", а rel го казва изрично и пази и в по-старите.
Пробвай
Попълни
Връзката трябва да скача до цената на същата страница. Какво пише в href?
<a href="">Към цената</a>
…
<p id="price">Цена: 1,80 €</p>#price: решетка и id-то на елемента. Браузърът не зарежда страницата наново, а я превърта до него.
Идеята
Текстът: план, абзаци, списъци
Заглавията <h1> … <h6> не са шест размера шрифт. Те са планът на страницата, като съдържанието на книга. <h1> е заглавието на страницата, <h2> са разделите в нея, <h3> са части от раздел. Нивата не се прескачат: след <h2> идва <h3>, а не <h5>. Екранният четец показва този план като списък и човек скача от раздел на раздел. Размерът се сменя с CSS, без да се пипа планът.
Останалото:
<p>е абзац.<br>е нов ред вътре в абзац (адрес, стих), а не начин да се правят списъци.<ul>е списък без ред (съставки),<ol>е с ред (стъпки). Всеки елемент е<li>.<dl>е списък от двойки „име и стойност“:<dt>е името (Тегло),<dd>е стойността (650 г).<strong>е важно („Съдържа глутен.“), а<em>е ударение, което сменя смисъла („в торба, не в найлон“). Ако искаш само удебелен вид без смисъл, това е CSS.
Конзола
Пробвай
Направи план
Колега е избрал заглавията по размер: името на хляба е <h4>, а промоцията е <h1>. Направи плана: името на продукта е заглавието на страницата, „Съставки“ и „Как да го пазиш“ са разделите. Промоцията не е заглавие: нека е важен текст в абзац. Съставките са списък.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Хляб „Добруджа“ · Магазинът</title>
</head>
<body>
<main>
<h1>Хляб „Добруджа“</h1>
<p><strong>Промоция: −10% до неделя</strong></p>
<p>Бял хляб, 650 г, изпечен тази сутрин.</p>
<h2>Съставки</h2>
<ul>
<li>пшенично брашно</li>
<li>вода</li>
<li>мая</li>
<li>сол</li>
</ul>
<h2>Как да го пазиш</h2>
<p>В торба от плат, <em>не</em> в найлон.</p>
</main>
</body>
</html>
Името е <h1>, разделите са <h2>, а промоцията става <p><strong>…</strong></p>: тя е важна, но не започва раздел. Съставките са <ul> с по едно <li> за всяка, без ред, защото редът им няма значение. Проверката търси заглавията по ниво и брои елементите на списъка: точки и <br> не са списък, колкото и да приличат.
Идеята
Картинки
<img src="img/bread.svg" alt="Кръгъл бял хляб с хрупкава кора" width="240" height="240">srcе адресът на картинката. Той се сглобява катоhref.altе текстът вместо картинката. Екранният четец го чете, търсачката го индексира, а ако картинката не се зареди, браузърът го показва на мястото ѝ. Пиши какво показва картинката и защо е там.- Картинка, която е само украса или повтаря текста до нея, е с
alt="". Тогава екранният четец я прескача. Безaltизобщо е грешка: четецът не знае, че е украса. - Картинка, която е единственото съдържание на връзка, дава името на връзката.
altе къде води връзката: „Магазинът“, а не „лого“. widthиheightса размерите в пиксели. Докато картинката идва, браузърът не знае колко е голяма и ѝ дава 0 пиксела височина. Когато дойде, текстът под нея подскача надолу. Сwidthиheightбраузърът пази мястото отнапред, дори когато CSS я смали.
Пробвай
Сложи alt и размери
Логото е единственото във връзката към началото: връзката трябва да се казва „Магазинът“. Снимката на хляба показва нещо: опиши го в alt. Иконата подарък повтаря текста до нея. Снимката е 240 × 240 пиксела: кажи го на браузъра.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Хляб „Добруджа“ · Магазинът</title>
</head>
<body>
<header>
<a href="/"><img src="img/logo.svg" alt="Магазинът" width="40" height="40"></a>
</header>
<main>
<h1>Хляб „Добруджа“</h1>
<img src="img/bread.svg" alt="Кръгъл бял хляб с хрупкава кора" width="240" height="240">
<p>Цена: 1,80 €</p>
<p><img src="img/gift.svg" alt="" width="24" height="24"> Подарък при поръчка над 30 €</p>
</main>
</body>
</html>
Логото е с alt="Магазинът": това е името на връзката. Снимката е с alt, който описва хляба, и с width="240" height="240". Иконата е с alt="": текстът до нея вече казва „подарък“. Проверката брои картинките по роля: картинка с alt="" няма роля „картинка“, а картинка без alt има, затова празният alt не е същото като липсващия.
Екранният четец казва за една връзка само „връзка“. На кой ред е грешката?
На ред 5 връзката към кошницата съдържа само картинка с alt="". Така връзката е без име. Картинката не е украса: тя е единственото, което казва къде води връзката. Трябва alt="Кошница".
Идеята
Таблици с данни
Таблицата е за данни в редове и колони: цени, поръчки, разписание. Екранният четец я чете като таблица: „ред 3, колона Цена, 7,90 €“. Затова тя е само за данни, а не за нареждане на страницата в колони. Това прави CSS.
<table> <caption>Цени днес</caption> <thead> <tr><th scope="col">Продукт</th><th scope="col">Цена</th></tr> </thead> <tbody> <tr><th scope="row">Сирене</th><td>7,90 €</td></tr> </tbody></table><caption>е името на таблицата. То е в таблицата, а не заглавие над нея.<tr>е ред.<td>е клетка с данни, а<th>е заглавна клетка.scope="col"казва, че заглавието е за колоната под него, аscope="row"за реда вдясно.<thead>са заглавните редове,<tbody>са данните,<tfoot>е сборът отдолу.
Пробвай
Ценоразписът
Ценоразписът е направен с клетки <td> и удебелен текст. Направи го таблица с данни: името „Цени днес“ е на таблицата, заглавният ред е в <thead>, а продуктите са в <tbody>. Заглавията на колоните и имената на продуктите са заглавни клетки; кажи със scope за какво е всяка.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Цени днес · Магазинът</title>
</head>
<body>
<table>
<caption>Цени днес</caption>
<thead>
<tr><th scope="col">Продукт</th><th scope="col">Цена</th><th scope="col">Наличност</th></tr>
</thead>
<tbody>
<tr><th scope="row">Хляб „Добруджа“</th><td>1,80 €</td><td>24</td></tr>
<tr><th scope="row">Прясно мляко 3%</th><td>2,40 €</td><td>35</td></tr>
<tr><th scope="row">Сирене</th><td>7,90 €</td><td>18</td></tr>
<tr><th scope="row">Ябълки, 1 кг</th><td>2,10 €</td><td>80</td></tr>
</tbody>
</table>
</body>
</html>
<caption>Цени днес</caption> дава името на таблицата: екранният четец го казва, когато стигне до нея. Заглавният ред е в <thead> с три <th scope="col">, а всяко име на продукт е <th scope="row">. Сега клетката „7,90 €“ има две заглавия: „Сирене“ и „Цена“.
В проста таблица като тази Chromium се досеща за заглавията и без scope, по мястото им. scope го казва изрично и не зависи от догадки: в таблица със слети клетки догадката може да сгреши. Проверката търси по scope, затова <th> без него не минава.
По-точно, за любопитните
Още за адресите. ./milk е същото като milk. ?page=2 пази пътя и сменя само заявката: /bread/white/dobrudzha?page=2. Адрес, който започва с //, пази само схемата: //cdn.example/x.js е https://cdn.example/x.js. ../ над корена не води никъде по-нагоре: ../../../milk от нашата страница е /milk. В JavaScript това сглобяване е new URL('../milk', 'https://shop.example/bread/white/dobrudzha').
target="_blank" и window.opener. Chromium вече дава на нов раздел от target="_blank" window.opener === null, както с rel="noopener", а rel="opener" връща връзката. Пишем rel="noopener", за да е ясно и в браузъри, които не го правят сами.
Картинки за различни екрани. srcset дава няколко размера на една картинка, а браузърът избира според екрана. loading="lazy" зарежда картинката, когато наближи екрана. И двете са за модула за CSS и бързината.
Слети клетки. colspan="3" слива три клетки в ред, а rowspan="2" две клетки в колона. Тогава scope е важен: без него браузърът гадае на кои клетки е заглавието.
<b>, <i> и <br>. Те съществуват и имат смисъл: <b> е текст, който се откроява без да е по-важен (ключова дума), <i> е друг глас (термин, заглавие на книга). За важно е <strong>, за ударение е <em>.
Упражнение
Поръчка 1042
Направи страницата на поръчка 1042 от празно. Меню с връзка „Моите поръчки“ към /orders. Заглавие „Поръчка 1042“, под него „Статус: изпратена“. После таблица „Продуктите в поръчката“ с колони Продукт, Количество, Цена, Сума: хляб „Добруджа“ 2 × 1,80 € = 3,60 €, прясно мляко 3% 1 × 2,40 € = 2,40 €, сирене 1 × 7,90 € = 7,90 €. Пред всяко име има картинка 32 × 32 (img/bread.svg, img/milk.svg, img/cheese.svg). Най-долу е редът „Общо“ с 13,90 € в последната колона.
Конзола
Решение
index.html<!doctype html>
<html lang="bg">
<head>
<meta charset="utf-8">
<title>Поръчка 1042 · Магазинът</title>
</head>
<body>
<nav>
<a href="/orders">Моите поръчки</a>
</nav>
<main>
<h1>Поръчка 1042</h1>
<p>Статус: <strong>изпратена</strong></p>
<table>
<caption>Продуктите в поръчката</caption>
<thead>
<tr>
<th scope="col">Продукт</th>
<th scope="col">Количество</th>
<th scope="col">Цена</th>
<th scope="col">Сума</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row"><img src="img/bread.svg" alt="" width="32" height="32"> Хляб „Добруджа“</th>
<td>2</td>
<td>1,80 €</td>
<td>3,60 €</td>
</tr>
<tr>
<th scope="row"><img src="img/milk.svg" alt="" width="32" height="32"> Прясно мляко 3%</th>
<td>1</td>
<td>2,40 €</td>
<td>2,40 €</td>
</tr>
<tr>
<th scope="row"><img src="img/cheese.svg" alt="" width="32" height="32"> Сирене</th>
<td>1</td>
<td>7,90 €</td>
<td>7,90 €</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row" colspan="3">Общо</th>
<td>13,90 €</td>
</tr>
</tfoot>
</table>
</main>
</body>
</html>
Името на продукта е <th scope="row">, а картинката в него е с alt="": името е до нея и тя е украса. С alt="Хляб „Добруджа“" заглавието на реда става „Хляб „Добруджа“ Хляб „Добруджа““. „Общо“ е в <tfoot>: това е сборът на таблицата, а не още един продукт. Клетката с „Общо“ е <th scope="row" colspan="3"> и заема трите колони вляво.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: HTML документът
- Продължава в: Формуляри · Достъпност · Responsive дизайн · Събития
- Задачи по темата: HTML: структурата на страницата