HTML & CSS IS HARD - НА РУССКОМ

ВВЕДЕНИЕ

УРОК Nº 1.

МИНИ-ВСТУПЛЕНИЕ ОТ ПЕРЕВОДЧИКА

Признаться, я ни за что бы не начал изучать учебник который называется "HTML & CSS Is Hard". Но этот учебник в своем блоге порекомендовал Дерек Сиверс, один из удивительнейших известных мне людей.

Я перечитал его на английском дважды. Читая в первый раз, я почти ничего не знал об Html&CSS. Тем не менее я быстро смог разобраться в базовых положениях. Проскочив несколько глав я прочитал как сделать адаптивный дизайн для смартфонов. Я тут же попробовал и... у меня получилось!!!

Читая далее, с каждым разом я понимал все больше. Восхищала краткость и ясность подачи материала. Именно из-за этой ясности, легкодоступности, ну и из-за краткости тоже, я решил перевести этот учебник на русский язык. В процессе перевода я рассчитывал продвинуться на более глубокий уровень понимания языка разметки и стилей.

Надеюсь, что читателю тоже понравится и пригодится этот учебник. Перевод сделан близко к тексту, но дословным переводом его назвать конечно же нельзя.
Предполагаю, что какой-никакой базовый английский у вас все-таки есть... а как иначе?

Если ваш английский все-таки "хромает", одна из самых лучших лично мне известных методик изучения иностранных языков - speakasap.ru Елены Шипиловой. Может вам начать с бесплатного курса Английский за 7 уроков

В некоторых местах текста я сделал "примечания переводчика" для русскоязычного читателя. Чтобы выделить отделить их от оригинального текста, примечания переводчика [заключены в квадратные скобки] или выделены знаком "*" как сноски.

Если читатель обнаружит ошибки в терминологии, да и вообще любые опечатки или логические нестыковки, прошу сообщить об этом мне по мейлу [email protected].


ВВЕДЕНИЕ в курс HTML & CSS IS HARD

Изучать HTML&CSS нелегко? Нет, это стереотип. Данный учебник, состоящий из 14 глав, является одним из самых легкопонятных руководств по HTML и CSS в Интернете. В нем рассказано обо всем, начиная с выбора хорошего текстового редактора (что на удивление важно) и заканчивая созданием полноценных веб-страниц профессионального качества. И все это "с нуля".

Interneting is hard HTML+CSS
Скриншот 1: программист, создающий веб-страницы

Данный курс задуман как учебник HTML и CSS, включающий ВСЁ, что необходимо знать на эту тему. Если вы приложите усилия для изучения каждого урока, собственноручно напишите все приведенные фрагменты кода, то этот учебник заменит вам онлайн-курсы и тренинги стоимостью в сотни и даже тысячи долларов.

Главная цель данного учебника - максимально упростить ваше превращение из новичка в профессионала веб-разработки. Если вы никогда не писали кода, но подумываете о смене профессии, сварите себе чашечку кофе и присаживайтесь поудобнее. Мы начинаем.

HTML, CSS, & JAVASCRIPT

Язык гипертекстовой разметки (HTML), каскадные таблицы стилей (CSS) и JavaScript - это языки, на которых работает Интернет. Они очень тесно связаны между собой, но при этом предназначены для решения совершенно разных задач. Понимание их взаимодействия между собой, поможет вам стать веб-разработчиком. Мы будем раскрывать эту тему на протяжении всего курса, но суть ее такова:

Другими словами, HTML это абстрактный текст и изображения, лежащие в основе веб-страницы.
CSS это отображение страницы на экране.
JavaScript это элементы поведения, которые могут управлять как HTML, так и CSS.

* - content означает содержимое. Переводы других терминов ЗДЕСЬ.

Interneting is hard HTML+CSS
Скриншот 2: HTML как древо узлов, CSS как отрисованная веб-страница, JavaScript как интерактивная веб-страница

Например, с помощью этого HTML можно выделить определенный фрагмент текста как абзац:

<p id='some-paragraph'>Здесь помещается содержимое абзаца.</p>

Затем с помощью CSS можно задать размер и цвет этого абзаца:

p {
font-size: 20px;
color: blue;
}

И если вы вошли во вкус, с помощью JavaScript можно сделать так, что после щелчка мышью, текст полностью поменяется! Первоначальный текст: "Здесь помещается содержимое абзаца" после щелчка мышью поменяется на 'Текст который "щелкнули"' (однако язык JavaScript мы оставим для будущих учебников.)

var p = document.getElementById('some-paragraph');
p.addEventListener('click', function(event) {
p.innerHTML = 'Текст который щелкнули.';
});

Как видите, HTML, CSS и JavaScript - это совершенно разные языки, но все они так или иначе связаны друг с другом. Большинство веб-сайтов используют все три языка, но внешний вид каждого сайта определяется HTML и CSS. Это делает данный учебник отличной отправной точкой в вашем путешествии по веб-разработке.

ЯЗЫКИ И "ВЕБ-РАЗРАБОТКА"
languages versus “web development”

К сожалению, владение HTML, CSS и JavaScript - это лишь необходимое условие для того, чтобы стать профессиональным веб-разработчиком. Существует целый ряд других практических навыков, необходимых для работы с сайтом:

Для решения этих довольно сложных задач необходимо настроить различные "среды" [environments] для организации файлов и сборки/развертывания сайта. Это не связано с кодом HTML, CSS и JavaScript, из которого состоит сайт. Данные процессы выходят за рамки нашего курса. Основное внимание уделяется языкам HTML и CSS, а не настройке этих "сред".

Interneting is hard HTML+CSS 3
Скриншот 3: HTML, CSS и JavaScript, указывающие на создание веб-сайта (инструменты сборки, доменное имя, веб-сервер), в результате чего создается веб-сайт

Однако сейчас нет необходимости забивать голову этими процессами. Сейчас ваша цель - свободное владение HTML и CSS. Это важный первый шаг к тому, чтобы стать настоящим веб-разработчиком. Нам не хотелось бы создать иллюзию, что после изучения этого учебника вы сходу сможете самостоятельно создать полноценный сайт. Однако у вас будут навыки, позволяющие воссоздать подавляющее большинство сайтов в Интернете.

ВЕБ-ПУБЛИКАЦИЯ
web publishing

Итак, что же нужно для того, чтобы "выучить" HTML и CSS? Давайте посмотрим через призму истории полиграфии. Еще во времена первых печатных станков печатники создавали документы, располагая металлические бруски (типографские литеры), обмакивая их в краску и делая оттиск на лист бумаги.

Почти то же самое делают сегодня веб-разработчики. Только вместо расставления типографских литер, они пишут HTML и CSS. Происходит тот же процесс, что и ранее: передача содержания в осмысленном виде. Даже задачи остаются те же: выбор шрифта, установка размера заголовков, определение расстояния между строками текста.

Interneting is hard HTML+CSS
Скриншот 4: металлический штамп становится HTML и CSS, печатная страница становится веб-страницей, книга - веб-сайтом

Раньше в типографии печаталась пачка страниц и скреплялась в книгу. Сегодня мы создаем множество HTML-файлов и соединяем их в веб-сайт. Изучение HTML и CSS сводится к пониманию доступной разметки HTML и правил CSS, позволяющих браузеру отображать эти файлы так, как задумано.

ФУНДАМЕНТАЛЬНЫЕ ОСНОВЫ
ВМЕСТО ФРЕЙМВОРКОВ
fundamentals, not frameworks

Существует множество фреймворков для разработки сайтов ( Bootstrap, ZURB foundation, Pure CSS и др.). Цель каждого из них - абстрагироваться от излишеств, связанных с созданием веб-страниц с нуля. Подобные фреймворки являются важной частью реальной веб-разработки, и их обязательно стоит изучить, но только после того, как вы освоите основы HTML и CSS.

Данный учебник посвящен основам HTML и CSS. Вы сможете создать практически все, что может понадобиться вам как веб-разработчику, используя только HTML и CSS. Это знание останется с вами навсегда, несмотря на новые блестящие дополнения к стандартам HTML и CSS или новомодные фреймворки, помогающие работать быстрее.

ПРАКТИЧЕСКОЕ ОБУЧЕНИЕ
hands-on learning

Данный учебник - это обучение основанное на практике. За исключением того, что вы уже прочитали, весь этот учебник выстроен на конкретных примерах, попутно объясняя концептуальные аспекты HTML и CSS.

Чтобы получить максимальную пользу от этого курса, необходимо активно создавать веб-страницы и выполнять все шаги каждой главы. Если вы всерьез намерены стать веб-разработчиком, то вам следует набирать каждый фрагмент кода "ручками", а не копипастить Сtrl+V.

Почему? Потому что именно это вы будете делать в качестве настоящего веб-разработчика. "Ручной" ввод примеров кода способствует развитию моторной памяти, которая пригодится вам в реальной работе по разметке контента для реальных сайтов.

ПРОФЕССИОНАЛЬНЫЕ ИНСТРУМЕНТЫ
tools of the trade

Для этого курса достаточно иметь удобный текстовый редактор и веб-браузер. Основная работа заключается в том, чтобы написать код в текстовом редакторе, а затем открыть его в браузере и посмотреть, как он выглядит. По мере создания собственных сайтов вы будете добавлять в свой инструментарий все новые и новые инструменты, но важно начать с минимума и досконально изучить основы HTML и CSS.

Interneting is hard HTML+CSS
Скриншот 5: текстовый редактор (здесь пишут код) и веб-браузер (здесь код отображается)

Не пожалейте времени на то, чтобы освоить работу с текстовым редактором. Хорошие редакторы оснащены функциями (автозавершение тегов, переход по тексту, навигация по файловой системе и т.п.), позволяющими писать код быстрее обычного. Мастерское владение текстовым редактором это часть изучения HTML и CSS.

Единственным и самым важным требованием для хорошего браузера является его актуальность и широкое распространение. Chrome и Firefox - фавориты среди веб-разработчиков. Safari тоже подойдет, если вы работаете в OS X. Настоятельно рекомендуем при создании сайтов отказаться от Internet Explorer. Для профессиональной веб-разработки часто требуется эффективный способ тестирования кода на всех этих браузерах. Но изучением темы тестирования кода займемся в другой раз. Сейчас в этом нет критической необходимости.

ТЕКСТОВЫЙ РЕДАКТОР ATOM
atom text editor

Мы рекомендуем текстовый редактор Atom. Он удобен даже для начинающих пользователей, обладает всеми полезными функциями, о которых мы говорили выше, и доступен для всех основных операционных систем. Кроме того, его можно бесконечно настраивать, что будет важно по мере выявления повторяющихся задач, которые можно автоматизировать.

Если у вас еще нет Atom, загрузите его прямо сейчас, поскольку он понадобится вам на следующем уроке. После загрузки откройте его, чтобы мы могли вкратце ознакомиться с его основными возможностями. Вы должны увидеть две панели с различными окнами приветствия:

Interneting is hard HTML+CSS
Скриншот 6: приветственное окно текстового редактора Atom

Оба эти экрана приветствия нам не нужны. Закройте их, щелкнув на значок X в соответствующих вкладках. Для их закрытия можно также воспользоваться сочетанием клавиш Cmd+W (Mac) или Ctrl+W (Windows/Linux)
(сочетания клавиш - отличная вещь, пользуйтесь ими при любой возможности). У вас должна остаться одна вкладка без названия.

СОЗДАНИЕ ПРОЕКТА
creating a project

Каждый сайт, над которым вы работаете в Atom, представляет собой "проект". По сути, это просто папка в вашей файловой системе, содержащая HTML- и CSS-файлы. Давайте познакомимся с Atom, создав фиктивный проект и добавив в него несколько текстовых файлов. Нажмите File > Open в строке меню, чтобы открыть диалоговое окно файла, затем создайте новую папку, выбрав New Folder. Назовите ее hello-atom и щелкните Open.

Interneting is hard HTML+CSS
Скриншот 7: устройство редактора Atom: в левой боковой панели - файловый браузер, справа - рабочая панель (здесь пишем и редактируем код)

В левой части интерфейса должна появиться боковая панель с надписью hello-atom вверху рядом с маленьким значком папки. Это и есть наш файловый браузер. Конечно, он ничего не покажет, пока мы не добавим туда файлы, так что давайте это и сделаем.

СОЗДАНИЕ ФАЙЛОВ
creating files

Добавьте на вкладку без названия произвольный текст. Сохраните изменения нажав Cmd+S (Mac) или Ctrl+S (Windows, Linux). Назовите файл page-one.html. После этого вы должны увидеть его в браузере файлов Atom.

Создадим еще один файл, нажав Cmd+N (Mac) или Ctrl+N (Windows, Linux). Это создаст еще одну вкладку без названия. Как и в предыдущем файле, добавьте любой текст и сохраните его под именем page-two.html.

НАВИГАЦИЯ ПО ФАЙЛОВОЙ СИСТЕМЕ
navigating the file system

Один из важнейших аспектов полноценного редактора - удобная навигация по всем файлам проекта. В Atom вы можете выбрать вкладку файла, с которым хотите работать, или найти его в браузере файлов в левой части интерфейса. Переходить по открытым вкладками можно также с помощью Ctrl+Tab.

Interneting is hard HTML+CSS
Скриншот 8: файловый браузер Atom после создания нескольких HTML-файлов

Все это хорошо и удобно для просмотра файлов, но зачастую возникает необходимость поиска конкретного файла. Например, во время проверки работоспособности, вы обнаружили неработающую ссылку на своем сайте. Вы хотели бы с помощью Atom мгновенно "прыгнуть" в этот файл, чтобы быстро исправить сломанную ссылку?

Interneting is hard HTML+CSS
Скриншот 9: результаты поиска в Atom’s fuzzy finder,

Вам поможет так называемый Atom’s fuzzy finder. Это строка поиска, вызваемая комбинацией Cmd+T (Mac) или Ctrl+T (Windows, Linux). Эта комбинация клавиш открывает строку поиска и позволяет ввод имени (или части имени) искомого файла. Попробуйте закрыть обе вкладки, нажать Cmd+T или Ctrl+T и ввести "one". На экране появится файл page-one.html, и вы сможете нажать Enter для редактирования этого файла. Данная опция бесценна, когда проект разрастается до десятков файлов в разных папках.

ДОПОЛНИТЕЛЬНЫЕ ПАНЕЛИ
multiple panes

Atom позволяет иметь не только несколько вкладок, но и несколько панелей. Чтобы понять, о чем идет речь, щелкните правой кнопкой мыши на один из файлов в браузере файлов и выберите команду Split Right. Файл откроется в новой панели, что позволит просматривать несколько файлов одновременно.

Interneting is hard HTML+CSS
Скриншот 10: две панели [pane] редактора Atom, расположенные рядом друг с другом

Дополнительные панели очень удобны для одновременного просмотра CSS-файла и связанного с ним HTML-файла.

ЗА ПРЕДЕЛАМИ РЕДАКТОРА ATOM
outside of atom

Иногда требуется работать с файлами "за пределами" редактора Atom (например, для добавления картинки на наш сайт). Для этого воспользуйтесь встроенным файловым браузером. Щелкните правой кнопкой мыши на файл в браузере файлов Atom и выберите Show in Finder/File Manager/Explorer ... Это позволит открыть данный файл в Проводнике или в другом файловом браузере, открывающимся в вашем компьютере по умолчанию.

Отсюда вы можете добавлять новые файлы, создавать папки или открывать HTML-файлы в веб-браузере. Это станет обычной процедурой до конца всего курса, поэтому давайте попробуем это сделать с файлом page-one.html. Щелкните его правой кнопкой мыши в стандартном файловом браузере вашей системы и выберите Open With > Chrome/Firefox/Safari. Текст в файле, должен отобразиться в виде веб-страницы в вашем стандартном веб-браузере.

Interneting is hard HTML+CSS
Скриншот 11: EDIT HERE - редактируем код в редакторе Атом, RELOAD HERE - перезагружаем браузер и просматриваем изменения

Теперь можно редактировать страницу page-one.html в Atom, сохранять изменения и просматривать в браузере. Для обновления окна браузера нажмите Cmd+R (Mac) или Ctrl+R (Windows, Linux). Это и есть базовый процесс редактирования для всех веб-разработчиков, и вы очень быстро привыкнете к нему задолго до конца изучения последующих 13 уроков.

РЕЗЮМЕ

Поздравляем! Вы сделали первый шаг к тому, чтобы стать профессиональным веб-разработчиком. Надеемся, что эта глава дала вам базовое понимание того, как HTML и CSS используются в сфере веб-разработки, а также общей философии нашего учебника.

Все вышесказанное об Atom станет частью нашей повседневной работы. Поэтому прежде чем двигаться дальше, убедитесь, что вам все понятно. Мы рекомендуем немного поиграть с нашим фиктивным проектом, добавляя новые файлы и тренируясь в переходах от одного файла к другому. Овладение навыками написания HTML и CSS - это то, что отличает невероятно продуктивных разработчиков от обычных.

Теперь, когда у нас есть полноценный текстовый редактор, мы готовы приступить к созданию полноценных веб-страниц. В следующих двух главах мы начнем с изучения наиболее распространенных элементов HTML, а затем добавим к ним CSS.


HTML & CSS IS HARD - НА РУССКОМ

ЧТО НУЖНО ЗНАТЬ О ВЕБСТРАНИЦАХ

УРОК Nº 2.

Простое и понятное руководство по созданию (по-настоящему) простых веб-страниц

HTML определяет содержание каждой веб-страницы в Интернете. Разметив исходное содержимое с помощью HTML-тегов, можно указать веб-браузерам, как следует отображать различные части содержимого. Создание HTML-документа с правильно размеченным содержимым - это первый шаг в разработке веб-страницы.

Interneting is hard HTML+CSS
Скриншот 1: исходное содержимое (контент) становится HTML-кодом, затем веб-страницей

В этой главе мы создадим нашу первую веб-страницу. На ней не будет ни одного CSS, поэтому выглядеть она будет как полная хрень. Зато она послужит основательным введением в элементы HTML, с которыми веб-разработчики работают каждый день.

При работе с примерами старайтесь подходить к ним как к более практичной версии WYSIWYG-редактора, например Google Docs или Microsoft Word. Мы будем работать со всеми теми же типами контента (заголовки, абзацы, списки и т.д.), просто мы будем определять их немного более наглядно с помощью HTML.

подготовка
setup

Для начала создадим в Atom новый проект с именем basic-web-pages. Затем создадим в этой папке новый файл basics.html. Этот HTML-файл представляет собой одну веб-страницу, и именно в него мы поместим весь наш код для этой главы. Если вы еще не знакомы с Atom, обязательно прочитайте Введение к этой серии уроков.

Interneting is hard HTML+CSS
Скриншот 2: EDIT HERE - редактируем в редакторе Атом, просматриваем изменения в браузере

Напоминаем, что рабочий процесс веб-разработчиков - большей частью редактирование HTML в текстовом редакторе и просмотр изменений в веб-браузере. Именно это вы должны делать для каждой секции этого урока.

СТРУКТУРА ВЕБ-СТРАНИЦЫ
structure of a web page

Добавьте в наш файл basics.html показанную ниже HTML-разметку. Это то, с чего вы будете начинать каждую свою веб-страницу. Обычно для того, чтобы избежать повторного ввода лишних частей, используется какой-либо шаблонизатор, но в данном учебном пособии мы сосредоточимся на исходном HTML.

<!DOCTYPE html>
<html>
<head>
<!-- Метаданные будут здесь -->
</head>
<body>
<!-- Содержание (content) будет здесь -->
</body>
</html>

Прежде всего, с помощью строки <!DOCTYPE html>, необходимо указать браузерам, что это веб-страница HTML5. Это специальная строка, которую браузеры ищут при попытке отобразить нашу веб-страницу, и она всегда должна выглядеть в точности так, как показано выше.

Затем вся наша веб-страница должна быть обернута в теги <html>. Сам текст <html> называется "открывающим тегом" [opening tag], а </html> - "закрывающим тегом" [closing tag]. Все, что находится внутри этих тегов, считается частью "элемента" <html>, то есть той невидимой части, которая создается, когда веб-браузер анализирует ваши HTML-теги.

Interneting is hard HTML+CSS
Скриншот 3: элемент HTML, состоящий из открывающего и закрывающего тегов

Внутри элемента <html> есть еще два элемента, называемые <head> и <body>. В головном элементе веб-страницы содержатся все метаданные, такие как заголовок страницы [page title], таблицы стилей CSS [CSS stylesheets] и другие элементы, необходимые для отображения страницы, но которые пользователю видеть совсем не обязательно. Основная часть нашей HTML-разметки будет находиться в элементе <body>, который представляет собой видимое содержимое страницы. Обратите внимание, что при открытии нашей страницы в браузере ничего не отобразится, поскольку она имеет пустой <body>.

Interneting is hard HTML+CSS
Скриншот 4: веб-страница, разделенная на элементы <head> и <body>

Назначение этого разделения <head>/<body> станет более понятным через несколько уроков, когда мы начнем работать с CSS.

Обратите также внимание на синтаксис HTML-комментария в приведенном выше фрагменте. Все, что начинается с <!-- и заканчивается на -->, будет полностью проигнорировано браузером. Это удобно для работы над документированием кода и создания заметок "для себя". Эти заметки пользователь не увидит.

ЗАГОЛОВКИ ДОКУМЕНТА
page titles

Одной из наиболее важных частей метаданных является заголовок документа. Он задается HTML-элементом <title>. Браузеры отображают этот элемент на самом верху страницы - а именно на вкладке (см. скриншот ниже). Также заголовок документа отображается в результатах поиска [в Гугл и др. поисковиках].

Попробуйте обновить <head> нашего файла basic.html следующим образом:

<!DOCTYPE html>
<html>
<head>
<title>Interneting Is Easy! </title>
</head>
<body>
<!-- Содержание (content) будет здесь -->
</body>
</html>

При перезагрузке страницы в браузере должна появиться пустая страница, но при этом во вкладке браузера будет отображаться надпись Interneting Is Easy!

Interneting is hard HTML+CSS
Скриншот 5: Веб-страница с элементом <title>, отображаемым на вкладке браузера

Обратите внимание, как аккуратно вложены все HTML-теги в нашей веб-странице. Очень важно следить за тем, чтобы не было пересекающихся элементов. Например, элемент <title> должен находиться внутри <head>, поэтому ни в коем случае нельзя добавлять закрывающий тег </head> перед закрывающим тегом </title>:

<!-- (Никогда не делайте так!) -->
<head>
<title>Interneting Is Easy!</head>
</title>

абзацы
paragraphs

Заголовки - это, конечно, хорошо, но давайте сделаем что-то, что можно реально увидеть воочию. Элемент <p> выделяет весь текст внутри себя как отдельный абзац. Добавьте следующий элемент <p> в тело нашей веб-страницы:

<!DOCTYPE html>
<html>
<head>
<title>Interneting Is Easy! </title>
</head>
<body>
<p>First, we need to learn some basic HTML.</p>
</body>
</html>

На странице должно появиться некоторое содержимое. Опять же, поскольку это содержимое, которое мы хотим отобразить, оно должно быть помещено в элемент <body>, а не в <head>.

Interneting is hard HTML+CSS
Скриншот 6: Веб-страница, показывающая элемент <p> с неким содержимым

Обратите внимание, что элементы <p> и <title> имеют двойной indent-отступ*, а <body> и <head> - одинарный. Подобные отступы для вложенных элементов - наилучшая практика. Это делает ваш HTML более удобным для чтения другими разработчиками (или для вас лично, если вы вернетесь через 5 месяцев и захотите что-то изменить).

Вы и ваша команда разработчиков сами решаете, использовать ли для отступов пробелы или символы табуляции. Вы можете установить это предпочтение в своем текстовом редакторе в разделе Atom > Preferences > Editor и прокрутить вниз до параметра Tab Type.

* - по техническим причинам, в русскоязычном переводе данного учебника indent-отступы отсутствуют.

заголовки секций
headings

Заголовок секции <h1> похож на заголовок документа <title>. Но в отличие от заголовков документов, заголовки h1...h6 фактически отображаются на странице. В HTML предусмотрено шесть уровней заголовков. Это <h1>, <h2>,<h3>, ... , <h6>. Чем выше номер, тем менее значимым является заголовок.

Первым заголовком на странице, как правило, должен быть <h1>, поэтому давайте вставим его над существующим элементом <p>. Очень часто первый элемент <h1> совпадает с <title> документа, как это сделано здесь:

<body>
<h1>Interneting Is Easy! </h1>
<p>First, we need to learn some basic HTML.</p>
</body>

По умолчанию браузеры отображают менее важные заголовки меньшим шрифтом. Для примера включим заголовок второго уровня и посмотрим, что получится:

<!DOCTYPE html>
<html>
<head>
<title>Interneting Is Easy! </title>
</head>
<body>
<h1>Interneting Is Easy! </h1>
<p>First, we need to learn some basic HTML.</p>

<h2>Headings</h2>
<p>Headings define the outline of your site. There are 6 levels of headings.</p>
</body>
</html>

В результате веб-страница будет выглядеть примерно так:

Interneting is hard HTML+CSS
Скриншот 7: Веб-страница с бОльшим элементом <h1> и меньшим элементом <h2>

Заголовки секций - это основной способ обозначения различных компонентов содержимого. Элементы заголовков секций определяют контур веб-страницы, как ее видят люди и поисковые системы. Поэтому выбор подходящих заголовков очень важен для создания качественной веб-страницы.

неупорядоченные списки
unordered lists

Всякий раз, заключая какой-либо текст в HTML-теги, мы придаем ему новый смысл. "Обертывание" содержимого в теги <ul> сообщает браузеру, что все, что находится внутри, должно отображаться как "неупорядоченный список". Чтобы обозначить отдельные элементы этого списка, нужно обернуть каждый из этих элементов тегами <li>, например, так:

<h2> Lists </h2>

<p>This is how you make an unordered list:</p>

<ul>
<li>Add a "ul" element (it stands for unordered list)</li>
<li>Add each item in its own "li" element</li>
<li>They don't need to be in any particular order</li>
</ul>

После добавления этой разметки в элемент <body> (под существующим содержимым) должен появиться маркированный список с отдельным маркером в виде круга (bullet) для каждого элемента <li>:

Interneting is hard HTML+CSS
Скриншот 8: веб-страница, на которой показан элемент <ul> с элементами <li> внутри него

Спецификация HTML определяет строгие правила относительно того, какие элементы могут находиться внутри других элементов. В данном случае элементы <ul> должны содержать только элементы <li>. Это означает, что вы никогда не должны писать что-то подобное:

<!-- Никогда не делайте так! -->
<ul>
<p>Add a "ul" element (it stands for unordered list)</p>
</ul>

Вместо этого следует обернуть этот абзац тегами <li>:

<!-- Вместо этого сделайте вот это -->
<ul>
<li><p>Add a "ul" element (it stands for unordered list)</p></li>
</ul>

А откуда мы знаем, что <ul> принимает только элементы <li> и что <li> допускает вложенные абзацы? Потому что так утверждает Mozilla Developer Network (MDN). MDN - это превосходный справочник по элементам HTML. В этом учебнике мы постараемся рассказать как можно больше о том, как использовать основные элементы HTML, но если вы не уверены в каком-либо элементе, введите в Google* такой запрос "MDN <некий элемент>".

* - Если желаете увидеть результаты поиска на русском языке, вместо Гугла ищите в Яндексе. Например, спросите в Яндексе: "MDN <li>".

упорядоченные списки
ordered lists

В неупорядоченном списке перестановка элементов <li> не должна изменить смысл списка. Если же последовательность элементов списка все же имеет значение, то вместо нее следует использовать "упорядоченный список". Чтобы создать упорядоченный список, просто замените родительский элемент <ul> на <ol>. Добавьте следующее содержимое в раздел Lists файла basics.html:

<p>This is what an ordered list looks like:</p>

<ol>
<li>Notice the new "ol" element wrapping everything</li>
<li>But, the list item elements are the same</li>
<li>Also note how the numbers increment on their own</li>
<li>You should be noticing things is this precise order, because this is an ordered list</li>
</ol>

При перезагрузке страницы в браузере можно заметить, что браузер автоматически увеличил числовое значение для каждого элемента <li>. В разделе Привет, CSS мы узнаем, как изменить тип отображаемых чисел.

Interneting is hard HTML+CSS
Скриншот 9: Веб-страница, на которой отображается <ol> с элементами <li> внутри него

Разница между неупорядоченным и упорядоченным списком может показаться незначительной, но для веб-браузеров, поисковых систем и, конечно же, читателей разница очень даже значительна. Кроме того, это проще, чем вручную нумеровать каждый элемент списка.

Пошаговые процедуры, такие как рецепты, инструкции и даже оглавления, являются хорошими "кандидатурами" для упорядоченных списков. В то время как списки <ul> лучше подходят для представления инвентаризации товаров, характеристик продуктов, сравнения "за" и "против", а также для создания меню навигации.

акцентирующие (курсивные) элементы
emphasis (italic) elements

До сих пор мы работали только с "блоковыми элементами" [block-level elements]. Они также называются "потоковый контент" [flow content]. Второй тип содержимого, крупный и крайне важный - "строчные элементы" [inline elements]. Другое название - "фразовый контент" [phrasing content]. Блочные элементы всегда отображаются на новой строке, в то время как строчные элементы могут воздействовать на участки текста в любом месте строки.

Interneting is hard HTML+CSS
Скриншот 10: сравнение блоковых элементов (обертывающих несколько строчных элементов) и строчных (inline) элементов (внутри блокового элемента)

Например, <p> - это блоковый элемент, а <em> - строчный элемент. <em> воздействует на участок текста внутри абзаца. Он означает "акцентирование" и обычно отображается в виде текста, выделенного курсивом. Для демонстрации акцентированного текста на нашей веб-странице, добавьте на нее новый раздел:

<h2> Inline Elements </h2>

<p><em>Sometimes</em>, you need to draw attention to a particular word or
phrase.</p>

При этом часть, обернутая в тэги <em>, должна отображаться курсивом, как показано на скриншоте ниже. Обратите внимание, что затронута только часть строки. Это характерно для строчных элементов. В главе Блоковая модель CSS мы узнаем, как строчные и блоковые элементы могут существенно влиять на оформление страницы.

Interneting is hard HTML+CSS
Скриншот 11: веб-страница с выделением текста курсивом (акцентированием), с помощью элемента <em>

На всякий случай, если все еще осталась неясность, повторимся. Крайне важно правильно вложить друг в друга элементы HTML. Когда несколько HTML элементов вложены друг в друга, легко может возникнуть путаница с порядком следования тегов. Поэтому убедитесь, что ваша разметка не выглядит так, как показано ниже:

<!-- (Никогда не делайте так!) -->
<p>Это курсивом <em>выделенный текст</p></em>

элементы сильной значимости
strong (bold) elements

Если вы хотите придать тексту еще больше значения, серьезности или срочности, чем с помощью тега <em>, используйте элемент <strong>. Это такой же строчный элемент, как и <em>, а выглядит он так:

<p>Other times, you need to <strong>strong</strong>ly emphasize the importance
of a word or phrase.</p>

На веб-странице элемент <strong> проявится в виде полужирного* текста, см. ниже:

* - для меня все еще загадка, почему в ИТ слово bold переводится как "полужирный".

Interneting is hard HTML+CSS
Скриншот 12: веб-страница, выделяющая полужирным шрифтом текст, созданный с помощью элемента <strong>

Чтобы привлечь еще большее внимание к участку текста, можно вложить элемент <strong> в элемент <em> (или наоборот). В результате текст будет одновременно и полужирным и курсивным:

<p><em><strong>And sometimes you need to shout!</strong></em></p>

Как следует из текста примера, это фактически типографский эквивалент крика. Ознакомьтесь с главой Веб-Типографика, чтобы не переборщить с использованием полужирных и курсивных шрифтов.

Interneting is hard HTML+CSS
Скриншот 13: веб-страница c полужирным курсивным текстом, созданным с помощью элемента <strong>, обернутого в элемент <em>
структура и внешний вид
structure versus presentation

Вам интересно, почему мы используем термины "акцентирование" [emphasis] вместо "курсив" [italic] и "сильный" [strong] вместо "полужирный" [bold]? Вот мы и подошли к важному различию между HTML и CSS. Разметка HTML должна предоставлять семантическую [смысловую] информацию о контенте, а не презентационную. Другими словами, HTML должен определять структуру документа. В то время как в за его внешний вид отвечает CSS.

Interneting is hard HTML+CSS
Скриншот 14: HTML и CSS. HTML как абстрактное дерево узлов. А CSS как различные формы визуализируемого текста

Классическими примером вышеупомянутого различия являются якобы устаревшие элементы <b> и <i>. Раньше они обозначали "полужирный" [bold] и "курсив" [italic] соответственно. Однако в HTML5 была сделана попытка создать четкое разделение между структурой документа и его презентацией. Поэтому <i> был заменен на <em>, поскольку акцентировать текст можно не только курсивом, но и другими способами (например, другим шрифтом, другим цветом или бОльшим размером). По такому же принципу <b> поменяли на <strong>.

В разделе Привет, CSS, вы узнаете, как изменять отображение браузером элементов <strong> и <em>. Это еще раз подтверждает тезис, согласно которому не следует выделять курсивом или жирным шрифтом текст в HTML. Это должен делать CSS.

пустые html-элементы
empty html elements

HTML-теги, с которыми мы до сих пор встречались, обертывают либо текстовый контент (например, <p>), либо другие HTML-элементы (например, <ol>). Но это не относится ко всем элементам HTML. Некоторые из них могут быть "пустыми" или "самозакрывающимися". Переносы строк и горизонтальные прямые - наиболее распространенные пустые элементы.

ЭЛЕМЕНТ ПЕРЕНОСА СТРОКИ
line breaks

HTML объединяет идущие друг за другом пробелы, табуляции или новые строки (вместе известные как "пробельные символы") в один пробел. Для лучшего понимания добавим в наш файл basics.html следующий раздел:

<h2>Empty Elements</h2>

<p>Thanks for reading! Interneting should be getting easier now.</p>

<p>Regards,
The Authors</p>

Новая строка после Regards в приведенном фрагменте будет преобразована в пробел, а не отображена как перенос строки:

Interneting is hard HTML+CSS
Скриншот 15: веб-страница, показывающая пользователю пробел вместо переноса строки в документе html

Такое поведение может показаться интуитивно понятным, но веб-разработчики часто устанавливают в своих редакторах ограничение на длину строки около 80 символов. Программисту так удобнее работать с кодом. Но если каждая новая строка будет отображаться на готовой веб-странице, это сильно испортит ее внешний вид.

Чтобы "приказать" браузеру сделать на готовой веб-странице перенос строки, используем элемент <br/>, например, так:

<p>Regards,<br/>
The Authors</p>

Элемент <br/> полезен там, где важно форматирование текста. Хайку, тексты песен, подписи - вот лишь несколько примеров, где он может пригодиться.

Interneting is hard HTML+CSS
Скриншот 16: веб-страница, показывающая пользователю перенос строки благодаря элементу <br/> в документе html

Однако следует быть очень осторожным и не злоупотреблять тегом <br/>. Каждый из них должен нести смысловую нагрузку. Не стоит использовать его, например, для добавления промежутков между абзацами:

<!-- За такой код вас "запинают" -->
<p>This paragraph needs some space below it...</p>
<br/><br/><br/><br/><br/><br/><br/><br/>
<p>So, I added some hard line breaks.</p>

Как уже упоминалось ранее, подобная презентационная вёрстка должна быть определена в CSS, а не в HTML.

ГОРИЗОНТАЛЬНЫЕ ПРЯМЫЕ
horizontal rules

Элемент <hr/> - это "горизонтальное прямая", которое представляет собой тематическое разделение. Переход от одной сцены рассказа к другой или между концом письма и постскриптумом - хорошие примеры того, когда горизонтальное линия уместна. Например:

<h2>Empty Elements</h2>

<p>Thanks for reading! Interneting should be getting easier now.</p>

<p>Regards,<br/>
The Authors</p>

<hr/>

<p>P.S. This page might look like crap, but we'll fix
that with some CSS soon.</p>

Одной из тем этого урока было отделение содержания (HTML) от презентации (CSS), и <hr/> не является исключением. Как и <em> и <strong>, он имеет определенный вид по умолчанию (горизонтальная линия). Но как только мы начнем работать с CSS, мы сможем использовать его для создания дополнительного пространства между секциями, декоративного символа или вообще для любых других целей.

Interneting is hard HTML+CSS
Скриншот 17: веб-страница, демонстрирующая элемент <hr/>

Подобно <br/>, элемент <hr/> должен нести смысловую нагрузку - не стоит использовать его, когда нужно просто вывести строку лишь для эстетики. Для эстетики лучше использовать свойство CSS "border", о котором мы поговорим через несколько уроков.

Другой способ восприятия элемента <hr/> заключается в том, что он имеет меньшее значение, чем разделение, создаваемое элементом заголовка нового абзаца, но большее значение, чем непосредственно новый абзац.

ЗАВЕРШАЮЩИЙ СЛЕШ НЕОБЯЗАТЕЛЕН!
optional trailing slash

Завершающий слеш (символ "/") во всех пустых HTML-элементах совсем необязателен. Приведенный ранее фрагмент можно было бы разметить и так, как показано на скриншоте ниже. Обратите внимание на отсутствие слеша в тегах <br> и <hr>:

<p>Regards,<br>
The Authors</p>

<hr>

В принципе, нет разницы, какую разметку вы выберете, но для достижения единообразия выберите одну и придерживайтесь ее. В данном учебнике мы будем включать символ "/" [slash], так как он ясно показывает, что это самозакрывающийся элемент. А это, в свою очередь, поможет избежать поиска закрывающего тега в другом месте документа.

РЕЗЮМЕ

Этот урок мог показаться бесконечным списком элементов HTML, и, в общем-то, так оно и было. HTML довольно прост, если разобраться. Веб-страницы состоят из HTML-элементов. Каждый элемент привносит свой смысл в текст, который он содержит. Элементы могут быть вложены друг в друга.

То, что мы сделали в этом уроке, схематично показывает первый шаг в процессе разработки веб-страниц: сначала определяем, что будет сказано - это HTML. А затем уже определяем как оно будет представлено - это CSS. Надеемся, что файл basics.html, созданный нами в этой главе, послужит полезным кратким справочником по основным элементам HTML. Если вы вдруг потеряете его, то вот как он должен выглядеть:

Interneting is hard HTML+CSS
Скриншот 18: основные элементы HTML: <title>, <p>, <h1>, <ol> и др.

Ранее говорилось, что написание HTML кода похоже на работу в редакторе WYSIWYG. Разумеется, писать на HTML - гораздо более трудоемкий процесс. Однако трудоемкость уравновешивается его невероятной гибкостью. Написанный вами код отобразится на экране ноутбука или ПК, смартфоне, планшете или на листе бумаги. Причем каждое из этих отображений может иметь другое оформление. Изменить стиль нескольких документов, можно всего лишь изменив одну строку CSS. Microsoft Word и близко не стоит к потенциалу HTML/CSS как инструмента для работы с контентом.

На следующем уроке мы завершим наше обучение HTML с помощью остальных элементов, с которыми вы будете сталкиваться постоянно: ссылок и изображений. Если желаете самостоятельно изучить менее известные элементов, рекомендуем справочник MDN по элементам HTML.


HTML & CSS IS HARD - НА РУССКОМ

ССЫЛКИ И КАРТИНКИ

УРОК Nº 3

Просто и понятно про взаимодействие веб-страниц друг с другом

На предыдущем уроке были рассмотрены некоторые весьма важные элементы HTML, но мы имели дело только с одной вебстраницей. Принципиальное отличие ссылок и изображений в том, что они имеют дело с внешними ресурсами. Гиперссылки [тж. просто "ссылки"] указывают пользователю на другой HTML-документ, а изображения добавляют на страницу другой файл.

Interneting is hard HTML+CSS
Скриншот 1: картинка, указывающая на элемент <img> на веб-странице, и HTML-ссылка, указывающая с веб-страницы на другую веб-страницу

Для использования ссылок и картинок нам также необходимо познакомиться с еще одним компонентом синтаксиса HTML - атрибутами. Атрибуты откроют перед нами целый мир новых возможностей для наших веб-страниц.

На этом уроке мы создадим простой сайт, состоящий из нескольких HTML-документов и файлов изображений*. Хотя урок называется "Ссылки и картинки", на самом деле основная тема - структура файлов и папок. Начав работать с несколькими файлами, вы поймете, насколько организованность важна для веб-разработчика.

* - десь и далее понятия "изображение" и "картинка" - синонимы, означающие одно и то же.

подготовка
setup

Поскольку этот урок посвящен взаимодействию веб-страниц друг с другом, прежде чем приступить к созданию кода, мы создим несколько новых HTML-файлов. Мы будем работать с тремя отдельными веб-страницами, а также с несколькими файлами изображений различных форматов:

Interneting is hard HTML+CSS
Скриншот 2: Семь файлов для данного проекта (3 HTML-файла, 4 файла картинок)

Для начала создайте новую папку links-and-images. Все наши файлы будут храниться в ней. Попробуйте сделать это в Atom, следуя инструкциям из главы Введение.

СТРАНИЦА LINKS
links page

Затем добавьте в созданную папку новый файл links.html. Напишите внутри него следующий HTML-код. Он вам уже знаком по предыдущему уроку.

<!DOCTYPE html>
<html>
<head>
<title>Links</title>
</head>
<body>
<h1>Links</h1>
</body>
</html>

СТРАНИЦА IMAGES
images page

В той же папке создаем еще один файл с именем images.html:

<!DOCTYPE html>
<html>
<head>
<title>Images</title>
</head>
<body>
<h1>Images</h1>
</body>
</html>

СТРАНИЦА EXTRAS
extras page

Наша последняя страница поможет продемонстрировать нам относительные ссылки. Создайте в папке links-and-images новую папку misc. Добавьте в нее новый файл - extras.html:

<!DOCTYPE html>
<html>
<head>
<title>Extras</title>
</head>
<body>
<h1>Extras</h1>
</body>
</html>

Кстати можно создать новую папку прямо в Atom, щелкнув правой кнопкой мыши на панели браузера файлов и выбрав в контекстном меню пункт New Folder. Жизнь прекрасна, когда не нужно выходить из текстового редактора.

СКАЧАЙТЕ КАРТИНКИ
image downloads

Мы будем вставлять изображения в наш файл images.html, поэтому обязательно скачайте эти примеры с картинками моти*. Распакуйте их в папку links-and-images, сохранив родительскую папку images из скачанного ZIP-файла. Теперь ваш проект должен выглядеть так:

* - "моти" или "мочи" (яп. 餅) - японский десерт в виде колобков или брусков из рисовой муки.

Interneting is hard HTML+CSS
Скриншот 3: браузер редактора Atom после создания файлов примеров
якоря
anchors

Ссылки создаются с помощью элемента <a>, который сокращенно означает "якорь" [anchor]. Этот элемент работает так же, как и все элементы из предыдущей главы: когда вы оборачиваете фрагмент текста тегами <a>, это изменяет смысл его содержимого. Рассмотрим это на примере добавления следующего абзаца в элемент <body> файла links.html:

<p>This example is about links and <a>images</a>.</p>

Если вы загрузите эту страницу в браузере, то заметите, что элемент <a> совсем не похож на ссылку. Увы, к сожалению, элемент <a> сам по себе ничего особенного не умеет.

Подобно тому, как элемент придает смысл содержимому, которое он содержит, HTML-атрибут придает смысл элементу, к которому он присоединен.

Interneting is hard HTML+CSS
Скриншот 4: HTML-атрибут href, присоединенный к HTML-элементу <a>, который в свою очередь присоединен к исходному контенту

Разные элементы могут использовать различные атрибуты, и за подробностями о том, какие элементы принимают те или иные атрибуты, можно обратиться к MDN. В данный момент нас интересует атрибут href, поскольку он определяет, куда переходит пользователь при нажатии на элемент <a>. Обновите свою ссылку, как показано ниже:

<p>This example is about links and <a href='images.html'>images</a>.</p>

Обратите внимание, как атрибуты располагаются внутри открывающего тега. Сначала идет имя атрибута, затем знак равенства, затем "значение" атрибута в одинарных или двойных кавычках. Такой синтаксис отличает атрибуты от содержимого (которое находится между тегами).

Дополнительная информация, предоставляемая атрибутом href, сообщает браузеру, что данный элемент <a> является ссылкой, и он должен отобразить содержимое ссылки в виде синего текста, используемого по умолчанию:

Interneting is hard HTML+CSS
Скриншот 5: веб-страница с синей ссылкой <a href>.

Теперь, когда мы работаем со ссылками, нам необходимо понять, как устроен сайт. В нашем случае сайт - это просто набор HTML-файлов, разложенных по папкам. Чтобы ссылаться на эти файлы изнутри другого файла, в Интернете используются "единые локаторы ресурсов" (URL). В зависимости от того, на что вы ссылаетесь, URL могут принимать различные формы. Ниже выделены три типа URL, с которыми мы будем иметь дело:

Interneting is hard HTML+CSS
Скриншот 6: абсолютные (absolute) ссылки, указывающие на другой сайт, относительные (relative) ссылки, указывающие на другую страницу того же сайта и корневые (root-relative) ссылки, указывающие на другую страницу того же сайта через его домен

Абсолютные, относительные и корневые ссылки зависят от значения атрибута href. Далее вы узнаете, как и когда использовать каждый из них. Но сначала давайте добавим в файл links.html следующее:

<p>This example is about links! There are three kinds of links:</p>

<ul>
<!-- Сюда добавляем элементы <li> -->
</ul>

АБСОЛЮТНЫЕ ССЫЛКИ
absolute links

"Абсолютные" ссылки [absolute links] - это наиболее подробный способ обращения к веб-ресурсу. Они начинаются со "схемы" (обычно http:// или https://), за которой следует доменное имя сайта, а затем путь к целевой веб-странице.

Interneting is hard HTML+CSS
Скриншот 7: схема (https://), домен (developer.mozilla.org), путь (/en-us/docs/web/html).

Попробуем, например, создать ссылку на справочник HTML-элементов Mozilla Developer Network:

<li>Absolute links, like to
<a href='https://developer.mozilla.org/en-US/docs/Web/HTML'> Mozilla
Developer Network, which is a very good resource for web
developers. </li>

Можно использовать абсолютные ссылки для ссылок на страницы собственного сайта, но жесткое кодирование своего доменного имени может привести к возникновению неприятных ситуаций. Поэтому абсолютные ссылки рекомендуется использовать только для перенаправления пользователей на другой сайт.

Interneting is hard HTML+CSS
Скриншот 8: абсолютная ссылка, указывающая с нашего сайта на другой сайт
ОТНОСИТЕЛЬНЫЕ ССЫЛКИ
relative links

"Относительные" ссылки [relative links] указывают на другой файл на вашем сайте с перспективы того файла, который вы редактируете. При этом подразумевается, что схема и доменное имя совпадают с текущей страницей. Поэтому единственное, что необходимо указать - это путь.

Вот как можно сослаться на наш файл extras.html из файла links.html:

<li>Relative links, like to our <a href='misc/extras.html'> extras
page</a>.</li>

В данном случае атрибут href представляет собой путь к файлу extras.html из файла links.html*. Поскольку extras.html находится в другой папке, в URL необходимо включить папку misc.

* - обратите внимание, что путь пролегает из одного файла в другой. Причем другой файл extras.html лежит в другой папке, а именно в папке misc.

Interneting is hard HTML+CSS
Скриншот 9: относительная ссылка, указывающая с одной страницы нашего сайта на другую

Каждая папка и файл разделяются слешем (/). Таким образом, если бы мы пытались получить файл, находящийся в двух вложенных друг в дружку папках, потребовался бы URL вот такого вида:

misc/other-folder/extras.html

РОДИТЕЛЬСКИЕ ПАПКИ
parent folders

Как ссылаться на файлы в той же самой папке или во вложенной папке мы разобрались. А вот как ссылаться на файл, помещенный в папку уровнем выше? Давайте в нашем файле extras.html создадим относительные ссылки на links.html и images.html. Для этого дообавим немного кода в файл extras.html:

<p>This page is about miscellaneous HTML things, but you may
also be interested in <a href='links.html'>links</a> or
<a href='images.html'>images</a>.</p>

Однако при щелчке на любую из этих ссылок браузере будет "ругаться" - дескать такая страница не существует. Взглянув на адресную строку, мы обнаружим, что браузер пытается загрузить misc/links.html и misc/images.html. Но ведь он ищет эти файлы не в той папке! Все это объясняется тем, что наши ссылки являются относительными по отношению к расположению файла extras.html, который находится в папке misc.

Interneting is hard HTML+CSS
Скриншот 10: заведомо неудачная попытка ссылки на HTML-страницы из-за отсутствия обращения к каталогу родителя [parent reference]

Чтобы исправить эту ошибку, нам понадобится вот такой синтаксис ".." [две последовательные точки без кавычек]. Именно эти две последовательные точки вставленный в путь к файлу укажут на родительский каталог:

<p>This page is about miscellaneous HTML things, but you may
also be interested in <a href='links.html'>links</a> or
<a href='images.html'>images</a>.</p>

Это все равно, что сказать: "Файл extras.html находится в папке misc. Поднимись в папку и найди там links.html и images.html".

Interneting is hard HTML+CSS
Скриншот 11: корректная ссылка на HTML-страницы с обращением к каталогу родителя

Для перехода вверх по каталогам используйте соответствующее число точек. В нашем случае точек будет две:

../../elsewhere.html

Относительные ссылки удобны тем, что позволяют перемещаться по всему каталогу без необходимости обновлять все href в элементах <a>. Однако возможна и путаница, если все ссылки начинаются с кучи точек. Лучше всего относительные ссылки подходят подходят для привязки к файлам, находящимся в одной папке или в отдельном разделе сайта.

Например, все картинки в нашем учебнике загружаются через относительные ссылки (про картинки поговорим чуть ниже). Благодаря относительным ссылкам мы можем переименовать название любого урока без необходимости обновлять все пути к картинкам.

КОРНЕВЫЕ ССЫЛКИ
root-relative links

"Корневые" ссылки [root-relative links] аналогичны вышеупомянутым относительным ссылкам. Но вместо того, чтобы относиться к текущей странице, они относятся к "корню" всего сайта. Например, если ваш сайт: our-site.com, то все URL-адреса, относящиеся к корню, будут относиться к our-site.com.

Interneting is hard HTML+CSS
Скриншот 12: ссылка с одной веб-страницы нашего сайта, проходящая через наш домен, затем на другую страницу нашего сайта

К сожалению, в нашей дискуссии про корневые ссылки есть одна оговорка: в данном учебнике используются локальные HTML-файлы, а не сайт, размещенный на веб-сервере. Это означает, что мы не сможем экспериментировать с корневыми ссылками. Но если бы у нас был настоящий сервер, то ссылка на нашу домашнюю страницу выглядела бы так:

<!-- Это не будет работать для наших локальных HTML-файлов -->
<li>Root-relative links, like to the <a href='/'>home page</a> of our website,
but those aren't useful to us right now.</li>

Единственное отличие корневой ссылки от относительной заключается в том, что корневая начинается с прямого слеша*. Cлеш представляет корень нашего сайта. После слеша можно добавлять в указанный путь дополнительные папки и файлы, как и в случае с относительными ссылками. Следующий путь будет работать корректно независимо от того, где находится текущая страница (даже в misc/extras.html):

/images.html

* - слеш (forward slash или просто slash) - косая прямая, выглядит как знак дроби "/".

Корневые ссылки - это один из наиболее полезных видов ссылок. Они достаточно явны, чтобы избежать потенциальной путаницы с относительными ссылками, но не настолько явны, как абсолютные ссылки. Вы будете часто видеть их на протяжении всей своей карьеры веб-разработчика, особенно на больших сайтах, где трудно уследить за относительными ссылками.

ЦЕЛИ ССЫЛОК
LINK TARGETS

Итак, атрибуты изменяют значение HTML-элементов. Но иногда требуется изменить не один, а несколько аспектов элемента. Например, элементы <a> также допускают атрибут target, определяющий место отображения страницы, после того, как пользователь щелкнул на ссылку. По умолчанию большинство браузеров заменяют текущую страницу на новую. Однако мы можем использовать атрибут target. С помощью этого аттрибута мы даем команду браузеру открыть ссылку в новом окне/вкладке.

Попробуйте изменить нашу абсолютную ссылку в файле links.html как указано ниже. Обратите внимание, что второй атрибут выглядит так же, как и первый, но они отделены друг от друга пробелом (или новой строкой):

<li>Absolute links, like to
<a href='https://developer.mozilla.org/en-US/docs/Web/HTML'
target='_blank'>Mozilla Developer Network</a>, which is a very good
resource for web developers.</li>

Атрибут target имеет несколько предопределенных значений, имеющих для браузеров особый смысл. Самым распространенным значением является _blank, который говорит браузеру: "данную ссылку открой в новой вкладке (или в новом окне)*". Об остальных значениях можно прочитать на сайте MDN.

* - так все-таки в новой вкладке или в новом окне? Англоязычная страница MDN поясняет, что пользователь может изменить настройки своего браузера, где открывать ссылок с _target: в новой вкладке либо в новом окне. "_blank: usually a new tab, but users can configure browsers to open a new window instead."

стандарты наименования файлов
naming conventions

Вы заметили, ни один из наших файлов и папок не содержит пробелов в своем названии? Это не случайно. Пробелы в URL требуют особого обращения, поэтому ни в коем случае не допускайте пробелов. Для лучшего понимания попробуйте создать в нашем проекте links-and-images новый файл под названием "spaces are bad.html". Добавьте в него какой-либо небольшой текст, а затем откройте его в браузере Chrome или Safari (Firefox схитрит и сохранит пробелы).

links-and-images/spaces%20are%20bad.html

В адресной строке вы увидите, что все наши пробелы были заменены на "%20", как показано выше. Пробелы в URL не допускаются, поэтому для их обозначения используется специальная кодировка. Вместо пробела всегда следует использовать дефис, как это сделано во всем этом учебнике. Для единообразия также рекомендуется всегда использовать строчные символы вместо заглавных.

Обратите внимание, что существует прямая связь между именами файлов и папок и URL-адресом веб-страницы, которую они представляют. Названия наших папок и файлов определяют URL-адреса наших веб-страниц. Они видны пользователю, а значит, к наименованию файлов нужно приложить не меньше усилий, чем к созданию содержащегося в них содержимого.

Эти стандарты наименования относятся ко всем файлам сайта, а не только к HTML-файлам. В CSS-файлах, JavaScript-файлах и картинках также следует избегать пробелов и заглавных букв.

КАРТИНКИ
IMAGES

В отличие от всех элементов HTML, с которыми мы до сих пор сталкивались, содержимое изображения находится вне веб-страницы, на которой отображается изображение. К счастью, у нас уже есть возможность ссылаться на внешние ресурсы из HTML-документа: с помощью абсолютных, относительных и корневых ссылок.

Картинки добавляются на веб-страницы с помощью тега <img/> и его атрибута src, указывающего на файл отображаемой картинки. Заметьте, что это пустой элемент, как <br/> и <hr/> из предыдущего урока. (Не стоит пока добавлять его в наш проект. Конкретные примеры мы рассмотрим далее).

<img src='some-photo.jpg'/>

Retina-дисплеи и мобильные устройства делают работу с изображениями несколько сложнее, чем старый добрый <img/>. Мы оставим эти сложности для главы Responsive Images. Также не забудьте ознакомиться с элементами <figure> и <figcaption> на уроке Семантика HTML.

А мы пока что сфокусируемся на форматах изображений, используемых в сети.

ФОРМАТЫ ИЗОБРАЖЕНИЙ
IMAGE FORMATS

Существует четыре основных формата изображений, используемых в сети. Все они предназначены для выполнения различных задач. Понимание их предназначения позволяет значительно улучшить качество веб-страниц.

Interneting is hard HTML+CSS
Скриншот 13: примеры форматов JPG, GIF, PNG и SVG

В следующих нескольких секциях мы рассмотрим идеальные варианты использования каждого из этих форматов. Прежде чем двигаться дальше, убедитесь, что ZIP-файл с картинками моти уже скачан, распакован и добавлен в проект links-and-images.

ФОРМАТ JPG

Изображения в формате JPG предназначены для работы с большими цветовыми палитрами без чрезмерного увеличения размера файла. Поэтому они отлично подходят для фотографий и картинок с множеством оттенков. Но JPG не позволяют создавать прозрачные фон, в чем можно убедиться, присмотревшись к картинке ниже. Видите каемку на изображении?

Interneting is hard HTML+CSS
Скриншот 14: моти в прозрачном "пузыре", с каймой

Добавьте mochi.jpg на нашу страницу images.html с помощью следующего кода (он также содержит немного навигации по другим нашим страницам):

<p>This page covers common image formats, but you may also be looking for <a
href='links.html'>links</a> and <a href='misc/extras.html'>useful
extras</a>.</p>

<h2>JPGs</h2>

<p>JPG images are good for photos.</p>

<img src='images/mochi.jpg'/>

ФОРМАТ GIF

GIF-файлы - это оптимальный вариант для простой анимации, но их недостатком является то, что они несколько ограничены в плане цветовой палитры. Поэтому никогда не используйте "гифки" для фотографий. Прозрачные пиксели - это бинарная опция для GIF, т.е. вы не получите полупрозрачных пикселей. Это может затруднить получение высокого уровня детализации на прозрачном фоне. По этой причине лучше использовать PNG-картинки, если вам не требуется анимация.

Interneting is hard HTML+CSS
Скриншот 15: анимированный моти (mochi.gif)

Добавить этого малыша в наш файл images.html поможет следующий код:

<h2>GIFs</h2>

<p>GIFs are good for animations.</p>

<img src='images/mochi.gif'/>

ФОРМАТ PNG

PNG-файлы отлично подходят для всего, что не является фотографией или анимацией. Для фотографий PNG-файл такого же качества (как воспринимает человеческий глаз), обычно "весит" больше, чем эквивалентный JPG-файл. Однако PNG прекрасно справляются с непрозрачностью и не имеют ограничений по цветовой палитре. Поэтому они отлично подходят для иконок, технических диаграмм, логотипов и т.д.

Interneting is hard HTML+CSS
Скриншот 16: простой моти в формате .png

Давайте добавим и эту PNG-картинку в наш проект:

<h2>PNGs</h2>

<p>GIFs are good for diagrams and icons.</p>

<img src='images/mochi.png'/>

ФОРМАТ SVG

В отличие от описанных выше форматов, основанных на пикселях, SVG - это векторный графический формат. Он может увеличиваться или уменьшаться до любых размеров без потери качества. Это свойство делает SVG-изображения прекрасным инструментом для адаптивного дизайна. SVG подходят практически для всех тех же целей, что и PNG. Используйте SVG при любой возможности.

Interneting is hard HTML+CSS
Скриншот 17: SVG-изображение с четкими краями по сравнению с пикселизированным PNG-изображением

Обе картинки на скриншоте выше имели первоначальный размер 100×100 пикселей и одинаковую резкость. Затем масштаб увеличили до 300×300 пикселей. Почувствуйте разницу. Четкие, чистые линии на SVG (слева), в то время как PNG (справа) заметно пикселизировано.

Несмотря на то, что SVG является векторным форматом, его можно использовать точно так же, как и его растровый аналог. Добавьте файл mochi.svg на нашу страницу images.html:

<h2>SVGss</h2>

<p>SVGs are <em>amazing</em>. Use them wherever you can.</p>

<img src='images/mochi.svg'/>

Однако у SVG есть одна проблемка: для их корректного отображения в разных браузерах, нужно преобразовать все текстовые поля в контуры. Например с помощью Adobe Illustrator или Sketch). Если ваши картинки содержат много текста (как, например, причудливые скриншоты в этом учебнике), это может сильно повлиять на размер файла. По этой причине мы используем PNG вместо SVG. Но в любом случае SVG - это супер!

размеры изображений
image dimensions

По умолчанию элемент <img/> использует унаследованные размеры своего файла изображения. Наши JPG, GIF и PNG на самом деле имеют размер 150×150 пикселей, в то время как размер нашего SVG всего 75×75 пикселей.

Interneting is hard HTML+CSS
Скриншот 18: веб-страница после встраивания <img>-элементов JPG, GIF, PNG и SVG

Для корректного отображения пиксельные форматов на дисплеях retina [например на дивайсах от Apple] размеры изображений должны быть в два раза больше. Мы обсудим это в разделе Адаптивные картинки. А сейчас атрибут width элемента <img/> поможет нам уменьшить наши пиксельные картинки до нужного размера 75×75. В файле images.html обновите все наши пиксельные изображения, как показано ниже:

<!-- в раздел JPG -->
<img src='images/mochi.jpg' width='75'/>

<!-- в раздел GIF -->
<img src='images/mochi.gif' width='75'/>

<!-- в раздел PNG -->
<img src='images/mochi.png' width='75'/>

Атрибут width ["ширина"] задает четкий размер изображения. Также существует атрибут height ["высота"]. Задание только одного из них приведет к пропорциональному масштабированию изображения, в то время как определение обоих приведет к растяжению изображения. Значения размеров указываются в пикселях. Никогда не добавляйте указание каких-либо единиц измерения (например, width='75px' будет неверным).

Атрибуты width и height полезны, но все же в больштнстве случаев лучше задавать размеры изображения с помощью CSS, чтобы можно было легко изменять их с помощью медиавыражений [media queries]. Мы обсудим это более подробно, когда дойдем до адаптивного дизайна.

Текстовые альтернативы
text alternatives

Добавление атрибутов alt к элементам <img/> является лучшей практикой. Эти атрибуты определяют "текстовую альтернативу" отображаемому изображению. Это влияет как на поисковые системы, так и на пользователей невизуальных браузеров, использующих только текст (например, для людей с нарушениями зрения, использующих программы для чтения с экрана).

Обновим все наши картинки, включив в них описательные атрибуты alt:

<!-- в раздел JPG -->
<img src='images/mochi.jpg' width='75' alt='A mochi ball in a bubble'/>

<!-- в раздел GIF -->
<img src='images/mochi.gif' width='75' alt='A dancing mochi ball'/>

<!-- в раздел PNG -->
<img src='images/mochi.png' width='75' alt='A mochi ball'/>

<!-- в раздел SVG -->
<img src='images/mochi.png' alt='A mochi ball with Bézier handles'/>

Дополнительные примеры использования атрибута alt приведены в безумно подробной официальной спецификации.

другие html-атрибуты
more html attributes

Мы надеемся, что вы достаточно хорошо освоили синтаксис атрибутов HTML. Теперь можно добавить пару завершающих штрихов к HTML-коду нашего проекта. Каждая создаваемая вами веб-страница должна определять язык, на котором она написана, и набор символов.

ЯЗЫК ДОКУМЕНТА
document language

Язык веб-страницы по умолчанию определяется атрибутом lang в элементе верхнего уровня <html>. Наш документ написан на английском языке*, поэтому в качестве значения атрибута мы будем использовать код страны en. Сделайте это для всех созданных нами страниц:

<html lang='en'>

* - для вебстраниц с html-файлами данного перевода я, естественно, использовал указание на язык текста 'ru', то есть Russian (<html lang='ru'>).

Если интересно узнать какому языку соответствует какой языковой код, загляните на эту страницу в поле Subtag.

КОДИРОВКИ СИМВОЛОВ
CHARACTER SETS

"Кодировки символов" [или просто "кодировки"] - это что-то вроде цифрового алфавита для вашего браузера. Он отличается от языка вашего документа тем, что влияет только на отображение самих букв, а не на язык контента. Попробуйте скопировать и вставить несколько слов с необычными символами в наш misc/extras.html. Посмотрим, что получится.

<h2>Кодировки</h2>

<p>UTF-8 можно использовать для записи счета в турецком языке:</p>

<ol>
<li>bir</li>
<li>iki</li>
<li>üç</li>
<li>dört</li>
<li>beş</li>
</ol>

Просматривая эту запись в браузере, Вы увидите какие-то кракозябры вместо международных символов ü, ç, ö и ş:

Interneting is hard HTML+CSS
Скриншот 19: веб-страница показывает кракозябры [weird stuff] вместо специальных символов

Это происходит потому, что стандартный набор символов, используемый в большинстве браузеров, не учитывает эти "специальные" символы. Чтобы исправить это, укажите кодировку UTF-8, добавив элемент <meta> с атрибутом charset в <head> нашего файла misc/extras.html:

<meta charset='UTF-8'/>

Теперь все "специальные символы" должны отображаться корректно. В наши дни UTF-8 является чем-то вроде универсального алфавита. Каждая создаваемая вами веб-страница должна содержать эту строку в <head>.

HTML-сущности
html entities

Эта секция не имеет никакого отношения к ссылкам и картинкам. И все же, прежде чем перейти к CSS, необходимо упомянуть еще одну вещь. Речь идет о "сущностях" [HTML entities]. HTML сущность - это специальный символ, который не может быть представлен в виде обычного текста в HTML-документе. Обычно это означает либо то, что этот символ зарезервирован в HTML, либо то, что отсутствует такая клавиша на вашей клавиатуре.

ЗАРЕЗЕРВИРОВАННЫЕ СИМВОЛЫ
reserved characters

Символы <, > и & называются "зарезервированные (специальные) символы", поскольку их нельзя вставлять в HTML-документ без кодирования. Это происходит потому, что они что-либо означают в синтаксисе HTML: "<" начинает новый тег, ">" заканчивает тег, а знак амперсанта "&" задает в HTML какую-либо сущность.

В файл misc/extras.html добавьте следующее:

<h2>HTML Entities</h2>
<p>There are three reserved characters in HTML: &lt; &gt; and &amp;. You
should always use HTML entities for these three characters.</p>

Сущности всегда начинаются с амперса́нда (&) и заканчиваются точкой с запятой (;). Между ними вы помещаете специальный код, который ваш браузер будет интерпретировать как символ. В данном случае он интерпретирует lt, gt и amp как символы "меньше", "больше" и "амперсанд", соответственно.

Существует бесчисленное множество сущностей HTML. Если интересно, большинство из них найдете на этом сайте.

КАВЫЧКИ
QUOTES

Изогнутые кавычки* ни в коем случае не являются необходимыми, но если Вы заботитесь о типографике, то они будут одними из наиболее часто используемых вами элементов HTML. Существует четыре различных вида изогнутых кавычек (открывающие и закрывающие одиночные и двойные кавычки):

* - "Изогнутые кавычки" (в оригинале сurly quotes) википедия называет "английские двойные" и "английские одиночные". Используемые компьютером "прямые" кавычки соответствуют ивритским кавычкам (мерхао́т кфуло́т). См. https://ru.wikipedia.org/wiki/Кавычки

Изогнутые кавычки можно использовать их вместо прямых кавычек ' и ". Например, вот так:

<p>If you’re into “web typography,” you’ll also find
yourself using curly quotes quite a bit.</p>

В отличие от прямых кавычек, эти изогнутые кавычки должны обхватывать текст.

UTF-8 И HTML-СУЩНОСТИ
utf-8 and html entities

В былые времена Интернета в HTML-файлах не разрешалось вставлять специальные символы, что делало сущности гораздо более полезными. Но поскольку сейчас мы используем набор символов UTF-8, мы должны иметь возможность вставлять любые символы непосредственно в HTML-документ. Это делает сущности в основном полезными в качестве зарезервированных символов или для удобства при создании стандартного HTML.

резюме

По сути, вебсайт - это просто набор связанных между собой HTML, картинок и CSS-файлов. Темой "CSS" мы займемся уже на следующем уроке. Попробуйте начать думать о сайте как об удобной навигации пользователей по папкам и файлам, которые мы создаем в процессе веб-разработки. С такой точки зрения должно быть понятно, что поддержание хорошо организованной файловой системы является важнейшим аспектом создания вебсайта.

Мы также узнали о важных атрибутах lang и charset, которые дают базовый шаблон. Используйте его в начале каждой создаваемой вами веб-страницы:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Some Web Page</title>
</head>
<body>
<h1>Некая вебстраница</h1>
<!-- Здесь помещается все остальное содержимое -->
</body>
</html>

Все таки еще не хватает одной очень серьезной составляющей: CSS. На следующем уроке мы изучим атрибуты HTML, позволяющие подключать стили CSS к всему нашему сайту. Возможность работать с несколькими файлами и связывать их друг с другом "умным" способом станет еще более значимой, чем это было на сегодняшнем уроке.


HTML & CSS IS HARD - НА РУССКОМ

ПРИВЕТ, CSS

УРОК Nº 4.

Самый понятный учебник по созданию более привлекательных вебсайтов

Первые несколько глав этого учебника были посвящены исключительно HTML. Теперь пришло время сделать все (типа) красивым. В этом нам помогут каскадные таблицы стилей - CSS. Можно считать, что CSS определяет "дизайн" веб-страницы. CSS определяет такие параметры, как размер шрифта, поля и цвета, используя язык, совершенно не похожий на HTML.

Почему это отдельный язык? Потому что он служит совершенно иным целям. HTML представляет собой содержимое веб-страницы, а CSS определяет, как это содержимое будет представлено пользователю. Это фундаментальное различие, являющееся основой современной веб-разработки.

Interneting is hard HTML+CSS
Скриншот 1: эскиз (mockup) превращается в CSS, а исходный текст (raw content) - в HTML-разметку (html markup). И CSS, и HTML превращаются в веб-страницу (web-page).

CSS содержит терминологию, командующую браузеру что-нибудь вроде такого: "Я хочу, чтобы мои заголовки были очень большими, а боковая панель располагалась слева от основной статьи". HTML не имеет терминологии для подобных указаний по компоновке. Все, что HTML может сказать браузеру: "это заголовок, а это боковая панель".

На этом уроке мы рассмотрим базовый синтаксис CSS, а также способы его подключения к нашим HTML-документам. Цель урока состоит не в том, чтобы стать экспертом по CSS или запомнить все доступные стили, а в том, чтобы понять, как взаимодействуют CSS и HTML. CSS обычно хранится в собственном файле, поэтому, как и в предыдущей главе, правильная организация файлов играет первостепенную роль.

подготовка
setup

Для простоты мы будем хранить примеры каждого урока этого учебника в отдельной папке. Используя Atom, создайте новый проект hello-css. Мы будем стилизовать страницу hello-css.html, поэтому создайте ее и добавьте следующую разметку:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Hello, CSS</title>
</head>
<body>
<h1>Hello, CSS</h1>

<p>CSS lets us style HTML elements. There’s also
<a href='dummy.html'>another page</a> associated with this example.</p>

<h2>List Styles</h2>

<p>You can style unordered lists with the following bullets:</p>

<ul>
<li>disc</li>
<li>circle</li>
<li>square</li>
</ul>

<p>And you can number ordered lists with the following:</p>

<ol>
<li>decimal</li>
<li>lower-roman</li>
<li>upper-roman</li>
<li>lower-alpha</li>
<li>upper-alpha</li>
<li>(and many more!)</li>
</ol>
</body>
</html>

Еше нам понадобится страница-болванка для изучения того, как стили CSS применяются к нескольким веб-страницам. Создайте файл dummy.html и добавьте в него следующее:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Dummy</title>
</head>
<body>
<h1>Dummy</h1>

<p>This is a dummy page that helps us demonstrate reusable CSS
stylesheets. <a href='hello-css.html'>Go back</a>.</p>

<p>Want to try crossing out an <a href='nowhere.html'>obsolete link</a>? This
is your chance!</p>
</body>
</html>

таблицы стилей
css stylesheets

Таблицы стилей CSS находятся в текстовых файлах с расширением .css. Создайте новый файл styles.css в папке hello-css. В нем будут храниться все наши примеры фрагментов для этой главы. Добавим одно правило CSS, чтобы можно было определить, правильно ли подключена наша таблица стилей к HTML-страницам.

body {
color: #FF0000;
}

CSS-правило всегда начинается с "селектора", определяющего, к каким HTML-элементам оно применяется. В данном случае мы пытаемся придать стиль элементу <body>. После селектора находится заключенный в фигурные скобки "блок деклараций". Все "свойства", которые мы там зададим, будут влиять на элемент <body>.

Interneting is hard HTML+CSS
Скриншот 2: CSS-правило (Rule), состоящее из селектора и ряда пар "свойство-значение" (property-value)

color - это встроенное свойство, определенное спецификацией CSS и определяющее цвет текста выбранных HTML-элементов. Оно принимает шестнадцатеричное значение, представляющее цвет. #FF0000 означает ярко-красный цвет.

В свойствах CSS (как и в атрибутах HTML), используются пары "ключ-значение". Только в CSS мы определяем внешний вид, в то время как HTML задает семантический смысл основного контента.

подключение таблицы стилей css
linking a css stylesheet

Если вы попробуете загрузить одну из HTML-страниц в браузер, то не увидите нашу таблицу стилей в действии. Это потому, что мы еще не связали их между собой. Для этого предназначен элемент HTML <link/>. В файле hello-css.html изменим <head> на такой:

<head>
<meta charset='UTF-8'/>
<title>Hello, CSS</title>
<link rel='stylesheet' href='styles.css'/>
</head>

Элемент <link/> указывает браузеру, что при отображении нашей страницы hello-css.html нужно загрузить файл styles.css. Теперь весь текст на странице должен стать красным:

Interneting is hard HTML+CSS
Скриншот 3: веб-страница с красным текстом из-за селектора body

Элемент <link/> - это такой же элемент, как и <a>, но он используется только внутри <head>. Находясь в голове документа, <link/> подключается к метаданным, определенным за пределами данного документа. Также обратите внимание, что <link/> это пустой элемент. Поэтому ему не нужен закрывающий тег.

Атрибут rel устанавливает связь между ресурсом и HTML-документом. Наиболее распространенное значение - stylesheet, но есть и несколько других вариантов. Атрибут href работает так же, как рассказано на предыдущем уроке, только он должен указывать на файл .css, а не на другую веб-страницу. Значение href может быть абсолютной, относительной или корневой ссылкой.

Interneting is hard HTML+CSS
Скриншот 4: HTML-элемент <link> отсылает браузер к таблице стилей CSS

Обратите внимание на отсутствие прямой связи между браузером и нашей таблицей CSS. Браузер может найти ее только через HTML-разметку. Картинки, CSS, и даже JavaScript - все они находятся на HTML-странице, которая "склеивает" все это вместе. Поэтому HTML-страница является сердцевиной большинства веб-сайтов.

комментарии css
css comments

Теперь, когда наша таблица стилей подключена, давайте немного поиграем с ней. Этот красный цвет просто ужасен. Давайте сменим тон на приятный глазу серый:

body {
color: #414141; /* Темно-серый */
}

Обратите внимание, что комментарии в CSS отличаются от комментариев в HTML. Вместо синтаксиса <!-- --> в CSS игнорируется все, что находится между символами /* и */.

Установка нескольких свойств
setting multiple properties

В блок деклараций CSS можно поместить сколько угодно свойств. Попробуем задать цвет фона всей веб-страницы, изменив наше правило на следующее:

body {
color: #414141; /* Темно-серый */
background-color: #EEEEEE;/* Светло-серый */
}

Свойство background-color очень похоже на свойство color, но оно определяет цвет фона для любого выбранного элемента. Обратите внимание на точки с запятой в конце каждого объявления. Их удаление приведет к нарушению правила CSS, поэтому всегда ставьте точки с запятой!

Почему мы выбрали оттенки серого, а не черно-белый? Использование фона #000000 с цветом текста #FFFFFF дает слишком высокий контраст. Создается впечатление, что страница как-бы вибрирует, что может сильно отвлекать читателя.

выбор различных элементов
selecting different elements

Само собой, вы захотите применить стили к элементам, отличным от <body>. Для этого просто добавьте дополнительные правила CSS с различными селекторами. Например, измените размер шрифта заголовков <h1>:

body {
color: #414141; /* Dark gray */
background-color: #EEEEEE;/* Dark gray */
}

h1 {
font-size: 36px;
}

А для изменения размера заголовков h2 добавьте другое правило:

h2 {
font-size: 28px;
}

единицы измерения
units of measurement

Многие свойства CSS требуют указания единиц измерения. Существует множество единиц измерения, но наиболее часто встречающиеся - px (пиксель) и em (произносится как "эм"). Первое - это то, что вы интуитивно называете пикселем, независимо от того, есть ли у пользователя дисплей retina или нет. А второе - это текущий размер шрифта рассматриваемого элемента.

Interneting is hard HTML+CSS
Скриншот 5: размеры 1em, 1.6em и 2em для основных размеров шрифта 12px, 16px и 20px. Размеры em становятся больше по мере увеличения основного размера шрифта.

Единица em очень удобна для определения размеров относительно некоторого основного шрифта. На скриншоте выше показано масштабирование единиц em для соответствия основным размерам шрифта 12px, 16px и 20px. Конкретным примером является следующий вариант предыдущего кода:

body {
color: #414141; /* Dark gray */
background-color: #EEEEEE;/* Dark gray */
font-size: 18px;
}

h1 {
font-size: 2em;
}

h2 {
font-size: 1.6em;
}

Сначала задаем основной размер шрифта документа - 18px. Тогда наши <h1> будут быть в два раза больше, а наши <h2> - в 1,6 раза. Если захотите уменьшить или увеличить базовый, единицы em позволят соответственно масштабировать всю страницу.

выбор нескольких элементов
selecting different elements

А если мы решим добавить некоторые стили ко всем заголовкам? Мы же не хотим иметь множество почти одинаковых правил, поскольку это в итоге превратится в кошмар для техподдержки:

/* (Вы сильно пожалеете о создании таких вот дублирующихся стилей) */
h1 {
font-family: "Helvetica", "Arial", sans-serif;
}

h2 {
font-family: "Helvetica", "Arial", sans-serif;
}

h3 {
font-family: "Helvetica", "Arial", sans-serif;
}

/* (и так далее) */

Вместо этого мы можем выделить несколько HTML-элементов в одном CSS-правиле, разделив их запятыми. Добавьте это правило в наш файл styles.css:

h1, h2, h3, h4, h5, h6 {
font-family: "Helvetica", "Arial", sans-serif;
}

С помощью одного правила мы зададим шрифт для всех наших заголовков. Это здорово. Ведь если мы захотим сделать правки, мы сделаем это только в одном месте. Копировать и вставлять код - плохая идея для разработчиков, а "множественные селекторы" [multiple selectors] позволяют значительно сократить количество подобных действий.

Interneting is hard HTML+CSS
Скриншот 6: веб-страница с заголовками <h1> и <h2> набраными разными шрифтами
ВЫБОР ШРИФТОВ
defining fonts

font-family - еще одно встроенное CSS-свойство, определяющее шрифт для выбранного элемента. Оно принимает несколько значений, поскольку не у всех пользователей установлены одинаковые шрифты. На скоиншоте браузер сначала пытается загрузить самый левый шрифт (Helvetica), затем переходит к Arial, если у пользователя его нет, и наконец, выбирает шрифт без засечек, встроенный в систему sans serif.

Interneting is hard HTML+CSS
Скриншот 7: Helvetica, переходящая в Arial, переходящая в шрифт без засечек

Исторически сложилось так, что встроенные в систему шрифты ограничивают возможности веб-дизайнеров. Сегодня системные шрифты в значительной степени вытеснены веб-шрифтами. Подробнее об этом можно прочитать в главе Веб-типографика.

стили списка
list styles

Свойство list-style-type позволяет изменять маркет "пульки", используемый для элементов <li>. Как правило, его нужно задавать для родительского элемента <ul> или <ol>:

ul {
list-style-type: circle;
}

ol {
list-style-type: lower-roman;
}

Другие распространенные значения можно найти на hello-css.html. Особо интересно значение none, обычно используемое для разметки навигационного меню с помощью списка <ul>. Значение none позволяет стилизовать элементы списка меню под кнопки. В главе Продвинутое позиционирование мы используем этот прием для создания навигационного меню, показанного ниже.

Interneting is hard HTML+CSS
Скриншот 8: веб-страница с элементами <ul> и <li> без маркеров элементов списка (bullets)

Это хороший пример разделения контента и внешнего вида. Навигационное меню - есть неупорядоченный список, но в данном случае имеет смысл отображать его в виде кнопок, а не в виде обычного маркированного списка. Грамотно разработанный HTML позволяет поисковым системам делать выводы о структуре нашего содержимого, а CSS - красиво отображать его для людей.

Можно даже создавать собственные маркеры списка для элементов <li> с помощью свойства list-style-image (см. соответствующую статью в MDN).

Определение цвета текста и внешнего вида списка может показаться мелочью. И вообщем так оно и есть. Но взгляните на картину в целом: речь идет о получении полного контроля над внешним видом HTML-документа. Отдельное свойство CSS - да, это мелочь. Но соберите все CSS-свойства вместе, и у вас получится уникальная веб-страница.

Таблицы стилей многократного использования
reusable stylesheets

Итак, мы определили несколько основных стилей для одной из наших веб-страниц. Было бы очень удобно, если бы мы могли повторно использовать их и на другой странице. Для этого достаточно добавить тот же элемент <link/> на все остальные страницы, которые мы хотим стилизовать. Добавьте в <head> файла dummy.html следующую строку:

<link rel='stylesheet' href='styles.css'/>

Теперь наши страницы dummy.html должны отвечать стилям hello-css.html. При изменении стиля в styles.css эти изменения будут автоматически отражаться на каждой из наших веб-страниц. Таким образом достигается единый внешний вид и восприятие всего сайта.

Interneting is hard HTML+CSS
Скриншот 9: таблица стилей (global CSS stylesheet), связанная с тремя HTML-файлами

Почти всегда используется хотя бы одна таблица стилей, применяемая ко всему сайту. Подключать таблицы стилей обычно рекомендуется через корневые ссылки. Это поможет избежать проблем на вложенных страницах. Например, в some-folder/page.html для ссылки на наш файл styles.css следует использовать ../styles.css. Но это может быстро привести к путанице.

дополнительные стили текста
more text styles

Данный курс познакомит вас с множеством существующих различных CSS-свойств. А пока что закончим с некоторыми наиболее распространенными способами форматирования текста.

ПОДЧЕРКИВАНИЯ
UNDERLINES

Подчеркивание текста задается свойством text-decoration. Установив значение none, можно убрать стандартное подчеркивание из всех наших ссылок. Подробнее о стилях ссылок мы поговорим позже.

a {
text-decoration: none;
}

Другим распространенным значением для text-decoration является line-through, которое зачеркивает "удаленный" текст. Но помните, что смысл всегда должен передаваться с помощью HTML, а не CSS. Лучше использовать элементы <ins> и <del>, вместо добавления стиля line-through, например, к элементу <p>.

ВЫРАВНИВАНИЕ ТЕКСТА
TEXT ALIGNMENT

Метко названное свойство text-align* определяет выравнивание текста в HTML-элементе.

* - align по-английски: "выравнивать".

p {
text-align: left;
}

Другие допустимые значения: right, center или justify. Обратите внимание, что текст всегда выравнивается по всей странице:

Interneting is hard HTML+CSS
Скриншот 10: веб-страница с текстом, выровненным по правому краю

Но это не совсем то, что нужно для большинства сайтов. Почему? Узнаете на следующем уроке, когда речь пойдет о CSS-блоках.

НАЧЕРТАНИЕ ШРИФТОВ И ИХ СТИЛИ
FONT WEIGHT AND STYLES

Свойство font-weight определяет "жирность" текста в элементе, а свойство font-style указывает, является ли он курсивным или нет.

Давайте предположим, что мы не хотим, чтобы наши заголовки были жирными. Обновим правило шрифта заголовков в styles.css следующим образом:

h1, h2, h3, h4, h5, h6 {
font-family: "Helvetica", "Arial", sans-serif;
font-weight: normal; /* Добавьте эту строку */
}

Эти свойства наглядно демонстрируют разделение содержания (HTML) и внешнего вида (CSS). Следующие правила изменяют внешний вид элементов <em> и <strong>:

/* Пожалуй, не стоит этого делать */
em {
font-weight: bold;
font-style: normal;
}

strong {
font-weight: normal;
font-style: italic;
}

Однако мы не советуем делать это для реальных сайтов. Стили шрифтов это довольно важная тема. Мы углубимся в нее на уроке Веб-типографика.

КАСКАДНОСТЬ
the cascade

В CSS правила "каскадируются" (передаются) из нескольких источников. До сих пор мы видели только одно место, где CSS может быть определен: внешние .css-файлы. Однако внешние таблицы стилей - это лишь одно из многих мест, куда можно поместить CSS-код.

Иерархия CSS для каждой веб-страницы выглядит следующим образом:

Порядок следования - от наименьшего к наибольшему. То есть стили, определенные на каждом последующем шаге, отменяют предыдущие. Так, встроенные стили всегда будут заставлять браузер игнорировать стили по умолчанию. Следующие несколько разделов будут посвящены последним двум вариантам, поскольку именно их мы можем контролировать как веб-разработчики (в дополнение к внешним стилям, с которыми мы уже начали работать).

Interneting is hard HTML+CSS
Скриншот 11: внешняя таблица стилей, указывающая на внутренние стили, указывающие на встроенные стили

Мы постарались помочь вам с самого начала найти верный подход к работе с внешними стилями. Понимание page-specific и inline стилей очень важно, поскольку вы наверняка столкнетесь с ними в дальнейшей работе. Но внешние стили - это, безусловно, лучшее место для настройки внешнего вида вашего сайта.

ВНУТРЕННИЕ СТИЛИ
PAGE-SPECIFIC*

Элемент <style> используется для добавления в отдельные HTML-документы соответствующих страниц CSS-правил. Элемент <style> всегда находится в <head> веб-страницы, что логично, поскольку он представляет метаданные, а не контент как таковой.

* - Page-Specific - "стили для конкретной страницы". Другое название Internal, так. наз. "внутреннее" подключение стилей. В Рунете встречаются также названия "глобальный" или "внедренный" вид подключения.

В качестве примера зададим некоторые стили для нашей страницы dummy.html, изменив ее элемент <head> следующим образом:

<head>
<meta charset='UTF-8'/>
<title>Dummy</title>
<link rel='stylesheet' href='styles.css'/>
<style>
body {
color: #0000FF; /* Синий */
}
</style>
</head>

Итак, эти стили будут применяться только для dummy.html. На hello-css.html они не повлияют. Если вы все сделали правильно, то при загрузке dummy.html в браузере вы текст должен стать синим.

Interneting is hard HTML+CSS
Скриншот 12: синий текст вследствие внутреннего (page-specific / internal) подключения таблицы CSS к конкретной странице

В элемент <style> можно поместить все, что и наш элемент styles.css. Он использует точно такой же синтаксис, что и styles.css, но все внутри <style> будет переопределять правила из styles.css. В нашем случае мы приказываем браузеру игнорировать свойство color, определенное для <body> в styles.css. Новое свойство color: #0000FF; заменяет свойство color из styles.css.

Interneting is hard HTML+CSS
Скриншот 13: три CSS-правила с внутренним (page-specific / internal) подключением в трех различных HTML-документах

Проблема внутренних стилей в том, что их крайне сложно обслуживать. Для применения этих стилей на другой HTML-странице необходимо скопировать и вставить их в раздел <head> HTML-кода другой страницы (см. скриншот выше). Отслеживать излишние CSS-правила в нескольких .html-файлах много сложнее редактирования всего одого файла .css.

Interneting is hard HTML+CSS
Скриншот 14: три веб-страницы, относящихся к одной глобальной таблице стилей CSS

Внутренние стили иногда имеют смысл для быстрых изменений внешнего вида конкретной страницы. И все-же мы не рекомендуем помещать CSS код внутрь элемента <style>. Вместо этого, много лучше подключать внешнюю таблицу стилей styles.css.

ВСТРОЕННЫЕ СТИЛИ
INLINE STYLES

Правила CSS можно также поместить в атрибут style HTML-элемента. В файле dummy.html у нас есть ссылка, которая никуда не ведет. Давайте сделаем ее красной с помощью встроенного стиля, чтобы мы помнили, что это неработающая ссылка:

<p>Want to try crossing out an <a href='nowhere.html'
style='color: #990000; text-decoration: line-through;'>obsolete link</a>?
This is your chance!</p>

Как и в случае с внутренними стилями, используется тот же синтаксис CSS, с которым мы уже работали. Однако, поскольку он находится в атрибуте, его необходимо сжать до одной строки. Встроенные стили - это самое конкретное определение CSS. Определенные при этом свойства color и text-decoration имеют наивысший приоритет. Даже добавив в элемент <style> некое правило типа text-decoration: none, это не даст никакого эффекта.

Interneting is hard HTML+CSS
Скриншот 15: 10 правил CSS, подключенных напрямую к 10 различным HTML-элементам с помощью встроенных стилей

Избегайте внутренние стили любой ценой. Одна из причин - их вышеупомянутый приоритет. Изменить стиль страницы из внешнего CSS файла будет невозможно. Если вы захотите изменить стиль своего сайта, будет недостаточно просто изменить несколько правил в файле styles.css. Придется исправлять и обновлять каждый элемент HTML, имеющий атрибут style. Это приводит в ужас.

Впрочем, иногда необходимо применить стили только к конкретному элементу HTML. Для этого всегда следует использовать классы CSS, а не встроенные стили. Классы мы рассмотрим на уроке Селекторы CSS.

НЕСКОЛЬКО ТАБЛИЦ СТИЛЕЙ
multiple stylesheets

Правила CSS можно распределять по нескольким внешним таблицам стилей, просто добавляя несколько элементов <link/> на одну и ту же страницу. Часто используется разделение стилей для различных разделов сайта. Это позволяет выборочно применять согласованные стили к различным категориям веб-страниц.

Представим, что у нас есть куча страниц с товарами, выглядящими иначе, чем страница блога. Тогда мы могли бы использовать следующий код (но на самом деле эти таблицы стилей у нас не определены, поэтому не добавляйте их в наш пример):

<!-- (Все сайты с продуктами имеют такой код) -->
<head>
<link rel='stylesheet' href='styles.css'/>
<link rel='stylesheet' href='product.css'/>
</head>

<!-- (Все статьи блога имеют такой код) -->
<head>
<link rel='stylesheet' href='styles.css'/>
<link rel='stylesheet' href='blog.css'/>
</head>

Порядок следования элементов <link/> имеет особое значение. Таблицы стилей, созданные позднее, будут переопределять, то есть преобладать над стилями, созданными ранее. Обычно "базовые" стили или стили "по умолчанию" (default) помещаются в одну таблицу стилей (styles.css) и дополняются таблицами стилей для конкретных разделов (напр. product.css и blog.css). Это позволяет организовать CSS-правила в управляемых файлах, избегая опасностей, связанных со спецификой страниц и встроенными стилями.

РЕЗЮМЕ

На этом уроке мы много говорили о разделении содержания и внешнего вида. Это позволяет использовать одну таблицу стилей CSS в нескольких HTML-документах, а также применять различные правила CSS к одинаковому HTML-контенту для смартфонов, планшетов и ноутбуков/ПК. Эта технология называется Адаптивный дизайн.

Interneting is hard HTML+CSS
Скриншот 16: единый HTML-файл с отдельными CSS-стилями для мобильных и настольных компьютеров

Будучи веб-разработчиком, для работы вы получите уже готовый дизайн. Ваша задача - используя знания CSS, превратить его в реальную веб-страницу. Как говорилось ранее, настройка отдельных свойств CSS на самом деле довольно проста. Самое сложное - объединить огромное число встроенных свойств и создать именно то, что ожидает веб-дизайнер, и сделать это быстро.

На этом уроке речь шла в основном о форматировании текста, но язык каскадных таблиц стилей способен на гораздо большее. На следующем уроке мы начнем изучать, как CSS определяет верстку веб-страниц. Напоминаем, что при возникновении вопросов о том, как работает то или иное свойство, всегда можно обратиться к Руководству по CSS от MDN.


HTML & CSS IS HARD - НА РУССКОМ

БЛОКОВАЯ МОДЕЛЬ В CSS

УРОК Nº 5.

Просто и понятно про рамки и отступы (padding, borders, margins)


На предыдущем уроке были представлены основные свойства CSS для форматирования текста, но это был лишь один из аспектов стилизации страниц. Определение разметки веб-страницы - это совершенно другое дело. Именно этому и посвящен данный урок.

"Блоковая модель CSS" это набор правил, определяющих отображение в Интернете любой веб-страницы. CSS рассматривает каждый элемент HTML-документа как "блок" [или "бокс"] с кучей различных свойств, определяющих его местоположение на странице. До сих пор все наши веб-страницы были просто набором элементов. Блоковая модель - это набор инструментов для настройки стандартной схемы расположения элементов.

Interneting is hard HTML+CSS
Скриншот 1: таблица стилей CSS, разбитая на две части (форматирование текста и блоковая модель)

Значительная часть работы веб-разработчика - это превращения дизайнерского эскиза в веб-страницу посредством блоковой модели CSS. Возникнает вопрос - а зачем изучать все эти правила вместо того, чтобы просто загрузить одно большое статичное изображение веб-страницы? Загрузил эскиз-картинку на веб-сервер и все. Разве этого недостаточно?

Да, это значительно упростило бы жизнь. Однако, если не разделять контент на HTML, поисковики не смогут определить структуру наших веб-страниц, не будет возможности сделать наш сайт адаптивным и добавить шикарную анимацию или интерактивность с помощью JavaScript. Цена этого компромисса слишком высока, чтобы игнорировать использование CSS.

Ниже мы рассмотрим основные компоненты блоковой модели: paddings, margins, рамки, inline- и блоковые блоки. Можно считать, что это "микро" CSS-макеты, ибо эта модель определяет специфику поведения блоков. На следующих уроках вы больше узнаете о том, как структура HTML и блоковая модель объединяются для создания сложных CSS-версток.

подготовка
setup

Для начала создайте новую папку css-box-model. Поместите туда новую веб-страницу boxes.html. Напишите следующий код:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Boxes Are Easy!</title>
<link rel='stylesheet' href='box-styles.css'/>
</head>
<body>
<h1>Headings Are Block Elements</h1>

<p>Paragraphs are blocks, too. <em>However</em>, &lt;em&gt; and &lt;strong&gt;
elements are not. They are <strong>inline</strong> elements.</p>

<p>Block elements define the flow of the HTML document, while inline elements
do not.</p>
</body>
</html>

Вы помните из урока Hello, CSS как HTML-файл ссылается на таблицу стилей CSS? В данном случае это файл будет box-styles.css. Создайте и этот файл для данного урока (пока что его можно оставить пустым).

Надеемся, что вы уже освоились с особенностями работы в редакторе Atom для создания файлов и папок. Если нет, то обязательно просмотрите инструкцию по использованию редактора Atom на вводном уроке этого учебника.

блоковые и строчные элементы
block elements and inline elements

В разделе Что нужно знать о веб-страницах мы вкратце рассказали, как CSS использует "блоки" для разметки веб-страницы. Каждый отображаемый элемент HTML это блок. Они бывают двух видов: "блоковые*" и "строчные (inline)".

* - "блоковый блок" (block box) звучит немного неуклюже. И все же я сознательно не употребляю другой перевод слова box - "бокс". Потому что на ресурсе, на который ссылается Oliver James, автор данного учебника - Mozilla Developers Network (MDN), box переводится как "блок". Interneting is hard HTML+CSS

Скриншот 2: сравнение элементов: блоковый [block box] и строчные [inline boxes]

Все элементы HTML, с которыми мы работали, по умолчанию имеют определенный тип блока. Например, <h1> и <p> - это элементы блокового уровня, а <em> и <strong> - inline-элементы. Давайте улучшим внешний вид наших блоков, добавив в box-styles.css следующий код:

h1, p {
background-color: #DDE0E3; /* светло-серый */
}

em, strong {
background-color: #B2D6FF; /* светло-голубой */
}

Свойство background-color заполняет только фон выбранного блока. Это даст нам четкое представление о структуре нашей страницы-примера. Наши заголовки и абзацы должны иметь светло-серый фон, а акцентирующие [italic] и сильные [strong] элементы - голубой.

Interneting is hard HTML+CSS
Скриншот 3: веб-страница, где блоковые блоки - серые, а строчные - голубые.

Это демонстрирует нам несколько очень важных особенностей поведения, присущего блоковым и строчным блокам:

изменяем поведение блоков
changing box behavior

Мы можем переопределить установленный по умолчанию тип box элементов HTML с помощью CSS-свойства display. К примеру, вам вдруг захотелось строчные элементы <em> и <strong> превратить в блоковые. Для этого необходимо обновить наше правило в box-styles.css таким образом:

em, strong {
background-color: #B2D6FF;
display: block;
}

Теперь эти элементы действуют как наши заголовки и абзацы: они начинаются с отдельной строки и заполняют всю ширину браузера. Это очень удобно, когда мы хотим сделать элементы <a> кнопками или отформатировать элементы <img/> (оба эти элемента по умолчанию inline-блоки).

Interneting is hard HTML+CSS
Скриншот 4: вот что происходит, когда с помощью CSS-свойства display мы из inline-блоков делаем блоковые блоки

Однако делать <em> и <strong> блоковыми элементами - плохая идея. Поэтому давайте превратим их обратно в inline-блоки. Для этого поменяем их свойство display на inline, как показано ниже:

em, strong {
background-color: #B2D6FF;
display: inline; /* em и strong строчные (inline) по умолчанию */
}

контент, padding, рамка, margin
content, padding, border, and margin

Блоковая модель CSS - это набор правил, определяющих размеры каждого элемента веб-страницы. Для каждого блока (как inline-, так и блокового), данная модель предусматривает четыре свойства:

Все это необходимо браузеру для отображения блока какого-либо элемента. Контент есть "содержимое" HTML-документа. Из этих четырех свойств только контент несет cемантическую ценность (именно поэтому контент находится в HTML). Остальные три свойства отвечают за внешний вид, то есть за презентацию контента. Поэтому все три определяются правилами CSS.

* - понятия внешнего и внутреннего отступов из-за схожести легко может привести к путанице. Поэтому я решил оставить исходные англ. названия: padding и margin. По этой же причине, для лучшей наглядности, "содержимое" зачастую заменяется словом "контент".

Interneting is hard HTML+CSS
Скриншот 5: блоковая модель CSS: содержимое (content), внутренний отступ (padding), рамка (border) и внешний отступ (margin)
внутренний отступ
padding

Давайте начнем изнутри. Мы уже рассматривали контент, теперь на очереди padding. Свойство padding... вы уже наверно догадались... определяет отступ для выбранного элемента:

h1 {
padding: 50px;
}

Это добавляет по 50 пикселей с каждой стороны заголовка <h1>. Обратите внимание (скриншот ниже), как расширяется цвет фона, заполняя это пространство. Так всегда происходит с padding, поскольку он находится внутри рамки, а все, что находится внутри рамки, имеет фон.

Interneting is hard HTML+CSS
Скриншот 6: увеличение отступов в <h1> (размер фона увеличился)

Иногда требуется стилизовать только одну сторону элемента. Для этого в CSS предусмотрены следующие свойства:

p {
padding-top: 20px;
padding-bottom: 20px;
padding-left: 10px;
padding-right: 10px;
}

Для изменения padding можно использовать любые единицы измерения (не только пиксели!). Помните единицы em? Они особенно удобны тем, что делают margin ваших элементов изменяющимся вместе с изменением размера основного шрифта.

СОКРАЩЕННЫЕ ФОРМАТЫ
shorthand formats

Вводить все эти свойства может быть утомительно, поэтому CSS предусматривает альтернативную "сокращенную" форму свойства padding. Вы сможете задать верхний/нижний и левый/правый padding всего одной строкой CSS. Когда вы указываете два значения свойства padding, они интерпретируются как значения вертикального и горизонтального padding соответственно.

Interneting is hard HTML+CSS
Скриншот 7: свойство "внутренний отступ" (padding) с выделенными вертикальными и горизонтальными значениями

Это означает, что наше предыдущее правило может быть переписано так:

h1 {
padding: 20px 10px; /* вертикально горизонтально */
}

Альтернативный вариант: четыре значения устанавливают padding для каждой стороны элемента по отдельности. Значения идут по часовой стрелке, начиная с верхнего:

Interneting is hard HTML+CSS
Скриншот 8: cвойство padding с разноцветными значениями верх, справа, низ и слева

Давайте попробуем удалить 10px правого padding из предыдущего правила. Получится по 20 пикселей сверху и снизу каждого абзаца, 10 пикселей слева и ни одного справа:

h1 {
padding: 20px 0 20px 10px; /* сверху,справа, снизу и слева */
}

Использовать сокращенные форматы или нет - в значительной степени вопрос личных предпочтений и стандартов работы в будущей команде. Некоторым разработчикам импонирует лаконичность сокращенного формата. А другие считают, что длинную форму легче понять с первого взгляда (и следовательно, легче обслуживать). В какой-то момент своей карьеры веб-разработчика вы столкнетесь со всеми этими форматами.

рамки
borders

Продолжая наше путешествие от центра блоковой модели CSS, мы видим рамку: линию, проведенную вокруг контента и padding элемента. Свойство рамки требует нового синтаксиса, который нам еще не знаком. Сначала мы определим ширину обводки рамки, затем ее стиль, а затем ее цвет.

Interneting is hard HTML+CSS
Скриншот 9: свойство "рамка" (border), показывающее синтаксис размера, стиля и цвета

Попробуйте добавить рамку вокруг нашего заголовка <h1>, изменив правило в файле box-styles.css:

h1 {
padding: 50px;
border: 1px solid #5D6063;
}

Это команда браузеру нарисовать тонкую серую линию вокруг нашего заголовка. Посмотрите как рамка вплотную примыкает к padding, не оставляя никакого зазора. А если уменьшить размеры браузера так, что заголовок будет разделен на две строки, то padding и рамка все равно останутся на своих местах.

Если нарисовать рамку вокруг всего заголовка, то он будет выглядеть как вебсайт из 1990-х. Так что мы ограничимся только нижней частью заголовка. Как и для свойства padding, так и для border существуют четыре свойства: -top, -bottom, -left и -right.

border-bottom: 1px solid #5D6063;

Рамки являются обычными элементами дизайна, но они также неоценимы для отладки. Когда Вы не уверены в том, как отображается блок, задайте следуещее правило: border: 1px solid red; Это отчетливо покажет padding, margin и общие размеры блока с помощью всего одной строки CSS. После того, как Вы выяснили причину сбоя, просто удалите это правило.

Дополнительную информацию о стилях оформления рамок вы найдете на сайте Mozilla Developer Network.

внешние отступы
margins

Margins определяют пространство за рамкой элемента. Или, точнее, пространство между блоком и окружающими его блоками. Давайте добавим немного свободного пространства к нижней части каждого элемента <p>:

p {
padding: 20px 0 20px 10px;
margin-bottom: 50px; /* добавьте это */
}

Это демонстрирует специфический для боковых сторон вариант свойства margin, и это свойство допускает те же сокращенные форматы, что и padding.

Свойства margin и padding могут выполнять одну и ту же задачу во многих ситуациях, что затрудняет определение того, какой из них является "правильным" выбором. Наиболее характерными причины для выбора:

Если ни один из этих пунктов не помог вам принять решение в пользу padding или margin, то не заморачивайтесь по этому поводу - просто выберите один из них. В CSS обычно существует несколько способов решения проблемы.

MARGINS И СТРОЧНЫЕ ЭЛЕМЕНТЫ
margins on inline elements

Одним из самых заметных отличий между блоковыми и inline-элементами - их поведение по отношению к margin. Inline-блоки полностью игнорируют верхний и нижний margin элемента. Для примера добавим достаточно большой margin к нашему элементу <strong>. Посмотрите, что произойдет.

strong {
margin: 50px;
}

Горизонтальные margin-отступы отображаются так, как ожидалось, но при этом вертикальное пространство вокруг нашего <strong> ничуть не изменилось.

Interneting is hard HTML+CSS
Скриншот 10: демонстрация отсутствия вертикального пространства у inline-блоков

Если мы изменим margin на padding, то обнаружим совсем другое поведение у padding в блоке. Пространство вокруг блока расширилось, однако вертикальное отображение окружающих блоков не изменилось.

Interneting is hard HTML+CSS
Скриншот 11: демонстрация вертикального padding на inline-блоках

Дело в том, что inline-блоки форматируют фрагменты текста внутри блока и, таким образом, оказывают ограниченное влияние на отображение страницы. Если хотите поэкспериментировать с вертикальным пространством страницы, вам следует использовать элементы блокового уровня (к счастью, мы уже знаем, как изменить тип блока элемента).

Итак, прежде чем биться головой о стену, пытаясь понять, почему не работает верхний или нижний margin, вспомните о проверке свойства display. Поверьте, рано или поздно это произойдет.

вертикальное схлопывание
vertical margin collapse

Еще одной странностью блоковой модели CSS является "вертикальное схлопывание margin". Когда два блока с вертикальными margin расположенны друг над другом, они схлопываются. Казалось бы оба margin должны добавляться друг к другу. Однако отображается только самый большой из них.

Давайте для наглядности добавим к нашему элементу <p> верхний margin в 25 пикселей.

p {
padding: 20px 0 20px 10px;

margin-top: 25px;
margin-bottom: 50px;
}

Каждый абзац получит по 50 пикселей снизу и 25 сверху. Вместе получается 75 пикселей между нашими элементами <p>, верно? Неверно! Между ними по-прежнему будет только 50px, потому что меньшее верхнее поле схлопывается в большее нижнее.

Interneting is hard HTML+CSS
Скриншот 12: cлева: вертикальное поле без схлопывания [uncollapsed], справа: схлопывающееся вертикальное поле [collapsed]

Такое поведение очень полезно при работе с множеством различных типов элементов когда вы хотите определить их минимальное пространство между другими элементами.

предотврашение схлопывания
preventing margin collapse

Эффект схлопывания полей может быть и очень досадным. Все таки иногда хотелось бы не допускать этого. Все, что нужно сделать, это поместить между ними еще один невидимый элемент:

<p>Paragraphs are blocks, too. <em>However</em>, &lt;em&gt; and &lt;strong&gt;
elements are not. They are <strong>inline</strong> elements.</p>

<div style='padding-top: 1px'><div> /* добавьте это */

<p>Block elements define the flow of the HTML document, while inline elements
do not.</p>

Подробнее о <div> поговорим в следующей секции. Самое важное здесь то, что только следующие друг за другом элементы могут схлопываться друг в дружку. Помещение элемента с ненулевой высотой (padding-top) между абзацами заставляет их отображать оба поля - и верхнее в 25px, и нижнее в 50px.

Interneting is hard HTML+CSS
Скриншот 13: добавление пустого <div> не дает вертикальному полю схлопываться

Помните, что padding никогда не схлопывается. Поэтому в виде альтернативы можно использовать padding вместо margin. Однако это срабатывает только, если не использовать padding ни для чего другого (а в данный момент мы используем, поэтому остановимся на варианте с <div>).

Третий вариант избежать схлопывания - соблюдение правила для margin "только снизу или только сверху*". Например, если все наши элементы определяют только bottom-margin, они не будут схлопываться.

И наконец, в схеме компоновки flexbox margin не схлопывается, так что для современных сайтов это вообще не проблема.

* - bottom-only or top-only margin convention.

универсальные блоки
generic boxes

До сих пор все рассмотренные HTML-элементы придавали дополнительный смысл их контенту. В этом и заключается смысл HTML, но все же иногда нужен некий универсальный блок только для стилизации веб-страницы. Для этого и предназначены <div> и <span>.

И <div>, и <span> являются "контейнерными" элементами, не оказывающими никакого влияния на семантическую структуру HTML-документа. Однако они позволяют добавлять CSS-стили к любым местам веб-страницы. Например, иногда нужно предотвратить добавить margin-схлопывание невидимой рамкой или сгруппировать первые абзацы статьи в краткий обзор с иным форматированием.

На протяжении всего курса мы будем часто использовать <div>. А пока давайте создадим простую кнопку, добавив в нижнюю часть нашего файла boxes.html следующее:

<div>Button</div>

А в файл box-styles.css добавьте стили для нашей кнопочки. Большинство из них должны быть знакомы по предыдущей главе, за исключением нового свойства border-radius:

div {
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063;
border-radius: 5px;
}

В результате мы получим большую синюю кнопку, занимающую всю ширину браузера:

Interneting is hard HTML+CSS
Скриншот 14: элементы <div> используемые для кнопки

Эти стили применяются и к невидимому <div>, которым мы отменили margin-схлопывание (см. выше). Очевидно, что для практической пользы от отдельных <div> необходимо их как-то выделить. Для этого и нужны селекторы классов (см. следующ. урок). А пока что просто удалим или закомментируем этот невидимый <div>.

Единственная реальная разница между <div> и <span> заключается в том, что <div> предназначен для блоков, а <span> - для строк.

явно выраженные размеры
explicit dimensions

До сих пор мы позволяли нашим HTML-элементам определять свои размеры автоматически. Paddings, margins, рамки, с которыми мы экспериментировали, обхватывают все внутри блока элемента. Если добавить в наш <em> больше текста, то все будет расширяться, чтобы вместить его:

Interneting is hard HTML+CSS
Скриншот 15: элемент <em> расширяется при добавлении контента

Но иногда в макете требуется явно выраженный размер, например, боковая панель шириной ровно 250 пикселей. Для этого в CSS предусмотрены свойства width и height. Они имеют приоритет над размером содержимого блока по умолчанию.

Давайте придадим нашей кнопке фиксированную ширину, добавив в box-styles.css следующее свойство:

div {
/* уже заданные декларации */
width: 200px;
}

Вместо ширины во все окно браузера, ширина кнопки стала 200px и она прилегает к левой стороне страницы:

Interneting is hard HTML+CSS
Скриншот 16: демонстрания явного CSS-свойства width для кнопки

Также заметьте, что сделав заголовок кнопки длиннее, он автоматически перейдет на следующую строку, а элемент увеличится по вертикали, чтобы вместить этот новый контент. Это стандартное поведение можно изменить свойствами white-space и overflow.

блоки контента и блоки рамки
content boxes and border boxes

Свойства width и height в блоке определяют только размер контента. Padding и рамка добавляются поверх заданных вами размеров. Это объясняет, почему на скриншоте нашей кнопки вы получите изображение шириной 244 пикселя, несмотря на то, что заявленная ширина width: 200px.

Interneting is hard HTML+CSS
Скриншот 17: размеры блока контента, добавляющие padding и рамку к ширине элемента

Само собой разумеется, это может быть несколько противоречивым, когда вы пытаетесь разметить страницу. Представьте, что вы пытаетесь заполнить контейнер размером 600px тремя блоками шириной: 200px, но они не помещаются, поскольку все они имеют рамку в 1px (что делает их фактическую ширину 202px).

К счастью, CSS позволяет изменить способ расчета ширины блока с помощью свойства box-sizing. По умолчанию оно имеет значение content-box, что приводит к описанному выше поведению. Посмотрим, что произойдет, если мы изменим его значение на border-box:

div {
color: #FFF;
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063;
border-radius: 5px;

width: 200px;
box-sizing: border-box; /* добавьте это */
}

В результате фактическая ширина блока будет равна 200px - с учетом padding и рамки. Разумеется, ширина контента теперь определяется автоматически:

Interneting is hard HTML+CSS
Скриншот 18: размеры border-box с учетом padding и рамки в сочетании с шириной элемента

Это гораздо более интуитивно понятно, поэтому border-box для всех блоков веб-разработчики сегодня считают оптимальным решением.

выравнивание блоков
aligning boxes

Выравнивание блоков по горизонтали - распространенная задача для веб-разработчиков, и блоковая модель предлагает множество способов ее решения. Мы уже рассмотрели свойство text-align, которое выравнивает контент и строчные блоки внутри элемента блокового уровня. Выравнивание блоковых блоков - это совсем другая история.

Попробуйте добавить в нашу таблицу стилей следующее правило. Оно будет выравнивать только контент внутри блоковых блоков, но не сами блоки. Наша кнопка <div> все равно будет выровнена по левому краю, независимо от выравнивания текста в <body>:

body {
text-align: center;
}

Существует три метода горизонтального выравнивания элементов на уровне блоков: центрирование auto-margins, floats для выравнивания по левому/правому краю и flexbox для полного контроля над выравниванием. Да, к сожалению, выравнивание на уровне блоков совершенно не связано со свойством text-align.

ЦЕНТРИРОВАНИЕ С ПОМОЩЬЮ АВТО-ОТСТУПОВ
centering with auto-margins

Floats и flexbox - это сложные темы, которым мы посвятили отдельные главы-уроки. Зато сейчас у нас есть все необходимые знания для работы с auto-margins. Устанавливая для левого и правого полей элемента блокового уровня значение auto, мы получаем центрирование блока в его родительском элементе.

Например, мы можем отцентрировать нашу кнопку следующим образом:

div {
color: #FFF;
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;

width: 200px;
box-sizing: border-box;
margin: 20px auto; /* вертикально горизонтально */
}

Обратите внимание, что это работает только с блоками, для которых явно задана ширина. Уберите строку width: 200px, и наша кнопка будет занимать всю ширину браузера, что сделает "центрирование" бессмысленным.

сброс стилей
resetting styles

Заметили белую каемку вокруг нашей страницы (см. скриншот ниже)? Это marging, padding и поля, добавленные браузером по умолчанию. Различные браузеры имеют разные стандартные стили для всех HTML-элементов, что затрудняет создание одинаковых таблиц стилей.

Interneting is hard HTML+CSS
Скриншот 19: слева веб-страница с стандартной белой каемкой из-за margin и padding. Справа веб-страница без белой каемки после сброса настроек (with reset)

В большинстве случаев полезно переопределить стили по умолчанию на предсказуемое значение с помощью "универсального" CSS-селектора (*). Попробуйте добавить его в верхнюю часть нашего файла box-styles.css:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

Этот селектор соответствует каждому элементу HTML, эффективно сбрасывая свойства margin и padding на нашей веб-странице. Все наши блоки также были преобразованы в border-box, что, опять же, является налучшей практикой.

Подобный сброс можно найти в верхней части почти каждой таблицы стилей CSS в Интернете. Все может оказаться гораздо сложнее, но три простых декларации, показанные выше, позволяют нам уверенно настраивать блоковую модель CSS для своих целей, не опасаясь непредвиденных взаимодействий со стилями браузера по умолчанию.

резюме

Более подробно о практическом использовании блоковой модели CSS мы узнаем по мере углубления в создание сложных веб-страниц. Пока же воспринимайте ее как новый инструмент в вашем арсенале CSS. Ознакомившись с несколькими ключевыми понятиями из этой главы, вы ощутите себя гораздо более подготовленным к преобразованию дизайнерского эскиза в реальную веб-страницу:

Как и на прошлом уроке, только что рассмотренные CSS-свойства могут показаться простыми - так оно и есть. Но стоит взглянуть на посещаемые сайты через призму блоковой модели, - и вы увидите эти свойства буквально повсюду.

Наше изучение универсальных блоков (<div> и <span>) было несколько ограниченным, поскольку у нас не было возможности извлечь отдельный HTML-элемент из нашей веб-страницы. Мы исправим это на следующем уроке, где более подробно рассмотрим селекторы CSS.


HTML & CSS IS HARD - НА РУССКОМ

СЕЛЕКТОРЫ CSS

УРОК Nº 6.

Самый понятный учебник веб-разработки о выборке HTML-элементов

Еще в главе Ссылки и картинки мы узнали, как связать HTML-документ с другими файлами нашего проекта. CSS-селекторы работают аналогично, только вместо навигации по целым файлам они позволяют привязать одно CSS-правило к конкретному HTML-элементу. Это позволяет выборочно стилизовать отдельные элементы, игнорируя другие.

Interneting is hard HTML+CSS
Скриншот 1: CSS-селектор, связывающий CSS-правило с HTML-элементом

Если вы не хотите, чтобы все секции вашего сайта выглядели одинаково, к вашим услугам очень полезная функциональная особенность. С ее помощью мы можем сказать: "Я хочу, чтобы этот абзац был синим, а тот - желтым". До сих пор мы могли сделать все абзацы только синими (или желтыми).

До сих пор мы использовали только один CSS-селектор, так наз. "селектор типа" [type selector]. Он определяет все соответствующие элементы на странице. На этом уроке мы рассмотрим более детальные способы стилизации веб-страниц с помощью селекторов классов, потомков, псевдоклассов и идентификаторов.

подготовка
setup

Для нашего примера к этому уроку нам понадобится только один HTML-файл и таблица стилей CSS. Создайте новую папку css-selectors и новую веб-страницу selectors.html со следующей разметкой:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>CSS Selectors</title>
<link rel='stylesheet' href='styles.css'/>
</head>
<body>
<h1>CSS Selectors</h1>

<p>CSS selectors let you <em>select</em>, individual HTML elements in an HTML
document. This is <strong>super</strong> useful.</p>

<p>Classes are ridiculously important, since they allow you to select
arbitrary boxes in your web pages.</p>

<p>We’ll also be talking about links in this example, so here’s
<a href='https://internetingishard.com'>Interneting Is Hard</a> for us to
style.</p>

<div>Button One</div>

</body>
</html>

Создайте в той же папке таблицу стилей styles.css. Тогда у нас будет все необходимое для изучения селекторов CSS.

Если вы только что начали изучать эту серию уроков, обязательно прочтите введение, чтобы освоиться с редактором Atom.

селекторы классов
Class Selectors

"Селекторы классов" позволяют применять стили CSS к определенному элементу HTML. Они позволяют различать HTML-элементы одного типа, как, например, в предыдущей главе, когда у нас было два элемента <div>, но мы хотели придать стиль только одному из них. Для использования селекторов классов необходимы две вещи:

Interneting is hard HTML+CSS
Скриншот 2: селектор класса CSS, связывающий правило CSS с атрибутом class HTML-элемента

Мы можем использовать селектор класса для того, чтобы стилизовать первый абзац нашего примера страницы иначе, чем остальные. Это может быть, например, синопсис [краткий обзор содержания] газетной статьи. Сначала добавим атрибут class к нужному абзацу:

<p class='synopsis'>CSS selectors let you <em>select</em>, individual HTML
elements in an HTML document. This is <strong>super</strong> useful. </p>

Теперь мы можем выбрать этот элемент <p class='synopsis'> в нашем CSS с помощью следующего правила (добавьте его в файл styles.css):

.synopsis {
color: #7E8184; /* светло-серый */
font-style: italic;
}

Это правило применяется только к элементам с соответствующим атрибутом class. Обратите внимание на точку (.) в префиксе имени класса. Это отличает селекторы классов от селекторов типов, с которыми мы работали до этого урока.

Interneting is hard HTML+CSS
Скриншот 3: выделенный курсивом элемент <p>, стилизованный с помощью селектора класса
СТАНДАРТЫ НАИМЕНОВАНИЯ КЛАССОВ
Class Naming Conventions

Значение атрибута HTML class может быть (почти) любым, если оно соответствует селектору в ваших CSS. Стандартный порядок именования классов - все строчные буквы и дефисы для пробелов, как в именах файлов и папок.

Добавление атрибута class не меняет семантического смысла HTML-документа - он служит исключительно для подключения к таблице стилей CSS. Тем не менее, обычно рекомендуется избегать именования классов по их внешнему виду. Если мы назовем наш класс .italic, то в CSS мы не сможем сделать ничего, кроме как сделать его курсивным, что приведет к запутанной ситуации. Использование смыслового имени, например .synopsis, дает нам больше свободы в CSS для настройки отображения синопсиса.

полезные возможности div
More Useful Divs

Атрибут class не ограничивается элементами <p> - он может быть определен для любого HTML-элемента. Вооружившись новоприобретенными селекторами классов CSS, мы получаем гораздо больше возможностей применения универсальных контейнеров <div> и <span> из предыдущего урока. Мы можем использовать их для стилизации как отдельных элементов, так и любых секций нашей веб-страницы.

Interneting is hard HTML+CSS
Скриншот 4: веб-страница, на которой выделен элемент <div> в виде кнопки, стилизованный с помощью селектора класса

Начнем с отдельных элементов, воссоздав нашу кнопку из предыдущей главы. На этот раз вместо селектора div мы используем класс. Добавьте в файл styles.css следующее:

.button {
color: #FFF;
background-color: #5995DA; /* синий */
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063; /* темно-серый */
border-radius: 5px;

width: 200px;
margin: 20px auto;
}

Разумеется, для этого нам необходим соответствующий атрибут class. Измените <div> в файле selectors.html следующим образом:

<div class='button'>Button One</div>.

В отличие от предыдущего урока, в котором стилизовались все элементы <div>, на этом уроке мы можем использовать их не только для кнопок.

div-контейнеры
Container Divs

Помните, что <div> не изменяет смысловую структуру веб-страницы. Это делает его отличным инструментом для структуры внешнего вида страницы. Обернув другие HTML-элементы в теги <div>, мы можем разделить наш сайт на крупные сегменты, ориентированные на верстку, не испортив при этом восприятия поисковиками нашего контента.

Interneting is hard HTML+CSS
Скриншот 5: люди видят элемент <div> с отступами (margins), веб-роботы его не видят

В качестве примера создадим макет фиксированной ширины с использованием техники auto-margin, которую мы изучали в предыдущей главе. Сначала упакуем весь наш документ в общий <div> и присвоим ему cвой собственный класс:

<body>
<div class='page'> <!-- добавьте это -->
<h1>CSS Selectors</h1>

<p class='synopsis'>CSS selectors let you <em>select</em>, individual HTML elements in an HTML
document. This is <strong>super</strong> useful.</p>

<p>Classes are ridiculously important, since they allow you to select
arbitrary boxes in your web pages.</p>

<p>We’ll also be talking about links in this example, so here’s
<a href='https://internetingishard.com'>Interneting Is Hard<a> for us to
style.</p>

<div class='button'>Button One</div>
</div> <!-- и это добавьте -->
</body>

Затем в styles.css добавим вот такой код:

.page {
width: 600px;
margin: 0 auto;
}

Как бы вы ни изменяли размеры окна браузера, наша веб-страница всегда будет иметь ширину 600 пикселей и центрироваться в доступном пространстве. Обратите внимание, что точно таким же образом мы центрировали нашу кнопку, но теперь мы делаем это для нескольких элементов одновременно, вложив их в общий контейнер.

Interneting is hard HTML+CSS
Скриншот 6: обертывание всего документа веб-страницы посредством <div> с классом .page

Именно так задаются макеты в более сложных веб-страницах. Например, если бы на нашей странице была боковая панель, мы бы вложили все элементы боковой панели в другой <div> с классом .sidebar. Мы увидим это в действии на следующем уроке. Пока же важно понять, что без селекторов классов, позволяющих отделять элементы <div>, ничего этого сделать было бы невозможно.

многократное использование стилей классов
Reusing Class Styles

Один и тот же класс можно применять к нескольким элементам в одном HTML-документе. Это означает, что теперь мы можем повторно использовать любые CSS-декларации в любом месте. Чтобы создать еще одну кнопку, достаточно добавить еще один HTML-элемент с тем же классом:

<div class='button'>Button One</div>
<div class='button'>Button Two</div>

Таким образом, мы получаем вторую кнопку, которая выглядит так же, как и первая, без написания даже одной строки CSS! Подобная организация схожих графических элементов в многократно используемые правила CSS значительно облегчает жизнь веб-разработчика. Если мы захотим, например, изменить цвет кнопки, нам нужно будет сделать это только в одном месте, и все наши кнопки автоматически обновятся.

Interneting is hard HTML+CSS
Скриншот 7: две стрелки, идущие от одного правила CSS к двум разным элементам HTML
Изменение стилей классов
Modifying Class Styles

А что если мы захотим немного изменить нашу вторую кнопку? К счастью, мы можем применить несколько классов к одному и тому же HTML-элементу. Стили каждого класса будут применены к элементу, позволяя нам:
а) повторно использовать стили из .button и
б) переопределить некоторые из стилей в новом классе.

Interneting is hard HTML+CSS
Скриншот 8: две стрелки, идущие от двух CSS-правил к одному HTML-элементу

Добавим к нашей второй кнопке еще один класс call-to-action. Обратите внимание, что оба класса находятся в одном атрибуте class, разделенные пробелом:

<div class='button call-to-action'>Button Two</div>

Теперь у этого элемента есть два отдельных класса, и мы можем использовать любой из них для его стилизации. Это открывает некоторые возможности. Стили, общие для обеих кнопок, могут находиться в классе .button (как это уже сделано), а стили, специфичные для второй кнопки, - в классе .call-to-action (не забудьте добавить его после правила .button):

.call-to-action {
font-style: italic;
background-color: #EEB75A; /* желтый */
}

ОЧЕРЕДНОСТЬ ИМЕЕТ ЗНАЧЕНИЕ
Order Matters

Теперь в нашей второй кнопке происходит несколько важных вещей:

Переопределение [overriding] происходит из-за порядка следования .call-to-action и .button в нашей таблице стилей. Когда в CSS-файле присутствуют два конфликтующих свойства, всегда применяется последнее. Так, если переместить .call-to-action в верхнюю часть styles.css, то последнее слово в значении background-color будет за .button, и фон останется синим.

Отсюда следует, что порядок следования атрибутов class в нашем HTML-элементе не влияет на поведение переопределения. Несколько классов к одному элементу применяются "одинаково" (за неимением лучшего термина), поэтому старшинство определяется исключительно порядком следования правил в styles.css. Другими словами, следующие элементы фактически эквивалентны:

<!-- В результате, страница будет отображаться без изменений -->
<div class='button call-to-action'>Button Two</div>
<div class='call-to-action button'>Button Two</div>

Однако все усложняется, когда в дело вступает специфика CSS, о которой мы поговорим в конце этого урока.

селекторы потомков
Descendant Selectors

Вы, наверное, заметили, что элемент <em> в нашем первом абзаце уже не отличим от окружающего текста, поскольку правило .synopsis сделало все курсивом.

Чтобы изменить этот элемент <em>, мы могли бы добавить другой класс непосредственно к нему, но это не приведет к удобству работы с кодом. Мы хотим рассматривать .synopsis как свой собственный независимый компонент, который мы можем полностью стилизовать с помощью CSS (т.е. без необходимости вносить изменения в наш HTML только для того, чтобы что-то стилизовать).

Interneting is hard HTML+CSS
Скриншот 9: веб-страница с текстом span внутри другого элемента, стилизованным с помощью селектора-потомка

Для этого и нужны "селекторы потомков". Они позволяют выбрать только те элементы, которые находятся внутри другого элемента. Например, мы можем извлечь этот <em> в параграфе .synopsis следующим образом:

.synopsis em {
font-style: normal;
}

Добавление этого правила в файл styles.css приведет к тому, что <em> будет отображаться в виде "обычного" шрифта (т.е. не курсивного), отличаясь тем самым от курсива, которым мы выделяем весь текст <p>. Остальные элементы <em> на странице не будут затронуты.

Interneting is hard HTML+CSS
Скриншот 10: единичная стрелка, идущая от составного CSS-правила [CSS rule] к HTML-элементу внутри другого HTML-элемента

Селекторы-потомки не ограничиваются селекторами классов - таким образом можно объединять любые другие группы селекторов. Например, если мы хотим выбрать только элементы <em> внутри заголовков, мы можем использовать что-то вроде этого:

h1 em {
/* некие другие стили */
}

Повторим, цель этого урока - дать возможность применять стили именно к тому элементу, который вам нужен. Селекторы-потомки - отличный инструмент для достижения этой цели. Если еще осталось свободное место в вашем "ящике инструментов", ознакомьтесь с селектором дочерних элементов на сайте MDN.

НЕ ПЕРЕУСЕРДСТВУЙТЕ
Don’t Overdo It

Вкладывать селекторы-потомки можно сколь угодно глубоко, но не стоит увлекаться. Жизнь становится запутанной и ужасной, когда вы начинаете писать правила, которые выглядят примерно так:

/* постарайтесь избежать такого */
.article h2 .subheading em {
/* особые стили */
}

Это ни в коей мере не пригодно для повторного использования, поскольку соответствует только следующей структуре HTML:

<div class='article'>
<h2>
<span class='.subheading'>This is <em>really</em> special text</span>
</h2>
</div>

Если вы захотите применить эти стили к заголовку <h2>, не обернутому в теги <div class='article'>, то будет, как говорится, полный облом. То же самое произойдет, если вы захотите применить их к заголовку <h3> в любом месте страницы. Такой CSS только приведет к кошмару специфичности.

До сих пор все рассмотренные CSS-селекторы привязывались непосредственно к созданному нами фрагменту HTML-разметки. Однако на отображаемой веб-странице присутствует нечто большее, чем просто наш HTML-контент. Кроме созданного нами контента, там есть "служебная" информация о том, что делает пользователь.

Классический пример - ссылка. Как веб-разработчик, вы создаете элемент <a href>. После того как браузер отобразит его, пользователь может взаимодействовать с этой ссылкой. Он может навести на нее курсор, щелкнуть и перейти по URL-адресу.

Interneting is hard HTML+CSS
Скриншот 11: селектор псевдокласса, связывающий CSS-правило с поведением пользователя [hover - наведение курсора]

"Псевдоклассы" CSS это механизм, позволяющий подключаться к такого рода временной информации о пользователе. Элемент <a href> может находиться в нескольких различных состояниях, и вы можете использовать псевдоклассы для стилизации каждого из этих состояний в отдельности. Считайте, что это селекторы классов, которые не нужно писать самостоятельно, ибо они уже встроены в браузер.

ОСНОВНЫЕ СТИЛИ ССЫЛОК
Basic Link Styles

Псевдоклассы начинаются с двоеточия, за которым следует имя нужного класса. Наиболее распространенными псевдоклассами ссылок являются следующие:

Давайте рассмотрим все это, добавив в таблицу стилей CSS следующие правила (также обратите внимание на использование ключевых цветов вместо привычных hex-кодов [шестнадцатеричных кодов]):

a: link {
color: blue;
text-decoration: none;
}
a: visited {
color: purple;
}
a: hover {
color: aqua;
text-decoration: underline;
}
a: active {
color: red;
}

Если вы никогда не были на главной странице InternetingIsHard.com [веб-страница англоязычного оригинала данного учебника], данная ссылка должна быть синего цвета. А если уже там были, то цвет ссылки будет фиолетовым. При наведении курсора на ссылку ее цвет поменяется на aqua [цвет морской волны], а при нажатии на нее - цвет станет красным.

ССЫЛКА КОТ. ПОСЕЩАЛИ ПРИ НАВЕДЕНИИ НА НЕЕ МЫШИ
Visited Hover State

Приведенный выше фрагмент кода вполне подходит для большинства сайтов, но обратите внимание на поведение a:visited, изменив атрибут href на URL, который вы уже посещали. Наш стиль a:hover применяется как к посещенным, так и к непосещенным ссылкам. Можно еще более усовершенствовать наши ссылки, просто добавляя псевдоклассы. В конец вышеприведенного кода добавим еще пару строк:

a: visited:hover {
color: orange;
}

Это создаст особый стиль hover для посещаемых ссылок. При наведении на непосещаемую ссылку ее цвет уже не будет меняется на aqua. А при наведении на посещенную ссылку - ее цвет станет оранжевым. Фантастиш! За исключением того факта, что это ломает наш стиль a:active из-за некоторых сложных CSS-интерфейсов, с которыми вы наверняка никогда не захотите разбираться. И еще, когда вы щелкнете на ссылку, она уже не станет красной.

АКТИВНОЕ СОСТОЯНИЕ ПОСЕЩЕННОЙ ССЫЛКИ
VISITED ACTIVE STATE

Мы можем исправить это с помощью a:visited:active. Добавьте следующее в конец нашей таблицы стилей. Помните, что, как и в случае с классом .call-to-action, порядок, в котором они определены в styles.css, имеет значение:

a: visited:active {
color: red;
}

Последние два секции объясняют как стилизовать посещенные ссылки отдельно от непосещенных. Это хорошая возможность, но, опять же, вы можете ограничиться базовыми стилями ссылок. Может вам их будет достаточно?

псевдоклассы для кнопок
Pseudo-Classes for Buttons

Помимо стилизации текстовых ссылок псевдоклассы можно применять для стилизации любого типа селекторов (не только селекторов типов). Вместо стилизации a:link и других ссылок, в этой секции с помощью псевдоклассов мы будем модифицировать класс .button. Тем самым мы создим кнопки, которые реально работают и куда-то ведут.

ЭЛЕМЕНТЫ ССЫЛОК, ВМЕСТО ЭЛЕМЕНТОВ DIV
Link Elements, Not Div Elements

Прежде всего, нам нужно изменить наши кнопки так, чтобы они были элементами <a href>, а не обычными элементами <div>, что показано ниже:

<div class='button' href='nowhere.html'>Button One</a>
<div class='button call-to-action' href='nowhere.html'>Button Two</a>

Добавив этот код и перезагрузив страницу, увидим, что некоторые стили потерялись, хотя мы используем все те же классы. Причина? Это происходит потому, что <a> по умолчанию это строчный элемент со своим стандартным значением color.

Interneting is hard HTML+CSS
Скриншот 12: изображение кнопок на веб-странице с искаженными стилями CSS

Нам нужно изменить его на блоковый элемент и удалить некоторые стили ссылок по умолчанию.

СТИЛИ КНОПОК
Button Styles

Начнем с :link и :visited. Мы используем тот же шаблон, что и в предыдущей секции, но с одним отличием. Поскольку мы стилизуем кнопки, желательно сохранить одинаковый цвет для непосещенных и уже посещенных. Измените существующие правила .button следующим образом:

.button:link, /* измените это */
.button:visited { /* измените это */
display: block; /* добавьте это */
text-decoration: none; /* добавьте это */

color: #FFF; /* остальное без изменений */
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063;
border-radius: 5px;

width: 200px;
margin: 20px auto;
}

Обратите внимание на новые псевдоклассы :link и :visited в селекторе. Без них наш цвет не будет переопределять стандартный стиль браузера a:link. Cпецифичность CSS более подробно объясняет, почему это так. Далее давайте займемся состояниями наведения курсора [hover]:

.button:hover,
.button:visited:hover {
color: #FFF;
background-color: #76AEED; /* голубой */
}

При наведении курсора обе кнопки будут становиться светло-голубыми. И наконец, сделаем кнопку немного темнее, когда пользователь щелкает мышью. В этом нам поможет псевдокласс :active:

.button:active,
.button:visited:active {
color: #FFF;
background-color: #5995DA; /* синий */
}

Самое чудесное в этом то, что все только что заданные стили, можно использовать многократно, то есть сколько угодно. Примените класс .button к любому элементу HTML, и вы превратите его в интерактивную кнопку.

ВТОРАЯ КНОПКА
The Other Button

А как насчет второй кнопки? Она должна иметь желтый фон, но мы нарушили это правило с помощью кода из предыдущей секции. Наш селектор .button:link был более "конкретным", чем наше текущее правило .call-to-action, поэтому он получил приоритет. Опять же, мы рассмотрим это подробнее в конце данного урока.

А пока давайте исправим это, применив некоторые псевдоклассы к нашему правилу .call-to-action. Замените существующее правило следующим (убедитесь, что данные изменения расположены после кода стилей .button из предыдущей секции):

.call-to-action:link,
.call-to-action:visited {
font-style: italic;
background-color: #EEB75A; /* Желтый */
}

.call-to-action:hover,
.call-to-action:visited:hover {
background-color: #F5CF8E; /* Светло-желтый */
}

.call-to-action:active,
.call-to-action:visited:active {
background-color: #EEB75A; /* Желтый */
}

Поскольку мы добавили класс .call-to-action только ко второй кнопке, только она станет желтой. Конечно, нам все еще нужен класс .button для обоих элементов <a>, потому что он определяет общие стили, такие как padding, округление углов рамки и жирность шрифта.

псевдоклассы для структуры
Pseudo-Classes For Structure

Состояния ссылок - это лишь один из аспектов псевдоклассов. Существует также множество других псевдоклассов, которые предоставляют дополнительную информацию об окружении элемента. Например, псевдокласс :last-of-type выбирает последний элемент определенного типа в его родительском элементе. Это дает нам альтернативу селекторам классов для выбора конкретных элементов.

Например, мы можем использовать :last-of-type, чтобы добавить немного пустого пространства после последнего абзаца на нашей странице:

p:last-of-type {
margin-bottom: 50px;
}

Это позволяет избежать селекции первых двух элементов <p>, не требуя нового атрибута class для последнего абзаца:

Interneting is hard HTML+CSS
Скриншот 13: нижнее поле последнего абзаца на странице, стилизованное с помощью псевдокласса-селектора :last-of-type

Мы даже можем использовать псевдокласс :first-of-type вместо класса .synopsis. Заменив существующее правило .synopsis следующим фрагментом, вы получите точно такую же страницу.

p:first-of-type {
color: #7E8184;
font-style: italic;
}

У этого метода есть свои плюсы и минусы по сравнению с обычными классами. Например, он работает только в том случае, если наш синопсис - это элемент <p>. Если мы захотим создать многопараграфный синопсис, обернув кучу элементов <p> в <div class='synopsis'>, нам придется соответствующим образом переписать наш CSS. С другой стороны, метод псевдоклассов позволяет нам стилизовать определенные элементы без необходимости изменять HTML. Таким образом, мы получаем очень чистое разделение контента и внешнего вида.

ОГОВОРКИ
Caveats

На самом деле метод псевдоклассов немного сложнее. Но они все равно являются полезным инструментом - при условии, что вы знаете их особенности и недостатки. Селекторы :first-of-type и :last-of-type действуют только внутри родительского элемента. То есть p:first-of-type выбирает первый <p> в каждом элементе-контейнере.

У нас есть один общий <div>, обертывающий наш контент (.page), поэтому для нас это не проблема. Однако посмотрите, что произойдет, если мы добавим это в нижнюю часть нашего элемента .page:

<div class='sidebar'>
<p>If this page had a sidebar...</p>
<p>We’d have some problems with pseudo-classes.</p>
</div>

Мы еще не умеем делать настоящую боковую панель (об этом на следующем уроке), но это подчеркивает сложность псевдоклассов для структуры. Первый элемент <p> здесь также будет соответствовать p:first-of-type, потому что область действия псевдокласса ограничена родительским элементом.

Если бы мы хотели избежать абзацев боковой панели и выбрать только первый <p> в нашем <div class='page'>, нам бы пришлось ограничить его область действия с помощью дочернего селектора, как показано ниже:

.page > p:first-of-type {
color: #7E8184;
font-style: italic;
}

Все это - еще один пример того, что в удивительном мире HTML и CSS существует множество способов сделать одну и ту же вещь. Разные разработчики придерживаются разных школ и подходов. Кому-то нравится семантическая природа псевдоклассов, а кого-то заносит аж до использования атрибутов классов для каждого элемента HTML.

id-селекторы
ID Selectors

"Селекторы ID" - это более жесткая альтернатива селекторам классов. Они работают практически так же, за исключением того, что на странице может быть только один элемент с одинаковым ID. Это означает, что вы не можете повторно использовать стили. Вместо атрибута class они требуют атрибут id у HTML-элемента, который вы пытаетесь задействовать. Попробуйте добавить его к нашей второй кнопке:

<a id='button-2' class='button' href= 'nowhere.html'>Button Two</a>

Соответствующий селектор CSS должен начинаться с знака хеш (#), а не с точки. Добавив следующее в файл styles.css, вы измените цвет текста нашей желтой кнопки:

#button-2 {
color: #5D6063; /* темно-серый */
}

Проблема в том, что как только мы захотим поделиться этим стилем с другой кнопкой, нам придется присвоить ей еще один уникальный атрибут id. Очень скоро наш CSS выглядел бы довольно неприглядно:

/* (обслуживать такой код очень напряжно) */
#button-2,
#button-2,
#checkout-button,
#menu-bar-call-to-action
{
color: #5D6063;
}

По этой причине селекторы ID обычно не одобряются. Вместо них используйте селекторы классов.

ФРАГМЕНТЫ URL
URL Fragments

Атрибуты id должны быть уникальными, потому что они служат целью для "фрагментов URL", которые мы вроде как проглядели в нашем обсуждении URL. Фрагменты - это способ указать пользователю на определенную часть веб-страницы. Они выглядят как селектор ID, вставленный в конец URL.

Interneting is hard HTML+CSS
Скриншот 14: синтаксис URL - схема, домен, путь, фрагмент.

Например, если бы мы хотели указать пользователю на нашу вторую кнопку, мы могли бы использовать следующее. Обратите внимание, что мы можем полностью опустить URL, если мы ссылаемся на другую секцию на этой же странице:

<!-- В случае, когда одна и та же страница -->
<a href='#button-2'>Go to Button Two</a>

<!-- В случае, когда путь ведет на другую страницу -->
<a href='selectors.html#button-2'>Go to Button Two</a>

Если вы добавите первый вариант на нашу страницу selectors.html и щелкнете по нему, вы увидите, как изменится URL в браузере. Чтобы увидеть переход ко второй кнопке, вам придется добавить на страницу еще немного фиктивного контента или сделать высоту окна очень маленькой, так как браузер ограничит прокрутку экрана видимым пространством страницы.

Interneting is hard HTML+CSS
Скриншот 15: две стрелки от фрагментов URL к двум элементам HTML и две стрелки от правил CSS к этим же элементам

Такая накладывающаяся функциональность - еще одна причина избегать селекторов ID. Они создают зависимость между URL-адресами вашего сайта и стилями CSS. Представьте, что вы используете кучу атрибутов id в заголовках в качестве фрагментов URL и селекторов ID. Если бы вы забывали обновлять таблицу стилей каждый раз, когда редактировали URL-адрес секции, вы бы фактически сломали свой сайт.

специфичность
css specificity

Ранее на этом уроке мы говорили о том, что очередность имеет значение, когда речь идет о правилах CSS во внешней таблице стилей. При прочих равных условиях правила применяются сверху вниз. Это позволило нам переопределять правила предсказуемым образом.

Interneting is hard HTML+CSS
Скриншот 16: четыре правила CSS с одинаковой спецификой, применяемые по порядку

К сожалению, не все селекторы CSS созданы одинаковыми. "Специфичность CSS - это степень значимости различных категорий селекторов. Это означает, что одни селекторы всегда будут преобладать над другими, независимо от того, где они находятся в таблице стилей.

Для начала давайте посмотрим, где это не нарушается. Если вы добавите следующее после существующего правила .call-to-action, оно отменит предыдущий цвет фона. Если вы поместите его в начало файла, он будет отменен позже, поэтому наша кнопка не станет красной. Это ожидаемое поведение.

.call-to-action:link,
.call-to-action:visited {
background-color: #D55C5F; /* Красный */
}

Теперь посмотрите, что произойдет, если мы попытаемся сделать то же самое с селектором ID. Сначала удалите предыдущий фрагмент, а затем попробуйте добавить его перед существующими правилами .call-to-action:

#button-2 {
background-color: #D55C5F; /* Красный */
}

Селекторы ID имеют более высокую специфичность, чем селекторы классов. Поэтому наша вторая кнопка будет красной и все тут. Даже если мы попытаемся установить цвет фона с помощью .call-to-action:link ниже в нашей таблице стилей - это не поможет. Вся концепция "порядок имеет значение" работает только тогда, когда все ваши правила имеют одинаковую специфику.

Interneting is hard HTML+CSS
Скриншот 17: четыре правила CSS. Третье правило имеет более высокую специфичность, поэтому четвертое игнорируется.

Специфичность селекторов, которые мы рассматривали в этой главе, показана ниже, от наибольшего к наименьшему:

Это может привести к большой путанице. Это настолько большая проблема, что возникла целая методология под названием BEM. BEM пытается сделать правила CSS многократно используемыми, превращая все в селекторы классов. Это полностью устраняет возможность возникновения проблем с определением специфичности.

РЕЗЮМЕ

На этом уроке мы получили практический опыт работы с селекторами классов, селекторами потомков, псевдоклассами, стилизацией ссылок и селекторами ID. Цель всего этого заключалась в том, чтобы иметь возможность выбирать конкретный элемент HTML из вашего CSS. Селекторы классов являются наиболее универсальными и имеют наименьшее количество недостатков. В результате они станут частью вашей повседневной жизни веб-разработчика.

Нравится вам это или нет, начиная с этого урока все стало намного сложнее. Теперь мы можем заставить наш CSS взаимодействовать с HTML-документом несколькими разными способами. Более того, чем дальше, тем яснее станет взаимодействие между HTML-структурой и макетом веб-страницы. Из-за этого взаимодействия CSS и HTML бывает трудно понять, с чего начать создание новой веб-страницы.

Разделение контента и внешнего вида помогает направить этот процесс. Прежде чем подать контент, нужно его разметить. Поэтому первым шагом обычно является разметка исходного контента с помощью HTML-тегов. После чего можно добавить атрибуты класса к элементам и стилизовать их один за другим. Если возникает необходимость в дополнительной структуре для создания нужного макета (например, превращения группы элементов в боковую панель), то вы начинаете помещать содержимое в контейнеры <div>.

На этом уроке мы рассмотрели почти все селекторы CSS, используемые на реальных веб-сайтах. Теперь у вас есть инструменты, необходимые для более глубокого изучения сложных CSS-макетов. На следующем уроке данного учебника мы узнаем, как создавать колонки и боковые панели с помощью "обтекающих" элементов CSS.


HTML & CSS IS HARD - НА РУССКОМ

FLOATS

УРОК Nº 7.

Добротный учебник классической веб-разработки + user-friendly введение в CSS-верстку

За последние несколько уроков мы научились управлять размером блоков и пространством вокруг них, но в основном мы были привязаны к стандартному вертикальному потоку страницы. Блоковые элементы всегда располагались вертикально друг под другом, ограничивая нас одноколоночным макетом.

Interneting is hard HTML+CSS
Скриншот 1: вертикальный поток элементов в сравнении с горизонтальным потоком

"Обтекание" [float] позволяют размещать элементы блокового уровня рядом, а не друг под другом. Это очень важно. С его помощью можно создавать всевозможные макеты, включая боковые колонны, многоколоночные страницы, grid-сетки и статьи в журнальном стиле с текстом, обтекающим изображение. Именно здесь наконец-то мы начнем создавать настоящие веб-страницы.

В современных веб-сайтах макеты на основе плавающих элементов в основном заменены на Flexbox. Но это не значит, что этот урок не стоит читать. На протяжении более десяти лет плавающие макеты служили основой большинству веб-сайтов, а это значит, что в какой-то момент своей карьеры вы с ними обязательно столкнетесь.

Возможно, ограниченная природа обтекающих элементов сделает их более мягким введением в верстку CSS, чем Flexbox. Вместо того чтобы быть перегруженными всеми возможностями Flexbox, это ваш шанс сосредоточиться на процессе создания сложного макета веб-страницы.

подготовка
setup

На этом уроке на примере довольно простого проекта мы рассмотрим CSS-понятие "обтекание" [float]. Вместо того чтобы работать с HTML-контентом, как это было в предыдущих главах, мы будем стилизовать кучу пустых элементов <div>. В итоге мы получим нечто похожее на изображение ниже. Это довольно сильно отличается от тех типов веб-страниц, которые мы создавали до сих пор, не так ли?

Interneting is hard HTML+CSS
Скриншот 2: веб-страница с боковой float-панелью, текстом, обтекающим картинку и плавающей сеткой в футере

Сначала создайте новую папку floats, затем добавьте новую веб-страницу floats.html со следующей разметкой:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Floats</title>
<link rel='stylesheet' href='styles.css'/>
</head>
<body>
<div class='page'>
<div class='menu'>Menu</div>
<div class='sidebar'>Sidebar</div>
<div class='content'>Content</div>
<div class='footer'>Footer</div>
</div>
</body>
</html>

Это дает нам базовую структуру большинства сайтов в Интернете. У нас есть место для размещения навигационного меню, боковой панели, основного контента и футера. Все эти элементы можно считать div-контейнерами, в которые помещается HTML-контент.

Открыв файл floats.html в браузере, вы не увидите ничего особенного, потому что у пустых элементов высота равна нулю. Мы исправим это в следующей секции.

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

Не забудьте создать таблицу стилей styles.css, как показано выше. Этот код сбрасывает стандартное поведение блока,

стандартная модель поведения html-макета
default html layout behavior

Плавающие элементы изменяют стандартный макет веб-страницы, поэтому для начала нам следует разобраться, что именно является "стандартным" поведением. Мы уже говорили об этом в разделе Блоковые и строчные элементы, но сейчас это приобретает гораздо большее значение.

Мы можем лучше рассмотреть наш пример страницы, добавив некоторые цвета фона и четко выраженную высоту для каждого из наших элементов <div>. Добавьте следующее в файл styles.css:

.menu {
height: 100px;
background-color: #B2D6FF; /* умеренно синий */
}

.sidebar {
height: 300px;
background-color: #F09A9D; /* красный */
}

.content {
height: 500px;
background-color: #F5CF8E; /* желтый */
}

.footer {
height: 200px;
background-color: #D6E9FE; /* голубой */
}

В результате мы получаем красивую радугу, но это не совсем то, что нам нужно, хотя и демонстрирует некоторые полезные концепции.

Interneting is hard HTML+CSS
Скриншот 3: веб-страница с четырьмя цветными блоками, появляющимися вертикально один за другим

Здесь важно то, что каждый элемент уровня блока заполняет 100 % ширины родительского элемента (в данном случае <div class='page'>), и они отображаются вертикально друг под другом. И по-прежнему мы ограничены одноколоночным макетом.

Обычно высота этих блоков определяется автоматически в зависимости от содержащегося в них контента. Однако на этом уроке речь идет об управлении макетами, поэтому мы не будем иметь дело с реальным контентом. Вот почему нам нужны явно выраженные свойства высоты.

Стоит взглянуть на то, что происходит, когда мы уменьшаем ширину элемента. Обновите наше правило .sidebar, изменив его на следующее:

.sidebar {
width: 200px; /* добавьте это */
height: 300px;
background-color: #F09A9D;
}

Элемент боковой панели становится более узким, но остальные блоки остаются на прежних местах. Все блоки по-прежнему отображаются вертикально один за другим. Именно такое поведение мы и будем получать с помощью плавающих элементов.

Interneting is hard HTML+CSS
Скриншот 4: веб-страница с красным блоком боковой панели в левой части страницы и белым фоном рядом с ним
перемещение плавающего элемента
floating an element

Свойство CSS float дает нам контроль над горизонтальным положением элемента. Чтобы "сплавить" боковую панель влево, мы командуем браузеру выровнять ее по левой стороне страницы. Переместите нашу боковую панель влево с помощью следующей строки:

.sidebar {
float: left; /* добавьте это */
width: 200px;
height: 300px;
background-color: #F09A9D;
}

Однако это не только выравнивает боковую панель, но и сообщает окружающим элементам, что они могут обтекать боковую панель, а не начинаться под ней. Как если бы боковая панель находилась внутри блока .content, так что любая HTML-разметка в .content обходила бы блок боковой панели. Таким образом, мы получаем макет в стиле журнальной страницы:

Interneting is hard HTML+CSS
Скриншот 5: веб-страница с красным блоком боковой панели, "плавающим" поверх следующего элемента

Вы также можете перемещать элементы вправо, как показано ниже (однако мы оставим нашу боковую панель перемещенной влево). Или, если вы переопределяете объявление float, вы можете отменить его с помощью значения none. Это наиболее распространенные значения для свойства float.

float: right; /* Выравнивание по правому краю */
float: none; /* Возврат к стандартному потоку */

Теперь у нас есть все необходимые инструменты для выравнивания элементов на уровне блоков: плавающие элементы для выравнивания по левому/правому краю и метод auto-margins для выравнивания по центру. Помните, что это относится только к блоковым блокам. Строчные [inline] блоки выравниваются с помощью свойства text-align, как описано ранее.

Interneting is hard HTML+CSS
Скриншот 6: float left (блок в левой части контейнера), auto margins (блок в центре контейнера), float right (блок в правой части контейнера)
перемещение внутри родителей
floating inside of parents

Плавающие блоки всегда выравниваются по левому или правому краю родительского элемента. В нашем примере родителем боковой панели является <div class='page'>, ширина которого равна ширине окна браузера. Поэтому наша боковая панель плавает в крайней левой части страницы.

Давайте изменим это, придав нашей странице макет фиксированной ширины. И снова пригодится метод центрирования auto-margins. Добавьте в файл styles.css следующее:

.page {
width: 900px;
margin: auto;
}

Теперь мы видим, что .sidebar плавает слева от контейнера .page, а не у края окна браузера.

Interneting is hard HTML+CSS
Скриншот 7: веб-страница с цветными блоками, расположенными по центру браузера

Подобное позиционирование вложенных div-контейнеров - это способ создания сложных макетов веб-сайтов. Мы начали с .page, чтобы отцентрировать всю страницу. Затем выровняли по левому краю боковую панель внутри этой отцентрированной страницы. Все может оказаться гораздо сложнее, но наш простой пример демонстрирует простую истину верстки CSS: все является блоком внутри блока внутри другого блока.

множественные плавающие элементы
multiple floats

Давайте рассмотрим наш плавающий элемент "в журнальном стиле", добавив четко выраженную ширину в блок .content:

.content {
width: 650px; /* Добавьте это */
height: 500px;
background-color: #F5CF8E;
}

Это наглядно показывает, что наша боковая панель находится внутри блока .content: если вы сделаете их скриншот, то получите изображение шириной 650 пикселей, а не 850 (ширина нашей боковой панели - 200 пикселей).

Interneting is hard HTML+CSS
Скриншот 8: на веб-странице показана плавающая слева красная боковая панель поверх статично расположенного элемента

Такое поведение плавающего элемента хорошо для картинок (что мы рассмотрим позже), но для макета страницы мы хотим, чтобы блок контента находился рядом с боковой панелью, а не обтекал ее. Для этого нам нужно указать блоку контента, чтобы он тоже "плавал" слева. Добавьте еще одну строку в правило .content:

.content {
float: left; /* Добавьте это */
width: 650px;
height: 500px;
background-color: #F5CF8E;
}

Когда вы располагаете несколько плавающих элементов в одном направлении, они будут располагаться горизонтально, как в стандартном алгоритме вертикального расположения, только повернутые на 90 градусов. Приведенный выше код приводит к тому, что весь наш блок контента оказывается справа от боковой панели, а не оборачивается вокруг нее.

Interneting is hard HTML+CSS
Скриншот 9: веб-страница, показывающая красную боковую панель рядом с плавающим элементом, выровненным по левому краю

Это дает нам полный контроль над горизонтальным выравниванием наших блочных блоков. Попробуйте поэкспериментировать со значениями плавающих элементов для .sidebar и .content, и вы увидите, что в вашем распоряжении уже есть несколько различных макетов:

Interneting is hard HTML+CSS
Скриншот 10: четыре потенциальные комбинации левого и правого плавающих элементов для двух элементов

Прежде чем двигаться дальше, убедитесь, что оба элемента плавают слева. Это позволит создать макет для боковой панели и блоков контента, но, к сожалению, испортит наш элемент .footer.

после float
After a Float

Вы, наверное, заметили, что наш футер отображается в правом верхнем углу, прямо под .menu. Это происходит потому, что плавающие элементы удаляются из нормального потока страницы. Высота наших плавающих элементов не влияет на вертикальное положение футера, поэтому он просто размещается под последним элементом, который не был плавающим.

Interneting is hard HTML+CSS
Скриншот 11: веб-страница с прозрачными блоками, показывающая плавающие элементы поверх статично расположенного футера

Мы можем увидеть это более четко, добавив красную рамку вокруг нашего элемента .page:

.page {
width: 900px;
margin: 0 auto;
border: 1px solid red; /* Добавьте это */
}

Обратите внимание, что рамка есть только вокруг элементов .menu и .footer. Словно плавающих элементов там вообще не было. Есть два способа исправить это: очистить плавающий элемент и скрыть переполнение.

ОЧИСТКА ПЛАВАЮЩИХ ЭЛЕМЕНТОВ
Clearing Floats

"Очистка" плавающего элемента - это когда мы командуем блоку игнорировать все плавающие элементы, которые появляются перед ним. Вместо того чтобы обтекать плавающий блок, очищенный элемент всегда появляется после всех плавающих элементов. Это как бы заставляет блок вернуться в вертикальный поток страницы по умолчанию.

Мы можем использовать свойство clear, чтобы опустить наш футер в нижнюю часть страницы:

.footer {
clear: both; /* Добавьте это */
height: 200px;
background-color: #FD6E9FE;
}

Обычно нужно очистить и левый, и правый плавающие элементы, как мы сделали здесь, но вы можете выбрать очистку только одного или другого элемента, указав значения left или right. Обратите внимание, что красная рамка теперь проходит по всему футеру, указывая на то, что плавающие элементы действительно учитываются при определении высоты контейнера .page:

Interneting is hard HTML+CSS
Скриншот 12: веб-страница, показывающая, как футер опускается после очистки к нижней части плавающих элементов

В зависимости от типа макета, который вы пытаетесь создать, это вполне приемлемое решение. На этом можно было бы остановиться, но мы собираемся подробнее изучить поведение плавающих элементов, превратив нашу страницу в макет без окружающих полей, в котором цвета фона заполняют все окно браузера.

Посмотрите, что произойдет, если мы уберем меню и футер из элемента .page. Измените элемент <body> так, чтобы он соответствовал следующему:

<body>
<div class='menu'>Menu</div>

<div class='page'>
<div class='sidebar'>Sidebar</div>
<div class='content'>Content</div>
</div>

<div class='footer'>Footer</div>
</body>

Поскольку .menu и .footer находятся за пределами фиксированной ширины .page, они занимают всю ширину окна. И это именно то, что нам нужно. Однако обратите внимание, что у .page снова нулевая высота, несмотря на то, что футер по-прежнему освобождает боковую панель и блоки контента.

Interneting is hard HTML+CSS
Скриншот 13: веб-страница, выделяющая нулевую высоту .page <div> с плавающими элементами

И снова единственные элементы в .page - плавающие элементы, поэтому они не учитываются при определении высоты. Другими словами, перемещение футера за пределы контейнера .page нарушило наше исправление с помощью свойства clear.

СКРЫТИЕ ПЕРЕПОЛНЕНИЯ
Hiding Overflow

Очистка плавающих элементов решает проблему высоты только в том случае, если внутри элемента-контейнера есть элемент, к которому можно добавить свойство clear. Теперь, когда наш футер находится за пределами .page, нам нужен новый способ заставить плавающие элементы учитывать высоту их контейнера.

Interneting is hard HTML+CSS
Скриншот 14: слева: очистка с помощью дочернего элемента. Справа: очистка с помощью родительского элемента

Решением является свойство overflow. Добавляя overflow: hidden к контейнеру div, мы указываем ему на необходимость распознавать высоту всех плавающих элементов, которые он содержит. Вот как мы можем добавить цвет фона к элементу .page и добиться того, чтобы он действительно отображался:

.page {
width: 900px;
margin: 0 auto;
overflow: hidden; /* Добавьте это */
background-color: #EAEDF0; /* Добавьте это */
}

Теперь вы увидите светло-серый фон на странице .page вместо белого, задаваемого по умолчанию. Это еще не полноценный фон (мы рассмотрим его в следующей секции). Важным моментом здесь является поведение этого самого overflow: hidden. Без него мы бы не смогли увидеть фон контейнера .page, потому что его высота была бы нулевой.

Interneting is hard HTML+CSS
Скриншот 15: серый фон, заполняющий всю высоту контейнера .page <div>

Подводя итог, можно сказать, что если у вас есть избыточный элемент HTML в нижней части контейнера div, используйте прозрачное решение. В прочих случаях добавьте объявление overflow: hidden к элементу контейнера. Суть обоих вариантов заключается в том, что вам нужен способ указать браузеру на необходимость включения плавающих элементов в высоту их контейнерного элемента, чтобы их фон отображался.

макеты во всю ширину окна
Full-Bleed Layouts

Далее мы хотим сделать так, чтобы фон нашей .page заполнял все окно браузера, не изменяя выравнивания боковых панелей и блоков контента. Проблема в том, что наш .page занят центрированием всего, и мы не можем использовать его для полноцветного фона, поскольку центрирование требует явно выраженного свойства width.

Interneting is hard HTML+CSS
Скриншот 16: веб-страница, на которой виден серый фон, заполняющий всю высоту .page <div>, вплоть до левого и правого краев

Пора сделать еще один контейнер div. Поместив блок вокруг .page, мы продолжаем центрировать материал, одновременно предоставляя место для определения свойства background-color. Измените <body> как показано ниже:

<body>
<div class='menu'>Menu</div>

<div class='container'> <!-- Добавьте это -->
<div class='page'>
<div class='sidebar'>Sidebar</div>
<div class='content'>Content</div>
</div>
</div> <!-- Добавьте это -->

<div class='footer'>Footer</div>
</body>

Помните, что при стандартном отображении блоков [default block-rendering behavior] элементы заполняют ширину своего контейнера. Поэтому мы можем перенести объявление фонового цвета в правило .container, чтобы получить фон на всю щирину страницы:

.page {
width: 900px;
margin: 0 auto;
}

.container {
overflow: hidden;
background-color: #EAEDF0;
}

Как и в предыдущей секции, нам по-прежнему нужна строка overflow: hidden, чтобы заставить .container обращать внимание на высоту плавающих элементов. Без нее мы бы не увидели цвет фона, потому что высота .container была бы нулевой.

Таким образом, мы получаем три вложенных элемента <div> для оформления нашей страницы: обертку .container для заполнения всего окна браузера, страницу фиксированной ширины .page для выравнивания по центру и, наконец, блоки .sidebar и .content, выровненные по левому краю. Подобное вложение и выравнивание довольно типично для большинства макетов веб-сайтов.

обтекание для колонок одной ширины
Floats for Equal-Width Columns

Мы уже рассмотрели макет страницы с боковой панелью, макет с фиксированной шириной и макет с заполнением всего окна браузера. Float-элементы также можно использовать для создания многоколоночных макетов. Это работает так же, как и плавающие элементы .sidebar и .content - просто их будет больше.

Следующий шаг - добавить три колонки одинаковой ширины в наш футер. Обновите элемент <footer> следующим образом:

<div class='footer'>
<div class='column'></div>
<div class='column'></div>
<div class='column'></div>
</div>

Мы можем оформить каждую из этих колонок так же, как и остальную часть нашей страницы. Добавьте новое правило в styles.css:

.column {
float: left;
width: 31%;
margin: 20px 1.15%;
height: 160px;
background-color: #B2D6FF; /* умеренно синий */
}

Впервые мы используем процентные значения вместо пиксельных. Проценты в CSS относятся к ширине родительского элемента. В результате мы получаем три колонки, размер которых автоматически изменяется на одну треть окна браузера. Измените размер окна браузера, и вы увидите, как наши колонки увеличиваются и уменьшаются соответственно. Это начало адаптивного дизайна.

Interneting is hard HTML+CSS
Скриншот 17: веб-страница с футером, состоящим из трех дочерних элементов одинаковой ширины

Однако давайте не будем упускать из виду главный тезис этого урока: плавающие элементы позволяют располагать элементы горизонтально, а не вертикально. Изменяя ширину плавающих элементов, получаем всевозможные варианты компоновки, от боковых панелей до нескольких колонок и сеток.

обтекание для сеток
Floats for Grids

Хотите сетку [grid] в футере вместо 3 колонок? Запросто! Когда не хватает места для горизонтальной укладки плавающего элемента, он опускается на следующую строку. Все, что нам нужно сделать, это добавить еще несколько элементов .column:

<div class='footer'>
<div class='column'></div>
<div class='column'></div>
<div class='column'></div>
<div class='column'></div>
<div class='column'></div>
<div class='column'></div>
</div>

Вуаля! Сетка! Ну, почти...

Interneting is hard HTML+CSS
Скриншот 18: веб-страница с футером, имеющим 3 колонки и 2 строки дочерних элементов

Наш фон футера слишком короток. К счастью, мы уже знаем, как это исправить. Давайте заменим явную высоту футера на другую - overflow: hidden, чтобы он мог вместить любое количество элементов сетки:

.footer {
overflow: hidden;
background-color: #D6E9FE;
}

С помощью этой же техники можно создавать сетки любого размера. Например, для создания фотогалереи с кучей миниатюр достаточно поместить элементы сетки в .page, а не в футер, и добавить к ним элементы <img/>. Но, опять же, помните, что flexbox - это более современный способ создания подобных макетов.

О СТАНДАРТАХ НАИМЕНОВАНИЯ ФАЙЛОВ
A Brief Note on Naming Conventions

Название класса .column уже не совсем корректно. Этот сценарий - хороший пример того, почему мы хотим избегать имен классов, которые ссылаются на внешний вид. "Column" не очень подходит, потому что содержащийся в ней контент не обязательно должен отображаться в нескольких колонках (например, в мобильном макете, скорее всего, будет только одна колонка). Лучшим названием было бы что-нибудь вроде .footer-item, но мы оставим это на ваше усмотрение.

обтекание для контента
Floats for Content

Существует два аспекта определения макета веб-страницы. У вас есть общая структура страницы, над которой мы работали на протяжении всей этой главы. Это такие вещи, как расположение боковой панели, размер навигационного меню и т. д. Другой аспект макетов - это стилизация отдельных HTML-компонентов (вашего фактического контента), которые находятся внутри общей структуры страницы.

Процесс работы с последними такой же, просто они вложены внутрь первых. Давайте добавим немного фиктивного контента в наш элемент .content, чтобы было с чем экспериментировать:

<div class='container'>
<div class='page'>
<div class='sidebar'></div>
<div class='content'>

<p>Ad netus sagittis velit orci est non ut urna taciti metus donec magnis
hendrerit adipiscing mauris sit a proin ultrices nibh.</p>

<p>Enim suspendisse ac scelerisque nascetur vestibulum parturient sed mi
dolor eu non adipiscing non neque scelerisque netus ullamcorper sed
parturient integer.Eros dui risus non sodales ullamcorper libero a dis
cubilia a orci iaculis cursus.</p>

<p>Egestas at aliquam a egestas accumsan cum elementum consectetur conubia
tristique eu et vitae condimentum in ante consectetur suscipit a a duis
vestibulum gravida morbi sagittis.Parturient scelerisque facilisis
ullamcorper a a pretium a nisl parturient semper senectus accumsan ipsum
mus scelerisque eget ridiculus.Accumsan dolor a.</p>

<p>Ligula taciti vel primis sit a tincidunt habitant parturient parturient
in parturient ante nulla consectetur sem.Facilisis parturient litora.</p>

</div>
</div>
</div>

У нас есть изображение и несколько абзацев, которые мы можем стилизовать так же, как и наши структурные div'ы. Например, давайте создадим макет в журнальном стиле, плавающий элемент изображения и текст вокруг него. Для этого в таблицу стилей нужно добавить еще несколько правил:

.content {
padding: 20px;
}

.article-image {
float: left;
width: 300px;
height: 200px;
margin-right: 20px;
margin-bottom: 20px;
}

p {
margin-bottom: 20px;
}

Обратите внимание, что у нас есть плавающий элемент внутри плавающего элемента, и все работает просто замечательно. Создание сайта - это рекурсивный процесс: вы создаете высокоуровневую структуру для работы, а затем заполняете ее реальным контентом. Более сложные макеты могут потребовать еще один или два уровня вложенности, но идея та же.

Interneting is hard HTML+CSS
Скриншот 19: веб-страница, показывающая плавающий элемент с обтекающим его текстовым контентом
СКРЫТИЕ ПЕРЕПОЛНЕНИЯ (ДЛЯ КОНТЕНТА)
Hiding Overflow (For Content)

Примеры вложенных макетов можно встретить повсюду. В качестве последнего примера рассмотрим базовую тему комментариев пользователя. У вас есть изображение, плавающий элемент слева от заголовка и текст рядом с ним:

Interneting is hard HTML+CSS
Скриншот 20: веб-страница, показывающая футер с иконкой и текстом рядом с ней, но не обтекающая его из-за overflow: hidden

Давайте попробуем создать это в нашем футере. В ваш любимый элемент .column добавьте следующее:

<div class='column'>
<div class='avatar'></div>
<h3 class='username'>Bob Smith</h3>
<p class='comment'>Aptent vel egestas vestibulum aliquam ullamcorper volutpat
ullamcorper pharetra hac posuere a rhoncus purus molestie torquent. Scelerisque
purus cursus dictum ornare a phasellus. A augue venenatis adipiscing.</p>
</div>

А также соответствующие правила CSS:

.avatar {
float: left;
width: 60px;
height: 60px;
margin: 25px;
border-radius: 40px;
background-color: #D6E9FE;
}

.username {
margin-top: 30px;
}

.comment {
margin: 10px;
overflow: hidden; /* это важно */
}

Это показывает еще один случай использования нашего трюка с overflow: hidden. Наклеив его на наш блок .comment, мы убедились, что текст "горизонтально очищен" (это не технический термин) от плавающего элемента. Без этого последняя строка текста .comment оказалась бы под изображением.

Interneting is hard HTML+CSS
Скриншот 21: веб-страницы со скрытым переполнением (with hidden overflow: текст выровнен по левому краю) и без скрытого переполнения (without...: текст обтекает иконку)

Другими словами, overflow: hidden ломает макет в журнальном стиле из предыдущей секции, но очень полезным образом.

РЕЗЮМЕ

В этой главе мы впервые познакомились с максимально реалистичными макетами веб-страниц. Мы узнали, как размещать плавающие элементы слева и справа, как работать с контентом после плавающего элемента и как сочетать плавающие элементы с техникой центрирования "auto-margin" из урока Блоковая модель в CSS. Эти инструменты нужны нам для создания боковых панелей, сеток и макетов в стиле журнала.

Важно чтоб вы помнили вашу роль в процессе создания сайта. Ваша работа как веб-разработчика заключается в том, чтобы получив красивый дизайнерский эскиз, превратить его в HTML и CSS, которые браузеры могут отобразить конечным пользователям. Плавающие элементы - большой шаг вперед в этом направлении, но эта технология уже устаревает. Ей на смену приходит верстка flexbox.

На следующем уроке мы узнаем дополнительные способы компоновки сложных сайтов с помощью flexbox. Свойства CSS будут новыми, но процесс будет таким же, как и сегодня: мы по-прежнему будем выравнивать блоки внутри других блоков, внутри других блоков и так далее, пока не добьемся желаемого макета.


МУДРЕНЫЙ HTML&CSS

FLEXBOX

УРОК Nº 8.

Самый понятный учебник современной CSS-верстки

Режим макета Flexbox ["Гибкий блок"] предлагает альтернативу плавающим элементам Floats для создания общего вида веб-страницы. В то время как плавающие элементы позволяют нам только горизонтально располагать наши блоки, flexbox дает нам полный контроль над выравниванием, направлением, порядком и размером наших блоков.

Interneting is hard HTML+CSS
Скриншот 1: сравнение свойств выравнивания (alignment), направления (direction), порядка (order) и размера (size) flexbox

В настоящее время веб переживает серьезные изменения, поэтому стоит немного поговорить о состоянии отрасли. В последнее десятилетие плавающие элементы Floats были единственным вариантом для создания сложной веб-страницы. В результате они хорошо поддерживаются даже в устаревших браузерах, а разработчики используют их для создания миллионов веб-страниц. Это означает, что вы неизбежно столкнетесь с плавающими элементами во время своей карьеры веб-разработчика (так что предыдущий урок не был пустой тратой времени).

Изначально плавающие элементы предназначались для макетов в журнальном стиле (см. статью Floats для контента). Несмотря на все изученное на прошлом уроке, виды макетов, создаваемых с помощью плавающих элементов, несколько ограничены. Даже простой макет боковой панели, с технической точки зрения, является немного хаком. Чтобы избавиться от этих ограничений, был изобретен Flexbox.

Наконец-то мы достигли того момента, когда поддержка браузерами достигла критической массы и разработчики могут начать создавать полноценные сайты с использованием flexbox. Мы рекомендуем использовать flexbox для компоновки веб-страниц как можно чаще, оставляя плавающие элементы для тех случаев, когда вам нужно, чтобы поток страницы обтекал блок (например, при верстке в журнальном стиле), или для поддержки устаревших веб-браузеров.

Interneting is hard HTML+CSS
Скриншот 2: плавающие элементы Floats для обтекания текста вокруг блока ("журнальная" структура) и Flexbox для остальной части макета (основная структура страницы)

На этом уроке мы шаг за шагом рассмотрим всю модель макета flexbox. Вы научитесь создавать практически любой макет, который предложит веб-дизайнер.

подготовка
setup

Пример для этого урока относительно прост, но он наглядно демонстрирует все важные свойства flexbox. В итоге мы получим что-то похожее на это:

Interneting is hard HTML+CSS
Скриншот 3: веб-страница с макетом на основе flexbox

Для начала нам нужен пустой HTML-документ, в котором нет ничего, кроме строки меню. Создайте новый Atom-проект под названием flexbox, в котором будут храниться все файлы примеров для этого урока. Затем создайте файл flexbox.html и добавьте в него следующую разметку:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Some Web Page</title>
<link rel='stylesheet' href='styles.css'/>
</head>
<body>
<div class='menu-container'>
<div class='menu'>
<div class='date'>Aug 14, 2016</div>
<div class='signup'>Sign Up</div>
<div class='login'>Login</div>
</div>
</div>
</body>
</html>

Далее нужно создать таблицу стилей styles.css. Выглядеть это будет не очень презентабельно: просто синяя полоса меню во всю ширину с белым блоком в ней. Обратите внимание, что для центрирования меню мы будем использовать flexbox вместо уже привычной техники auto-margin.

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

.menu-container {
color: #fff;
background-color: #5995DA; /* синий */
padding: 20px 0;
}

.menu {
border: 1px solid #fff; /* для отладки */
width: 900px;
}

Напоследок скачайте несколько изображений для нашего примера веб-страницы. Распакуйте их в проект flexbox, сохранив родительский каталог images. Ваш проект должен выглядеть примерно так:

Interneting is hard HTML+CSS
Скриншот 4: скриншот файлов проекта
обзор
flexbox overview

Flexbox использует два типа блоков, которые мы никогда не видели раньше: "flex контейнеры" [flex containers] и "flex элементы" [flex items]. Задача flex контейнера - сгруппировать несколько flex элементов и определить, как они будут располагаться.

Interneting is hard HTML+CSS
Скриншот 5: flex-контейнер в виде выделенного контейнера, обертывающего серые элементы, и flex-элементы в виде выделенных блоков внутри контейнера

Каждый HTML-элемент, являющийся прямым дочерним элементом flex контейнера, представляет собой "элемент" [flex item]. Flex элементами можно манипулировать по отдельности, но в основном их расположение определяет контейнер. Основная задача flex элементов - сообщить контейнеру, сколько элементов ему нужно расположить.

Как и в случае с макетами на основе плавающих элементов [floats], создание сложных веб-страниц с помощью flexbox сводится к созданию вложенных блоков. Вы выравниваете кучу flex элементов внутри контейнера, и, в свою очередь, эти элементы могут служить flex контейнерами для своих собственных элементов. Работая с примерами этого урока, помните, что основная задача компоновки страницы не изменилась: мы по-прежнему просто перемещаем группу вложенных блоков.

флекс-контейнеры
flex containers

Первый шаг в использовании flexbox - превращение одного из наших HTML-элементов в flex-контейнер. Для этого мы используем свойство display, которое должно быть знакомо нам по уроку Блочная модель в CSS. Значение flex сообщает браузеру, что все в блоке должно отображаться с помощью flexbox, а не блоковой модели, как это делается по умолчанию.

Добавьте следующую строку в наше правило .menu-container, чтобы превратить его в flex контейнер:

.menu-container {
/* ... */
display: flex;
}

Это активирует режим верстки flexbox - без него браузер будет игнорировать все свойства flexbox, которые мы сейчас рассмотрим. Явное определение flex-контейнеров означает, что вы можете смешивать и сочетать flexbox с другими моделями верстки (например, с плавающими элементами и всем тем, что мы будем изучать в разделе Продвинутое позиционирование).

Interneting is hard HTML+CSS
Скриншот 6: смешивание и сочетание макета flexbox с блочными блоками и плавающими элементами

Ура! У нас есть flex контейнер с одним flex элементом в нем. Однако наша страница будет выглядеть точно так же, как и раньше, потому что мы не указали контейнеру, как отображать его элемент.

Выравнивание элемента
aligning a flex item

После того как вы создали flex-контейнер, нужно задать горизонтальное выравнивание его элементов. Для этого предназначено свойство justify-content. Мы можем использовать его, чтобы выровнять по центру наше .menu, как показано ниже:

.menu-container {
/* ... */
display: flex;
justify-content: center; /* добавьте это */
}

Это имеет тот же эффект, что и добавление объявления margin: 0 auto к элементу .menu. Но обратите внимание, что мы добавили свойство к родительскому элементу (flex-контейнеру), а не непосредственно к элементу, который мы хотим выровнять по центру (flex-элементу). Управление элементами через их контейнеры является общей темой в flexbox, и это немного отличается от того, как мы позиционировали блоки до сих пор.

Interneting is hard HTML+CSS
Скриншот 7: flex-start (3 блока с выравниванием по левому краю), center (3 блока с выравниванием по центру), flex-end (3 блока с выравниванием по правому краю)

Другие значения для justify-content показаны ниже:

Попробуйте изменить justify-content на flex-start и flex-end. Это позволит выровнять меню по левой и правой стороне окна браузера соответственно. Не забудьте изменить его обратно на center, прежде чем двигаться дальше. Последние две опции полезны только когда в контейнере находятся несколько flex-элементов.

Распределение нескольких элементов
distributing multiple flex items

"Подумаешь! Мы уже умеем выравнивать влево/вправо с помощью плавающих элементов и центрировать с помощью auto-margins" - скажете вы. Верно. Но Flexbox не проявляет себя по-настоящему, пока в контейнере всего один элемент. Свойство justify-content также позволяет равномерно распределить элементы внутри контейнера.

Interneting is hard HTML+CSS
Скриншот 8: space-around (3 блока с одинаковым пространством между ними и их контейнером), space-between (3 блока с пробелами между ними, но не между их контейнером)

Измените наше правило .menu следующим образом:

.menu {
border: 1px solid #fff;
width: 900px;
display: flex;
justify-content: space-around;
}

Это превращает наше .menu во вложенный flex контейнер, а значение space-around распределяет его элементы по всей ширине. Вы должны увидеть что-то вроде этого:

Interneting is hard HTML+CSS
Скриншот 9: веб-страница, на которой элементы <li> строки меню размещены с использованием пространства между ними

Flex-контейнер автоматически распределяет дополнительное горизонтальное пространство по обе стороны от каждого элемента. Значение space-between аналогично, но оно только добавляет дополнительное пространство между элементами. Это именно то, что требуется для нашей страницы. Поэтому обновите строку justify-content:

justify-content: space-between;

Конечно, вы также можете использовать здесь center, flex-start, flex-end, если хотите сдвинуть все элементы в ту или иную сторону. Но давайте оставим значение space-between.

группировка элементов
grouping flex items

Flex контейнеры умеют позиционировать только элементы, находящиеся уровнем ниже (то есть свои дочерние элементы). Их нисколько не волнует, что находится внутри тех flex элементов. Это означает, что группировка flex элементов - еще одно оружие в вашем арсенале для создания HTML-макета. Если обернуть множество элементов в дополнительный <div>, получится совершенно другая веб-страница.

Interneting is hard HTML+CSS
Скриншот 10: обертывание двух flex-элементов в <div> для устранения одного из flex-элементов

Предположим, вы хотите, поместить ссылки Sign Up и Login в правую часть страницы (см. скриншот ниже). Для этого достаточно поместить их в другой <div>:

<div class='menu'>
<div class='date'>Aug 14, 2016</div>
<div class='links'>
<div class='signup'>Sign Up</div> <!-- это вложено -->
<div class='login'>Login</div> <!-- и это вложено -->
</div>
</div>

Вместо трех элементов в нашем flex-контейнере .menu теперь только два (.date и .links). В соответствии с существующим поведением пространства между ними, они будут привязаны к левой и правой стороне страницы.

Interneting is hard HTML+CSS
Скриншот 11: веб-страница, c двумя полями меню, внутри контейнеров <div>

Но теперь нам нужно разместить элемент .links, поскольку он использует стандартный режим блокового размещения. Решение: больше вложенных flex-контейнеров! Добавьте новое правило в наш файл styles.css, которое превратит элемент .links в flex-контейнер:

.links {
border: 1px solid #fff; /* для отладки */
display: flex;
justify-content: flex-end;
}

.login {
margin-left: 20px;
}

Это позволит разместить наши ссылки именно там, где мы хотим. Обратите внимание, что поля по-прежнему работают так же, как и в блоковой модели CSS. Как и в обычной блоковой модели, в flexbox особое значение имеют auto отступы (подробнее об этом в конце урока).

Interneting is hard HTML+CSS
Скриншот 12: поля меню, размещенные с помощью вложенных контейнеров flexbox

Белые рамки нам больше не понадобятся. Можно их смело удалить.

выравнивание по оси (вертикальное)
cross-axis (vertical) alignment

До сих пор мы манипулировали горизонтальным выравниванием, но flex-контейнеры могут также определять вертикальное выравнивание своих элементов. Это то, что просто невозможно сделать с плавающими элементами.

Interneting is hard HTML+CSS
Скриншот 13: justify-content (слева и справа), align-items (сверху и снизу)

Чтобы изучить это, нам нужно добавить заголовок под нашим меню. Добавьте следующую разметку в файл flexbox.html после элемента .menu-container:

<div class='header-container'>
<div class='header'>
<div class='subscribe'>Subscribe ▾</div>
<div class='logo'><img src='images/awesome-logo.svg'/></div>
<div class='social'><img src='images/social-icons.svg'/></div>
</div>
</div>

Затем добавьте несколько базовых стилей, чтобы выровнять его по элементу .menu:

.header-container {
color: #5995DA;
background-color: #D6E9FE;
display: flex;
justify-content: center;
}

.header {
width: 900px;
height: 300px;
display: flex;
justify-content: space-between;
}

Все это должно быть знакомо, однако сценарий немного отличается от нашего меню. Так как .header имеет явную высоту, элементы могут быть расположены вертикально внутри него. В официальной спецификации это называется "выравнивание по оси" [cross-axis] - вскоре узнаете, почему. Но для наших целей это можно назвать "вертикальным" выравниванием.

Interneting is hard HTML+CSS
Скриншот 14: вертикальное выравниванием в контейнере заголовка с помощью свойства align-items

Вертикальное выравнивание определяется добавлением свойства align-items к flex-контейнеру. Чтобы наша страница-пример соответствовала приведенному выше скриншоту, добавьте следующую строку:

.header {
/* ... */
align-items: center; /* добавьте это */
}

Варианты свойства align-items аналогичны justify-content:

Interneting is hard HTML+CSS
Скриншот 15: flex-start (блоки в верху контейнера), center (блоки в центре контейнера), flex-end (блоки в низу контейнера, stretch (блоки, заполняющие высоту контейнера)

Большинство из вышеназванных вариантов довольно просты. С вариантом stretch стоит немного поэкспериментировать, потому что stretch позволяет отобразить фон каждого элемента. Давайте рассмотрим это ближе, добавив в файл styles.css следующее:

.header {
/* ... */
align-items: stretch; /* Измените это */
}

.social,
.logo,
.subscribe {
border: 1px solid #5995DA;
}

Блок для каждого элемента расширяется на всю высоту flex-контейнера, независимо от того, сколько контента он содержит. Чаще всего такое поведение используется для создания колонок одинаковой высоты с переменным количеством контента в каждой из них - что очень сложно сделать с плавающими элементами.

Перед тем как двигаться дальше, обязательно удалите вышеуказанные изменения и вертикально отцентрируйте наш контент внутри .header.

обертывание элементов
wrapping flex items

Flexbox - это более мощная альтернатива grid-сеткам на основе плавающих элементов. Он может не только отображать элементы в виде сетки, но и изменять их выравнивание, направление, порядок и размер. Для создания сетки нам понадобится свойство flex-wrap.

Interneting is hard HTML+CSS
Скриншот 16: без обертывания (блоки выходят за пределы контейнера), с обертыванием (блоки переходят на следующую строку в контейнере)

Добавьте ряд фотографий в файл flexbox.html, чтобы нам было с чем работать. Поместите их внутрь <body>, под элементом .header-container:

<div class='photo-grid-container'>
<div class='photo-grid'>
<div class='photo-grid-item first-item'>
<img src='images/one.svg'/>
</div>
<div class='photo-grid-item'>
<img src='images/two.svg'/>
</div>
<div class='photo-grid-item'>
<img src='images/three.svg'/>
</div>
</div>
</div>

Опять же, соответствующие CSS должны быть вам знакомы по предыдущим секциям:

.photo-grid-container {
display: flex;
justify-content: center;
}

.photo-grid {
width: 900px;
display: flex;
justify-content: flex-start;
}

.photo-grid-item {
border: 1px solid #fff;
width: 300px;
height: 300px;
}

Все должно работать, как и ожидалось, но посмотрите, что произойдет, если мы добавим больше элементов, чем поместится в flex-контейнер. Вставьте две дополнительные фотографии в .photo-grid:

<div class='photo-grid-item'>
<img src='images/four.svg'/>
</div>
<div class='photo-grid-item last-item'>
<img src='images/five.svg'/>
</div>

По умолчанию они вытекают за край страницы:

Interneting is hard HTML+CSS
Скриншот 17: веб-страница с неправильной версткой из-за отсутствия обертывания flexbox

Такое вытекание за край еще можно оправдать, если вы пытаетесь создать баннер с горизонтальной прокруткой кучи фотографий, но это совсем, совсем не то, чего мы хотим. Мы хотим, чтобы не помещающиеся элементы смещались в следующий ряд. Для этого воспользуемся свойством flex-wrap:

.photo-grid {
/* ... */
flex-wrap: wrap;
}

Теперь наши flex-элементы ведут себя так же, как плавающие элементы, только flexbox дает нам больше контроля над тем, как "лишние" элементы выравниваются в последней строке с помощью свойства justify-content. Например, последняя строка сейчас выровнена по левому краю. Попробуйте выровнять ее по центру, обновив наше правило .photo-grid, например, так:

.photo-grid {
width: 900px;
display: flex;
justify-content: center; /* Измените это */
flex-wrap: wrap;
}

Добиться этого с макетами на основе плавающих элементов невероятно сложно.

Interneting is hard HTML+CSS
Скриншот 18: веб-страница, с корректной grid-сеткой, созданной с помощью правильного обертывания flexbox
направление контейнера
flex container direction

"Направление" означает, в каком направлении контейнер отображает свои элементы - горизонтально или вертикально. До сих пор все контейнеры, которые мы видели, использовали горизонтальное направление по умолчанию, что означает, что элементы рисуются один за другим в одной строке, а затем переходят в следующий столбец, когда заканчивается место.

Interneting is hard HTML+CSS
Скриншот 19: ряд (ROW - 3 горизонтальных блока), столбец (COLUMN - 3 вертикальных блока)

Одна из самых удивительных вещей в flexbox - его способность преобразовывать ряды в столбцы с помощью всего одной строки CSS. Попробуйте добавить следующее объявление flex-direction в наше правило .photo-grid:

.photo-grid {
/* ... */
flex-direction: column;
}

Это изменит направление контейнера по сравнению со стандартным значением ряда [row value]. Вместо сетки наша страница теперь имеет одну вертикальную колонку:

Interneting is hard HTML+CSS
Скриншот 20: веб-страница с сеткой, превращенная в вертикальный столбец ячеек

Ключевым условием адаптивного дизайна является одна HTML-разметка как для мобильных, так и ноутбуков/ПК. Небольшая проблема состоит в том, что большинство мобильных макетов имеют одну колонку, в то время как большинство макетов для ноутбуков/ПК располагают элементы горизонтально. Только представьте, насколько полезным станет flex-direction, когда мы начнем создавать адаптивные макеты.

АСПЕКТЫ ВЫРАВНИВАНИЯ
alignment considerations

Обратите внимание, что колонка прижимается к левой стороне своего flex-контейнера, несмотря на наше объявление justify-content: center;. Когда вы меняете направление контейнера, вы также меняете направление свойства justify-content. Теперь оно относится к вертикальному выравниванию контейнера, а не к горизонтальному.

Interneting is hard HTML+CSS
Скриншот 21: оси перевернуты, когда flex-direction равно column

Чтобы горизонтально выровнять колонку, нам нужно задать свойство align-items для нашей .photo-grid:

.photo-grid {
/* ... */
flex-direction: column;
align-items: center; /* Добавьте это */
}

порядок контейнеров
flex container order

До сих пор существовала тесная взаимосвязь между порядком расположения HTML-элементов и тем, как блоки отображаются на веб-странице. С помощью плавающих элементов или техники flexbox, которую мы сейчас изучаем, единственный способ заставить блок отображаться перед или после другого блока - это перемещение по HTML-разметке. Однако скоро все изменится.

Interneting is hard HTML+CSS
Скриншот 22: ряд (ROW - слева направо), обратный ряд (ROW-REVERSE - справа налево), столбец (COLUMN - сверху вниз), обратный столбец (COLUMN-REVERSE - снизу вверх)

Свойство flex-direction тоже позволяет контролировать порядок отображения элементов с помощью свойств row-reverse и column-reverse. Чтобы увидеть это в действии, преобразуем наш столбец обратно в сетку, но на этот раз мы изменим порядок отображения:

.photo-grid {
width: 900px;
display: flex;
justify-content: center;
flex-wrap: wrap;
flex-direction: row-reverse; /* <--- Реально офигенно круто! */
align-items: center;
}

Теперь оба ряда отображаются справа налево, а не слева направо. Но обратите внимание, что порядок меняется только для каждой строки: первый ряд начинается не с 5, а с 3. Это полезное поведение для многих распространенных паттернов дизайна (в частности, обратный порядок колонок открывает много возможностей для мобильных макетов). В следующем разделе вы научитесь еще большей детализации.

Interneting is hard HTML+CSS
Скриншот 23: веб-страница, на которой строки сетки отображаются в обратном порядке (3, 2, 1 в первом ряду и 5, 4 во втором)

Переупорядочивание элементов внутри таблицы стилей - это серьезное дело. До появления flexbox для этого приходилось прибегать к хакам JavaScript. Однако не стоит злоупотреблять своими новыми возможностями. Как уже говорилось в начале учебника, всегда следует отделять структуру от презентации. Изменение порядка является чисто визуальным - ваш HTML должен быть понятен и без применения этих стилей.

порядок элементов
flex item order

Весь этот урок до сего момента был посвящен позиционированию flex элементов через их родительские контейнеры. Однако также существует возможность управлять отдельными элементами. В оставшейся части урока мы сместим фокус с flex контейнеров на элементы, которые в них содержатся.

Interneting is hard HTML+CSS
Скриншот 24: настройка порядка отдельных flex элементов через свойство order

Добавление свойства order к flex элементу определяет его порядок в контейнере, не затрагивая окружающие элементы. По умолчанию его значение равно 0, а увеличение или уменьшение этого значения перемещает элемент вправо или влево соответственно.

Это можно использовать, например, чтобы поменять местами порядок элементов .first-item и .last-item в нашей сетке. Мы также должны изменить значение row-reverse из предыдущего раздела обратно на row, потому что так будет немного легче распознать наши исправления:

.photo-grid {
/* ... */
flex-direction: row; /* Обновите это */
align-items: center;
}

.first-item {
order: 1;
}

.last-item {
order: -1;
}

В отличие от настроек row-reverse и column-reverse в flex контейнере, порядок действует вне границ рядов/колонок. Приведенный выше фрагмент поменяет местами первый и последний элементы, даже если они находятся в разных рядах.

выравнивание элементов
flex item alignment

То же самое мы можем сделать с вертикальным выравниванием. Что если мы хотим, чтобы ссылка "Подписаться" [Subscribe] и иконки соцсетей находились внизу заголовка, а не в центре? Выровняйте их по отдельности! Здесь на помощь приходит свойство align-self. Добавление этого свойства к элементу flex отменяет значение align-items из его контейнера:

.social
.subscribe {
align-self: flex-end;
margin-bottom: 20px;
}

Это должно отправить их в нижнюю часть .header. Обратите внимание, что и margin и padding действуют так, как от них ожидается.

Interneting is hard HTML+CSS
Скриншот 25: веб-страница, показывающая иконки, с помощью свойства align-self выровненные по нижнему краю [bottom-aligned]

Элементы можно выравнивать и другими способами, используя те же значения, что и свойство align-items, перечисленные ниже для удобства.

гибкие элементы
flexible items

Все наши примеры были связаны с элементами с фиксированной шириной или определяемой контентом шириной. Это позволило нам сосредоточиться на аспектах позиционирования flexbox, но это также означает, что мы игнорировали природу "гибкого блока". Flex элементы являются гибкими: они могут сжиматься и растягиваться в соответствии с шириной своих контейнеров.

Свойство flex определяет ширину отдельных элементов в flex контейнере. Точнее, оно позволяет им иметь гибкую ширину. Оно работает как некий коэффициент веса [weight], указывающий flex контейнеру, как распределить дополнительное пространство между элементами. Например, элемент со значением flex, равным 2, будет увеличиваться в два раза быстрее, чем элементы с стандартным значением, равным 1.

Interneting is hard HTML+CSS
Скриншот 26: отсутствие flex (3 квадратных блока), равный flex (3 прямоугольных блока), неравный flex (2 меньших блока, один вытянутый)

Для дальнейших экспериментов нам нужен футер. Вставьте его после элемента .photo-grid-container:

<div class='footer'>
<div class='footer-item footer-one'></div>
<div class='footer-item footer-two'></div>
<div class='footer-item footer-three'></div>
</div>

Затем, немного CSS:

.footer {
display: flex;
justify-content: space-between;
}

.footer-item {
border: 1px solid #fff;
background-color: #D6E9FE;
height: 200px;
flex: 1;
}

Этот flex: 1; велит элементам растягиваться в соответствии с шириной .footer. Поскольку все они имеют одинаковый вес [weight], они будут растягиваться одинаково:

Interneting is hard HTML+CSS
Скриншот 27: три одинаковых голубых блока, растянутые по всей ширине футера

Если увеличить вес одного из элементов, он будет расти быстрее остальных. Например, мы можем заставить третий элемент расти в два раза быстрее, чем два других, с помощью следующего правила:

.footer-three {
flex: 2;
}

Сравните это со свойством justify-content, которое распределяет дополнительное пространство между элементами. Это выглядит похоже, но теперь мы распределяем это пространство в самих элементах. В результате мы полностью контролируем размещение гибких элементов в своих контейнерах.

ЭЛЕМЕНТЫ ФИКСИРОВАННОЙ ШИРИНЫ
static item widths

Мы даже можем сочетать гибкие блоки с блоками фиксированной ширины. В flex: initial происходит возврат к конкретному свойству ширины элемента. Это позволяет нам по-разному комбинировать статические и гибкие блоки.

Interneting is hard HTML+CSS
Скриншот 28: блок фиксированной ширины (flex: initial), гибкий блок (flex: 1)

Мы хотим, чтобы наш футер вел себя так, как на скриншоте выше. Гибкий блок в центре, а те, что по обе стороны, фиксированной ширины. Все, что для этого нужно сделать - добавить следующее правило в нашу таблицу стилей:

.footer-one
.footer-three {
background-color: #5995DA;
flex: initial;
width: 300px;
}

Без этого flex: initial; объявление flex: 1; было бы унаследовано от правила .footer-item, в результате чего свойства ширины игнорировались бы. initial исправляет это, и мы получаем гибкий макет, который также содержит элементы фиксированной ширины. Измененяя размер окна браузера, мы увидим, что в футере изменяется только размер среднего блока.

Interneting is hard HTML+CSS
Скриншот 29: два блока фиксированной ширины по обе стороны от гибкого блока. Все три полностью заполняют весь футер.

Это довольно распространенная компоновка, и не только в футерах. Например, на многих сайтах есть боковая панель фиксированной ширины (или несколько боковых панелей) и гибкий блок контента, содержащий основной текст страницы. По сути, это более насыщенная версия футера, который мы только что создали.

элементы и отступы
flex items and auto-margins

Auto отступы [auto-margins] в flexbox - это нечто особенное. Они могут использоваться как альтернатива дополнительному <div> при попытке выровнять группу элементов по левому/правому краю контейнера. Воспринимайте auto-margin как "разделитель" для flex элементов в одном контейнере.

Давайте посмотрим, как выровнять наши элементы в .menu, чтобы получилось следующее:

<div class='menu-container'>
<div class='menu'>
<div class='date'>Aug 14, 2016</div>
<div class='signup'>Sign Up</div>
<div class='login'>Login</div>
</div>
</div>

При перезагрузке страницы пункты должны равномерно распределиться по нашему меню, как в начале главы. Мы можем воспроизвести желаемый макет, вставив auto-margin между пунктами, которые мы хотим отделить, как показано ниже:

.signup {
margin-left: auto;
}

auto-margin съедает все лишнее пространство в flex-контейнере, поэтому вместо равномерного распределения элементов, мы перемещаем .signup и все следующие элементы (.login) в правую часть контейнера. Получится точно такой же макет, как и раньше, но без лишнего вложенного <div> для группировки. Иногда приятнее оставить HTML более простым.

резюме

Flexbox дал нам тонну потрясающих новых инструментов для верстки веб-страниц. Сравните эти приемы с тем, что мы могли сделать с float элементами, и станет ясно, что flexbox - это более совершенный способ компоновки современных веб-сайтов:

Помните, что эти свойства flexbox - всего лишь язык, позволяющий указывать браузерам, как расположить множество HTML-элементов. Самое сложное - это не написание HTML- и CSS-кода, а концептуальное (на листе бумаги) определение поведения всех необходимых блоков для создания желаемого макета.

Когда дизайнер передает вам эскиз для воплощения, ваша первая задача - нарисовать на нем кучу блоков и определить, как они должны складываться, растягиваться и сжиматься, чтобы добиться желаемого дизайна. Как только вы это сделаете, вам будет довольно легко создать код, используя новые техники flexbox.

Режим верстки flexbox должен использоваться для большинства ваших веб-страниц, но есть некоторые вещи, с которыми он не очень хорошо справляется, например, мягкая настройка положения элементов и предотвращение их взаимодействия с остальной частью страницы. После того как на следующем уроке мы рассмотрим эти виды продвинутых техник позиционирования, вы станете экспертом по позиционированию в HTML и CSS.


HTML & CSS IS HARD - НА РУССКОМ

ПРОДВИНУТОЕ ПОЗИЦИОНИРОВАНИЕ

УРОК Nº 9.

Самое понятное руководство по статическому, относительному, абсолютному и фиксированному позиционированию

Под "статическим позиционированием" подразумевается нормальный поток страницы, с которым мы работали до сих пор. Блоковая модель CSS, float элементы и схемы верстки flexbox работают в этом "статическом" потоке, но это не единственная схема позиционирования, доступная в CSS.

Interneting is hard HTML+CSS
Скриншот 1: сравнение схем статического, относительного, абсолютного и фиксированного позиционирования

Три других типа позиционирования - "относительное", "абсолютное" и "фиксированное". Каждый из них позволяет вручную позиционировать элементы по определенным координатам, в отличие от более семантических вариантов flexbox и floats. Вместо того чтобы сказать: "Этот блок поместить в центр его контейнера", продвинутое позиционирование позволяет сказать нечто-то вроде: "Этот блок поместить на 20 пикселей выше и на 50 пикселей правее от начала координат его родителя".

Подавляющее большинство элементов на веб-странице должно быть расположено в соответствии со статическим потоком страницы. Другие схемы позиционирования появляются, когда вы хотите сделать более сложные вещи, например, изменить положение определенного элемента или анимировать компонент пользовательского интерфейса, не испортив окружающие элементы.

Эта глава состоит из двух частей. Мы начнем с изучения относительного, абсолютного и фиксированного позиционирования по отдельности, а затем применим все, что узнали, к созданию шикарного выпадающего меню.

подготовка
setup

Начните с создания нового проекта Atom под названием advanced-positioning и нового файла schemes.html со следующей разметкой:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Positioning Is Easy!</title>
<link rel='stylesheet' href='styles.css'/>
</head>
<body>

<div class='container'>
<div class='example relative'>
<div class='item'><img src='images/static.svg' /></div>
<div class='item item-relative'><img src='images/static.svg' /></div>
<div class='item'><img src='images/static.svg' /></div>
</div>
</div>

<div class='container'>
<div class='example absolute'>
<div class='item'><img src='images/static.svg' /></div>
<div class='item item-absolute'><img src='images/absolute.svg' /></div>
<div class='item'><img src='images/static.svg' /></div>
</div>
</div>

<div class='container'>
<div class='example fixed'>
<div class='item'><img src='images/static.svg' /></div>
<div class='item item-fixed'><img src='images/fixed.svg' /></div>
<div class='item'><img src='images/static.svg' /></div>
</div>
</div>

</body>
</html>

У нас есть три примера для работы, все с одинаковой HTML-структурой. Изменение поведения позиционирования в каждом из них будет иметь кардинально разные эффекты.

Interneting is hard HTML+CSS
Скриншот 2: файлы в проекте примера

На этой странице используются изображения, чтобы сделать наш пример немного нагляднее. При распаковке файлов в проект сохраняйте родительскую папку images, как показано выше. Не забудьте также создать файл styles.css и заполнить его необходимыми базовыми стилями:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
height: 1200px;
}

.container {
display: flex;
justify-content: center;
}

.example {
display: flex;
justify-content: space-around;
}

width: 800px;
margin: 50px 0;
background-color: #D6E9FE;
}

.item img {
display: block;
}

Здесь нет ничего нового, просто знакомые приемы flexbox для создания сетки элементов. Единственная особенность - четко указанная высота элемента <body>, которая позволит нам прокручивать страницу вверх и вниз, чтобы продемонстрировать различные варианты позиционирования.

Interneting is hard HTML+CSS
Скриншот 3: веб-страница со статичными, относительными [relative], абсолютными и фиксированными блоками разных цветов
позиционированные элементы
positioned elements

Свойство CSS position позволяет изменять схему позиционирования конкретного элемента. Его значение по умолчанию, как можно догадаться, статично. Если свойство position элемента не имеет значения static, он называется "позиционированным элементом". Именно позиционированным элементам посвящен весь этот урок.

Interneting is hard HTML+CSS
Скриншот 4: относительные, абсолютные и фиксированные элементы, обозначаемые как позиционированные элементы

Можно смешивать и сочетать различные схемы позиционирования. Опять же, большая часть вашей веб-страницы должна быть статически позиционирована, но часто можно встретить относительно и абсолютно позиционированные элементы внутри других элементов, которые являются частью нормального потока страницы.

относительное позиционирование
relative positioning

"Относительное позиционирование" перемещает элементы относительно того места, где они обычно появляются в статическом потоке страницы. Это полезно для перемещения блоков, когда стандартный поток немного смещен.

Interneting is hard HTML+CSS
Скриншот 5: относительно позиционированный блок смещен относительно левого верхнего угла своей статической позиции

Давайте превратим элемент .item-relative в файле schemes.html в относительно позиционированный элемент. Добавьте следующее правило в styles.css:

.item-relative {
position: relative;
top: 30px;
left: 30px;
}

Благодаря position: relative; он становится позиционированным элементом, а свойства top и left позволяют определить, насколько он смещен от своего статического положения. Это похоже на задание координат (x, y) для элемента.

Interneting is hard HTML+CSS
Скриншот 6: веб-страница с относительно (relative) позиционированным элементом

Относительное позиционирование работает аналогично отступам margin, с одним очень важным отличием: значения top и left не влияют ни на окружающие элементы, ни на родительский элемент. Все остальное отображается так, как если бы .item-relative находился в своем исходном положении. Смещение можно рассматривать как действие, применяемое после того, как браузер завершит компоновку страницы.

Свойства top и left отмеряются от верхнего и левого краев исходного блока. С помощью свойств bottom и right мы можем задать смещение относительно других краев.

Interneting is hard HTML+CSS
Скриншот 7: верхнее, левое, нижнее и правое смещение относительно позиционированного элемента

Например, следующий код сдвинет блок в противоположном направлении:

.item-relative {
position: relative;
bottom: 30px;
right: 30px;
}

Обратите внимание, что эти свойства принимают отрицательные значения, что означает два способа задать одно и то же смещение. Мы могли бы с тем же успехом использовать top: -30px; вместо объявленного ранее bottom: 30px;.

абсолютное позиционирование
absolute positioning

"Абсолютное позиционирование" - это то же самое, что и относительное позиционирование, но смещение происходит относительно всего окна браузера, а не исходной позиции элемента. Поскольку в этом случае нет никакой связи со статическим потоком страницы. Считайте, что это самый ручной способ размещения элемента.

Interneting is hard HTML+CSS
Скриншот 8: абсолютно позиционированный элемент, смещенный от левого верхнего края окна браузера

Давайте рассмотрим это, добавив следующее правило в нашу таблицу стилей:

.item-absolute {
position: absolute;
top: 10px;
left: 10px;
}

Наша HTML-структура точно такая же, как и в предыдущем примере, но в этом случае фиолетовое изображение будет помещено в левый верхний угол окна браузера. Вы также можете попробовать задать значение bottom или right, чтобы получить более четкое представление о происходящем.

Interneting is hard HTML+CSS
Скриншот 9: веб-страница с абсолютно позиционированным элементом

Другой интересный эффект абсолютного позиционирования заключается в том, что оно полностью удаляет элемент из нормального потока страницы. Это легче увидеть на примере элементов, выровненных по левому краю, поэтому давайте временно изменим свойство justify-content в нашем правиле .example:

.example {
display: flex;
justify-content: flex-start; /* Обновите это */
/* ... */
}

В нашем примере с относительным позиционированием (первый ряд) на месте позиционируемого элемента все еще остается пространство, а при абсолютном позиционировании это пространство исчезает. Как будто .item-absolute даже не существует для своего родителя и окружающих элементов. Перед тем как двигаться дальше, обязательно измените justify-content обратно на space-around.

Interneting is hard HTML+CSS
Скриншот 10: веб-страница, выделяющая пустое пространство, оставленное абсолютно позиционированным элементом

В большинстве случаев такое поведение не слишком полезно, поскольку в этом случае все на вашей странице должно быть абсолютно позиционировано - иначе мы получим непредсказуемые наложения статических элементов на абсолютные. Итак, зачем вообще существует absolute?

(ОТНОСИТЕЛЬНО) АБСОЛЮТНОЕ ПОЗИЦИОНИРОВАНИЕ
(RELATIVELY) ABSOLUTE POSITIONING

Абсолютное позиционирование становится гораздо более практичным, когда оно осуществляется относительно какого-либо другого элемента, находящегося в статическом потоке страницы. К счастью, существует способ изменить систему координат абсолютно позиционированного элемента.

Interneting is hard HTML+CSS
Скриншот 11: абсолютный элемент, позиционированный относительно родительского позиционированного элемента

Координаты абсолютных элементов всегда относительны к ближайшему контейнеру, который является позиционированным элементом. Он становится относительным по отношению к браузеру только тогда, когда ни один из его родителей не позиционирован. Так, если мы изменим родительский элемент .item-absolute на относительно позиционированный, он должен появиться в левом верхнем углу этого элемента, а не в окне браузера.

.absolute {
position: relative;
}

div-контейнер .absolute располагается в соответствии с нормальным потоком страницы, и мы можем вручную перемещать наш .item-absolute, куда нам нужно. Это великолепно, потому что если мы захотим изменить нормальный поток контейнера, скажем, для мобильного макета, любые абсолютно позиционированные элементы автоматически передвинутся вместе с ним.

Interneting is hard HTML+CSS
Скриншот 12: веб-страница с абсолютно позиционированным элементом внутри другого элемента, который позиционирован относительно

Обратите внимание, что мы не указали никаких координат смещения для .absolute. Мы используем относительное позиционирование только для того, чтобы позволить нашему абсолютному элементу вернуться в нормальный поток страницы. Так мы безопасно сочетаем абсолютное позиционирование со статическим позиционированием.

фиксированное позиционирование
fixed positioning

У "фиксированного позиционирования" много общего с абсолютным: оно очень "ручное", элемент удален от нормального течения страницы, а система координат относительна ко всему окну браузера. Ключевое отличие заключается в том, что фиксированные элементы не прокручиваются вместе с остальной частью страницы.

Interneting is hard HTML+CSS
Скриншот 13: фиксированный элемент, расположенный относительно окна браузера, но с отключенной прокруткой

Перейдем к обновлению нашего третьего примера, чтобы использовать фиксированное позиционирование:

.item-fixed {
position: fixed;
bottom: 0;
right: 0;
}

В результате красная картинка окажется в правом нижнем углу экрана. Попробуйте прокрутить страницу, и вы обнаружите, что она не перемещается вместе с остальными элементами на странице, в то время как абсолютно позиционированная фиолетовая картинка перемещается.

Так создаются навигационные панели, которые всегда остаются на экране, а также назойливые всплывающие и упорно не исчезающие pop-up баннеры.

позиционированные элементы для анимации
positioned elements for animation

Это немного выходит за рамки данного руководства, поскольку речь идет о HTML и CSS, а не о JavaScript. Однако анимация - это один из основных вариантов использования относительного и абсолютного позиционирования, поэтому давайте заглянем в будущее, анимировав один из наших элементов.

Эти усовершенствованные схемы позиционирования позволяют JavaScript перемещать элементы, избегая при этом какого-либо взаимодействия с окружающими элементами. Например, попробуйте скопировать и вставить следующее в файл schemes.html после третьего элемента .container. Элемент <script> должен быть последним внутри <body>.

<script>
var left = 0;

function frame() {
var element = document.querySelector('.item-relative');
left += 2;
element.style.left = left + 'px';
if (left >= 300) {
clearInterval(id)
}
}

var id = setInterval(frame, 10)
</script>

Этот код JavaScript создает простую анимацию, которая постоянно обновляет свойство left в .item-relative. При перезагрузке страницы вы должны увидеть, что синее изображение плавает по правому краю своего контейнера.

Interneting is hard HTML+CSS
Скриншот 14: веб-страница, показывающая простую анимацию относительно позиционированного элемента

Это довольно примитивный пример, но вы, надеюсь, видите, как он применим к причудливым анимациям пользовательского интерфейса. Если бы вы попытались добиться того же эффекта, манипулируя свойствами margin или padding, вы бы невольно переместили статически расположенные блоки и/или содержащий их элемент .example.

позиционированные элементы для меню
positioned elements for menus

Итак, это основные приемы. Давайте сделаем с их помощью что-нибудь продвинутое! В оставшейся части урока мы применим полученные навыки для создания замечательного навигационного меню с интерактивным выпадающим подменю для одной из ссылок. Мы создадим эту страницу с самого нуля.

Interneting is hard HTML+CSS
Скриншот 15: веб-страница с выпадающим меню

Фиксированное позиционирование позволит сделать меню прикрепленным к верхней части страницы, а относительное позиционирование создаст якорь для абсолютно позиционированного выпадающего меню. Мы также поговорим о методиках создания навигационных меню и рассмотрим практическое применение псевдоклассов, о которых мы говорили на уроке Селекторы CSS.

Для начала нам нужна новая веб-страница под названием menu.html, которая имеет заголовок и простое меню верхнего уровня:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Awesome!</title>
<link href='menu.css' rel='stylesheet'/>
</head>
<body>

<div class='header'>
<div class='logo'><img src='images/awesome-logo.svg'/></div>
<ul class='menu'>
<li class='dropdown'><span>Features ▾</span></li>
<li><a href='#'>Blog</a></li>
<li><a href='#'>Subscribe</a></li>
<li><a href='#'>About</a></li>
</ul>
</div>

</body>
</html>

Навигационные меню почти всегда должны быть оформлены в виде списка <ul>, а не кучи элементов <div>. Такая семантика делает навигацию вашего сайта гораздо более доступной для поисковых систем. Также обратите внимание, как мы готовимся к созданию нашего выпадающего меню, добавляя атрибут class к первому <li> в списке. Этот <span> позволит нам отличить ярлык от подменю, которое он открывает.

Далее нам понадобится новая таблица стилей menu.css, которая, помимо прочего, сделает наш .header более похожим на заголовок:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
height: 1200px;
font-size: 18px;
font-family: sans-serif;
color: #5D6063;
}

a:link,
a:visited {
color: #5D6063;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}

.header {
position: fixed;
display: flex;
justify-content: space-between;

width: 100%;
padding: 50px;
background: #D6E9FE;
}

Все это должно быть вам знакомо. Однако обратите внимание на фиксированное положение .header, благодаря которому наше меню навигации находится поверх любого контента, размещенного на странице.

Interneting is hard HTML+CSS
Скриншот 16: веб-страница с меню, составленным из блоков <li> (без позиционирования)
строчные элементы меню
inline menu items

Хотя навигационные меню на большинстве сайтов размечены как неупорядоченные списки, на самом деле они не выглядят как списки. Мы можем исправить это. С помощью свойства display, мы сделаем элементы списка строчными блоками вместо блоковых блоков. Добавьте в menu.css следующее:

.menu {
margin-top: 15px;
}

.menu > li {
display: inline;
margin-right: 50px;
}

.menu > li: last-of-type {
margin-right: 0;
}

Мы используем селекторы дочерних элементов, вместо селекторов потомков. Все потому, что мы хотим выбрать только элементы <li>, находящиеся как раз внутри .menu. Это станет особенно важным, когда мы добавим подменю, имеющее свои собственные элементы <li>, которые мы не хотим стилизовать с помощью этого правила. Также мы добавили отступы margins ко всем элементам списка, но удалили их из последнего <li> псевдоклассом :last-of-type. Отступы margins между элементами - довольно распространенная практика.

Interneting is hard HTML+CSS
Скриншот 17: меню, состоящее из строчных элементов <li> (без позиционирования)
подменю
submenus

Наше подменю будет выглядеть так же, как и меню верхнего уровня, за исключением того, что все оно будет вложено в cписок [list]. Измените элемент .menu следующим образом, чтобы весь список .features-menu был завернут в первый <li> элемента .menu.

<ul class='menu'>
<li class='dropdown'><span>Features &#9662;</span>
<ul class='features-menu'> <!-- Start of submenu -->
<li><a href='#'<Harder</a></li>
<li><a href='#'<Better</a></li>
<li><a href='#'<Faster</a></li>
<li><a href='#'<Stronger</a></li>
</ul> <!-- End of submenu -->
</li>
<li><a href='#'<Blog</a></li> <!-- These are the same -->
<li><a href='#'<Subscribe</a></li>
<li><a href='#'<About</a></li>
</ul>

Это дает много важной информации для поисковых систем. Google увидит, что все эти новые элементы связаны с меткой Features и что они образуют отдельную секцию нашего сайта. Рекомендуем размечать сложные навигационные меню именно таким образом.

Что касается CSS, то с интерактивным выпадающим меню мы разберемся позже. Сейчас же давайте просто приведем наше подменю в нужный вид. Добавьте несколько простых стилей, чтобы было видно блок, который мы пытаемся позиционировать:

.features-menu {
display: flex;
flex-direction: column;
background: #B2D6FF;
border-radius: 5px;
padding-top: 60px;
}

.features-menu li {
list-style: none;
border-bottom: 1px solid #FFF;

padding: flex;
margin: flex;
}

.features-menu li:last-of-type {
border-bottom: none;
}

Само подменю оформлено правильно, но оно отображается в неправильном месте и сильно портит остальные элементы меню верхнего уровня. Этого следовало ожидать, поскольку оно все еще статически позиционировано, а значит, взаимодействует со своим родителем и окружающими элементами.

Interneting is hard HTML+CSS
Скриншот 18: веб-страница с нестилизованным подменю (только HTML)

Для создания желаемой верстки используйте ваши новые навыки позиционирования CSS.

(Относительно) абсолютные подменю
(relatively) absolute submenus

Мы хотим, чтобы остальные элементы меню верхнего уровня отображались так же, как и до добавления подменю, как будто подменю вообще не было. Да это как раз то, как себя ведут абсолютно позиционированные элементы. Давайте попробуем? Добавьте несколько строк в правило .features-menu:

.features-menu {
display: flex;
flex-direction: column;
background: #B2D6FF;
border-radius: 5px;
padding-top: 60px;

position: absolute; /* Добавьте эти строки */
top: -25px;
left: -30px;
}

Отлично! Подменю больше не является частью статического потока страницы, поэтому наши элементы меню верхнего уровня вернулись в нормальное состояние. Однако подменю должно появиться ниже ярлыка Features, а не в углу окна браузера. Какое совпадение... мы только что узнали, как это делается!

Подменю находится в <li class='dropdown'>. Превращение его в позиционированный элемент должно изменить систему координат, используемую нашим абсолютно позиционированным .features-menu:

.dropdown {
position: relative;
}

Однако есть одна проблема. Хотя подменю находится в правильном месте, но теперь оно закрывает ярлык Features.

Interneting is hard HTML+CSS
Скриншот 19: веб-страница с абсолютно позиционированным подменю внутри относительного элемента
z-index

Ранее мы не сталкивались с проблемой "глубины". До сих пор все наши HTML-элементы отображались друг над другом или друг под другом интуитивно понятным образом. Но поскольку мы занимаемся продвинутыми вещами, полагаться на то, что браузер сам определит, какие элементы отображаются поверх других, не стоит.

Свойство z-index позволяет управлять глубиной расположения элементов на странице. Если представить экран как трехмерное пространство, то отрицательные значения z-index уходят дальше вглубь страницы, а положительные - выходят за ее пределы.

Interneting is hard HTML+CSS
Скриншот 20: положительный z-index при выходе со страницы и отрицательный z-index при входе на страницу

Другими словами, элемент .features-menu должен иметь меньший z-index, чем ярлык Features. По умолчанию значение z-index равно 0, поэтому давайте сделаем их оба выше этого значения. Мы удобно обернули ярлык Features в <span>, что позволяет нам стилизовать его с помощью дочернего селектора, как показано ниже:

.dropdown > span {
z-index: 2;
position: relative; /* Это важно! */
cursor: pointer;
}

.features-menu {
/* ... */
z-index: 1;
}

Теперь ярлык Features должен появиться в верхней части подменю. Обратите внимание на строку position: relative;. Она необходима, потому что только позиционированные элементы обращают внимание на свойство z-index. Об этом легко забыть, поэтому сделайте заметку на следующий раз, на случай, если у вас возникнут проблемы с глубиной, а ваши правила CSS не будут иметь никакого результата.

Interneting is hard HTML+CSS
Скриншот 21: подменю после добавления положительного z-индекса

Мы добавили пример использования свойства cursor, чтобы при наведении курсора на ярлык он выглядел как ссылка. Подробнее об этом можно прочитать на сайте Mozilla Developer Network.

псевдоклассы для выпадающих меню
pseudo-classes for dropdown menus

Отлично! Подменю готово! Наша последняя задача - скрыть его, пока пользователь не наведет на него курсор. Помните псевдокласс :hover из главы "Селекторы CSS"? Мы используем его, чтобы превратить наше подменю в интерактивное выпадающее меню.

Сначала нам нужно изменить существующее правило .features-menu, добавив селектор-потомок :hover. Тогда подменю будет видно только когда пользователь наведет на него курсор. Обновите селектор .features-menu следующим образом:

.dropdown:hover .features-menu { /* Раньше это было `.features-menu` */
display: flex; /* Оставьте все остальное в прежнем виде */
flex-direction: column;
background: #B2D6FF;
/* ... */
}

Затем нам нужно будет скрыть подменю с помощью свойства display. Добавьте новое правило в menu.css:

.features-menu { /* Это новое правило. Добавьте его. */
display: none;
}

Установка display в none заставляет элемент полностью исчезнуть. Переопределив это значение с помощью flex в правиле :hover, мы фактически говорим браузеру снова показать .features-menu. Эта хитрая комбинация селекторов-потомков и псевдоклассов позволяет нам по условию скрывать или показывать элемент.

резюме

В этой главе мы рассмотрели четыре новые схемы верстки CSS:

Относительное позиционирование изменяло положение элемента, не затрагивая окружающие его блоки. Абсолютное позиционирование выводило элементы из статического потока страницы и размещало их относительно окна браузера. Относительно абсолютное позиционирование позволяло вернуться в статический поток страницы. Наконец, фиксированное позиционирование позволяло нам создавать элементы, которые не прокручивались вместе с остальной частью страницы.

Interneting is hard HTML+CSS
Скриншот 22: сравнение схем относительного, абсолютного, относительно абсолютного и фиксированного позиционирования

Мы использовали эти новые методы позиционирования для создания довольно сложного навигационного меню. Если оно показалось вам сложным, значит, так оно и было. Но не волнуйтесь, вам не нужно заучивать HTML и CSS, на которых основано наше меню. Ваша цель должна заключаться в том, чтобы месяца через три вы могли вернуться к этому примеру и понять, что делают все эти декларации position: relative; и position: absolute;.

Это меню также является хорошим примером того, как начало работы с HTML-разметкой значительно упрощает жизнь. Сначала мы создали нужную нам смысловую структуру [semantic structure]. Затем мы написали несколько замысловатых CSS, чтобы расположить блоки именно там, где нам нужно. Если вы смотрите на сложный эскиз и не уверены, с чего начать, то это отличный способ начать решать поставленную задачу.

У нашего меню все еще есть одна большая недоработка: оно не создано для мобильных устройств. Во-первых, в смартфонах и планшетах отсутствует курсор. Во-вторых, наш макет не отображается хорошо, если размер браузера менее 960 пикселей. Первое требует немного магии JavaScript (или очень продвинутого CSS), поэтому мы оставим это для другого курса. Но второе мы сможем решить с помощью адаптивного дизайна на следующем уроке.


HTML & CSS IS HARD - НА РУССКОМ

АДАПТИВНЫЙ ДИЗАЙН

УРОК Nº 10.

Учебник веб-разработки для начинающих по созданию сайтов, адаптированных под мобильные устройства

В основе "адаптивного дизайна" заложена идея одинаково хорошего отображения сайта на всех устройствах - от широкоформатных мониторов до смартфонов. Это подход к веб-дизайну, который устраняет различие между мобильной версией сайта и его десктопным аналогом. В случае с адаптивным дизайном это одно и то же.

Адаптивный дизайн осуществляется на основе CSS "медиавыражений" [media queries]. Медиавыражения - это способ условного применения правил CSS. Они указывают браузеру игнорировать или применять определенные правила в зависимости от устройства пользователя.

Interneting is hard HTML+CSS
Скриншот 1: HTML-контент, указывающий на медиа-запросы, которые направлены на мобильные, планшетные и настольные компьютеры

Медиавыражения позволяют представить один и тот же HTML-контент в виде разных CSS-версток. Так, вместо того чтобы поддерживать один сайт для смартфонов и другой, не связанный с ним, для ноутбуков/ПК, можно использовать одну и ту же HTML-разметку (и веб-сервер) для них обоих. Всякий раз, когда мы добавляем новую статью или исправляем опечатку в HTML, эти изменения автоматически отражаются как в мобильном, так и в широкоэкранном макете. Именно по этой причине мы отделяем контент от внешнего вида.

На этом уроке вы узнаете, что медиавыражения - это всего лишь тонкая обертка вокруг старого доброго CSS, с которым мы работали до сих пор. Также вы узнаете, что реализовать адаптивный макет на самом деле довольно просто. А вот адаптивные изображения - это совсем другая история).

подготовка
setup

Создайте новый проект, назвав его responsive-design и новый файл - responsive.html. Это самая пустая веб-страница, которую вы видели на этом курсе, но вскоре она продемонстрирует нечто очень важное.

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Responsive Design</title>
<link rel='stylesheet' href='styles.css'/>
</head>
<body>
<!-- Здесь ничего нет! -->
</body>
</html>

Также для этого урока загрузите несколько изображений. Распакуйте их в ту же папку, что и responsive.html, сохранив родительскую папку images. Ваш проект должен выглядеть примерно так:

Interneting is hard HTML+CSS
Скриншот 2: файловый браузер Atom с файлами проекта в нем
медиавыражения
css media queries

Мы начнем с малого - обновим цвет фона элемента <body> в зависимости от ширины устройства. Это хороший способ убедиться, что наши медиавыражения действительно работают, прежде чем перейдем к сложным макетам.

Interneting is hard HTML+CSS
Скриншот 3: цвета фона для настройки с помощью медиавыражений: смартфон - красный фон, планшет - желтый, десктоп - синий.

Давайте разграничим узкую, среднюю и широкую верстки CSS, создав новую таблицу стилей styles.css и добавив в нее следующее:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

/* Стили для смарфонов */
@media only screen and (max-width: 400px) {
body {
background-color: #F09A9D; /* Красный */
}
}

/* Стили для планшетов */
@media only screen and (min-width: 401px) and (max-width: 960px) {
body {
background-color: #F5CF8E; /* Желтый */
}
}

/* Стили для ноутбуков и ПК */
@media only screen and (min-width: 961px) {
body {
background-color: #B2D6FF; /* Синий */
}
}

При изменении размера браузера вы должны увидеть три разных цвета фона: синий, если ширина больше 960px, желтый, если от 401px до 960px, и красный, если меньше 400px.

Медиавыражения всегда начинаются с @media. Это "at-правило". За ним следует какое-то условное выражение, а затем фигурные скобки. Внутри фигурных скобок помещается куча обычных правил CSS. Браузер воспринимает эти правила только когда выполняется условие.

Interneting is hard HTML+CSS
Скриншот 4: медиавыражение [media query], состоящее из правила @media at-rule, типа [media type], функции [media feature] и нескольких обычных CSS-правил

only screen это "медиа тип", означающий, что содержащиеся в нем стили должны применяться только к устройствам с экранами (в отличие от распечатываемых документов, например, когда вы в браузере нажимаете комбинацию клавиш Cmd+P*). Значения min-width и max-width называются "медиафункциями" [media features]. Они указывают размеры устройств, на которые вы ориентируетесь.

Вышеперечисленные медиавыражения являются наиболее распространенными, но существует множество других условий, которые можно проверить, включая портретный или ландшафтный** режим, разрешение экрана, наличие или отсутствие мыши.

* - в Windows: Ctrl+P;
** - portrait / landscape mode - расхожее обозначения вертикального и горизонтального режима отображения.

немного о дизайне
a few notes on design

Итак, @media - это то, как мы определяем различные макеты для определенной ширины устройства. Но какие макеты мы на самом деле пытаемся реализовать? Пример веб-страницы для этой главы будет выглядеть примерно так:

Interneting is hard HTML+CSS
Скриншот 5: эскизы веб-страниц для смартфонов, планшетов и настольных ПК

В реальном мире именно ваш веб-дизайнер должен предоставить вам такие макеты. Ваша задача как разработчика - воплотить отдельные верстки CSS с помощью медиавыражений, чтобы разделить различные правила CSS, применимые к каждой из них.

Существует несколько четко определенных шаблонов того, как макет для ноутбуков/ПК превращается в макет для мобильных устройств. Мы используем так. наз. "перевертыш" (layout shifter). Многие из этих решений относятся к области дизайна, что выходит за рамки данного учебника, ориентированного на код. Однако есть две концепции, которые вы как разработчик должны хорошо для себя уяснить:

Interneting is hard HTML+CSS
Скриншот 6: жидкий макет расширяется, заполняя всю ширину браузера, макет с фиксированной шириной остается неизменным, даже если браузер становится шире

В нашем примере веб-страница для мобильных устройств и планшетов жидкая, а для настольных ПК - фиксированной ширины.

ВЫБОР ТОЧЕК ОСТАНОВА
choosing breakpoints

Большинство шаблонов адаптивного дизайна имеют схожее поведение, используя жидкие макеты для смартфонов и планшетов и макеты фиксированной ширины для более широких экранов. На это есть своя причина.

Жидкие макеты позволяют ориентироваться не на определенные мобильные устройства, а на диапазон ширины экрана. Это очень важно для веб-дизайнеров. Когда они создают мобильный макет, они не пытаются сделать что-то, что будет хорошо смотреться на iPhone 6s, Galaxy S7 или iPad mini - они разрабатывают жидкий макет, который будет хорошо смотреться в диапазоне от 300 до 500 пикселей (или любом другом).

Иными словами, точные значения пикселей для параметров min-width и max-width в медиавыражении (в совокупности известные как "точки останова"* для адаптивного сайта) на самом деле не имеют значения. Нашему сайту все равно, с какого устройства его просматривает пользователь. Все, что ему нужно знать, - это то, чтобы отображаемый макет выглядел красиво на ширине 400 пикселей (или любой другой).

* - точку останова также называют "брейкпоинт". Это прямое заимствование исходного термина breakpoint.

сначала мобильные устройства
mobile-first development

Давайте сразу же приступим к воплощению приведенных выше скриншотов. Всегда стоит начинать с мобильного макета и затем переходить к десктопной версии. Макеты для настольных ПК обычно сложнее их мобильных аналогов. Подход "mobile-first" максимально увеличивает объем CSS, который потом можно использовать в последующей верстке.

Сначала в responsive.html заполним элемент <body> несколькими пустыми блоками. Чтобы было проще различать блоки, в каждом из них есть картинка.

<div class='page'>
<div class='section menu'></div>
<div class='section header'>
<img src='images/header.svg'/>
</div>
<div class='section content'>
<img src='images/content.svg'/>
</div>
<div class='section sign-up'>
<img src='images/sign-up.svg'/>
</div>
<div class='section feature-1'>
<img src='images/feature.svg'/>
</div>
<div class='section feature-2'>
<img src='images/feature.svg'/>
</div>
<div class='section feature-3'>
<img src='images/feature.svg'/>
</div>
</div>

А теперь наши базовые стили, которые должны применяться ко всем макетам (мобильным, планшетным и десктопным). Убедитесь, что они добавлены выше ранее созданных правил @media, но при этом ниже правила универсального селектора, которое сбрасывает наши отступы margins и paddings:

.page {
display: flex;
flex-wrap: wrap;
}

.section {
width: 100%;
height: 300px;
display: flex;
justify-content: center;
align-items: center;
}

.menu {
background-color: /* синий */

height: 80px;
}

.header {
background-color: #B2D6FF; /* голубой */
}

.content {
background-color: #EAEDF0;
/* светлый серый */
height: 600px;
}

.sign-up {
background-color: #D6E9FE; /* серо-голубой */
}

.feature-1 {
background-color: #F5CF8E; /* желтовато-оранжевый */
}

.feature-2 {
background-color: #F09A9D; /* розоватый */
}

.feature-3 {
background-color: #C8C6FA; /* лавандовый */
}

Уменьшая окно браузера, увидим, что таким образом получается весь наш мобильный макет. Довольно просто, да? Никаких медиавыражений не требуется. Вот почему это называется "mobile-first" - мобильная версия не требует никакой специальной обработки. Также обратите внимание на свойство flex-wrap в содержащем .page div. Оно легко позволит применить наши макеты для отображения на планшетах и ПК.

Interneting is hard HTML+CSS
Скриншот 7: Mobile-first CSS-версия для смартфонов (без медиавыражений)

Сохраняя эти базовые стили вне медиавыражений, можно дополнять и переопределять их по мере реализации наших конкретных макетов. Это очень удобно, если, например, ваш дизайнер захочет изменить цветовую схему для всего сайта. Вместо того чтобы искать лишние объявления о цвете фона в нескольких правилах @media, достаточно обновить его здесь. Это изменение автоматически применяется к макетам для смартфонов, планшетов и ноутбуков/ПК.

макет для планшета
tablet layout

Переходим к макету для планшета. Единственное различие между мобильным и планшетным макетами заключается в том, что разделы Sign Up и Feature формируют сетку 2×2, а не одну колонку.

Flexbox позволяет сделать это довольно легко. Достаточно установить ширину flex-элементов на половину экрана, и flex-wrap позаботится об остальном. Конечно, мы хотим, чтобы это поведение применялось только к экранам размером с планшет, поэтому его нужно включить в правило @media. Замените существующий медиазапрос /* Стили для планшета */ следующим:

/* Стили для планшета */
@media only screen and (min-width: 401px) and (max-width: 960px) {
.sign-up,
.feature-1,
.feature-2,
.feature-3 {
width: 50%;
}
}

Чтобы увидеть эти изменения, убедитесь, что ширина окна вашего браузера составляет от 400 до 960 пикселей, затем прокрутите страницу вниз. Вы должны увидеть разноцветную сетку:

Interneting is hard HTML+CSS
Скриншот 8: веб-страница, показывающая сетку, созданную с помощью медиазапроса для планшета

Опять же, не имеет значения точная ширина экрана: этот макет будет плавно реагировать на любую ширину в диапазоне медиазапроса. Наш мобильный макет жидкий, так что теперь у нас есть сайт, который выглядит красиво (хотя и несколько пустым) на любом устройстве с шириной экрана менее 960px.

макет для ПК
desktop layout

Вот тут-то и пригодится наш макет для десктопа. Мы не хотим, чтобы наша веб-страница бесконечно расширялась, поэтому зададим ей фиксированную ширину и выровняем по центру с помощью auto-margins. Как и в случае со стилями для планшетов, это нужно сделать в медиазапросе. Замените существующий медиазапрос /* Стили для ноутбуков и ПК */ следующим:

/* Стили для ноутбуков и ПК */
@media only screen and (min-width: 961px) {
.page,
width: 960 px;
margin: 0 auto;
}
.feature-1,
.feature-2,
.feature-3 {
width: 33.3%;
}
.header {
height: 400 px;
}
}

Это дает нам правильную ширину для всего. Теперь у нас есть больше возможностей поэкспериментировать. Для удобства наших экспериментов мы немного увеличили размер заголовка. Почти готово, но наш макет для ноутбуков/ПК требует некоторого переупорядочивания: блоки Sign Up и Content должны отображаться ниже блоков Features.

Interneting is hard HTML+CSS
Скриншот 9: макет веб-страницы для ноутбуков и ПК до [before] и после [after] переупорядочивания с помощью flexbox

Вот где флексбокс действительно блистает. Попытка создать такую комбинацию макетов для смартфонов и ноутбуков/ПК была бы очень сложной при использовании плавающих элементов floats. С помощью flexbox-свойства order это можно сделать всего парой строк CSS. Добавьте в медиазапрос для ноутбуков и ПК следующие правила :

.sign-up {
height: 200 px;
order: 1;
}
.content {
order: 2;
}

Ура! Адаптивный сайт! Весьма неплохо, учитывая то, что нам потребовалось менее сотни строк CSS. Что еще более важно, чтобы приспособить макеты для смартфонов, планшетов, ноутбуков и настольных ПК, не пришлось изменять ни одной строки HTML.

Это был лишь один пример создания адаптивного (отзывчивого) сайта. Вы можете использовать эти же приемы для реализации любого другого дизайна. Начните с базовых стилей, применяющихся ко всему сайту, затем подстройте их под ширину различных устройств, выборочно применяя правила CSS с помощью @media. Можно добавить еще одно медиавыражение, создающее особый макет для сверхширокоформатных мониторов.

отключение зум-режима
disabling viewport zooming

Для закрытия темы создания адаптивной веб-страницы, осталось решить последнюю задачу. До появления адаптивного дизайна мобильные устройства могли работать только с версией для ноутбуков/ПК. При этом мобильное устройство тупо уменьшало масштаб, чтобы вместить в ширину своего экрана весь макет для ноутбука/ПК. Пользователю приходилось просто увеличивать масштаб.

Interneting is hard HTML+CSS
Скриншот 10: слева - включенный zoom (отображается макет для ноутбуков/ПК) и справа - отключенный zoom (отображается мобильная версия)

Такое поведение по умолчанию не позволит мобильным устройствам использовать наш мобильный макет, что, разумеется, очень плохо. Чтобы отключить его, добавьте следующий элемент в <head> нашего документа. Как и <meta charset='UTF-8'/>, это критически важный элемент, который должен присутствовать на каждой созданной вами веб-странице:

<meta name='viewport'
content='width=device-width, initial-scale=1.0, maximum-scale=1.0' />

Чтобы увидеть это в действии, нам нужно смоделировать мобильное устройство в браузере ПК. Это немного сложно, учитывая ваш начальный уровень, но можно попробовать. В Google Chrome откройте файл responsive.html, затем в строке меню выберите View > Developer > Developer Tools. Чтобы смоделировать мобильное устройство, нажмите на иконку Toggle Device Toolbar (см. скриншот ниже).

Interneting is hard HTML+CSS
Скриншот 11: значок responsive в панели инструментов разработчика браузера Chrome

В браузере должна появиться версия приведенного выше скриншота с отключенным масштабированием, поскольку теперь он прикидывается мобильным устройством. (Мы оставим подробное обсуждение инструментария Chrome dev tools для одного из следующих учебников).

Если вы читаете эти строки на смартфоне, вы можете сравнить обе версии нашего проекта - это "до", а это "после". Как говорится - "почувствовуйте разницу!"

резюме

Хотите верьте, хотите нет, но это все, что нужно знать для создания адаптивных сайтов. Попросту говоря, нас заботят только три вещи:

В начале этого урока вы узнали разницу между жидкими макетами и макетами с фиксированной шириной. Затем мы создали стили, ориентированные на мобильные устройства. На основе общего набора базовых стилей там использовались медиавыражения для создания макетов для планшетов и ноутбуков/ПК. И наконец, мы отключили у мобильных браузеров стандартное масштабирование окна просмотра.

Итак, это была простая часть адаптивного дизайна. На следующем уроке мы изучим сложную часть - изображения. Создание различных CSS для определенных (мобильных) устройств не так уж сложно, в то время как оптимизация изображений для этих устройств требует более тщательного планирования.


HTML & CSS IS HARD - НА РУССКОМ

АДАПТИВНЫЕ КАРТИНКИ

УРОК Nº 11.

Адаптивные изображения - это сложно. Точнее, очень сложно. Но не пугайтесь.

На уроке адаптивный дизайн мы узнали, как использовать медиавыражения для создания версий для смартфонов, планшетов и настольных ПК. Теперь настала очередь картинок. Точно так же, как медиавыражения позволяют нам условно представлять различные правила CSS, мы хотим отображать различные изображения в зависимости от устройства пользователя.

Interneting is hard HTML+CSS
Скриншот 1: низкопиксельное изображение, передаваемое на ноутбук/ПК со стандартным экраном и мобильные устройства, в сравнении с высокопиксельным изображением, передаваемым на ноутбуки/ПК с ретина-экраном

Проблема в том, что изображения имеют свои размеры. Мы не можем растянуть фотографию размером 500×250 пикселей до размера, превышающего 500 пикселей в ширину, потому что она будет расплываться. Дисплеи Retina и мобильные устройства усложняют ситуацию еще более. Чтобы сделать наши изображения адаптивными, мы должны учитывать три фактора:

Это будет сложнее, чем медиавыражения, которые учитывали только ширину устройства. Но не волнуйтесь, существуют стандартные способы решения всех этих проблем, и мы пройдемся по ним шаг за шагом.

подготовка
setup

Для экспериментов с адаптивными изображениями, нам нужен адаптивный веб-сайт для работы. На этом уроке мы рассмотрим пример веб-страницы, которую мы создали в предыдущей главе. Мы добавим на страницу две картинки, чтобы она выглядела как на скриншоте ниже. Эта подготовка может показаться слишком простой, зато эти картинки будут меняться в зависимости от устройства пользователя (что реально круто).

Interneting is hard HTML+CSS
Скриншот 2: веб-страница с большой фотографией в заголовке и линейной иллюстрацией в контенте

Если вы продолжаете работу с предыдущего урока, вам просто нужно скачать эти изображения и добавить их в папку images/ вашего проекта.

Если вы только присоединились к нам, скачайте полный пример проекта, распакуйте его и откройте с помощью Atom. Если вы не знакомы с текстовым редактором Atom, обязательно прочитайте введение к этому учебнику.

Interneting is hard HTML+CSS
Скриншот 3: файловый браузер Atom после распаковки проекта

В итоге файлы вашего проекта должны выглядеть как на скриншоте выше. Обратите внимание, что у нас есть несколько копий изображений PNG и JPG (например, illustration-big.png и illustration-small.png). Мы будем позволять браузеру выбирать, какое из них загружать, в зависимости от размера и разрешения экрана устройства.

ретина-экраны
retina screens

Раз уж речь пошла о "ретиновых" устройствах, давайте немного поговорим о разрешении экрана. Ретина-экраны имеют в два раза больше пикселей на дюйм, чем экраны стандартного разрешения. То есть каждый пиксель Retina эквивалентен 4 стандартным пикселям. Это сильно влияет на то, как изображения отображаются в веб-браузере.

Interneting is hard HTML+CSS
Скриншот 4: экран стандартного разрешения с 4 пикселями и экран высокого разрешения (retina resolution) с 16 пикселями

Для корректного отображения картинки на ретина-устройстве, она должна быть в два раза больше, чем ее конечные размеры на экране. Например, при добавлении на страницу картинки 500×250 пикселей, соответствующий файл картинки должен иметь размер 1000×500 пикселей.

Interneting is hard HTML+CSS
Скриншот 5: картинка высокого разрешения, уменьшенная до половины размера на ретина-экране

На самом деле это некоторое упрощение - не все ретина-экраны созданы одинаковыми. Например, у iPhone 6 Plus в три раза больше пикселей на дюйм, чем у стандартного экрана. Здесь мы рассматриваем использование экрана 2x, но те же приемы применимы и к ретина-экранам 3x.

Более того, стандартным дисплеям и небольшим устройствам не нужны все эти дополнительные пиксели в изображениях высокого разрешения, а отправка такого количества ненужных данных обычно приводит к недовольству пользователя.

адаптивные svg-изображения
responsive svg images

Самый простой способ решить все эти проблемы - использовать картинки формата SVG. Картинки этого формата "работают на пятерочку". Поскольку они векторные, SVG-картинки позволяют избежать проблемы разрешения экрана (см. ниже). Хотите узнать, как добавить картинку на нашу страницу responsive.html? Замените существующую картинку в div .content так, чтобы она соответствовала следующему:

<div class='section content'>
<img class='illustration' src='images/illustration.svg' />
</div>

Браузеры автоматически масштабируют SVG для ретина-устройств, поэтому SVG 500×250 пикселей будет четко отображаться и на стандартных и на ретина-устройствах.

SVG поможет забыть о проблемах с разрешением экрана, но чтобы картинка вписалась в жидкие макеты [fluid layouts] для планшетов и смартфонов, ее нужно уменьшить. Firefox сделает это автоматически, но если вы откроете эту страницу в Chrome и сделаете окно узким, вы увидите, что картинка осталось того же размера.

Чтобы получить жидкое изображение в Chrome, нужно приказать картинке всегда заполнять ширину своего контейнера. В styles.css вместе с остальными базовыми стилями (вне медиавыражений!) поместите следующее правило:

.illustration {
width: 100%;
}

Задавая ширину картинки 100 %, высота задается автоматически. Предполагается, что мы хотим сохранить соотношение сторон. Это исправляет ситуацию с мобильным макетом, но теперь версия для ноутбуков/ПК становится огромной:

Interneting is hard HTML+CSS
Скриншот 6: SVG-картинка уменьшается до ширины смартфонов и планшетов, но становится огромной на ноутбуках/ПК

Такое поведение идеально для некоторых случаев дизайна, например для фото на всю ширину экрана (об этом чуть ниже). Сейчас же мы хотим ограничить ширину картинки до ее собственной, - в 500 пикселей. В этом нам поможет встроенный стиль:

<div class='section content'>
<img class='illustration' src='images/illustration.svg' style='max-width: 500px' />
</div>

Это один из редких случаев, когда встроенный стиль допустим, поскольку он описывает врожденное свойство изображения. Физические размеры изображения - это скорее контент, чем внешний вид, поэтому имеет смысл указывать их в HTML, а не в таблице стилей.

Interneting is hard HTML+CSS
Скриншот 7: добавление встроенного стиля для ограничения размера SVG-изображения
адаптивные PNG, GIF, JPG
responsive png, gif, and jpg images

Конечно, не все изображения в Интернете являются SVG. Иногда необходимо включить фотографию. Картинки PNG, GIF и JPG - это "растровые изображения", они определяются попиксельно, а не с помощью векторов. Поэтому они гораздо более чувствительны к разрешению экрана, чем SVG.

Если вы не беспокоитесь об оптимизации, адаптивные растровые изображения действительно ненамного сложнее, чем SVG. Попробуйте заменить наш существующий файл illustration.svg на PNG-файл:

<div class='section content'>
<img class='illustration' />
<img src='images/illustration-big.png' style='max-width: 500px' />
</div>
</div>

Мы немного изменили структуру HTML, вложив наш тег <img/> в другой контейнер. Без него изображение исказилось бы, потому что flexbox попытался бы установить его высоту равной высоте контейнера .content. Это также требует небольшого изменения нашего CSS-правила .illustration:

.illustration img {
width: 100%;
display: block;
}

Также обратите внимание на суффикс -big в имени файла изображения. Это версия PNG с высоким разрешением и размером 1000×500. Ретина-устройствам для четкого отображегния необходим такой размер "2x". Изображение с низким разрешением (500×250 пикселей) выглядит хорошо на стандартных экранах, а на ретина-экранах будет размытым.

Interneting is hard HTML+CSS
Скриншот 8: подача картинки высокого разрешения на стандартные и на ретина-экраны (последнее расточительно)

Данный способ создания адаптивных PNG, GIF и JPG можно назвать "лентяйским". Предполагается, что всем и всегда нужны высокопиксельные картинки. Но это не так. Картинка 1000×500 пикселей - это излишество для всех не ретиновых экранов. Об этом - чуть ниже.

Оптимизация адаптивных изображений
responsive image optimization

Разные устройства предъявляют разные требования к изображениям. К счастью, HTML позволяет выбрать лучшее изображение для конкретного устройства пользователя. В следующих нескольких секциях мы рассмотрим три сценария оптимизации адаптивных изображений:

Первый способ - самый простой. Он отлично подходит для изображений шириной менее 600 пикселей, поскольку они недостаточно велики, чтобы воспользоваться вторым сценарием. Второй способ - очень важная оптимизация для больших изображений, особенно для полноцветных фотографий. Третий - для тех случаев, когда вы чувствуете себя крутым.

оптимизация srcset для ретина-экранов
retina optimization using srcset

Изображения высокого разрешения очень большие. Наш illustration-big.png занимает более чем в два раза больше места на диске, чем его аналог с низким разрешением. Нет смысла пересылать все эти дополнительные данные, если они фактически не нужны пользователю.

Благодаря атрибуту srcset, добавленного к элементу <img/>, изображение с высоким разрешением будет подаваться только на ретина-экраны, а на обычные экраны будет подаваться версия с низким разрешением. Обновите элемент .illustration следующим образом:

<div class='illustration'>
<img src='illustration-small.png'
srcset='images/illustration-small.png 1x,
images/illustration-big.png 2x'

style='max-width: 500px' />
</div>

Атрибут srcset указывает на список альтернативных файлов изображений, а также свойства, определяющие, когда браузер должен использовать каждый из них. Значение 1x велит браузеру отображать illustration-small.png на обычных экранах, а 2x - отображать illustration-big.png на ретина-экранах. Старые браузеры, не понимающие srcset, возвращаются к атрибуту src.

Interneting is hard HTML+CSS
Скриншот 9: подача изображения с низким разрешением на стандартный экран и с высоким разрешением на ретина-экраны

Обычно версии изображения с низким и высоким разрешением абсолютно одинаковы (за исключением их размеров), но мы сделали illustration-small.png желтым, чтобы вы могли легко отличить его от версии для ретина-экрана, которая имеет синий цвет.

Увидеть это в действии без реального сайта немного сложно, поэтому мы включили предыдущий фрагмент кода на эту страницу. Картинка ниже должна быть синей, если вы просматриваете ее на ретина-экране. А вот на экранах стандартного разрешения она будет желтой.

Interneting is hard HTML+CSS
Скриншот 10: [если цвет желтый, то у вас экран стандартного разрешения. А если синий - то ретина-экран]

Если вы создаете эти примеры на компьютере с ретина-экраном, можно попробовать временно изменить 2x на 1x, чтобы посмотреть, как выглядит изображение без ретина-экрана. Оно будет немного размытым (и желтым).

оптимизация ширины экрана с помощью srcset
screen width optimization using srcset

Класс! Можно сэкономить несколько байтов для устройств без ретина. К сожалению техника srcset упускает важный момент с большими картинками: если у пользователя смартфон с ретина-экраном, загрузится высокопиксельная картинка, даже когда обычной будет достаточно.

Interneting is hard HTML+CSS
Скриншот 11: низкопиксельная картинка, отправляемая на ноутбуки/ПК и мобильные устройства со стандартным экраном, в сравнении с низкопиксельной картинкой, отправляемой на ноутбуки/ПК с ретина-экраном

Представьте, что в .header мы хотим отобразить большую фотографию. Ширина заголовка в нашем макете для ноутбуков/ПК - 960 пикселей. Тогда для хорошего отображения на ретина-экранах ширина фото должна быть не менее 1920 пикселей. Для стандартных экранов мы также предоставим фотографию шириной 960 пикселей. Теперь рассмотрим смартфон с ретина-экраном. Смартфоны обычно имеют ширину менее 400 пикселей в портретном режиме. Тогда ширина соответствующего фото с качеством "ретина" должна быть всего 800 пикселей.

Ого! Мы можем использовать фото стандартного разрешения на смартфонах с ретина-экраном!

Отсюда следует вывод: оптимизировать большие изображения нужно исходя из их конечных размеров, а не только из разрешения экрана устройства. Давайте добавим это большое фото в наш элемент .header:

<div class='section header'>
<div class='photo'>
<img src='images/photo-small.jpg'
srcset='images/photo-big.jpg 2000w,
images/photo-small.jpg 1000w'
sizes='(min-width: 960px) 960px,
100vw'
/>
</div>
</div>

У нас тот же элемент srcset, что и в предыдущем разделе, но вместо дескрипторов 1x и 2x мы указываем физическую ширину картинки. 2000w говорит браузеру, что photo-big.jpg имеет ширину 2000 пикселей. Аналогично, 1000w означает, что ширина photo-small.jpg равна 1000 пикселям. Символ w это специальная единица, используемая только для такого рода сценариев оптимизации изображений.

Interneting is hard HTML+CSS
Скриншот 12: srcset=1000w - ширина файла низкопиксельной картинки, srcset=2000w - ширина файла высокопиксельной картинки

Для того, чтобы устройство определило, какую картинку следует загрузить, одной ширины изображения недостаточно. Устройство хочет знать, какой будет конечная ширина картинки. Здесь на помощь приходит атрибут sizes. Он определяет серию медиазапросов, а также ширину картинки, отображаемой при выполнении медиазапроса.

Interneting is hard HTML+CSS
Скриншот 13: sizes=100vw - ширина изображения в мобильном макете, sizes=960px - ширина изображения в десктопном макете

Так, если ширина экрана составляет не менее 960px, то и картинка будет шириной 960 пикселей. Иначе стандартное значение 100vw говорит браузеру, что ширина картинки будет равна 100% от "ширины области просмотра" (англ. viewport width - модный термин для обозначения ширины экрана). Подробнее о vw читайте на сайте MDN. Все это соответствует поведению изменения размера картинки в нашем CSS.

Кстати, для правильного расположения нашего нового фото в заголовка нужно внести некоторые изменения. Добавьте оба следующих правила в наши другие базовые стили, прямо над медиазапросом мобильных стилей:

.header {
height: auto;
justify-content: inherit;
align-items: inherit;
}

.photo img {
width: 100%;
display: block;
}

Помните, что ширина нашего фото низкого разрешения равна 1000 пикселей. Это означает, что устройства с ретина-экраном 2x могут использовать ее, если ширина их экрана не превышает 500 пикселей. В Firefox теперь можно изменять размер браузера, чтобы видеть версию ретина ("Big") при ширине окна более 500 пикселей и версию без ретина ("Small") при меньшей ширине.

Теперь мы передаем на мобильные устройства изображение размером 115 КБ вместо изображения высокого разрешения размером 445 КБ. Это особенно актуально для сайтов с большим количеством фотографий.

ТЕСТИРОВАНИЕ В БРАУЗЕРЕ ХРОМ
testing with chrome

Эта техника отлично работает в Chrome, но не до конца понятно, как это происходит. Chrome всегда использует картинку с высоким разрешением, если она уже была локально кэширована. Поэтому мы не сможем увидеть картинку с низким разрешением, просто заузив окно браузера. Чтобы избежать локального кэша браузера, сделайте следующее: открыв новое окно Incognito Window, перед загрузкой страницы сделайте окно очень узким. Так можно предотвратить загрузку photo-big.jpg.

<picture> как решение проблемы художественного оформления
art direction using <picture>

Предыдущая секция вполне пригодна для оптимизации использования данных. На этом можно бы и остановиться, но ведь мы хотим стать более искусными и в "художественом оформлении". Считайте художественное оформление [art direction] оптимизацией адаптивных картинок для дизайнеров.

Художественное оформление позволяет оптимизировать макеты [layouts], отправляя пользователю разные варианты в зависимости от его устройства. В предыдущей секции, одну и ту же фотографию мы оптимизировали для разных устройств. Причем эта фотография в заголовке довольно широка. Разве не было бы здорово вместо широкой версии для ноутбуков/ПК, несколько обрезать края для отображения ее на мобильных устройствах?

Interneting is hard HTML+CSS
Скриншот 14: отображение фото, урезанного по высоте [tall-cropped] на мобильных устройствах и урезанного по ширине [wide-cropped] на ноутбуках/ПК с стандартными и ретина-экранами

Для этого нам нужны элементы <picture> и <source>. Первый является просто оберткой, а второй условно загружает картинки на основе медиавыражений. Попробуйте изменить наш элемент .header:

<div class='section header'>
<div class='photo'>
<picture>
<source media='(min-width: 401px)'
srcset='images/photo-big.jpg' />
<source media='(max-width: 400px)'
srcset='images/photo-tall.jpg' />
<img src='images/photo-small.jpg' />
</picture>
</div>
</div>

По своей концепции это похоже на использование медиавыражений в CSS. В каждом элементе атрибут media определяет, когда должна загружаться картинка, а srcset - какой файл должен быть загружен. Элемент <img/> используется только как запасной вариант для старых браузеров. Уменьшив окно браузера, вы сможете увидеть высокую версию фото:

Interneting is hard HTML+CSS
Скриншот 15: в мобильной версии фото урезано по высоте, а в версии для ноутбуков/ПК - по ширине

Такой уровень контроля очень обрадует вашего дизайнера. Однако есть и недостаток - браузер не может автоматически выбирать оптимальное изображение. То есть мы потеряли нашу оптимизацию для ретина-экранов из предыдущей cекции: до тех пор, пока ширина экрана составляет 401 пиксель или больше, браузер всегда будет использовать высокопиксельное изображение, урезанное по ширине [wide-cropped image].

Пытаясь совместить лучшее из двух миров, все быстро усложняется. Мы рекомендуем придерживаться версий srcset 1x и 2x для картинок шириной менее 600 пикселей, использовать метод srcset плюс sizes из предыдущей секции для больших фотографий, а <picture> оставить для тех случаев, когда вместе с дизайнером вы задумаете что-то сногсшибательное.

РЕЗЮМЕ

Адаптивные изображения могут показаться довольно сложными, но на самом деле мы пытаемся решить всего две задачи:

Мы решили первую задачу, заставив изображения всегда растягиваться, чтобы заполнить 100% своего контейнера, и ограничив их размер с помощью встроенного стиля max-width. Чтобы решить вторую задачу, мы использовали srcset для оптимизации под разрешение экрана, srcset и sizes для оптимизации под ширину устройства и, наконец, элемент <picture> для ручного управления отображением файла изображения.

Адаптивный дизайн - постоянно развивающаяся технология. Браузеры только недавно внедрили методы оптимизации изображений, рассмотренные выше. И это несмотря на то, что адаптивный дизайн является стандартом уже полдесятка лет. Технологии для создания адаптивного сайта могут меняться, однако фундаментальная проблема внешнего вида одного и того же контента на разных устройствах никогда не исчезнет. Со временем вам придется освоить новые инструменты, но базовые концепции из этого урока должны остаться с вами навсегда.

Оставшиеся пять глав полностью посвящены верстке. Мы изучили плавающие элементы, flexbox, продвинутое позиционирование и то, как применять все эти концепции для экранов разной ширины. Это практически все, что вам когда-либо понадобится для верстки веб-страниц с помощью HTML и CSS. В следующей главе мы вернемся в мир HTML изучая множество новых элементов, которые сильно "порадуют" поисковые системы оптимизацией наших сайтов.


HTML & CSS IS HARD - НА РУССКОМ

СЕМАНТИКА HTML

УРОК Nº 12.

Самый понятный учебник веб-разработки полноценных веб-страниц

"Семантика HTML" подразумевает, что вся ваша HTML-разметка должна передавать основной смысл вашего контента, а не его внешний вид. Мы уже писали семантический HTML код, например, используя <strong> вместо <b>), но существует целый набор элементов, созданных с единственной целью - добавить больше смысла в общий макет веб-страницы. Они называются "элементы секционирования" и выглядят примерно так:

Interneting is hard HTML+CSS
Скриншот 1: элементы <header>, <nav>, <article>, <aside>, <figure> и <footer> на типичной веб-странице.

Использование этих элементов вместо элементов <div> - важный аспект современной веб-разработки, так как это облегчает поисковым системам, программам чтения с экрана и т.п. идентификацию различных частей вашего сайта. Это также помогает вам как разработчику поддерживать сайт организованным, что, в свою очередь, облегчает его обслуживание.

Interneting is hard HTML+CSS
Скриншот 2: div-"солянка" (несколько серых <div>) и семантическая разметка (разноцветные <header>, <article>, <figure>, <footer>)

В этой главе мы вернемся к простому HTML - без блоковой модели, flexbox или схем позиционирования. Однако это не значит, что вы не можете применить все правила CSS из предыдущих глав к этим новым элементам. Считайте, что элементы секционирования - это <div>, только с определенным смыслом.

подготовка
setup

Нашим примером к этому уроку будет простой нестилизованный HTML-документ. Создайте новый проект Atom под названием semantic-html с новым файлом article.html. Добавьте в него следующее:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Semantic HTML</title>
</head>
<body>

<h1>Interneting Is Easy!</h1>
<ul>
<li><a href='#'>Home</li>
<li><a href='#'>About</li>
<li><a href='#'>Blog</li>
<li><a href='#'>Sign Up</li>
</ul>

</body>
</html>

Предполагается, что <h1> и <ul> - это баннер верхнего уровня для нашего сайта, а не основное содержимое веб-страницы. Нам никогда раньше не приходилось делать такое различие, но именно об этом и пойдет речь на этом уроке.

обводка документа
the document outline

Каждый HTML-документ имеет "обводку", с помощью которой поисковые системы и программы чтения с экрана видят иерархию содержимого страницы. Обводку страницы формируют элементы заголовков секций <h1> - <h6>. Мы проверим это, добавив фиктивный блог-пост в article.html:

<h1>Semantic HTML</h1>
<p>By Troy McClure. Published January 3rd</p>
<p>This is an example web page explaining HTML5 semantic markup.</p>

<h2>The Document Outline</h2>
<p>HTML5 includes several “sectioning content” elements that
affect the document outline.</p>

<h3>Headers</h3>
<p>The <code>&lt;header&gt;</code> element is one such sectioning
element.</p>

<h3>Footers</h3>
<p>And so is the <code>&lt;footer&gt;</code> element.</p>

<h2>Inline Semantic HTML</h2>
<p>The <code>&lt;time&gt;</code> element is semantic, but it’s not
sectioning content.</p>

<p>This fake article was written by somebody at InternetingIsHard.com, which
is a pretty decent place to learn how to become a web developer.</p>

<p>&copy; 2017 InternetingIsHard.com</p>

HTML5 Outliner - это удобный инструмент просмотра обводки документа на странице. Пройдите по ссылке и вставьте весь файл article.html в текстовое поле внизу. Вы должны увидеть обводку нашего примера, которая в данный момент напоминает структуру письменной работы, которую вы учились делать в школе (см. скриншот ниже).

Interneting is hard HTML+CSS
Скриншот 3: обводка структуры заголовков веб-страниц

Каждый элемент <h1> создает новую секцию в обводке документа, а все менее заметные заголовки, которые следуют за ним, считаются подразделами этого заголовка верхнего уровня. Например, секция Semantic HTML имеет две подсекции: The document outline [Обводка документа] и Inline Semantic HTML [Встроенный семантический HTML]. То же относится к элементам <h2>, <h3> и далее до <h6>.

Обратите внимание, что фактическое значение уровня заголовка не играет особой роли: важно то, больше или меньше он заголовка текущей секции. Например, измените заголовки <h3> на <h4> и снова запустите Outliner. Поскольку <h4> все равно меньше родительского <h2>, это никак не должно повлиять на обводку документа.

Interneting is hard HTML+CSS
Скриншот 4: схема правил, по которым заголовки создают новые секции в обводке документа

Как обводка документа связана с семантическим HTML? Заголовки - одни из самых семантических элементов веб-страницы. Они играют важную роль в том, как поисковые системы определяют, что является важным на вашей веб-странице. Кроме того, семантические элементы HTML, о которых мы сейчас расскажем, добавляют больше смысла, а иногда даже изменяют стандартное поведение обводки.

статьи
articles

Элемент <article> обозначает независимую статью на веб-странице. В него следует помещать только тот контент, который можно извлечь из вашей страницы и распространить в совершенно другом контексте. Например, такое приложение, как Flipboard, должно иметь возможность взять элемент <article> с вашего сайта, отобразить его в своем приложении и сделать так, чтобы он был понятен читателям.

Interneting is hard HTML+CSS
Скриншот 5: элемент <article>, отправленный из вашей страницы на Flipboard, поисковики и другие сайты

Мы можем использовать <article>, чтобы выделить основной контент страницы как самостоятельную единицу, например, так:

<article>
<h1>Semantic HTML</h1>
<p>By Troy McClure. Published January 3rd</p>
<p>This is an example web page explaining HTML5 semantic markup.</p>
<!-- ... -->
<p>This fake article was written by somebody at InternetingIsHard.com, which
is a pretty decent place to learn how to become a web developer.</p>
</article>

<p>&copy; 2017 InternetingIsHard.com</p>

Обратите внимание, мы оставили уведомление об авторских правах за пределами элемента <article>, так как это футер для всего сайта, а не конкретно для нашей статьи. По сути, элементы <article> это мини-веб-страницы в HTML-документе. У них есть свои заголовки, футеры и обводка документа, полностью изолированные от остальной части сайта.

ИСПОЛЬЗОВАНИЕ НЕСКОЛЬКИХ ARTICLE-ЭЛЕМЕНТОВ
using multiple article elements

Для таких вещей, как блог-посты, газетные статьи или веб-страницы, посвященные одной теме, часто используется только один элемент <article>. Однако вполне допустимо иметь более одного <article> на странице. Хороший пример - страница с множеством блог-постов. Каждый из них может быть обернут в отдельный набор тегов <article> (вам не нужно добавлять это в страницу article.html нашего примера):

<article>
<h1>First Post</h1>
<p>Some content</p>
</article>
<article>
<h1>Second Post</h1>
<p>Some content</p>
<h1>Subscription</h1>
<p>Some details</p>
</article>
<article>
<h1>Last Post</h1>
<p>Final bit of content</p>
</article>

Это говорит всем, кто смотрит на нашу страницу, о том, что здесь есть три разные статьи, которые можно разместить в интернете*. Думайте об этом как о способе объединить несколько HTML-файлов в один документ, не запутав поисковые системы, браузеры и другие машины, которые пытаются разобрать наш контент.

Сравните это с кучей общих элементов <div> с произвольными именами классов, и вы начнете понимать, как семантический HTML упрощает навигацию по Сети.

* - "разместить в интернете". В оригинале: can be syndicated. У этого слова огромное множество переводов. Наиболее подходящие переводы для данного случая: "синдицировать; передавать информацию в агентство печати; публиковать сразу в нескольких газетах; покупать статьи для их одновременной публикации в различных изданиях."

секции
sections

Элемент <section> похож на <article>, только он не должен иметь смысла вне контекста документа. То есть приложение вроде Flipboard не будет пытаться вытащить все <section>'s из вашей страницы и представить их как независимые части контента.

Interneting is hard HTML+CSS
Скриншот 6: элемент <section> не может быть извлечен из страницы

Представьте <section> как явный способ определения секций в обводке документа. Зачем нам это нужно, вместо того чтобы позволить уровням заголовков сделать это за нас? Часто для верстки секций нужен контейнер, и тогда имеет смысл использовать более описательный элемент <section>, а не общий <div>.

Давайте выделим две секции в нашем файле article.html:

<section> <!-- Добавьте это -->
<h2>The Document Outline</h2>
<p>HTML5 includes several “sectioning content” elements that
affect the document outline.</p>

<h3>Headers</h3>
<p>The <code>&lt;header&gt;</code> element is one such sectioning
element.</p>

<h3>Footers</h3>
<p>And so is the <code>&lt;footer&gt;</code> element.</p>
</section> <!-- Добавьте это тоже-->

<section> <!-- Добавьте и это тоже -->
<h2>Inline Semantic HTML</h2>
<p>The <code>&lt;time&gt;</code> element is semantic, but it’s not
sectioning content.</p>
</section> <!-- Не забудьте добавить и это -->

Это позволяет сохранить обводку документа в неизменном виде и придать ей дополнительную смысловую структуру, а также сделать отличный зацеп для любых CSS-стилей, которые мы захотим применить (например, цвет фона для определенной секции).

<SECTION> И ОБВОДКА ДОКУМЕНТА
<SECTION> and the document outline

Предыдущее изменение также имеет интересный побочный эффект для неявного поведения секций в наших заголовках. Посмотрите, что произойдет, если мы опустим второй <h2> на более низкий уровень заголовка:

<section>
<h6>Inline Semantic HTML</h6> <!-- Измените здесь уровень заголовка -->
<p>The <code>&lt;time&gt;</code> element is semantic, but it’s not
sectioning content.</p>
</section>

Строка <h6> находится ниже, чем предшествующая ей <h3>, поэтому можно ожидать, что она станет частью секции Footer. Но не тут-то было: обводка документа остается точно такой же, как и раньше.

Interneting is hard HTML+CSS
Скриншот 7: ожидаемые и фактические обводки, созданные с помощью схемы обводки документа HTML5, в сравнении с реальными веб-браузерами

Добавляя эти элементы <section>, мы говорим обводке документа, что она должна определяться структурой вложенности элементов <section>, а не уровнями заголовков. В основном это означает, что каждый <section> может иметь свой собственный набор заголовков <h1> - <h6>, не зависящих от остальной части страницы.

Однако не следует использовать элемент <section> для манипулирования обводкой документа таким образом, поскольку браузеры, программы чтения с экрана и некоторые поисковики неправильно интерпретируют влияние <section> на обводку документа. Вместо этого всегда определяйте обводку страницы через уровни заголовков, используя <section> только в качестве замены контейнеров <div>, когда это необходимо.

Также обратите внимание, что каждый элемент <section> должен содержать хотя бы один заголовок, иначе он добавит в обводку документа "секцию без названия". Для примера попробуем обновить article.html как показано ниже, а затем снова прогоним его через HTML5 Outliner:

<h2>Inline Semantic HTML</h2>
<section>
<!-- Это будет "Untitled Section" [Секция без названия] -->
<p>The <code>&lt;time&gt; element is semantic, but it’s not
sectioning content.</p>
</section>

Это создает новую секцию, но поскольку с ней не связан заголовок, обводка документа не знает, как ее назвать. При использовании элементов <section> подобного следует избегать.

Interneting is hard HTML+CSS
Скриншот 8: обводка с секцией без названия после добавления нового элемента <section>

Согласно спецификации HTML5, <section> - это довольно общий элемент. Это, а также тот факт, что браузеры и программы чтения с экрана не могут правильно интерпретировать его роль в обводке документа, затрудняет понимание того, когда и как его использовать. Советуем использовать <section> скорее как описательную обертку <div> для неявно определенных секций вашей страницы. Не используйте его для самостоятельного контента (для этого есть <article>) или когда он нужен исключительно для верстки.

элементы навигации
nav elements

Элемент <nav> позволяет разметить различные навигационные секции вашего сайта. Это касается основной навигации сайта, ссылок на связанные страницы в боковой панели, таблиц с контентом и практически любых групп ссылок. Например, в элемент <nav> следует поместить навигационное меню всего сайта:

<h1>Interneting Is Easy!</h1>
<nav> <!-- Добавьте это -->
<ul>
<li><a href='#'>Home</a></li>
<li><a href='#'>About</a></li>
<li><a href='#'>Blog</a></li>
<li><a href='#'>Sign Up</a></li>
</ul>
</nav> <!-- И это добавьте! -->

Это отличная семантическая информация для поисковых систем. Она помогает им быстро определить структуру всего вашего сайта, облегчая поиск других страниц. Как мы увидим в разделе Элементы <aside>, в одну страницу можно включить несколько элементов <nav> при наличии разных наборов связанных ссылок.

Interneting is hard HTML+CSS
Скриншот 9: элементы <nav>, группирующие навигационные ссылки в шапке, боковой панели и футере веб-страницы
хидеры
headers

<header> это новый элемент семантической разметки, который не следует путать с заголовками (элементы <h1>-<h6>). Он обозначает вводный контент для секции, статьи или всей веб-страницы. "Вводным контентом" может быть что угодно - от логотипа вашей компании до навигационных подсказок или информации об авторе.

Interneting is hard HTML+CSS
Скриншот 10: отдельные элементы <header> для всей веб-страницы в сравнении с элементом <article>

Название/логотип и основную навигацию сайта лучше всего заключать в <header>, поэтому давайте добавим его в наш пример проекта:

<header>
<h1>Interneting Is Easy!</h1>
<nav>
<ul>
<li><a href='#'>Home</a></li>
<li><a href='#'>About</a></li>
<li><a href='#'>Blog</a></li>
<li><a href='#'>Sign Up</a></li>
</ul>
</nav>
</header>

Заголовки связаны только с ближайшим элементом секции - как правило, элементом <body>, <section> или <article>. Это означает, что вы можете использовать несколько элементов <header> для добавления вводного контента в разные части документа. Например, название, автор и дата публикации нашей <article> - вполне подходящий кандидат для другого <header>:

<article>
<header>
<h1>Semantic HTML</h1>
<p>By Troy McClure. Published January 3rd</p>
</header>

<p>This is an example web page explaining HTML5 semantic markup.</p>
<!-- ... -->

Без этого <header> поисковые системы и программы чтения с экрана не узнают, что первый <p> отделен от основного контента статьи. Как и <section>, он также служит удобным CSS-крючком, поскольку заголовок и информация об авторе записи в блоге часто оформляются иначе, чем остальная часть статьи. Повторимся, <header> можно рассматривать как более семантическую альтернативу контейнеру <div>.

футеры
footers

Концептуально футеры - это то же самое, что и хидеры, за исключением того, что они обычно располагаются в конце статьи/сайта, а не в начале. Обычно они используются для уведомления об авторских правах, навигации по футеру и биографий авторов в конце записей блога.

Interneting is hard HTML+CSS
Скриншот 11: элемент <footer> для всей веб-страницы и для элемента

Футеры ведут себя так же, как и хидеры, - они тоже связаны с ближайшим элементом секции. Поэтому мы можем использовать их для уведомления об copyright страницы и информации об авторе внутри <article>. Добавьте следующие два элемента футера на нашу страницу article.html:

<article>
<header>
<h1>Semantic HTML</h1>
<p>By Troy McClure. Published January 3rd</p>
</header>

<p>This is an example web page explaining HTML5 semantic markup.</p>
<!-- ... -->

<footer> <!-- Добавьте это -->
<p>This fake article was written by somebody at InternetingIsHard.com,
which is a pretty decent place to learn how to become a web developer. This
footer is only for the containing <code>&lt;article&gt;</code> element.</p>
</footer> <!-- Добавьте это -->

</article>

<footer> <!-- И это тоже -->
<p>&copy; 2017 InternetingIsHard.com</p>
</footer> <!-- Не забудьте закрыть! -->

</body>
</html>

Элемент <footer> внутри <article> предназначен только для контента этой статьи, что вполне логично, поскольку он содержит биографию автора. Второй футер, в свою очередь, связан со всей страницей.

отступление
aside

Хидеры и футеры - это способ добавить дополнительную информацию в статью, но иногда мы хотим удалить информацию из статьи. Например, спонсируемая статья в блоге может содержать рекламу компании-спонсора; однако мы, вероятно, не захотим делать ее частью текста статьи. Именно для этого предназначен элемент <aside> - "отступление".

Interneting is hard HTML+CSS
Скриншот 12: элемент <aside> внутри для элемента <article> и в боковой панели всего сайта

Давайте добавим фейковое рекламное объявление в файл article.html, прямо под заголовком статьи:

<article>
<header>
<h1>Semantic HTML</h1>
<p>By Troy McClure. Published January 3rd</p>
</header>
<!-- Фейковое объявление [fake advertisement]! -->
<aside class='advert'>
<img src='some-advert-image.png'/>
</aside>

<p>This is an example web page explaining HTML5 semantic markup.</p>

Несмотря на то что изображение находится внутри элемента <article>, роботы понимают, что оно имеет лишь косвенное отношение к контенту статьи. Если она выглядит иначе, чем остальная часть статьи, скорее всего, это отступление. Помимо рекламы, <aside> также подходит для выделения определений, статистики или цитат.

Когда <aside> используется за пределами <article>, он ассоциируется со страницей в целом (так же, как <header> и <footer>). Это делает его хорошим выбором для разметки боковой панели всего сайта. Под закрывающим тегом </article>, перед вторым <footer> добавьте следующее:

<aside class='sidebar'>
<h2>Sidebar</h2>
<p>Some sidebar content</p>
<nav>
<h3>HTML &amp; CSS Tutorial</h3>
<ul>
<li><a href='#'>Introduction</a></li>
<li><a href='#'>Basic Web Pages</a></li>
<li><a href='#'>etc...</a></li>
</ul>
</nav>
<nav>
<h3>JavaScript Tutorial</h3>
<ul>
<li><a href='#'>Introduction</a></li>
<li><a href='#'>Hello, JavaScript</a></li>
<li><a href='#'>etc...</a></li>
</ul>
</nav>
</aside>

Обратите внимание на атрибуты class в обоих фрагментах. Если бы на этом уроке мы фокусировались на CSS, мы могли бы стилизовать наши элементы <aside> точно так же, как и все <div>, с которыми мы работали на протяжении всего этого учебника. Что приводит нас к...

divs для верстки
divs for layout

Используйте семантический HTML всегда, когда это возможно, поскольку он помогает машинам понять структуру вашего контента и дает вам стандартный словарь для организации веб-страниц. Однако иногда требуется элемент-контейнер, но не имеет смысла использовать ни один из только что рассмотренных семантических элементов HTML. Нет ничего плохого в том, чтобы использовать обычный <div> чисто для верстки.

Например, если мы хотим отцентрировать страницу с помощью знакомой техники auto-margin, нам придется поместить всю страницу в контейнер. Это полностью соотносится с идеей "внешнего вида", поэтому <div> будет наилучшим вариантом:

<body>
<div class='page'> <!-- Начало контейнера div -->
<header>
<h1>Interneting Is Easy!</h1>
<nav>
<ul>
<li><a href='#'>Home</a></li>
<li><a href='#'>About</a></li>
<li><a href='#'>Blog</a></li>
<li><a href='#'>Sign Up</a></li>
</ul>
</nav>
</header>
<!-- ... -->
<footer>
<p>&copy; 2017 InternetingIsHard.com</p>
</footer>
</div> <!-- Конец контейнера div -->
</body>
</html>

Это особенно актуально для flexbox, поскольку для правильной группировки элементов flex требуется много <div>. Иногда для этих flex-элементов подходит <section> или <nav>, но довольно часто в flexbox-макетах встречаются элементы <div>.

Суть в том, что не стоит использовать семантические элементы только ради того, чтобы их использовать. Неуместное использование хуже, чем полное отсутствие, поэтому, если сомневаетесь, смело используйте <div>.

даты и время
dates and times

Для людей даты и время существуют в разных формах. Вы можете назвать 3 января 2017 года "1/3/2017", "3 января" или в зависимости от даты, даже "вчера". Парсинг такого неоднозначного естественного языка для машин затруднителен и чреват ошибками, поэтому на помощь приходит <time>.

Элемент <time> представляет либо время суток, либо календарную дату. Предоставление машиночитаемой даты позволяет браузерам автоматически привязывать ее к календарям пользователей и помогает поисковикам легко определять конкретные даты. Простой поиск в Google покажет вам эффект от включения элемента <time> на вашей странице:

Interneting is hard HTML+CSS
Скриншот 13: результаты поиска Google с выделенной датой публикации

Давайте сделаем ясную дату публикации нашей статьи, обернув ее в теги <time>:

<article>
<header>
<h1>Semantic HTML</h1>
<p>By Troy McClure. Published <time datetime='2017-1-3'>January
3rd</time></p>
</header>
<!-- ... -->

Машиночитаемая дата определяется атрибутом datetime. Формат даты легко запомнить: от самого большого периода времени к самому маленькому: год, месяц, день (дата). Обратите внимание, что даже если год не включен в читаемый человеком текст, это говорит поисковым системам, что наша статья была опубликована в 2017 году.

Interneting is hard HTML+CSS
Скриншот 14: год, месяц, дата, время и часовой пояс в формате элемента <time>

В datetime также можно включать время и часовые пояса. Если бы мы хотели добавить к дате публикации время 3:00 вечера по тихоокеанскому времени, мы бы использовали следующее:

<time datetime='2017-1-3 15:00-0800'>January 3rd</time>

Само время указывается в 24-часовом формате, а -0800 - это смещение часового пояса относительно GMT* (в данном случае -0800 означает PST - тихоокеанское стандартное время**).

* - GMT - Greenwich Mean Time - среднее время по Гринвичу.
* - PST - Pacific Standard Time - тихоокеанское стандартное время.

адреса
address

Элемент <address> похож на <time> тем, что он не имеет отношения к общей структуре документа, а скорее украшает родительский элемент <article> или <body> некоторыми метаданными. Он определяет контактную информацию автора статьи или веб-страницы. <address> не следует использовать для обычных физических адресов.

Например, мы хотим добавить адрес электронной почты автора в футер нашей статьи:

<footer>
<p>This fake article was written by somebody at InternetingIsHard.com, which
is a pretty decent place to learn how to become a web developer. This footer
is only for the containing <code>&lt;article&gt;</code> element.</p>
<address>
Please contact <a href='mailto:[email protected]'>Troy
McClure</a> for questions about this article.
</address>
</footer>

По умолчанию он будет оформлен так же, как <em>, но это легко изменить простым CSS-правилом. Кстати вы заметили href-ссылку для электронной почты? Подробности на сайте Mozilla Developer Network.

иллюстрации и подписи
figures and captions

Последними (но, конечно, не по значимости), являются элементы <figure> и <figcaption>. Первый это "рисунок", например, диаграмма, иллюстрация или даже фрагмент кода. А опциональная <figcaption> это подпись, связанная с родительским элементом <figure>.

Чаще всего они используются для добавления видимых описаний к элементам <img/> в статье, например, так:

<section>
<h2>The Document Outline</h2>
<p>HTML5 includes several “sectioning content” elements that
affect the document outline.</p>

<figure>
<img src='semantic-elements.png'
alt='Diagram showing <article>, <section>, and <nav> elements'/>
<figcaption>New HTML5 semantic elements</figcaption>
</figure>
<!-- ... -->

Атрибут alt тесно связан с элементом <figcaption>. Атрибут alt должен служить текстовой заменой изображения, а <figcaption> - это вспомогательное описание, отображаемое либо с изображением, либо с его текстовым эквивалентом.

Используя <figcaption> вышеуказанным образом можно смело опустить атрибут alt картинки без ущерба для SEO. В зависимости от того, с какими картинками вы работаете, может оказаться более удобным (и менее избыточным) иметь видимые <figcaption>, которые описывают их, в отличие от невидимых атрибутов alt.

особенности css/legacy
css/legacy considerations

И наконец, небольшое замечание по поводу устаревших браузеров. Вышеперечисленные семантические элементы HTML появились в HTML5. Все современные браузеры распознают их без дополнительной работы, но иногда в глобальных таблицах CSS можно увидеть что-то вроде:

section, article, aside, footer, header, nav {
display: block;
}

Это заставляет новые семантические элементы вести себя в старых браузерах как элементы <div> (являющимися блоковыми блоками а не строчными).

РЕЗЮМЕ

Определение графических стилей с помощью CSS - это то, как мы передаем структуру веб-страницы людям. Размечая ее с помощью <header>, <article>, <figure> и других элементов <section> HTML, мы можем передать эти визуальные стили и машинам.

Interneting is hard HTML+CSS
Скриншот 15: неопределенная структура (серые элементы <div>) в сравнении с идентифицируемыми секциями (<header>, <article>, <figure> и <footer>)

Чтобы понять, почему это важно, представим себе машины, читающие наш контент. До появления семантического HTML разработчики использовали кучу элементов <div> с различными и несколько произвольными именами классов, определяющими структуру страницы. Например, все следующие элементы являются логическими именами для заголовка сайта:

<div class='main-menu'>
<div class='top-nav'>
<div class='top-banner'>
<div class='header'>

Раньше машины должны были понимать все вышеперечисленные <div> и многое другое. Новые семантические элементы HTML из этого урока - это как бы стандартизированные версии названий этих классов. Теперь они могут просто искать элемент <header>. Мы по-прежнему можем добавлять к нему любые имена классов для стилизации, но поисковики теперь имеют предсказуемый способ идентификации заголовков на всех HTML5-сайтах в Интернете.

Семантические элементы, описанные выше, для современных веб-сайтов являются оптимальными, но они едва ли исчерпывают все возможности, которые можнг придать веб-страницам. Вот только для начала:

Все эти аспекты относятся к области технического SEO, поэтому мы оставим их изучение на ваше усмотрение. На следующем уроке мы снова переключимся на изучение еще одного немаловажного компонента веб-сайтов (особенно электронной коммерции) - формами.


HTML & CSS IS HARD - НА РУССКОМ

ФОРМЫ

УРОК Nº 13.

Самый понятный учебник веб-разработки для получения пользовательских вводных

Элементы HTML-форм позволяют собирать данные от посетителей вашего сайта. Списки рассылки, контактные формы и комментарии в блогах - обычные примеры для небольших сайтов, но в организациях, которые полагаются на свой сайт для получения прибыли, формы священны и почитаемы.

Interneting is hard HTML+CSS
Скриншот 1: примеры ввода текста, текстовых полей, радиокнопок, чекбоксов и других элементов HTML-форм

Формы - это "денежные страницы". С их помощью сайты электронной коммерции продают свои товары, SaaS-компании* собирают оплату за свои услуги, а некоммерческие группы собирают деньги в Интернете. Многие компании оценивают успех своего сайта по эффективности его форм, потому что они отвечают на такие вопросы, как "сколько лидов наш сайт отправил в отдел продаж?" и "сколько людей подписались на наш продукт на прошлой неделе?". Зачастую формы подвергаются бесконечным A/B-тестированиям и оптимизации.

* - SaaS (Software as a service) - программное обеспечение как услуга.

Interneting is hard HTML+CSS
Скриншот 2: элементы фронтэнд-формы, отправляющие входные данные на бэкенд-сервер для обработки

У функциональной HTML-формы есть два аспекта: фронтенд (пользовательский интерфейс) и бэкенд (внутренний сервер). Первый - это внешний вид формы (определяемый HTML и CSS), а второй - это код, который ее обрабатывает (сохраняет данные в БД, отправляет e-mail и т. д.). Ниже мы полностью сосредоточимся на фронтенде. Обработку форм (бэкенд) оставим для следующего учебника.

подготовка
setup

К сожалению, невозможно обойти тот факт, что стилизация форм - это сложно. Всегда полезно иметь макет страницы, которую вы хотите создать, прежде чем начать ее кодировать, и это особенно актуально для форм. Итак, вот пример, который мы будем создавать в этой главе:

Interneting is hard HTML+CSS
Скриншот 3: макеты веб-страницs для смартфонов и ноутбуков/ПК с несколькими элементами форм

Как видите, это форма подачи заявок на участие в конференции для фиктивного докладчика. В ней присутствует довольно хороший набор элементов HTML-форм: различные типы текстовых полей, группа радиокнопок, выпадающее меню, флажок и кнопка отправки.

Создайте новый Atom-проект под названием forms и поместите в него новый HTML-файл под названием speaker-submission.html. Для начала добавим разметку для заголовка. (Эй, между прочим, здесь тоже есть семантический HTML!)

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Speaker Submission</title>
<link rel='stylesheet' href='styles.css'>
</head>
<body>
<header class='speaker-form-header'>
<h1>Speaker Submission</h1>
<p><em>Want to speak at our fake conference? Fill out
this form.</em></p>
</header>
</body>
</html>

Затем создайте файл styles.css и добавьте в него следующий CSS. Здесь используется простая техника flexbox для центрирования заголовка (и формы) независимо от ширины окна браузера:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
color: #5D6063;
background-color: #EAEDF0;
font-family: "Helvetica", "Arial", sans-serif;
font-size: 16px;
line-height: 1.3;

display: flex;
flex-direction: column;
align-items: center;
}

.speaker-form-header {
text-align: center;
background-color: #F6F7F8;
border: 1px solid #D6D9DC;
border-radius: 3px;

width: 80%;
margin: 40px 0;
padding: 50px;
}

.speaker-form-header h1 {
font-size: 30px;
margin-bottom: 20px;
}

Обратите внимание, что мы придерживаемся подхода mobile-first development (см. урок Адаптивный дизайн). Эти базовые правила CSS дают нам мобильный макет и служат основой макета для ноутбуков/ПК. Медиавыражение макета с фиксированной шириной (для ноутбуков/ПК) мы создадим чуть ниже.

формы
html forms

Переходим к формам! Каждую HTML-форму открывает элемент с подходящим названием - <form>. Он поддерживает множество атрибутов, но самые важные из них - action и method. Добавим пустую форму в наш HTML-документ, прямо под <header>:

<form action='' method='get' class='speaker-form'>
</form>

Атрибут action определяет URL, который обрабатывает форму. Именно сюда отправляются данные, собранные формой, когда пользователь нажимает кнопку Submit. Обычно это особый URL, определенный вашим веб-сервером, который знает, как обрабатывать данные. Распространенные технологии бэкенда для обработки форм это Node.js, PHP и Ruby on Rails, но на этом уроке мы сосредоточимся на фронтенде.

Interneting is hard HTML+CSS
Скриншот 4: <form>-атрибуты действия [action] и метода [method], отправляемые на бэкенд-сервер

Атрибут method может быть либо post, либо get. Оба они определяют, как форма отправляется на внутренний сервер. Это во многом зависит от того, как ваш веб-сервер хочет обрабатывать форму, но общее правило гласит: используйте post, когда вы изменяете данные на сервере. А get оставьте для тех случаев, когда вы только получаете данные.

Оставляя атрибут action пустым, мы указываем форме, что она должна отправляться по тому же URL. В сочетании с методом get это позволит нам просмотреть содержимое формы.

СТИЛИЗАЦИЯ ФОРМ
styling forms

Конечно, сейчас перед нами пустая форма, но это не значит, что мы не можем добавить к ней несколько стилей, как к контейнеру <div>. Это превратит ее в поле, соответствующее нашему элементу <header>:

.speaker-form {
background-color: #F6F7F8;
border: 1px solid #D6D9DC;
border-radius: 3px;

width: 80%;
padding: 50px;
margin: 0 0 40px 0;
}

текстовые поля ввода
text input fields

Для сбора пользовательских данных понадобится новый инструмент: элемент <input/>. Для создания текстового поля добавим в <form> немного кода:

<div class='form-row'>
<label for='full-name'>Name</label>
<input id='full-name' name='full-name' type='text'/>
</div>

Во-первых, наш контейнер <div> поможет со стилизацией. Это обычная практика для разделения элементов ввода. Во-вторых, для меток* формы у нас есть <label>. Это еще один семантический элемент HTML, так же как и <article> или <figcaption>. Атрибут метки for, должен совпадать с атрибутом id связанного с ней элемента <input/>.

* - метка - label.

Interneting is hard HTML+CSS
Скриншот 5: атрибут for элемента <label> указывает на атрибут id элемента <input>

В-третьих, элемент <input/> создает текстовое поле. Он немного отличается от других элементов, с которыми мы сталкивались, поскольку может кардинально менять внешний вид в зависимости от атрибута type, но он всегда создает некое интерактивное поле для ввода данных пользователем. Помимо текстовых данных далее мы рассмотрим и другие значения. Помните, что ID-селекторы - это плохо: атрибут id здесь нужен только для связывания его с элементом <label>.

Interneting is hard HTML+CSS
Скриншот 6: атрибут name элемента <input>, отправляющий переменную на сервер

Теоретически элемент <input/> представляет собой "переменную", отправляемую на внутренний сервер. Атрибут name определяет имя этой переменной, а значением является то, что пользователь ввел в текстовое поле. Заметьте, что можно заранее заполнить это значение, добавив к элементу <input/> атрибут value.

СТИЛИЗАЦИЯ ПОЛЕЙ ВВОДА ТЕКСТА
styling text input fields

Элемент <input/> можно стилизовать, как и любой другой элемент HTML. Давайте добавим немного CSS в styles.css, чтобы немного украсить его. Мы используем все концепции из уроков Привет, CSS, Блоковая модель в CSS, Селекторы CSS и Flexbox:

.form-row {
margin-bottom: 40px;
display: flex;
justify-content: flex-start;
flex-direction: column;
flex-wrap: wrap;
}

.form-row input[type='text'] {
background-color: #FFFFFF;
border: 1px solid #D6D9DC;
border-radius: 3px;
width: 100%;
padding: 7px;
font-size: 14px;
}

.form-row label {
margin-bottom: 15px;
}

Новый тип CSS-селектора input[type='text'], называемый "селектором атрибутов", подбирает только те элементы <input/>, у которых атрибут type равен text. Это позволяет нам специально выбирать текстовые поля, а не радиокнопки, которые определяются одним и тем же HTML-элементом (<input type='radio'/>). Подробнее о селекторах атрибутов вы можете прочитать на сайте Mozilla Developer Network.

Все наши стили "распределены по именам" в селекторе потомка .form-row. Подобная разделенность стилей <input/> и <label> облегчает создание различных типов форм. Почему следует избегать глобальных селекторов input[type='text'] и label, мы узнаем, когда доберемся до радиокнопок.

Наконец, давайте изменим базовые стили, чтобы создать версию для ноутбуков/ПК. Добавьте в конец нашей таблицы стилей следующее медиавыражение.

@media only screen and (min-width: 700px) {
.speaker-form-header,
.speaker-form
{
width: 600 px;
}
.form-row {
flex-direction: row;
align-items: flex-start; /* Чтоб избежать расползания */
margin-bottom: 20px;
}
.form-row input [type='text'] {
width: 250px;
height: initial;
}
.form-row label {
text-align: right;
width: 120px;
margin-top: 7px;
padding-right: 20px;
}
}

Посмотрите, как замечательно используется свойство flex-direction, чтобы <label> отображалась поверх своего элемента <input/> в мобильном макете, но слева от него в макете для ноутбуков/ПК.

Interneting is hard HTML+CSS
Скриншот 7: страница с одиночным текстовым полем, стилизованным с помощью CSS
поля ввода электронной почты
email input fields

Атрибут type элемента <input/> также позволяет выполнять базовую валидацию ввода. Добавим еще один элемент ввода, принимающий только адреса электронной почты, а не любые текстовые значения:

<div class='form-row'>
<label for='email'>Email</label>
<input id='email'
name='email'
type='email'
placeholder='[email protected]'/>
</div>

Это работает точно так же, как ввод type='text', за исключением автоматической проверки ввода email-адреса. Попробуйте в Firefox набрать что-то не являющееся мейл-адресом, а затем щелкните за пределами поля, чтобы оно потеряло фокус и подтвердило ввод. Поле станет красным, показывая, что введенное значение неверно. Chrome и Safari не выполняют такую проверку, до тех пор пока пользователь не попытается отправить форму. Мы увидим это в действии чуть ниже.

Interneting is hard HTML+CSS
Скриншот 8: в красной рамке - неверное значение поля электронной почты

Однако это больше, чем просто валидация. Сообщая браузерам, что мы ищем адрес электронной почты, они могут обеспечить более интуитивный пользовательский опыт. Например, когда браузер смартфона видит атрибут type='email', он отображает особую клавиатуру с легкодоступным символом @.

Также обратите внимание на атрибут placeholder, отображающий какой-либо стандартный текст, когда элемент <input/> пуст. Это хороший прием UX*, побуждающий пользователя ввести собственное значение.

Помимо email-адресов, существует множество других встроенных параметров валидации. Подробнее см. MDN- справочник по <input/>. Особенно интересны атрибуты required, minlength, maxlength и pattern.

* - UX - User Experience - Опыт взаимодействия.

СТИЛИЗАЦИЯ ПОЛЕЙ ВВОДА электронной почты
styling email input fields

Мы хотим, чтобы наше поле email соответствовало текстовому полю из предыдущей секции. Поэтому добавим еще один селектор атрибутов к существующему правилу input[type='text'], как показано ниже:

/* Измените это правило */
.form-row input[type='text'] {
background-color: #FFFFFF;
/* ... */
}

/* Чтобы получить еще один селектор */
.form-row input[type='text'],
.form-row input[type='email'] {
background-color: #FFFFFF;
/* ... */
}

Опять же, мы не хотим использовать здесь обычный input type селектор, потому что тогда будут стилизованы все элементы <input/>, включая радиокнопки и чекбоксы. Это часть того, что делает стилизацию форм сложной. Понимание CSS для выделения именно тех элементов, которые вам нужны - крайне важный навык.

Не будем забывать и о стилях для ноутбука/ПК. В нашем медиавыражении обновите правило input[type='text'] так, чтобы оно соответствовало следующему (обратите внимание, что мы готовимся к следующим секциям с селекторами select и textarea):

@media only screen and (min-width: 700px) {
/* ... */
.form-row input [type='text'],
.form-row input [type='text'], /* Добавьте */
.form-row input [type='text'], /* эти */
.form-row input [type='text'], /* селекторы */
width: 250px;
height: initial;
}
/* ... */
}

Поскольку теперь у нас возможно "верное" и "неверное" входное значение, наверно следует донести это до пользователей. Псевдоклассы :invalid и :valid позволяют стилизовать эти состояния независимо друг от друга. Например, мы хотим сделать рамку и текст красными, если пользователь ввел неприемлемое значение. Добавьте следующее правило в нашу таблицу стилей, вне медиавыражения:

.form-row input[type='text']: invalid,
.form-row input[type='email']: invalid {
border: 1px solid #D55C5F;
color: #D55C5F;
box-shadow: none; /* Удаление стандартного красного свечения в Firefox */
}

Пока мы не добавим кнопку отправки, вы сможете увидеть это только в Firefox, но идея вам понятна. Существует еще псевдокласс :focus, выбирающий элемент, который пользователь заполняет в данный момент. Это дает еще больше контроля над внешним видом форм.

радиокнопки
radio buttons

Изменение свойства type элемента <input/> на radio превращает его в радиокнопку. С радиокнопками дело обстоит немного сложнее, чем с текстовыми полями, поскольку они всегда работают в группах, позволяя пользователю выбрать один вариант из множества предопределенных.

Interneting is hard HTML+CSS
Скриншот 9: <fieldset>, обертывающий <legend> и ряд радиокнопок со связанными элементами <label>

Это означает, что нужна не только метка для каждого элемента <input/>, но и способ группировки радиокнопок и маркировки всей группы. Для этого предназначены <fieldset> и <legend>. Каждая созданная группа радиокнопок должна:

Наш пример с радиокнопкой содержит все эти компоненты. Добавьте в элемент <form> под полем электронной почты следующее:

<fieldset class='legacy-form-row'>
<legend>Type of Talk</legend>
<input id='talk-type-1'
name='talk-type'
type='radio'
value='main-stage' />
<label for='talk-type-1' class='radio-label'>Main Stage</label>
<input id='talk-type-2'
name='talk-type'
type='radio'
value='workshop'
checked />
<label for='talk-type-2' class='radio-label'>Workshop</label>
</fieldset>

В отличие от текстовых полей, пользователь не может вводить свои значения в радиокнопки, поэтому каждая из них нуждается в явном атрибуте value. Именно это значение отправится на сервер, когда пользователь отправит форму. Также очень важно, чтобы у каждой радиокнопки был одинаковый атрибут name, иначе форма не поймет, что они входят в одну группу.

Мы также добавили новый атрибут - checked. Это атрибут "булева типа". Он никогда не принимает значения - он либо существует в элементе <input/>, либо не существует. Если он присутствует на элементе радиокнопки или галочки, то этот элемент будет выбран/отмечен по умолчанию.

СТИЛИЗАЦИЯ РАДИОКНОПОК
styling radio buttons

Когда речь идет о стилизации радиокнопок, против нас работает несколько вещей. Во-первых, просто больше элементов, о которых нужно беспокоиться. Во-вторых, элементы <fieldset> и <legend> имеют довольно уродливые стили по умолчанию, и в разных браузерах они не слишком согласованы. В-третьих, на момент написания этой статьи <fieldset> не поддерживает flexbox.

Не волнуйтесь! Это хороший пример того, как обтекание [floats] может быть хорошим Plan B для устаревших/неудобных элементов. Вы заметили, что вместо существующего класса радиокнопки .form-row, мы выбрали новый класс .legacy-form-row? Так он будет полностью отделен от других элементов, используя floats вместо flexbox.

Interneting is hard HTML+CSS
Скриншот 10: мобильная версия, созданная блоковым блоком <label> и версия для ноутбуков/ПК с плавающим элементом слева

Начнем со стилей для смартфонов и планшетов, добавив следующие правила за пределами медиавыражения. Мы избавимся от стандартных стилей <fieldset> и <legend>, затем сделаем радиокнопки и ярлыки обтекаемыми, чтобы они отображались в одну строку под <legend>:

.legacy-form-row {
border: none;
margin-bottom: 40px;
}

.legacy-form-row legend {
margin-bottom: 15px;
}

.legacy-form-row .radio-label {
display: block;
font-size: 14px;
padding: 0 20px 0 10px;
}

.legacy-form-row input [type='radio'] {
margin-top: 2px;
}

.legacy-form-row .radio-label,
.legacy-form-row
input [type='radio'] {
float: left;
}

В версии для ноутбуков/ПК нужно, чтобы <legend> располагался на одной линии с элементами <label> из предыдущей секции (отсюда ширина: 120px), чтобы все элементы были плавающими (float), и отображались на одной линии. Обновите наши медиавыражения, включив в них следующее:

@media only screen and (min-width: 700px) {
/* ... */
.legacy-form-row {
margin-bottom: 10px;
}
.legacy-form-row legend {
width: 120px;
text-align: right;
padding-right: 20px;
}
.form-row legend {
float: left;
}
}

Что касается макетов, то это довольно хорошее кроссбраузерное решение. Однако настройка внешнего вида самой кнопки - это уже другая история. Это возможно, если воспользоваться атрибутом checked, но это немного сложно. Мы оставим вас гуглить "custom radio button CSS" и исследовать эту кроличью нору самостоятельно.

элементы select (выпадающие меню)
select elements (dropdown menus)

Выпадающие меню являются альтернативой радиокнопкам, поскольку они позволяют пользователю выбрать один из множества вариантов. Элемент <select> представляет собой выпадающее меню и содержит множество элементов <option>, которые представляют каждый элемент.

<div class='form-row'>
<label for='t-shirt'>T-Shirt Size</label>
<select id='t-shirt' name='t-shirt'>
<option value='xs'>Extra Small</option>
<option value='s'>Small</option>
<option value='m'>Medium</option>
<option value='l'>Large</option>
</div>

Как и в элементах радиокнопки <input/>, у нас есть атрибуты name и value, которые передаются на внутренний сервер. Но вместо того, чтобы быть определенными в одном элементе, они распределены между элементами <select> и <option>.

СТИЛИЗАЦИЯ ЭЛЕМЕНТОВ SELECT
styling select elements

Как и радиокнопки, элементы <select>, с трудом поддаются стилизации. На это есть своя причина. Выпадающие элементы - это сложный интерактивный элемент, и их поведение значительно отличается на разных устройствах. Например, на iPhone нажатие на элемент <select> приводит к появлению собственного прокручивающегося компонента пользовательского интерфейса, который значительно упрощает навигацию по меню.

Interneting is hard HTML+CSS
Скриншот 11: три элемента <option> в прокручивающемся меню <select> в нижней части экрана iPhone

Лучше всего позволить браузеру/устройству определить оптимальный способ предварительной настройки элемента <select>, поэтому мы сохраним простоту нашего CSS. К сожалению, даже самые простые вещи оказываются иногда на удивление сложными. Например, попробуйте изменить размер шрифта нашего элемента <select>:

.form-row select {
width: 100%;
padding: 5px;
font-size: 14px; /* Это не работает в Chrome или Safari */
}

Это работает в Firefox, но не в Chrome или Safari! Чтобы исправить ситуацию, можно использовать префикс для свойства appearance, характерный для конкретного производителя:

.form-row select {
width: 100%;
padding: 5px;
font-size: 14px; /* Это не работает в Chrome или Safari */
-webkit-appearance: none; /* Данный префикс заставит это работать */
}

Префикс -webkit будет применяться только к Chrome и Safari (они работают на движке WebKit), а Firefox останется незатронутым. По сути это хак. Даже MDN говорит о том, что не стоит использовать это свойство CSS.

Подобные трудности со стилями - серьезный аспект при создании формы. Если вам нужны пользовательские стили, лучше использовать радиокнопки или виджеты JavaScript UI. Bootstrap Dropdowns и jQuery Selectmenu - распространенные JavaScript-решения для настройки меню выбора. В любом случае, теперь вы хотя бы понимаете суть проблемы. Подробнее о проблемах <select> можно прочитать здесь.

ТЕКСТОВЫЕ ПОЛЯ
textareas

Элемент <textarea> создает многострочное текстовое поле, предназначенное для большого количества текста от пользователя. Они подходят для таких вещей, как биографии, эссе и комментарии. Давайте добавим <textarea> в нашу форму вместе с небольшим инструктирующим текстом:

<div class='form-row'>
<label for='abstract'>Abstract</label>
<textarea id='abstract' name='abstract'></textarea>
<div class='instructions'>Describe your talk in 500 words or less</div>
</div>

Заметьте, что этот элемент не является самозакрывающимся, как элемент <input/>, поэтому вам всегда нужен закрывающий тег </textarea>. Если вы хотите добавить текст по умолчанию, он должен находиться внутри тега, а не в атрибуте value.

СТИЛИЗАЦИЯ ТЕКСТОВЫХ ПОЛЕЙ
styling textareas

К счастью, стилизация текстовых полей довольно проста. Добавьте в ваш файл styles.css (перед медиавыражением!) следующее:

.form-row textarea {
font-family: "Helvetica", "Arial", sans-serif;
font-size: 14px;

border: 1px solid #D6D9DC;
border-radius: 3px;

min-height: 200px;
margin-bottom: 10px;
padding: 7px;
resize: none;
}

.form-row .instructions {
color: #999999;
font-size: 14px;
margin-bottom: 30px;
}

По умолчанию многие браузеры позволяют пользователю изменять размер элементов <textarea> до нужных размеров. Мы отключили это с помощью свойства resize.

Также нам нужно немного поправить макет для ноутбуков/ПК. <div>-элемент .instructions должен находиться под <textarea>, поэтому давайте сдвинем его влево на ширину колонки <label>. В конец нашего медиавыражения добавьте следующее правило:

@media only screen and (min-width: 700px) {
/* ... */
.form-row .instructions {
margin-left: 120px;
}
}

чекбоксы
checkboxes

Чекбоксы - это что-то вроде радиокнопок, но они позволяют пользователю выбрать сколько угодно вариантов вместо всего одного. Это упрощает задачу, ибо браузеру не нужно знать, какие флажки входят в одну группу. Другими словами, нам не нужна обертка <fieldset> или общие атрибуты имен [shared name attributes]. Добавьте в конец формы следующее:

<div class='form-row'>
<label class='checkbox-label' for='available'>
<input id='available'
name='available'
type='checkbox'
value='is-available'/>
<span>I’m actually available the date of the talk</span>
</label>
</div>

То, как мы использовали <label> здесь, немного отличается от предыдущих секций. Вместо того чтобы быть отдельным элементом, <label> обертывает соответствующий элемент <input/>. Это вполне допустимо, и так будет проще подобрать нужный нам макет. Но все же лучше использовать атрибут for.

СТИЛИЗАЦИЯ ЧЕКБОКСОВ
styling checkboxes

Для мобильного макета нам нужно всего лишь переопределить margin-bottom, который мы установили для остальных элементов <label>. Добавьте в styles.css, вне медиавыражения, следующее:

.form-row .checkbox-label {
margin-bottom: 0;
}

А внутри медиавыражения мы должны учесть 120-пиксельную колонку с метками:

@media only screen and (min-width: 700px) {
/* ... */
.form-row .checkbox-label {
margin-left: 120px;
width: auto;
}
}

Обернув и чекбокс, и текст метки, можно использовать ширину auto для расположения всего поля формы в одну строку. Помните, что ширина auto заставляет блок соответствовать размеру его контента?

Interneting is hard HTML+CSS
Скриншот 12: веб-страница с несколькими элементами HTML-формы, включая чекбокс
кнопки отправки
submit buttons

И наконец, завершим нашу форму кнопкой отправки. Элемент <button> это кнопка, отправляющая содержащуюся в ней <form>:

<div class='form-row'>
<button>Submit</button>
</div>

При нажатии на кнопку браузер проверяет все элементы <input/> в форме. Если проблем с валидацией не возникло, он отправляет ее по URL-адресу action. Если в поле email вы ввели что-то, не являющееся адресом электронной почты и нажмете кнопку <button>, то увидите сообщение об ошибке.

Interneting is hard HTML+CSS
Скриншот 13: сообщение об ошибке ввода недопустимого значения для поля электронной почты

Это также дает нам возможность увидеть, как данные пользователя отправляется на сервер. Сначала заполните все поля <input/> и убедитесь, что e-mail валидируется верно. Затем нажмите кнопку и просмотрите полученный URL в браузере. Там должно быть что-то вроде этого:

speaker-submission.html?full-name=Rick&email=rick%40internetingishard.com&talk-type=workshop&t-shirt=l&abstract=Derp.&available=is-available

Все, что находится после ? представляет собой переменные в нашей форме. За атрибутом name каждого <input/> следует знак равенства, затем его значение. Каждая переменная отделяется символом &. Если бы у нас был внутренний сервер, ему было бы очень просто получить всю эту информацию, запросить базу данных (или что-то еще) и сообщить, была ли отправка формы успешной или нет.

СТИЛИЗАЦИЯ КНОПОК
styling buttons

В секции "Псевдоклассы" урока Селекторы CSS у нас был опыт стилизации кнопок. Тогда мы применяли эти стили к элементу <a>, но мы можем использовать те же приемы и для <button>.

Interneting is hard HTML+CSS
Скриншот 14: кнопка отправки формы

Очистим этот безобразный стандартный стиль <button>, добавив в таблицу стилей следующее:

.form-row button {
font-size: 16px;
font-weight: bold;

color: #FFFFFF;
background-color: #5995DA;

border: none;
border-radius: 3px;

padding: 10px 40px;
cursor: pointer;
}

.form-row button:hover {
background-color: #76AEED;
}

.form-row button:active {
background-color: #407FC7;
}

Как и в случае с чекбоксом, учитываем колонку с метками шириной 120px, поэтому включаем в медиавыражения еще одно правило:

@media only screen and (min-width: 700px) {
/* ... */
.form-row button{
margin-left: 120px;
}
}

РЕЗЮМЕ

На этом уроке вы узнали про наиболее распространенные элементы форм HTML. Теперь у вас есть все эти инструменты для сбора данных от посетителей вашего сайта:

Для создания красивых форм вы должны хорошо разбираться в HTML и CSS, но для того, чтобы сделать эти формы функциональными, требуются навыки, которых у вас пока нет. Эти навыки выходят за рамки данного учебника, но, возможно, вам будет полезно узнать о них. В общем, существует два способа обработки форм:

В зависимости от структуры вашей компании, обработка форм может не входить в ваши обязанности фронтенд-веб-разработчика. В этом случае скооперируйтесь с бэкенд-разработчиком из вашей команды, чтобы убедиться, что <form> отправляет правильные пары имя-значение. Иначе вам придется позаботиться о том, чтобы фронтенд и бэкенд ваших форм гармонично сочетались друг с другом.

Далее вас ожидает заключительный урок. Мы завершим навыки работы с фронтендом, подробно обсудив веб-шрифты и практические принципы типографики, которые должен знать каждый разработчик.


HTML & CSS IS HARD - НА РУССКОМ

ВЕБ-ТИПОГРАФИКА

УРОК Nº 14.

Самый понятный учебник веб-шрифтов и основных принципов типографики

Под "веб-типографикой" понимают внешний вид всего текста на сайте. Она включает основные свойства текста CSS, например, какой тип шрифта использовать, когда выделять курсивом. Но типографика - это намного больше. Это пространство между и вокруг букв, слов и строк. Это размер различных участков текста по отношению друг к другу и история каждого семейства шрифтов.

Interneting is hard HTML+CSS
Скриншот 1: примеры семейств и относительных размеров шрифтов, стилей отступов, выравнивания текста, вертикального интервала и длины строки

Многие типографические решения вам подскажет дизайнер. Проблема в том, что типографика - это "невидимое" искусство. Чтобы понять, о чем просят дизайнеры, нужно уметь видеть типографику так же, как они.

Этот урок посвящен не только механике добавления веб-шрифтов на сайт или свойствам CSS для перемещения текста. Мы также выясним, как правильно использовать все эти инструменты для создания красивых, профессиональных сайтов. Допустим, дизайнер спрашивает: "Можно ли увеличить отступы в этом абзаце?" Так вот, к концу этого урока вы будете не только понимать о чем говорят дизайнеры, но и почему они этого хотят.

Можно позабыть конкретные свойства CSS, но концепции типографики, рассмотренные ниже, останутся с вами навсегда, потому что это не случайные правила - они основаны на функциях. Они делают ваш контент более читабельным и помогают эффективнее доносить информацию.

краткая история веб-шрифтов
a brief history of web fonts

Начнем с изучения того, как отображать веб-страницы собственным* шрифтом, ибо это самый интересный аспект современной веб-типографики. За последние несколько лет веб-шрифты сильно изменились, поэтому, прежде чем приступить к созданию нашего примера, вам необходимо получить базовое представление о различных форматах шрифтов в Интернете.

* - в оригинале: custom font - "пользовательский шрифт".

БЕЗОПАСНЫЕ ВЕБ-ШРИФТЫ
web safe fonts

Давным-давно существовали только "безопасные веб-шрифты". Их было около дюжины и они были предустановлены на большинстве компьютеров. Не было такого понятия, как пользовательский файл шрифта, отправляемый браузерам для использования на вашем сайте.

Interneting is hard HTML+CSS
Скриншот 2: веб-сервер запрашивает у компьютера пользователя отображение текста шрифтом Georgia, компьютер проверяет у себя наличие этого шрифта

Если вам был нужен особый шрифт, единственным вариантом было экспортировать изображение текста и включить его в веб-страницу с помощью элемента <img/>. Это безумно ограничивало возможности веб-дизайнеров и приводило к довольно сложным ситуациям для разработчиков. Честно говоря, мы не знаем, как мы выжили в ту эпоху HTML и CSS.

СОБСТВЕННЫЕ ВЕБ-ШРИФТЫ
custom web fonts

Примерно в 2010 году браузеры начали поддерживать собственные шрифты, что было замечательно. Однако для каждого браузера и дивайса требовался свой формат файла. Соответственно, большинство веб-сайтов предоставляли 4 разных файла веб-шрифтов:

ФОРМАТ ФАЙЛА БРАУЗЕР/УСТРОЙСТВО
.svg Очень старые Safari (iOS и десктоп)
.eot Internet Explorer
.ttf Все кроме Internet Explorer
.woff Более новые браузеры

В результате появился "пуленепробиваемый синтаксис" Bulletproof @font-face syntax, с которым вы наверняка столкнетесь в какой-то момент своей карьеры веб-разработчика.

Interneting is hard HTML+CSS
Скриншот 3: веб-сервер предоставляет браузеру для использования шрифты .svg, .eot, .ttf и .woff
ШРИФТЫ WOFF
woff fonts

С недавнего времени* были стандартизированы Web Open Font Format (WOFF), и жить стало немного проще. Более 90% современных браузеров поддерживают шрифты в формате .woff. Также растет и поддержка его следующей эволюции - .woff2. WOFF2 похож на оригинальный формат WOFF, но предлагает значительное уменьшение размера файла (что увеличивает производительность).

* - Данный учебник был опубликован в 2017 году.

Interneting is hard HTML+CSS
Скриншот 4: веб-сервер, предоставляющий браузеру только шрифты .woff и .woff2

Со временем, вероятно, вы полностью перейдете на WOFF2, но сейчас мы рекомендуем как WOFF, так и WOFF2. Это обеспечит безотказную работу на старых браузерах и повысит производительность на современных. Если только устаревшие браузеры не составляют большую часть вашей целевой аудитории, шрифты .ttf, .svg и .eot уходят в прошлое.

где найти веб-шрифты
where to find web fonts

В Интернете есть множество мест, где можно скачать как бесплатные, так и премиум шрифты. Три наших фаворита перечислены ниже. Какой шрифт использовать, обычно решает ваш дизайнер (и его бюджет), но для разработчика полезно знать компромиссы между этими вариантами.

САЙТ ЦЕНА КАЧЕСТВО ВЫБОР
Font Squirrel Халява Пан-Либо-Пропал Огромный
Google Fonts Халява Хорошее Приличный
Fontspring Дорого Хорошее Превосходный

Шрифты WOFF разработаны специально для современного веба, в то время как шрифты для ноутбуков/ПК содержат дополнительные функции, полезные для программ редактирования графики, таких как Adobe Illustrator. Обязательно загрузите или приобретите веб-версию шрифтов, которые вы хотите использовать, а не только версию для ноутбука/ПК.

подготовка
setup

Итак, мы готовы к экспериментам с веб-шрифтами. Для этого мы создадим этот пример веб-сайта. Мы подумали, что вам, вероятно, не захочется начинать его с нуля, поэтому загрузите начальный проект. Распакуйте его и откройте папку web-typography в своем любимом текстовом редакторе. Если у вас нет любимого текстового редактора, воспользуйтесь редактором Atom.

Interneting is hard HTML+CSS
Скриншот 5: файловый браузер редактора Atom после распаковки примера проекта

У нас есть 6 HTML-документов, использующих таблицу стилей typo.css. Мы продемонстрируем различные принципы типографики, добавив в каждый из этих HTML-файлов некоторые стили для конкретной страницы.

Interneting is hard HTML+CSS
Скриншот 6: наш пример веб-страницы с веб-шрифтами и системными шрифтами (до добавления веб-шрифтов)

Откройте один из HTML-файлов в браузере. Вы увидите, что наш исходный проект очень близок к финальному, за исключением веб-шрифтов и других типографических свойств CSS.

локальные веб-шрифты
locally hosted web fonts

Существует два различных способа добавления веб-шрифтов на ваш сайт: локальное размещение [locally hosted] и внешнее размещение [externally hosted]. Ниже мы рассмотрим оба способа. Сначала в наш проект мы добавим локально размещенный веб-шрифт. Этот процесс состоит из трех шагов:

  1. Скачайте веб-шрифт и добавьте его в свой проект.
  2. Вставьте веб-шрифт в таблицу стилей.
  3. Используйте шрифт в других местах таблицы стилей.

Мы будем работать с файлами web-fonts.html и typo.css. Откройте их в текстовом редакторе, если вы еще этого не сделали.

ХОСТИНГ ФАЙЛА WOFF
hosting a woff file

Итак, нам нужен веб-шрифт. В нашем примере используется бесплатный шрифт Roboto. Скачайте его с Font Squirrel. Убедитесь, что выбрана вкладка Webfont Kit, а не кнопка Download TTF. Снимите флажки со всех форматов, кроме WOFF, поскольку мы будем использовать только его. Затем нажмите на Download @font-face Kit.

Interneting is hard HTML+CSS
Скриншот 7: загрузка семейства шрифтов Roboto с сайта Font Squirrel

В итоге вы получите ZIP-файл с лицензией, инструкциями и папкой web fonts с кучей поддиректорий. Шрифт Roboto имеет множество различных начертаний - светлое, обычное, полужирное, курсивное и конденсированное. Каждая из этих папок содержит разные начертания. Нужная нам называется roboto_light_macroman. Откройте ее и скопируйте файл Roboto-Light-webfont.woff в наш проект.

ВСТРАИВАНИЕ ВЕБ-ШРИФТА
embedding a web font

Отлично. У нас есть файл WOFF. Для использования на нашей веб-странице, нужно вставить его в таблицу стилей с помощью правила @font-face. Веб-шрифты всегда должны быть включены в верхнюю часть таблицы стилей, поэтому добавьте код в самое начало typo.css:

@font-face {
font-family: 'Roboto';
src: url( 'Roboto-Light-webfont.woff') format( 'woff');
}

Свойство font-family определяет, как мы будем ссылаться на этот шрифт в дальнейшем. Оно работает как внутренний ярлык, поэтому может быть любым. Оно не обязательно должно совпадать с официальным названием шрифта, но это упрощает интуитивное понимание. Как будет показано ниже, стоит оставить название как можно более общим (например, Roboto вместо Roboto Light).

Далее у нас есть свойство src, определяющее путь к файлу .woff через нотацию url(). Путь может быть абсолютным, относительным или корневым. При использовании относительного пути, как в нашем случае, он всегда будет относительным к .css-файлу, а не к HTML-документу. Нотация format() позволяет браузерам узнать, к какому формату относится файл веб-шрифта.

Перезагрузив страницу web-fonts.html, вы не увидите никаких изменений, потому что @font-face предоставил нам доступ только к нашему файлу .woff. Нам все еще нужно использовать его где-то еще в нашей таблице стилей.

ИСПОЛЬЗОВАНИЕ ВЕБ-ШРИФТА
using a web font

В секции Выбор шрифтов говорилось про CSS-свойство font-family, определяющее, какой шрифт используется в конкретном HTML-элементе. После добавления правила @font-face at-rule мы можем использовать Roboto в качестве допустимого значения font-family в любом другом месте нашей таблицы стилей.

Давайте сделаем Roboto Light шрифтом по умолчанию для всего нашего проекта. Для этого изменим font-family в селекторе body файла typo.css:

body {
font-family: 'Roboto', sans-serif; /* Добавьте 'Roboto' сюда */
font-size: 18px;
line-height: 1.8em;
color: #5D6063;
}

Теперь весь текст должен отображаться шрифтом Roboto Light. А это значит, что мы потеряли сравнение с системным шрифтом sans-serif в файле web-fonts.html. Исправим это, добавив внутренние стили в <head> файла web-fonts.html:

<style>
.system-fonts {
font-family: sans-serif;
}
</style>

Класс .system-fonts применяется ко второму блоку в файле web-fonts.html. Вышеуказанное правило имеет приоритет над правилом body в typo.css, поэтому, открыв web-fonts.html в браузере, увидим наш Roboto Light сверху и стандартный системный шрифт снизу:

Interneting is hard HTML+CSS
Скриншот 8: страница с веб-шрифтами и системными шрифтами (после добавления веб-шрифтов)
семейства и начертания шрифтов
font families and font faces

Одно семейство шрифтов состоит из нескольких шрифтовых "лиц" [faces]*. Каждое начертание шрифта имеет в семействе свой вес или стиль. "Вес" [weight] это жирность конкретного шрифта, а "стиль" [style] - его начертание: романское (вертикальное), курсивное, конденсированное, расширенное или какое-либо другое.

* - "лицо" шрифта принято называть начертанием.

В нашем примере Roboto Light - один из шрифтов семейства Roboto. Остальные 17 шрифтов в скачанном ранее ZIP можно представить так:

Interneting is hard HTML+CSS
Скриншот 9: Шрифты Roboto - ось X: вес шрифта (100-900), ось Y: его стили (roman, italic, condensed)

В CSS вес шрифта выражается в виде числовых значений от 100 до 900. К счастью, для каждого из этих значений существуют стандартные, относительно удобные для понимания термины. "Черный" обычно означает 900, "полужирный" - 700, "обычный" - 400 и т. д. Как показано выше, большинство семейств не поставляют лица для каждого веса. В Roboto отсутствуют extra light (200), semi bold (600) и extra bold (800).

Стоит отметить, что каждая комбинация стиля и веса разработана как совершенно отдельное лицо. В высококачественном семействе шрифтов конденсированные стили - это не просто сжатые версии латинского шрифта, а полужирный шрифт - это не просто более "толстая" версия. Каждая буква в каждом начертании прорабатана вручную, чтобы обеспечить равномерное начертание текста.

Interneting is hard HTML+CSS
Скриншот 10: начертание буквы a - романское (вертикальное) в сравнении с курсивным

Это особенно заметно в курсивных и латинских начертаниях многих шрифтов с засечками. Например, строчная буква "а" в Century Schoolbook FS (шрифт, который вы сейчас читаете) приобретает совершенно другую форму, когда она выделена курсивом.

ПОДДЕЛЫВАНИЕ
fakin’ it

Почему так важен этот вес и стиль? В дизайне обычно используется несколько шрифтов одного семейства, поэтому следует знать, как встроить несколько файлов .woff, представляющих родственные шрифты.

Но сначала давайте посмотрим, что происходит, когда мы не предлагаем несколько шрифтовых лиц. Обновите левый абзац в файле web-fonts.html и добавьте в него элементы <em> и <strong>:

<section class= 'section section--gray' >
<h2>Web Fonts<h2>

<p>This paragraph is using a web font call <em>Roboto Light</em>. It’s a
little more refined and lends some <strong>unique character </strong> to
the web page.</p>
</section>

Перезагрузив страницу, вы заметите, что полужирный текст на самом деле не такой уж и полужирный. Это происходит потому, что он синтезируется. Мы не указали начертание полужирного шрифта для элемента <strong>, поэтому браузер пытается его подделать, автоматически преобразуя Roboto Light в более толстое начертание. То же самое происходит и с курсивом в элементе <em>, но определить это немного сложнее. Такое автоматическое преобразование почти всегда приводит к некачественной типографике.

Interneting is hard HTML+CSS
Скриншот 11: синтезированное полужирное начертание в виде чуть более жирного текста в сравнении с настоящим полужирным [genuine bold] начертанием в виде гораздо более жирного текста

Чтобы убедиться, что полужирный и курсивный шрифты действительно синтезируются, добавьте в typo.css следующее правило. Свойство font-synthesis определяет, разрешено ли браузеру подделать его или нет. На момент написания этой статьи* только Firefox обращает внимание на font-synthesis, поэтому в Chrome или Safari это не сработает:

/* Это работает только в Firefox */
em, strong {
font-synthesis: none;
}

Откройте файл web-fonts.html в Firefox, и элементы <em> и <strong> перестанут быть курсивными или полужирными - весь абзац будет набран латинским шрифтом Roboto Light.

* - Данный учебный курс был опубликован в 2017 году.

НЕСКОЛЬКО ШРИФТОВ (НЕПРАВИЛЬНЫЙ ПОДХОД)
multiple font faces (the wrong way)

Давайте попробуем добавить в наш проект шрифты Roboto Light Italic и Roboto Bold. Скопируйте из ZIP-файла Roboto, который мы скачали ранее, в папку web-typography следующие файлы:

Файл .woff представляет собой шрифтовое лицо одного семейства шрифтов, а @font-face позволяет нам внедрить это лицо в таблицу стилей. Наивным способом внедрения этих новых WOFF-файлов было бы простое добавление объявлений @font-face и изменение свойства font-family и по мере необходимости src. Добавьте в верхнюю часть файла typo.css следующее:

/* НЕ НАЗЫВАЙТЕ СЕМЕЙСТВА ШРИФТОВ ТАК */
@font-face {
font-family: 'Roboto Light Italic';
src: url('Roboto-LightItalic-webfont.woff') format('woff');
}

@font-face {
font-family: 'Roboto Bold';
src: url('Roboto-Bold-webfont.woff') format('woff');
}

Затем, чтобы использовать эти начертания в элементах <em> и <strong>, нам понадобятся следующие правила:

/* ЭТО НЕУКЛЮЖИЙ КОД */
em {
font-family: 'Roboto Light Italic', serif;
}

strong {
font-family: 'Roboto Bold', serif;
}

Это будет работать, и теперь при перезагрузке web-fonts.html в браузере вы должны увидеть правильные курсивные и полужирные шрифты. Проблема в том, что вручную указывать font-family каждый раз, когда мы хотим использовать курсивный или полужирный шрифт, как-то странно. Для этого следует использовать свойства CSS font-style и font-weight.

Interneting is hard HTML+CSS
Скриншот 12: три связанных файла .woff и три несвязанные объявления @font-face

Мы оказались в этой неуклюжей ситуации из-за того, как именно мы внедрили эти новые .woff-файлы. Использование отдельных значений font-family в @font-face заставляет их выглядеть как совершенно несвязанные начертания шрифтов. Хотя на самом деле все они из семейства Roboto.

По этой причине никогда не используйте описанную выше технику для вставки нескольких начертаний одного семейства шрифтов. Прежде чем двигаться дальше, удалите оба приведенных выше фрагмента.

НЕСКОЛЬКО ШРИФТОВ (ПРАВИЛЬНЫЙ ПОДХОД)
multiple font faces (the right way)

Чтобы сохранить родственные связи между тремя нашими шрифтами, все они должны использовать общее значение Roboto для свойства font-family. Чтобы различать светлый*, курсивный и полужирный шрифты, мы добавим в at-правило свойства font-style и font-weight. Замените все объявления @font-face в typo.css на следующие:

* - слово light из оригинала переводится в MDN по-разному: "светлый"; "сверхлегкий"

@font-face {
font-family: 'Roboto';
src: url('Roboto-Light-webfont.woff') format('woff');
font-style: normal;
font-weight: 300;
}

@font-face {
font-family: 'Roboto';
src: url('Roboto-LightItalic-webfont.woff') format('woff');
font-style: italic;
font-weight: 300;
}

@font-face {
font-family: 'Roboto';
src: url('Roboto-Bold-webfont.woff') format('woff');
font-style: normal;
font-weight: 700;
}

Считайте, что каждое правило @font-face - это описание файла .woff. Первое at-правило @font-face гласит, что это шрифт романский (нормальный) Roboto, вес шрифта 300 (light - "светлый*"). Второе гласит, что он также относится к семейству Roboto и имеет вес 300, но он курсивный. Наконец, третье сообщает браузеру, что Roboto-Bold-webfont.woff содержит романический шрифт весом 700 (bold - "полужирный**").

* - кроме "светлый" и "сверхлегкий" light в MDN переводится как "сверхтонкий";
** - bold вместо ожидаемого "жирный" в MDN переводится как "полужирный".

Interneting is hard HTML+CSS
Скриншот 13: связь трех связанных файлов .woff с тремя связанными объявлениями @font-face путем указания font-style и font-weight

Поскольку браузер знает, что наши шрифты связаны, наш CSS становится гораздо более интуитивным. В селекторе body мы можем задать стандартные семейство и вес шрифта. А когда мы захотим использовать курсив или полужирный шрифт для какого-либо элемента, можно просто указать font-style или font-weight, и браузер извлечет соответствующий файл .woff:

body {
font-family: 'Roboto', sans-serif;
font-weight: 300;
/* ... */
}

em {
font-style: italic;
}

strong {
font-weight: bold; /* Or 700 */
}

Значения font-style и font-weight для элементов <em> и <strong> установлены по умолчанию. Поэтому нам не нужно включать сюда последние два правила. Заметьте, что единственными удобными для человека ключевыми словами для font-weight являются normal (400) и bold (700). Все другие уровни жирности должны задаваться числами.

внешнее размещение веб-шрифтов
externally hosted web fonts

Ладно, все это было сложно. Существует способ использования веб-шрифтов попроще: внешнее размещение от Google Fonts. Мы сможем пропустить первые два шага, связанные с локальным размещением. Вместо добавления файлов .woff в наш проект и встраивания их с помощью @font-face, Google Fonts сделать все это за нас.

Interneting is hard HTML+CSS
Скриншот 14: обслуживание веб-шрифтов с собственного веб-сервера и обслуживание с сервера Google Fonts

Сейчас мы будем работать с файлом history.html, поэтому откройте его как в текстовом редакторе, так и в веб-браузере. Если вы хотите узнать краткую историю типографики, начиная с первого печатного станка, прочтите текст примера. Сейчас в каждом разделе history.html используется шрифт Roboto Light, но мы их изменим, чтобы они соответствовали периоду, о котором пойдет речь.

Interneting is hard HTML+CSS
Скриншот 15: копирование веб-шрифтов <link> из Google Fonts

Начнем с изменения шрифта для раздела Gothic/Blackletter. В Google Fonts найдите UnifrakturMaguntia. Он должен быть похож на те, которыми писали монахи в средние века. Нажмите кнопку Select this font. Во всплывающем меню вы увидите элемент <link/>. Скопируйте его в <head> файла history.html, над элементом <link/>, содержащим нашу таблицу стилей typo.css.

<link href="https://fonts.googleapis.com/css?family=UnifrakturMaguntia" rel="stylesheet">

Помните, что <link/> подключает внешние таблицы стилей. Как раз это и делает приведенный выше HTML. Однако вместо ссылки на локальный CSS-файл он включает CSS, определенный Google Fonts. Если вы вставите значение href в браузер, вы найдете то же самое объявление @font-face, которое мы использовали в предыдущем разделе - только на этот раз нам не пришлось его прописывать. Ура!

Теперь, когда мы внедрили наш веб-шрифт UnifrakturMaguntia, мы можем использовать его для стилизации любого HTML-элемента. Добавьте в <head> файла history.html следующее:

<style>
.blackletter {
font-family: 'UnifrakturMaguntia', cursive;
}
</style>

Первая секция имеет атрибут class='blackletter', поэтому теперь она будет напечатана готическим шрифтом:

Interneting is hard HTML+CSS
Скриншот 16: текст, набранный шрифтом blackletter

Google Fonts - быстрое и простое решение, но все же профессиональные сайты обычно используют локальными веб-шрифтами. Это дает гораздо больше возможностей (вы не ограничены ассортиментом Google шрифтов) и может повысить производительность/надежность, если оставшаяся часть сайта оптимизирована верно.

СЛИШКОМ МНОГО ШРИФТОВЫХ ФАЙЛОВ
too many font files

Заговорив о производительности, давайте сделаем нечто ужасное. На нашей странице history.html есть еще 10 разделов, и мы придадим каждому из них свой собственный веб-шрифт. Можно внедрить несколько шрифтов в один элемент <link/>. Поэтому измените нашу таблицу стилей Google Fonts, включив в нее все остальные:

<link%20href=%22https://fonts.googleapis.com/css%3ffamily=Alfa+Slab+One|Droid+Sans+Mono|Lato|Libre+Baskerville|Lobster|Questrial|Rokkitt|Rufina|Sorts+Mill+Goudy|UnifrakturMaguntia%22%20rel=%22stylesheet%22>

Заметим, что это можно сделать в Google Fonts, выбрав несколько шрифтов перед копированием элемента <link/>. Затем добавьте все эти новые шрифты в элемент <style> файла history.html:

.old-style {
font-family: 'Sorts Mill Goudy', serif;
}
.transitional {
font-family: 'Libre Baskerville', serif;
}
.didot {
font-family: 'Rufina', serif;
}
.slab {
font-family: 'Rokkitt', serif;
}
.fat-face {
font-family: 'Alfa Slab One', cursive;
}
.grotesque {
font-family: 'Roboto', sans-serif;
}
.geometric {
font-family: 'Questrial', sans-serif;
}
.humanist {
font-family: 'Lato', sans-serif;
}
.display {
font-family: 'Lobster', cursive;
}
.monospace {
font-family: 'Droid Sans Mono', monospace;
}

Теперь каждый раздел history.html отображается шрифтом той эпохи, которую он описывает. Это будет хорошим введением в историческую значимость различных шрифтов. Но на практике никогда не помещайте такое количество веб-шрифтов на одну веб-страницу.

Помните, что каждый веб-шрифт - это файл .woff или .woff2, который браузер должен загрузить, прежде чем отобразить страницу. Большее количество шрифтов увеличивает время загрузки. Ключ к эффективному использованию веб-шрифтов - баланс между производительностью (меньшее количество веб-шрифтов) и красиво набранным документом (большее количество веб-шрифтов).

Вот и все, что вам нужно знать о веб-шрифтах. Остальная часть этого урока посвящена основным принципам типографики. Это простые рекомендации (с простым CSS), обычно отличающие любительскую веб-страницу от профессиональной.

Отступы в абзацах
paragraph indents

Отделение абзацев друг от друга - одна из самых фундаментальных функций типографики. Есть два общепринятых решения: либо использовать отступ indent первой строки, либо margin между абзацами. Ваши читатели (надеемся) не глупы - им не нужны два признака того, что начинается новый абзац, поэтому никогда не используйте одновременно indent* и margin. Это уже перебор.

* - в русскоязычном MDN слово "отступ" используется для трех различных терминов: indent, margin, padding. Во избежании путаницы indent я перевожу как "indent" или "indent-отступ".

Interneting is hard HTML+CSS
Скриншот 17: indent-отступ первой строки нового абзаца ("ок"), добавление полей между абзацами ("ок"), оба варианта - никогда! (never both)

Свойство CSS text-indent определяет размер отступа первой строки определенного элемента (обычно это <p>). Мы можем изучить это на нашей странице indents.html. Измените существующие margin-стили в первом разделе на indent, добавив в элемент <style> следующее:

<style>
.paragraph-indent p {
text-indent: 1em;
margin-bottom: 0;
}
.paragraph-indent p:first-of-type {
text-indent: 0;
</style>

Обратите внимание, что первый абзац после заголовка никогда не должен иметь indent, так как обычно очевидно, что это новый абзац. Это очень хороший пример использования псевдокласса :first-of-type.

А вот негативный пример, чтобы мы помнили, чего делать не следует. Добавьте это в стили конкретной страницы в файле indents.html:

/* ДИЗАЙНЕРЫ ОСУДЯТ ВАС ЗА ЭТО */
.never-both p {
text-indent: 1em;
margin-bottom: 1em;
}

Это может показаться смешным, но предупреждение о том, что дизайнеры вас осудят, на самом деле вовсе не шутка.

выравнивание текста
text alignment

Выравнивание текста подсознательно влияет на то, как его читают. Возможно, вы не замечали ранее, что ваши глаза не двигаются плавно по мере чтения - они перескакивают со слова на слово и со строки на строку. Глаза фиксируются на одних местах и пропускают другие.

Interneting is hard HTML+CSS
Скриншот 18: текст с точками (вы читаете так) и потоки строк текста (так вы НЕ читаете)

В хорошо спроектированном HTML-документе выравнивание текста не бывает случайным. Оно учитывает вышеупомянутую особенность человеческой физиологии. Правильное выравнивание сильно облегчает пользователям чтение вашего текста, поскольку дает их глазам якорь, помогающий перемещаться от строки к строке.

Ниже будет показано, как правильно выравнивать выравнивание текста по левому краю, по центру, по правому краю и по обеим краям [justified]. Все эти примеры основаны на свойстве text-align, которое управляет выравниванием текста определенного HTML-элемента. В нашем проекте мы создали страницу alignment.html с несколькими сценариями.

ВЫРАВНИВАНИЕ СЛЕВА
left alignment

Большая часть текста должна быть выровнена слева, потому что это вертикальный якорь, к которому читатель может вернуться на каждой строке. Длинные фрагменты текста почти всегда выровнены по левому краю. Короткие тексты и заголовки имеют немного больше свободы действий.

Interneting is hard HTML+CSS
Скриншот 19: вертикальные точки по левому краю текста служат якорями для глаз

Выравнивание слева - это стандартное значение text-align. Но если бы мы хотели быть более выразительными, в элемент <style> нашего файла alignment.html можно было бы добавить следующее правило:

<style>
.left {
text-align: left;
}
</style>

Конечно, если вы работаете над сайтом на языке, который пишется справа налево, (например, арабский), вы можете поменять все эти советы. См. Выравнивание справа ниже.

ВЫРАВНИВАНИЕ ПО ЦЕНТРУ
center alignment

Текст, выровненный по центру, не имеет якоря, поэтому на переходах к следующей строке глазу легче потеряться. Он лучше всего подходит для коротких строк (подробнее об этом позже) и для особых видов контента, таких как стихи, тексты песен и заголовки.

Interneting is hard HTML+CSS
Скриншот 20: неравномерно расположенные точки на отцентрированном тексте

Выровняйте по центру второй абзац в файле alignment.html с помощью следующего встроенного [page-specific] стиля:

.center {
text-align: center;
}

Обратите внимание, что теперь страница кажется немного разрозненной. Второй абзац, выровненный по центру, нарушает течение первого абзаца, выровненного слева. Вообще, выравнивание текста должно быть одинаковым на всей веб-странице. Если отцентрирован один заголовок, отцентрируйте все заголовки.

ВЫРАВНИВАНИЕ СПРАВА
right alignment

Другой аспект при выборе выравнивания текста - это его связь с окружающими элементами. Взгляните на третий раздел в файле alignment.html. Мы хотим переместить надпись к изображению слева от него и выровнять ее по правому краю, чтобы она выглядела как прикрепленная к изображению:

Interneting is hard HTML+CSS
Скриншот 21: картинка и слева от нее выровненный по правому краю текст

В нашем примере изображение заключено в <figure>, а подпись - в <figcaption>, поэтому к вышеуказанному макету приведет добавление в alignment.html, точнее в элемент <style>, следующего кода.

figcaption {
display: none;
}
@media only screen and (min-width: 900px) {
figure {
position: relative;
}
figcaption {
display: block;

font-style: italic;
text-align: right;
background-color: #FFFFFF;

position: absolute;
left: -220px;
width: 200px;
}
}

Это также хороший пример продвинутого позиционирования. Относительное положение <figure> задает систему координат для абсолютного позиционирования <figcaption>. Сдвинув надпись влево на 220px и задав ей явную ширину 200px, мы получим хороший 20-пиксельный margin между картинкой и ее надписью.

Как и центрированный текст, выравнивание cправа следует использовать в особых случаях, поскольку неровный левый край затрудняет читателю поиск следующей строки.

JUSTIFY-ВЫРАВНИВАНИЕ
justified text

Justify-выравнивание* создается тонкой регулировкой интервалов между словами/буквами и разделения длинных слов дефисами, до тех пор, пока каждая строка не станет одинаковой ширины. Без хорошего дефисного движка**, justify-выравнивание приводит к большим пробелам между словами, затрудняющим глазам горизонтальное перемещение по тексту.

* - русский перевод justify в MDN и Википедии не найден. Поэтому здесь и далее используется "justify-выравнивание". Смысл: выравнивание левых и правых границ текста по левым и правым границам содержимого параграфа.
** - в оригинале: high-quality hyphenation engine.

Interneting is hard HTML+CSS
Скриншот 22: bad hyphenation - "плохой дефис" (неравномерные пробелы между буквами и словами) и good hyphenation - "хороший дефис" (равномерные пробелы)

К сожалению, большинство браузеров не имеют вообще никакого встроенного дефисного движка, поэтому выравнивания текста в HTML-документах лучше избегать. Для наглядности в наш файл alignment.html добавим еще одно правило:

.justify {
text-align: justify;
}

Сравните это с абзацем, выровненным по левому краю. Такой абзац будет выглядеть чуть более равномерно и привлекательно.

вертикальный интервал текста
vertical text spacing

Как выравнивание текста, так и вертикальный интервал не является чем-то случайным. В этом разделе мы рассмотрим грамотное использование трех свойств CSS:

  • margin-top (или padding-top)
  • margin-bottom (или padding-bottom)
  • line-height

Первые два свойства вам уже знакомы. Они определяют вертикальный интервал между отдельными абзацами. Новое свойство line-height задает интервал между строками в одном абзаце. В традиционной типографике высота строки называется leading - "лидирование"*. Ранее печатники использовали маленькие полоски свинца для увеличения интервала между строками текста.

* - от lead - свинец.

Вместе эти свойства создают "вертикальный ритм" веб-страницы. Существуют различные методы определения "оптимального" вертикального ритма для конкретного макета, но общие принципы таковы:

  • достаточно пространства чтоб свободно дышалось
  • одинаковые интервалы на всей странице.

Чтобы продемонстрировать это, мы разрушим вертикальный ритм во второй половине нашей страницы spacing.html. Добавьте следующие встроенные [page-specific] стили в файл spacing.html

<style>
.messy {
line-height: 1.2em;
}
.messy h2 {
line-height: .9em;
}
.messy:last-of-type {
line-height: 1.5em;
}
.messy:last-of-type h2 {
margin-bottom: .3em;
}
.messy .button:link,
.messy .button:visited {
margin-top: 0;
}
</style>

Несколько небольших изменений высоты строк, padding и margin могут существенно повлиять на качество страницы:

Interneting is hard HTML+CSS
Скриншот 23: сравнение больших, равномерных интервалов с тесными и неравномерными

В расчете вертикального ритма страницы на удивление много математики и психологии, но это работа для вашего дизайнера. Как разработчик, вы должны знать свойства CSS, чтобы реализовать то, о чем они просят. Важно понимать, что дизайнеры действительно думает об этих вещах. Поэтому уделяйте самое пристальное внимание свойствам margin, padding и line-height.

длина строки
line length

Если вертикальный интервал вашего текста не является произвольным, не стоит удивляться, что и горизонтальный интервал не является таковым. Длина строки или "мера" [measure] есть горизонтальная длина вашего текста. Это количество символов или слов, помещающихся в одну строку. Мера связана со следующими свойствами CSS:

  • width
  • margin-left (или padding-left)
  • margin-right (или padding-right)

Хорошим правилом является ограничение количества символов до 80 на строку. Как и выравнивание, это неявно влияет на читабельность вашего контента. Для перемещения от левого края абзаца к правому, глазу нужна энергия. Чем дальше ему приходится сканировать, тем быстрее он устает. Возврашение к началу следующей длинной строки напрягает. В длинных строках легко заблудиться.

Interneting is hard HTML+CSS
Скриншот 24: длина строки как ширина абзаца

Именно поэтому многие сайты (включая и этот) используют макеты фиксированной ширины или на более широких экранах разбивают контент на несколько колонок. Без ограничения ширины страницы или разделения на колонки длина строки становится невыносимо большой.

В нашем примере файл line-length.html имеет приемлемую меру. Давайте посмотрим, что произойдет, если мы разобьем нижнюю половину страницы, добавив в ее <head> следующее:

<style>
@media only screen and (min-width: 580px) {
.not-so-manageable {
max-width: 100%;
margin-left: 2em;
margin-right: 2em;
}
}
</style>

Теперь вторая секция растягивается на всю ширину окна браузера. Из-за большой длины строки это несколько неудобно для восприятия. Повторимся, цель хорошей веб-типографики - сделать так, чтобы посетителям было как можно легче воспринимать ваш контент.

дополнительные рекомендации
по типографике
other basic typography guidelines

Вышесказанного должно быть достаточно, чтобы вы начали свой путь к качественной веб-типографике. Типографика это целая индустрия и мы едва коснулись ее поверхности. Эта тема относится скорее к дизайну, чем к веб-разработке, поэтому мы просто дадим несколько финальных рекомендаций:

  • Для элемента body используйте размер шрифта от 14px до 20px.
  • Используйте "двойные кавычки" &rdquo;, &ldquo; и "одинарные" кавычки &rsquo;, &lsquo; посредством HTML- сущностей.
  • Используйте правильные тире (&ndash;, &mdash;) и другие символы (&copy;).
  • Не используйте text-decoration: underline (кроме случаев hover).
  • Используйте настоящие курсивные шрифты вместо синтезированных, если они не перегружают производительность.

Если вам нравятся такие вещи, то в Practical Typography есть фантастический список общих правил для верстки документов.

РЕЗЮМЕ

Цель этого урока была двоякой:

  • Изучить механику веб-шрифтов и основные свойства типографики CSS.
  • Понять, как дизайнеры относятся к типографике.

Возможно, по окончании этого урока вы не сможете с нуля создать роскошно набранную веб-страницу, но это и не важно. Его цель была познакомить вас с невидимым искусством типографики. Теперь у вас есть словарный запас, чтобы говорить о таких вещах, как семейства шрифтов, начертания, вес и стили, а также лидирование, мера и вертикальный ритм.

Ключевая мысль этого урока - на хорошо сверстанной веб-странице нет ничего случайного. Размер шрифта, стиль отступов, выравнивание текста, высота строки, margins и все мельчайшие детали страницы были тщательно продуманы. За всеми этими решениями стоит некий замысел.

Все рассмотренные в данном учебнике свойства CSS, на самом деле очень просты. По сути, мы просто перемещали кучу квадратиков, меняли цвета и изменяли внешний вид текста. Смысл этих действий зависит от дизайна и бизнес-целей сайта, который вы создаете.

Хотите верьте, хотите нет, но вы подошли к концу нашего учебника HTML & CSS is Hard. Мы рассмотрели все элементы HTML и свойства CSS, необходимые для создания профессиональных веб-страниц. Единственное, чего не хватает, - это опыта. Ваш следующий шаг - отработать все эти новые навыки, создав несколько веб-страниц с нуля.

Ждите следующие учебники!

HTML & CSS IS HARD - НА РУССКОМ

ИТ-терминология самого простого и понятного учебника веб-разработки

ГЛОССАРИЙ К УЧЕБНИКУ HTML & CSS IS HARD

Updated 10.04.2024


ПРИМЕЧАНИЯ
Стандарты перевода согласно MDN - Mozilla Developers Network. Второй источник русскоязычных терминов - Wikipedia.

Когда перевод состоит из нескольких слов, используем сначала первое, при повторении можно взять второе, при очередном повторении берем тогда уже третье. Пример: content - 1)контент, 2)содержание, 3)содержимое;

JS code terms are marked yellow. Пример: content - 1)контент, 2)содержание, 3)содержимое;

СОКРАЩЕНИЯ
англ. - английский
см. - смотри
тж. - также ex. - пример(ы), например



absolut and flexible sizes - фиксированные и гибкие размеры;
accessibility - доступность;
advanced - продвинутый;
advisory information - консультативная информация;
alignment - выравнивание;
alignment >> alignment control - управление выравниванием;
alignment >> alignment features - механизм выравнивания;
alignment >> text alignment - выравнивание текста;
annotation - аннотация;
appropriate - подходящий;
arbitrary number - произвольное число;
arbitrary number >> arbitrary number of other child elements - произвольное число других дочерних элементов;
ARIA role - ARIA-роль, ARIA-роли;
art direction - художественное оформление;
art direction problem - часто без перевода или: проблема художественного оформления;
ascending counter - возрастающий счетчик;
aside - отступление, элемент <aside>;
assuming it is... - при условии, что...
at-rules, @-rules - at-правила, @-правила. Это CSS операторы, которые показывают CSS как себя вести;
attribute selector - селектор атрибутов;
auto-margin - auto отступ;
axis - ось. Main and cross axis - главная и поперечная оси;
backend - бэкенд;
base color - основной цвет;
basic example - базовый пример;
basic sections of a document - основные составляющие документа;
blank line - пустая строка;
block of CSS - CSS блок;
blur radius - радиус размытия;
boolean attribute - аттрибут булева типа;
box - блок или бокс (оба понятия встречаются в MDN. прямоугольная область, являющаяся изображением элемента;
box model - блоковая модель, блочная модель, боксовая модель;
block - блок, тж. см. box;
block box - блоковый блок;
block-level behavior - блоковое поведение;
block scope - s. scope;
block statement also: compound statement - блок инструкций (или сложная инструкция в других языках);
body - тело, элемент body;
boolean - Boolean атрибут, булев атрибут, булевский атрибут;
border - рамка или границы. Сплошная линия, которая расположена рядом с внешним отступом (padding);
border area - область рамки;
border edge - края рамки;
break - разрыв;
break >> create a break at that location - создать разрыв в этом месте;
break onto a new line - начинать(ся) с новой строки;
breakpoint - точка останова, брейкпоинт;
breakpoint >> setting a breakpoint - установка точек останова;
bullet, bullet point - маркер в виде круга, "пулька";
bulleted list - маркированный список;
callback function - колбэк-функция;
canvas scripting API - отрисовка графики при помощи скриптов (обычно используется JavaScript);
capability - возможность;
caption - подпись (обычно под изображением, диаграммой, фото и т.п.);
carriage-return - возврат каретки;
cascade - каскадность;
cascade >> Cascading Style Sheets - Каскадные Таблицы Стилей;
case-sensitive - чувствительны к регистру;
case > in lower case - в нижнем регистре;
casing - регистр;
caveat - оговорка;
cell - ячейка;
сentering the image - Центрирование изображения;
character - символ;
character attribut - символьный атрибут (ex: type);
character set - стандарт кодировки символов, кодировка символов;
checkbox - чекбокс;
child >> first child - первый дочерний (элемент);
citation metadata - метаданные цитирования;
class selectors - селекторы по классу;
click - щелчок;
code units - кодовые значения;
collapse - схлопывание;
collapse >> margin collaps - схлопывание margin, схлопывание внешних отступов;
сolumn - колонка;
сolumn >> main content column - колонка основного содержимого;
columns and rows (in Grid Layout) - колонки и строки;
сollapse - объединение в одно;
combinator - комбинатор;
combinator >> descendant combinator - Комбинатор " " (пробел) ;
combinator >> child combinator (>) - комбинатор >. Разделяет 2 селектора, находит элементы заданные вторым селектором, являющие прямыми потомками для элементов отобранных первым селектором.;
complex - сложный;
compliant - совместимые;
comprehension - понятие;
comprehension >> Fundamental layout comprehension - Фундаментальное понятие вёрстки;
consecutive -последовательные, идущие подряд, идущие друг за другом;
container - контейнер;
content - контент, содержание, содержимое документа или страницы;
content >> content area - внутренняя область элемента;
content >> end content - конечный контент (содержимое в футере);
content >> introductory content - вводный контент, вводное содержимое;
content >> main content - основное содержимое;
content >> media content - медиа-контент;
content >> phrasing content - фразовый контент;
content >> self-contained content - самостоятельный контент;
content(-box) width - ширина контента;
content(-box) height - высота контента;
content items - элементы контента;
control flow statements - операторы управления потоком Ex. if...else and for.;
control of overlapping content - управление перекрывающимся контентом;
current element - текущий элемент;
conditional processing - условная обработка;
contextual menue - контекстное меню;
consistently - последовательно;
controls - управление;
core - ядро;
crafting - создание;
Event reference - справочник по событиям;
dealing with files - работа с файлами;
debugger >> invoke a debugger - вызвать функциональность отладки;
debugging - отладка;
declaration - использование; декларация #mdn; объявление (in CSS) #wiki;
declaration >> function declaration - использование функции; Variables declared with var = Переменные, объявленные через var
declaration block - блок деклараций, блок объявлений;
dedicated tags - выделенные теги;
definition list - список определений;
define >> in which it was defined - в котором оно было определено;
delete - удалять;
demarcating edits - разграничительные правки;
deprecated, but kept for compatibility purposes - устарели, но сохранены в целях совместимости;
descendants of this element - потомки данного элемента;
descendant selector - селектор потомков;
descriptor - дескриптор;
descriptor >> data d./accessor d. -
дескриптор данных/дескриптор доступа;
desktop - насто́льный (стациона́рный) компью́тер, ПК, дескто́п #wiki;
diff - разница, различие;
diff >> source code diff information - информация о различиях в исходном коде;
display type - тип отображения (элемента);
distributing - распределение;
drag - перетаскивать;
draw - отрисовывать;
draw >> draw graphics and animations - отрисовка графиков и анимации;
editor's note -примечание редактора;
effect - влияние;
effect >> have no effect on some elements - не оказывать влияния на некоторые элементы;
embed - встроенный;
embed >> embed sound content - встроенный звуковой контент;
empty string value - значение "пустая строка", указывает, что элемент должен быть редактируемым;
encoding >> UTF-16 e. - встроенный;
ensuring accessibility - обеспечение (улучшение) доступности;
entity, HTML entities - сущность, HTML-сущности;
entity >> memorable entities - запоминающиеся сущности (мнемоники). Напр. &copy; для символа копирайта (©);
enumerated attribute - логический атрибут;
environments - среды;
event handler - обработчики событий;
explicit - явный, четко выраженный;
external application - внешнее приложение;
external resource - внешний ресурс;
face, font face - начертание, начертание шрифта. Тж. см. value в типографике;
favicon - иконка в стиле "favicon";
feature - функция; особенность;
feature >> range feature - функция диапазона;
figure - иллюстрация;
file structure - файловая структура;
fixed width - фиксированная ширина;
fixed width layout - макет фиксированной ширины;
flavor - тип, вид;
flavor >> two main flavors - два основных типа;
flexbox - технология flexbox (инструмент CSS-верстки);
flex container - flex контейнер;
flex element - flex элемент (дочерний элемент flex контейнера);
flex item - см. flex element;
flexible box - flex блок;
float - в CSS: 1) обтекание, 2) свойство float, 3) плавающий (напр. плавающий элемент) Изначально созданное для плавающих изображений внутри текстовых блоков, свойство float стало одним из наиболее часто используемых инструментов для создания мульти-колоночной вёрстки веб-страниц.;
float element - плавающий элемент;
flow >> normal flow - нормальный поток;
flow content - потоковый контент;
flow layout - схема потока, поточная раскладка;
fluid - жидкий;
fluid layout / website - жидкий макет / жидкий сайт;
font - шрифт;
font > custom font - собственный шрифт;
font > downloadable font - загружаемый шрифт;
font > locally hosted font - локальный шрифт;
font > web safe font - безопасные веб-шрифты;
font file(s) - файл(ы) шрифтов;
font-size - размер шрифта;
font stack - стек шрифта;
font-weight - начертание шрифта;
footer - нижний колонтитул (футер), "подвал";
fr - блок fr - блок фракции (fraction) - единица для макета сетки;
frontend - фронтенд;
full bleed - polygr. без полей, без рамки по краям; (о фотографиях, графических материалах – напр., full bleed image;
full-bleed layout - макет (вебстраницы) без рамки по краям;
gap - разрыв;
generic container - универсальный контейнер;
generic container - таблица стилей (как правило, CSS) слово "global" в MDN и в русскоязычной википедии при переводе опускается;
global attribute - глобальный атрибут;
glossary entries - словарь;
grapheme - графема;
grid - сетка или грид;
grid >> CSS Grid Layout - макет сетки или CSS грид-раскладка (двумерная система вёрстки). Она позволяет вам размещать контент в строках и столбцах и имеет множество возможностей, которые упрощают построение сложных макетов;
grid inspector - грид-инспектор (en-US);
guides - руководство;
handle - обрабатывать;
handle >> automatically handle subtitles - автоматически обрабатывать субтитры;
hash - хеш, символ решетки (#);
header - шапка, элемент метаданных (header element), хидер, заголовок (колонтитул) большая полоса вверху страницы, с крупным заголовком и/или логотипом. Здесь указывается общая информация о веб-сайте, одинаковая для всех страниц. ;
header >> global h., specific h. - глобальный заголовок, конкретный з.;
heading - ??????;
homepage - домашняя страница;
horizontal rule - горизонтальный разделитель; горизонтальная прямая;
hook up - подключать. stylesheet is hooked up to our HTML page = таблица стилей подключена к HTML-страницам.;
<hr> thematic break element - горизонтальный разделитель, (для тематического изменения текста) напр. изменение темы или сцены ;
hyperlink - гипертекстовая ссылка;
hyphen - дефис;
identifier (ID) - идентификатор (ID);
image - изображение, картинка;
implicit - неявный;
image map (a clickable link area) - карта изображения (интерактивная область ссылок);
imaginative - творчески;
index - оглавление якорных ссылок;
indent - отступ, пустое место;
information architecture - планирование содержания всего веб-сайта;
inherent - собственная, естественная, присущая, оригинальная;
inline - строковый, строчный;
inline box - inline-блок, строковый блок;
inline element - строчный элемент;
inline >> inline display type - inline (строчный) тип отображения;
inline >> generic inline container - основной строковый контейнер;
innate property - врожденное свойство;
inner display type - внутренний тип отображения;
input value - входное значение;
instance - экземпляр;
instance >> every valid MathML instance - каждый допустимый экземпляр MathML;
interface - интерфейс;
invalid type - неверный тип;
italicized type - курсив;
item placement - расположение элемента;
justify - выравнивание левых и правых границ текста по левым и правым границам содержимого параграфа;
keyword colors - ключевые цвета;
label - метка, ярлык >;
layout - разметка (напр. web page layout = разметка вебстраницы); тж. раскладка (напр. клавиатуры);
layout (CSS) - верстка (напр. в CSS); макет (page layout = макет страницы); схема (s. flow layout);
layout >> CSS layout - CSS-макет;
layout >> Grid layout - Grid размещение;
layout shifter - "перевертыш" (перевод в MDN, Wiki не найден);
layout >> multiple-column layout - мульти-колоночная вёрстка;
legacy layout methods - устаревшие методы вёрстки;
legend - легенда;
light - сверхлегкий, см. value в типографике;
light > lighter - значение "светлее" в типографике;
<li> list item element - элемент для создания элементов списка;
integer attribute - числовой атрибут (ex.: value);
line - строка;
line >> break a line - разбить строку;
line break <br> - элемент "перенос строки";
line break in text - перенос строки в тексте;
line >> new lines - новые строки;
link - ссылка, тж. гиперссылка;
link >> relativ link - относительная ссылка;
link >> root-relativ link - корневая ссылка????;
linking - подключение, напр. таблицы CSS;
list of zero or more statements - группировка нуля или более инструкций;
log v. - выводить(ся); This logs 2 because = Здесь выводится "2" потому что...
machine-readable translation - машиночитаемое представление;
main-axis - главная ось (напр. flex контейнера);
main page - главная страница;
maintain - обслуживать, обслуживание (напр. вебсайта);
margin - внешний отступ тж. внешние отступы - пространство вокруг внешней стороны элемента;
margin area - отступы. добавляют пустое пространство вокруг элемента и определяют расстояние до соседних элементов;
margin-bottom - нижний отступ;
margin-top - верхний отступ;
markup - разметка, прежде всего HTML-разметка;
markup >> markup language - язык разметки;
media element - медиа-элемент;
media-feature - медиафункция;
media queries - медиавыражения;
@media at-rule - at-правило @media;
@media CSS at-rule - At-правило @media в CSS;
metadata - метаданные;
micro data - микроданные;
mockup - эскиз;
mode - режим;
mode >> display mode - режим отображения;
monospace font - моноширинный шрифт;
multimedia resources - мультимедийные ресурсы (изображения, аудио и видео);
naming conventions - стандарты наименования файлов;
navigation bar - навигационное меню;
navigational aids - ссылки навигации;
negative value - отрицательное число;
node - узел;
node >> node tree - древо узлов;
non-visual browsers - невизуальные браузеры;
not common to every page content - уникальный для каждой страницы контент;
non-replaced element - незаменяемый элемент;
notation - нотация;
object model >> CSS object model - объектная модель CSS;
offset - смещение, напр. горизонтальное, вертикальное; пересекать ?????
omit it from rendering - пропустить его при рендеринге;
outline - обводка;
operator - оператор - см. статью в MDN про JS-операторы присваивания, сравнения, арифметические, битовые, логические, строчные, и различные специальные операторы;
overflow - переполнение; свойство overflow;
override - переопределять;
padding - внутренний отступ или внутренние поля - пространство внутри рамки и в то же время вокруг контента (например,вокруг абзаца текста);
padding area - область отступов или поля элемента. Пустая область, окружающая контент;
padding edge - края полей;
padding >> thickness of the padding - размеры полей;
pane - панель;
parse - парсить;
parser - парсер;
parsing - парсинг;
path - путь;
people with visual impairments - люди с нарушениями зрения;
permitted content - допустимое содержимое;
platform convention - платформа;
platform convention >> defined by the platform convention - определяется платформой;
plug-in - плагин;
plug-in >> browser plug-in - плагин для браузера;
position - позиционирование. Тж. см. positioning;
positioning - позиционирование. П. позволяет брать элементы из нормального потока и изменять их поведение, например, заставляет находиться друг под другом или всегда оставаться в одном и том же месте внутри окна просмотра браузера;
positioning >> relative p., absolut p., fixed, sticky p. - позиционирование относительное, абсолютное, фиксированное??????, липкое;
preceding term - предшествующий термин;
preformatted text предварительно - отформатированный текст;
prerequisites - необходимые условия;
presentation - внешний вид #wiki;
property - свойство, напр. margin или color (in CSS);
property value - значение свойства (напр. red для свойства color (in CSS);
radio button - радиокнопка (переключатель);
range of text - диапазон текста;
related links - связанные ссылки;
render - отображаться, отрисовываться, рендериться. Ex. not rendered = не отображается;
repository - репозиторий, напр. репозиторий Github;
resetting - сброс;
respected - применяются;
the width and height properties are respected = будут применяться свойства width и height. ;
responsive web design (RWD) - отзывчивый (адаптивный) веб-дизайн;
responsive images - адаптивные изображения;
root element - корневой элемент;
root of the hard drive - корень жесткого диска;
root-relativ link - корневая ссылка;
rule - правило (не только в грамматике, но и в кодировании);
selector also: element selector, tag selector, type selector - селектор (др. названия: Селектор элемента/тега/типа), т.е. имя HTML-элемента в начале набора правил;
set - определять, отображать и др.;
set >> inner type sets the layout of children - внутренний тип (зд. отображения) определяет расположение дочерних элементов;
- универсальный селектор - * (in CSS) #wiki;
- селектор идентификаторов, напр. #paragraph1 (in CSS) #wiki;
- селектор атрибутов, напр. a[href="http://www.somesite.com"] (in CSS) #wiki;
- селектор потомков (контекстный селектор), напр. div#paragraph1 p.note (in CSS) #wiki;
- селектор псевдоклассов, напр. a:active (in CSS) #wiki;
- селектор псевдоэлементов, напр. p::first-letter (in CSS) #wiki;
scope - область видимости;
scope >> block scope - блочная область видимости;
scoped to the containing function - имеют областью видимости содержащую их функцию;
screen readers - программы чтения с экрана;
scripting - скриптинг, исполнение скриптов, использование скриптовых языков, напр. JavaScript;
search form - форма поиска;
sectioning - секционирование;
sectioning content - секционный контент;
sectioning root - секционный корень;
self-contained content - самостоятельный контент;
semi-opaque pixels - полупрозрачные пиксели;
sensible structure - рациональная структура;
sequential keyboard navigation, - последовательная навигация с клавиатуры;
shopping cart widget - виджет корзины в интернет-магазине;
siblings - соседние элементы;
siblings >> adjacent siblings - то же, что и siblings выше;
sidebar - боковая панель;
sitemap - карта сайта;
slash - косая прямая, слеш, знак дроби "/";
slash >> back slash, backward slash - обратный слеш;
slash >> forward slash - прямой слеш, то же самое что "косая прямая";
slug - дословно "слизняк", comp.: динамический идентификатор, одно или несколько слов в названии URL или файла в каталоге. Примеры: <locale>/docs/ или Glossary/Slug;
snippet - фрагмент кода;
sound HTML structure - осмысленная структурв HTML; writing a sound HTML structure = написание осмысленной структуры HTML;
space, space character - пробел;
space >> single space - один пробел;
spacing - расстояние, интервал, пробел;
spacing > letter s. - межбуквенное расстояние в тексте;
spacing > word s. - длина пробела между словами и между тегами;
spacing of the content - изменение интервалов контента;
spaces >> End-of-line spaces - Пробелы в конце строки;
specificity, CSS specificity - cпецифичность;
specify - указывать;
specify >> not specified in the standard - не указаны в стандарте;
spelling errors - орфографические ошибки;
srсset - свойство srсset;
statement - оператор;
statement >> statement block - блок инструкций;
statement >> empty statement - пустой оператор;
statements >> multiple statements - несколько операторов;
streamed media - потоковое мультимедиа;
string - строка;
stroke - обводка; контур;
stylesheet - стиль, таблица стилей;
subdirectory - поддиректория;
submenu also known as pop-up menus - подменю??? использовано впервые в уроке 9 строка 562;
tab, tabs - табулятор, табуляция;
tabular data - табличные данные;
tag - тег;
tag >> start tag, end tag - открывающий, закрывающий тег;
tag >> tag omission - пропуск тегов;
target file - целевой файл;
taxonomical designations - систематические обозначения;
template - шаблон;
textarea - элемент textarea;
text that has stress emphasis - акцентируемый текст;
textual replacement for the image - текстовое описание изображения;
thematic break, i.e. between paragraph - тематическое разделение, напр. абзацев;
top-level element - элемент верхнего уровня;
track - 1) отслеживать 2) полоса, трек;
track >> highlighted track - подсвеченная полоса (трек);
track changes - отслеживание изменений;
track size - размер полосы (или трека);
trick - уловка;
underlines - подчеркивания;
underscore - нижнее подчеркивание;
Uniform Resource Locators (URL) - Единый локатор ресурсов;
uniquely >> can be declared uniquely within the block - может быть объявлено единожды внутри блока;
unsupported type - неподдерживаемый тип;
usage notes - примечание; использование;
user agent - пользовательское приложение;
user input - ввод пользователя;
validation - валидация;
validation > constraint validation - валидация ограничений ;
validation > client-side form validation - валидация форм на стороне клиента;
validity - валидность;
it does so only to ensure that those contents are valid = он делает это, только чтобы убедиться в валидности содержимого;
value - значение, напр. 10px (in CSS);
value normal, bold, lighter*, bolder - значения начертаний шрифта: нормальное, полужирное, сверхтонкое (тж. см. light), сверхжирное;
value <number> - (в типографике) цифровые значения насыщенности шрифтов [между 1 и 1000];
value >> element's attribute values - значение аттибутов элемента;
value >> values of its Text - содержимое (его) узла Text;
variables introduced within a block - переменные, введённые внутри блока;
visual media - визуальная среда;
to be represented in visual media as blocks of text = быть представленым в визуальной среде в виде блоков текста ;
viewport - область просмотра, видимая пользователю область веб-страницы, то, что может увидеть пользователь, не прибегая к прокрутке.;
viewport >> visual viewport - окно просмотра. Окно просмотра это обычно прямоугольная область в компьютерной графике, которая в настоящее время просматривается на экране в полноэкранном режиме. visibility - свойство visibility скрывает или показывает элемент без изменения разметки документа. Также скрывает строки и столбцы;
void element - пустой элемент;
web - веб;
WebVR - веб виртуальная реальность;
weight > exact w. - заданное цифровое значение насыщенности;
weight > weight name - вес имени, вес насышенности. Также см. usWeightClass;
weight > fallback weights - недоступность заданного значения;
weight > relative w. - относительный вес;
whitespace - пробельные символы;
white-space - свойство white-space;
working draft - черновик #wiki;
wrapper - обертка;
wrapper >> class of wrapper - класс-обёртка;
writing mode - режим письма;

ОГЛАВЛЕНИЕ >