Веб-программирование
Веб-программирование · лекция 2 из 16
Три кита, на которых стоит любая страница. Первого прошли.
Валидная разметка. Правильная семантика. Заголовки по уровням, списки
списками, у каждой картинки alt.
И выглядит она как документ из 1996 года.
С HTML всё в порядке. Он и не должен отвечать за то, как это выглядит, — его работа сказать, что это за содержимое.
Не хватает второго языка. Того, который отвечает на вопрос как показать.
1994 → сегодня
<p><font color="red" size="4" face="Arial">Внимание!</font></p>
<p><font color="red" size="4" face="Arial">Ещё внимание!</font></p>
<center><font color="red" size="4" face="Arial">И тут</font></center>
Так оформляли страницы до 1996 года: внешний вид вшит прямо в разметку, на каждом элементе отдельно.
1994
Норвежский программист, работавший в ЦЕРН рядом с Бернерсом-Ли, публикует предложение Cascading HTML Style Sheets. Вместе с Бертом Босом он доводит идею до стандарта.
Оригинал предложения, 10 октября 1994Идея висела в воздухе. Победил вариант, который проще всех читался и не падал от незнакомой строчки.
// Netscape предлагал писать стили так
document.tags.H1.color = "blue";
document.tags.P.fontSize = "12pt";
Запомните этот слайд. Идея «стили на JavaScript» вернётся через двадцать лет под именем CSS-in-JS — поговорим о ней в лекции 5.
1996
Декабрь 1996 — рекомендация W3C. Цвета, шрифты, отступы, выравнивание. Через полтора года, в мае 1998, выходит CSS2.
Браузеры поддерживают это криво, частично и по-разному. Впереди пять лет боли.
Главный конфликт эпохи
width?
width — это вся коробка целиком, вместе с рамкой и
полями.
width — это только содержимое. Рамка и поля идут
сверху.
Один и тот же макет разъезжался в двух браузерах. Верстальщики писали два набора стилей и подсовывали их хаками.
Формально победила спецификация. Практически победил
здравый смысл: считать ширину вместе с рамкой оказалось удобнее, и
спустя пятнадцать лет в язык добавили
box-sizing: border-box.
Сегодня это правило ставят первым почти в каждом проекте. Вернёмся к нему в части 5.
2003
Дэйв Ши выкладывает одну HTML-страницу и говорит: разметку менять нельзя, присылайте свои стили. Приходит больше двухсот работ.
csszengarden.com — сад жив до сих пор.important {
text-decoration: blink;
}
У CSS было своё мигание — и это единственное свойство, которое
спецификация прямо разрешила браузерам
игнорировать. Они и перестали, все до одного.
<blink> из прошлой лекции умер не в одиночку.
Никакой. После CSS2.1 единого номера версии больше нет: язык растёт модулями. У селекторов свой уровень, у цвета свой, у сеток свой — и своя готовность в браузерах.
Поэтому «поддерживается ли это» — вопрос не к версии, а к конкретному свойству. Проверяют на caniuse.com.
Три способа и одно правило
<head>
<link rel="stylesheet" href="style.css">
</head>
Файл кэшируется, переиспользуется всеми страницами сайта и не мешает читать разметку. В работе — почти всегда этот способ.
<head>
<style>
h1 { color: teal; }
</style>
</head>
Годится для одной страницы, для быстрого опыта, для письма в почте. Не переиспользуется и не кэшируется отдельно.
<h1 style="color: teal">Заголовок</h1>
Работает, но переиспользовать нечего, читать тяжело, а перебить потом почти невозможно.
Запомните его отдельно: у атрибута style особая роль в
каскаде, вернёмся к нему в части 4.
h1 {
color: teal;
font-size: 32px;
}
color: teal;
Точка с запятой в конце. У последнего объявления её можно не ставить — но ставьте: завтра допишете строку и забудете.
/* Заголовки статей */
h1 {
color: teal;
}
/* color: crimson; — временно отключено */
Только такие. Двойного слэша в CSS нет: строка после
// не комментарий, а мусор, который сломает правило.
HTML, как мы помним, просто молчит
p {
color: blue;
font-sizee: 20px; ← свойства такого нет
background: pink;
}
Страница, использующая свойство из будущего, остаётся читаемой в старом браузере: новое он пропустит, старое применит.
Обратная сторона — опечатку вам никто не покажет. Правило просто не сработает, и вы будете искать причину глазами.
Пустая страница без единой строчки CSS уже оформлена: заголовки крупные
и жирные, ссылки синие с подчёркиванием, у списка маркеры, у
body отступ в восемь пикселей.
В DevTools такие правила подписаны
user agent stylesheet. Это нижний слой каскада.
Сносит стили браузера подчистую. Дальше всё рисуете сами, с нуля.
Не сносит, а выравнивает: чинит расхождения между браузерами, разумное оставляет.
Сегодня чаще пишут короткий собственный набор из нескольких правил. Одно из них разберём в части 5.
Главный инструмент на весь оставшийся семестр
Открывается по F12 или правой кнопкой → «Просмотреть код».
Как выбрать нужные элементы
Всё остальное в правиле — уже подробности оформления.
p { line-height: 1.6; }
a { color: teal; }
h1, h2, h3 { font-family: Georgia, serif; }
Выбирает все такие элементы на странице. Годится для базовой типографики — и плохо годится почти для всего остального.
<div class="card">...</div>
<div class="card featured">...</div>
.card { padding: 20px; }
.featured { border: 2px solid gold; }
Один класс — на многих элементах. Несколько классов — на одном элементе, через пробел.
.red — доживёт ровно до дня, когда дизайнер попросит
сделать предупреждения оранжевыми
.warning — переживёт любой редизайн#header { ... } — в стилях.header { ... } — в стиляхПравило курса: id — для якорей и JavaScript, классы — для стилей.
!importantНасколько именно тяжёлый — посчитаем в части 4.
h1, h2, h3 { margin-top: 0; } /* одно правило — трём тегам */
p.lead { font-size: 20px; } /* и тег, и класс сразу */
* { box-sizing: border-box; } /* вообще всем */
Между p и .lead нет пробела — это один и тот же
элемент. Пробел поменял бы смысл целиком.
nav a { } /* любая ссылка внутри nav, на любой глубине */
nav > a { } /* только прямые дети nav */
h2 + p { } /* абзац сразу после заголовка */
h2 ~ p { } /* все абзацы после заголовка, на том же уровне */
Разница между пробелом и > — место, где путаются чаще
всего. Сейчас посмотрим её вживую.
[type="checkbox"] { } /* точное совпадение */
[href^="https"] { } /* начинается с https */
[href$=".pdf"] { } /* заканчивается на .pdf */
[class*="card"] { } /* содержит подстроку card */
Прямая связка с формами из прошлой лекции: разные
input type оформляются по-разному, а класс дописывать не
надо.
:hoverПсевдокласс — элемент прямо сейчас в таком состоянии
a:hover { } /* курсор над элементом */
a:active { } /* прямо сейчас нажат */
a:visited { } /* по ссылке уже ходили */
input:focus { } /* поле в фокусе */
input:checked { } /* галка стоит */
input:disabled { } /* элемент выключен */
Ни одной строчки JavaScript. Состояние знает сам браузер.
:focus убиратьbutton:focus {
outline: none;
}
button:focus {
outline: 3px solid teal;
outline-offset: 2px;
}
Тот, кто ходит по странице клавишей Tab, без видимого фокуса теряет место и не может пользоваться формой вообще.
alt
В прошлой лекции договорились: alt — не формальность, а
единственный способ для незрячего понять картинку.
outline — ровно то же самое для тех, кто не пользуется
мышью. Убрали рамку, не дав замены, — сломали страницу,
просто не для себя.
li:first-child { } /* первый среди соседей */
li:last-child { } /* последний */
li:nth-child(3) { } /* третий */
li:nth-child(odd) { } /* нечётные: 1, 3, 5... */
tr:nth-child(2n) { } /* каждый второй */
Полосатая таблица — и ни одного лишнего класса в разметке.
p:not(.lead) { color: gray; }
li:not(:last-child) { margin-bottom: 8px; }
Второй пример — частый приём: отступ между пунктами есть, а лишнего отступа под последним нет.
blockquote::before {
content: "«";
}
.external::after {
content: " ↗";
}
Рисуют то, чего в разметке нет. Без свойства
content не появятся вообще — даже пустого.
:hover — состояние существующего элемента
::before — новый кусок, которого в DOM нет
В CSS2 писали одно двоеточие для всего. Потом их развели по записи, а
старую оставили ради совместимости — поэтому
:before тоже работает.
.card p { color: red; }
Сколько абзацев покрасится?
<div class="card">
<p>первый</p>
<blockquote><p>второй</p></blockquote>
</div>
<p>третий</p>
blockquote тоже попадает. Третий лежит вне
карточки — мимо.
С .card > p покрасился бы только первый.
li:nth-child(odd) { background: #eee; }
Список из пяти пунктов. Сколько закрасится и какие?
Кто побеждает, когда правил несколько
h1 { color: teal; }
.title { color: crimson; }
h1.title { color: navy; }
#main-title { color: green; }
Строго по порядку. Следующий вопрос задаётся, только если предыдущий не дал ответа.
style — сильнее любого файла!important — бьёт всё перечисленное#id
.class, [attr],
:hover
div, ::before
Универсальный * и комбинаторы
>, +, ~ не весят ничего.
nav ul li a → 0-0-4 четыре тега
.menu .item → 0-2-0 два класса
#sidebar → 1-0-0 один идентификатор
ul li.active → 0-1-2 класс и два тега
a:hover → 0-1-1 псевдокласс и тег
Давным-давно, в 2005 году,
Эндрю Кларк расписал вес селекторов
как расстановку сил в далёкой галактике.
Аналогия пережила все браузеры той эпохи.
Сравниваем слева направо: в первом разряде 1 против 0 — дальше незачем.
a:hover тяжелее, чем два тега.
Каждую строку написал человек, который просто хотел покрасить кнопку.
!important — этоОба случая — про лекцию 5, где будем разбирать методологии. Пока правило простое: не нужен.
Что течёт вниз по дереву
body {
color: #333;
font-family: Georgia, serif;
}
Два правила на body — и весь текст на странице сменил цвет и
шрифт. Это наследование: значение спускается к потомкам.
colorfont-family, font-sizeline-heighttext-alignlist-styleborderpadding, marginbackgroundwidth, height.child { color: inherit; } /* взять у родителя принудительно */
.child { color: initial; } /* сбросить к значению по умолчанию */
.child { color: unset; } /* наследуемое — наследовать,
остальное — сбросить */
button, input, textarea {
font: inherit;
}
Поля форм и кнопки шрифт не наследуют — браузер ставит им свой, системный. Одна строчка чинит это на всём сайте.
!important бьёт всёstyleЕсли правило не применилось — дело в одном из четырёх пунктов. И DevTools покажет, в каком.
Из чего состоит любой блок
padding и marginВоздух внутри коробки, между рамкой и содержимым. Фон элемента заходит сюда.
Расстояние снаружи, до соседей. Фон сюда не заходит — здесь уже не элемент.
Простой способ запомнить: покрасьте блок и посмотрите, докуда достаёт цвет.
padding: 20px; /* все четыре стороны */
padding: 10px 20px; /* верх-низ | лево-право */
padding: 10px 20px 30px; /* верх | лево-право | низ */
padding: 10px 20px 30px 40px; /* верх | право | низ | лево */
Четыре значения читаются по часовой стрелке, начиная сверху.
margin устроен точно так же.
border — три вещи в одной строкеborder: 1px solid #ccc;
/* ↑ ↑ ↑
толщина стиль цвет */
border: 3px dashed crimson;
border-radius: 8px;
И запомните главное: рамка занимает место. Это подводка к следующему слайду.
Это не картинка — это живой блок с width: 300px. Слово не
влезло и честно вылезло наружу.
Вы написали ширину — он её и держит. Ломать вашу вёрстку ради того, чтобы слово поместилось, он не станет: вдруг вы так и задумали.
Браузер делает ровно то, что написано. Всегда. Даже когда это выглядит глупо.
Сколько места блок займёт на экране?
Помните box model war из первой части? Вот он и есть. По умолчанию
width — это только содержимое, как и решила
спецификация.
Удобно это ровно никогда: вы задаёте ширину, а получаете другую.
box-sizing решает вопрос
По умолчанию. width — содержимое, рамка и поля
прибавляются снаружи.
width — вся коробка. Рамка и поля укладываются
внутрь.
*,
*::before,
*::after {
box-sizing: border-box;
}
Первое правило в файле. Смысл простой: что написал — то и получил.
Сколько пикселей окажется между блоками?
margin не складываются, а
берут больший из двух.
То же самое происходит между родителем и его первым ребёнком — и вот откуда берётся «дыра сверху, которую ничем не убрать».
padding или borderФлексы и гриды — лекция 3. Пока просто знайте, что там это поведение исчезает.
width: 300px; /* ровно столько, хоть тресни */
max-width: 300px; /* не шире, но может быть уже */
height: 200px;
min-height: 200px; /* не ниже, но может вырасти */
max-width обычно полезнее: на узком экране блок сожмётся
сам, и ничего никуда не вылезет.
px
Есть ещё em, rem, проценты,
vw и vh. Каждая со своей логикой, и разбирать
их наспех — только путать.
Займёмся ими в лекции 3, вместе с вёрсткой. Сегодня везде пиксели.
Чем уже можно оформить страницу
Короткий #rgb — сокращение, где каждая цифра удваивается.
В rgb() можно добавить прозрачность:
rgb(0 128 128 / 50%).
.note {
color: #333; /* цвет текста */
background-color: #fdf6ec; /* цвет фона */
}
color наследуется, background-color — нет.
Разница из части 4 работает прямо здесь.
Среди именованных цветов CSS есть rebeccapurple — он попал
в стандарт в 2014 году.
Эрик Мейер, по чьим книгам училось верстать целое поколение, потерял дочь Ребекку. Ей было шесть. Её любимый цвет рабочая группа W3C внесла в язык.
color: rebeccapurple
Eric Meyer, «Rebecca Purple»body {
font-family: Georgia, 'Times New Roman', serif;
}
Браузер идёт слева направо и берёт первый шрифт, который есть в системе.
В конце — обязательно общее семейство:
serif, sans-serif или
monospace.
font-size: 18px;
font-weight: bold; /* или 400, 700 — числом */
font-style: italic;
line-height: 1.6; /* без единиц — это множитель */
text-align: center;
text-decoration: none;
line-height без единиц — не случайность, а рекомендация:
такой множитель правильно пересчитается у потомков.
border: 1px solid #ddd;
border-radius: 8px;
border-radius: 50%; /* круг, если блок квадратный */
Аватарки во всех соцсетях — это ровно вот эта последняя строка.
a {
color: teal;
text-decoration: none;
border-bottom: 2px solid rgb(0 128 128 / 35%);
}
a:hover { border-bottom-color: teal; }
nav ul { list-style: none; padding-left: 0; }
Подчёркивание через border-bottom — потому что им можно
управлять: цвет, толщина, расстояние.
.container {
max-width: 800px;
margin: 0 auto;
}
auto слева и справа означает «поделить свободное место
поровну». Блок встаёт по центру.
Самый старый вопрос веба. Столько шуток не породила ни одна другая задача вёрстки.
margin: 0 auto — вот, готово
Приходите на лекцию 3
Разметка отвечает на вопрос, что это за содержимое.
Стили — на другой: как это показать.
Разметка отвечает на вопрос, что это за содержимое.
Стили — на другой: как это показать.
Разметка одна и та же — ровно то, что показал Zen Garden.
Свойств в CSS сотни, и держать их в голове не нужно. Нужно знать, где
смотреть, — и уметь читать, что написано.
Дока — справочник на русском, с примерами и живыми
песочницами.
displayem, rem, процентыz-index: 9999 — почему числа не помогаютПосле неё — ЛР 2 по итогам обеих лекций.
Слайды и все демо — в репозитории курса