CSS позиционирование
Браузер уже умеет располагать содержимое страницы без дополнительных правил. Заголовки и абзацы идут друг за другом, а ссылки остаются внутри строки. С помощью CSS можно собрать ссылки в меню, разместить разделы рядом и менять расположение элементов при сужении окна.
Откройте папку website с визиткой из предыдущей лабораторной. Сохраните её копию, чтобы сравнивать результат. Продолжайте редактировать index.html и assets/css/style.css, дополняя существующие правила.
Поток элементов и display
Обычный поток определяет расположение элементов в порядке HTML-разметки. Блоки вроде <p>, <section> и <div> начинаются с новой строки. Ссылки <a> и фрагменты <span> располагаются в строке вместе с текстом.
Свойство display позволяет изменить это поведение. Оно влияет на расположение элемента и его содержимого, сохраняя смысл HTML-тега. Например, ссылка с display: block по-прежнему остаётся ссылкой.
| Значение | Как располагается элемент |
|---|---|
block |
Начинается с новой строки, ему можно задать ширину и высоту |
inline |
Участвует в строке. У обычного текстового элемента вроде <span> свойства width и height не задают размер |
inline-block |
Участвует в строке как цельный блок с собственной шириной и высотой |
flex |
Располагает непосредственных потомков вдоль выбранной оси |
grid |
Размещает непосредственных потомков по строкам и столбцам сетки |
Изображение <img> тоже может находиться внутри строки, но его ширину и высоту можно задавать. Поэтому правило для обычного строчного <span> нельзя переносить на все элементы без исключения.
Скрытие элементов и обтекание текста
Значение display: none скрывает элемент вместе с его местом на странице. При visibility: hidden элемент невидим, но место сохраняется. Скрытое таким образом содержимое обычно недоступно и вспомогательным технологиям, поэтому не прячьте важные контакты только ради того, чтобы страница поместилась на телефоне.
Для обтекания изображения текстом используется float: left или float: right. Для меню и сетки разделов удобнее подходят Flexbox и Grid.
Меню на Flexbox
Запись display: flex превращает элемент в flex-контейнер. Его непосредственные потомки становятся flex-элементами. Например, если ссылки находятся прямо внутри <nav>, свойство нужно задать этому <nav>. Если между ними есть список <ul>, контейнером для пунктов будет сам список.
Свойство flex-direction задаёт главную ось. При row элементы выстраиваются в строку, а при column в колонку. justify-content распределяет свободное место вдоль главной оси, align-items выравнивает элементы поперёк неё. Поэтому justify-content не всегда означает горизонтальное выравнивание.
| Свойство контейнера | Для чего используется |
|---|---|
flex-direction: row |
Располагает элементы в строку |
justify-content: center |
Собирает элементы по центру главной оси |
justify-content: space-between |
Распределяет свободное место между элементами |
align-items: center |
Выравнивает элементы по центру поперечной оси |
gap: 12px |
Задаёт промежутки между элементами |
flex-wrap: wrap |
Разрешает перенос на следующую строку при нехватке места |
В меню ниже ссылки собраны у начала строки. Замените justify-content: flex-start на space-between. Где появится свободное место? Затем задайте center и сравните результат. Чтобы увидеть разницу, разверните редактор или расширьте область результата.
style.css самостоятельно.Распределение ссылок в меню
Код примера
Теперь оформите меню визитки. Дополните существующее правило nav, сохранив цвета ссылок, подчёркивание и состояния наведения и фокуса.
nav {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px;
padding: 12px;
background-color: white;
}Здесь gap создаёт промежутки между ссылками, а padding отделяет их от края меню. Уменьшите ширину окна и убедитесь, что ссылки переносятся и остаются доступными.
Растяжение и сжатие flex-элементов
Свойства flex-grow, flex-shrink и flex-basis задаются самим flex-элементам. Они определяют, как элемент получает свободное место, сжимается при его нехватке и с какого размера начинается расчёт. Запись flex: 1 1 200px задаёт эти три значения по порядку.
По умолчанию элементы могут сжиматься, но не обязаны становиться уже своего содержимого. Для блока с длинным текстом иногда требуется min-width: 0 и перенос длинных слов. Значение flex-wrap: wrap разрешает перенос элементов целиком на новую строку.
Шпаргалка и практика Flexbox
Шпаргалка по Flexbox поможет сравнить значения свойств контейнера и его элементов по наглядным примерам.
Закрепите выравнивание, направление осей и перенос элементов в одной из двух игр на выбор:
- Flexbox Froggy — расставляйте лягушек по кувшинкам с помощью свойств Flexbox. Есть русский язык.
- Flexbox Adventure — управляйте расположением героя с помощью Flexbox и проходите приключение с заданиями на CSS.
Разделы на Grid
Grid задаёт сетку из строк и столбцов. После display: grid непосредственные потомки контейнера заполняют её ячейки. Сетка удобна, когда нужно выровнять несколько разделов по общим колонкам.
Свойство grid-template-columns описывает колонки. Например, 1fr 2fr распределяет доступное место в пропорции один к двум. Единица fr обозначает долю свободного пространства. Расстояние между ячейками задаётся через gap.
Запись repeat(2, minmax(0, 1fr)) создаёт две равные колонки. repeat повторяет описание дважды, а minmax(0, 1fr) позволяет колонке сжиматься ниже минимальной ширины её содержимого. Сам текст при этом тоже должен уметь переноситься.
В сетке ниже четыре карточки занимают две строки. Замените число 2 в repeat на 3. Предположите, где окажется последняя карточка, затем проверьте результат. После сравнения верните исходное число колонок.
Колонки и промежутки сетки
Код примера
В визитке объедините существующие разделы «Навыки» и «Образование» контейнером <div class="profile-grid"> внутри <main>. Переместите в него целые <section>, сохранив их id, заголовки и содержимое. Раздел «О себе» останется перед контейнером, а «Контакты» после него.
.profile-grid {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 24px;
margin-bottom: 24px;
}
.profile-grid > section {
min-width: 0;
margin-bottom: 0;
}Одна колонка сохраняет удобное чтение в узком окне. Две колонки добавим условием по ширине окна. У вложенных разделов убран прежний margin-bottom, поскольку расстояние между ними уже задаёт gap. Селектор > выбирает только непосредственные дочерние разделы.
Объединение ячеек и автоматическое число колонок
Если карточка должна занять всю строку, задайте ей grid-column: 1 / -1. Числа обозначают первую и последнюю линии сетки. Запись grid-column: span 2 растягивает элемент на две колонки от его текущего места.
Число колонок можно подбирать по доступному месту через repeat(auto-fit, minmax(min(100%, 240px), 1fr)). Браузер разместит столько колонок, сколько помещается. Их минимальная ширина составит 240 пикселей, а в более узком контейнере ограничится его шириной благодаря min(100%, 240px). Оставшееся место разделится между колонками. Фиксированный минимум вроде minmax(240px, 1fr) может вызвать переполнение контейнера уже 240 пикселей.
Шпаргалка и практика Grid
Шпаргалка по Grid поможет подобрать свойства строк, колонок и расположения элементов в сетке.
Закрепите работу с линиями и ячейками сетки в одной из двух игр на выбор:
- Grid Garden — поливайте грядки, задавая расположение и размеры областей с помощью CSS Grid. Есть русский язык.
- Grid Attack — проходите приключение, решая задачи на расположение элементов с помощью CSS Grid.
Позиционирование и наложение
Flexbox и Grid определяют расположение групп элементов. Свойство position позволяет смещать отдельные элементы, привязывать метку к углу карточки или удерживать меню при прокрутке. Расстояние задаётся через top, right, bottom и left.
| Значение | Относительно чего располагается элемент | Сохраняется ли место в потоке |
|---|---|---|
static |
Обычного потока, смещения не применяются | Да |
relative |
Собственного исходного положения | Да |
absolute |
Содержащего блока, обычно ближайшего позиционированного предка | Нет |
fixed |
Обычно окна браузера | Нет |
sticky |
Области прокрутки с ограничением границами содержащего блока | Да |
У relative смещение оставляет прежнее место свободным, поэтому соседние элементы не передвигаются вслед за ним. У absolute место освобождается. Чтобы привязать такой элемент к карточке, самой карточке обычно задают position: relative. При отсутствии подходящего предка отсчёт идёт от начального содержащего блока документа.
У выделенного блока ниже задано position: relative. Замените его на absolute и посмотрите, куда переместится третий блок. Затем задайте static и проверьте, продолжают ли действовать top и left.
Место элемента при relative и absolute
Код примера
Добавьте в раздел «О себе» короткую метку <span class="profile-status">Открыт к общению</span>. Разместите её в правом верхнем углу раздела.
#about {
position: relative;
padding-top: 56px;
}
.profile-status {
position: absolute;
top: 12px;
right: 12px;
padding: 4px 8px;
font-size: 14px;
background-color: #e5f0eb;
border-radius: 4px;
}Верхний padding оставляет место для метки, поскольку сама она не увеличивает высоту раздела. Проверьте, что метка не закрывает заголовок и фотографию. Если текст метки станет длиннее, оставьте для него больше места или верните метку в обычный поток.
При наложении элементов порядок может задаваться через z-index. Например, у прилипающего меню можно установить z-index: 1, чтобы содержимое страницы проходило под ним. Фон меню при этом должен быть непрозрачным.
Fixed и sticky при прокрутке
fixed обычно закрепляет элемент относительно окна браузера. sticky сначала сохраняет обычное положение, затем удерживается у заданной границы прокрутки и останавливается у края своего содержащего блока. Для прилипания сверху нужно задать, например, top: 0.
Прокрутите результат ниже. Зелёная полоса прилипнет к верху, но уйдёт вместе с концом своего раздела. Синяя метка останется внизу окна результата.
Прилипание и фиксация при прокрутке
Код примера
Во встроенном редакторе fixed закрепляется внутри окна результата. Прокручивайте именно его. Если sticky не работает, проверьте наличие top, свободного места для перемещения и свойства overflow у предков. Значения auto, scroll или hidden могут изменить, к какому контейнеру относится прилипание.
Почему большой z-index не всегда помогает
Элементы могут образовывать отдельные контексты наложения. Внутри одного контекста сравниваются значения z-index, а весь контекст участвует в наложении как единое целое. Поэтому большое значение у дочернего элемента не позволяет ему произвольно перекрыть соседний контекст.
fixed и sticky создают контекст наложения сами по себе. У relative и absolute он создаётся при z-index, отличном от auto. Контекст также может возникнуть из-за opacity меньше единицы или transform.
Некоторые свойства предков, в том числе transform, могут изменить содержащий блок для absolute и fixed. Поэтому при неожиданном смещении проверяйте не только position, но и оформление предков. Подробнее об этом написано в описании содержащего блока на MDN.
Адаптация к ширине окна
Гибкая ширина, перенос ссылок и ограничение размера изображения уже помогают визитке помещаться на небольшом экране. Медиазапросы позволяют менять отдельные правила при выполнении условия. Например, при достаточной ширине окна разделы можно поставить рядом.
Сначала задайте оформление для узкого окна, затем добавьте изменения для широкого. Такой подход называется mobile-first. Порядок правил помогает постепенно усложнять расположение элементов. Весь CSS-файл при этом загружается целиком, а браузер применяет подходящие условия.
Добавьте в конец style.css следующее правило.
@media (min-width: 640px) {
.profile-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
nav {
position: sticky;
top: 0;
z-index: 1;
}
section {
scroll-margin-top: 96px;
}
}Условие срабатывает при ширине окна от 640 пикселей включительно. На более узком экране остаётся одна колонка и обычное меню. Свойство scroll-margin-top оставляет сверху место при переходе по ссылке к разделу, чтобы его заголовок не оказался под меню. Значение 96px рассчитано с запасом под это меню. Если его высота изменится, проверьте переходы и скорректируйте отступ.
Сравните расположение разделов при ширине результата 600 и 800 пикселей. Затем временно замените порог 640px на 800px и найдите, при какой ширине появятся две колонки.
Визитка в узком и широком окне
Код примера
Верните выбранный порог в визитке и проверьте переходы по меню. В файле должен остаться один согласованный набор правил для .profile-grid, без случайных копий с разным числом колонок. Фотография, списки и таблица из предыдущей лабораторной сохраняются.
Запросы к контейнеру
Медиазапрос ориентируется на окно браузера. Контейнерный запрос полезен, если одна карточка может находиться и в широкой основной области, и в узкой боковой колонке. Тогда оформление её потомков зависит от ширины самой карточки.
.profile-card {
container-type: inline-size;
}
.profile-content {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 16px;
}
@container (min-width: 500px) {
.profile-content {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}Элемент .profile-content должен находиться внутри .profile-card. Свойство container-type: inline-size разрешает проверять размер контейнера по строчной оси, при обычном горизонтальном письме это его ширина. Когда она достигнет 500 пикселей, содержимое перестроится в две колонки. Основы разобраны в руководстве MDN по контейнерным запросам.
Проверка и требования к работе
Откройте визитку в отдельной вкладке. Проверьте её при ширине окна примерно 320, 640 и 1280 пикселей. В инструментах разработчика можно включить режим устройства и задать точную ширину. Дополнительно увеличьте масштаб страницы до 200% и убедитесь, что текст читается, а ссылки остаются доступны.
- Содержимое и четыре раздела визитки сохранены, ссылки меню ведут к нужным
id. - Меню использует Flexbox, ссылки переносятся при нехватке места.
- Разделы «Навыки» и «Образование» объединены Grid-контейнером.
- В узком окне используется одна колонка, в широком две.
- Метка привязана к разделу «О себе» и не перекрывает его содержимое.
- В широком окне меню прилипает при прокрутке, заголовки остаются видимыми после перехода по ссылкам.
- При навигации клавишей Tab виден фокус, порядок ссылок соответствует их порядку в HTML.
- На узком экране нет горизонтальной прокрутки страницы, фотография и таблица помещаются внутри разделов.
Если элемент расположен неожиданно, проверьте его display, содержащий блок, размеры и отступы в DevTools. Для Flexbox и Grid в браузере можно включить подсветку контейнера, чтобы увидеть границы и промежутки. Если не срабатывает медиазапрос, проверьте ширину окна результата и наличие <meta name="viewport" content="width=device-width, initial-scale=1.0"> в <head> локальной страницы.
Сохраните index.html, assets/css/style.css и изображение в папке website.
- На дополнительные баллы можете добавить галерею как в Pinterest. Информацию как это сделать можно найти тут.
Полезные источники и инструменты
- Основы Flexbox на MDN поясняют оси, перенос и распределение места.
- Основы Grid на MDN помогут разобраться с колонками, строками и линиями сетки.
- Свойство position на MDN содержит пояснения и примеры разных способов позиционирования.
- Медиазапросы на MDN описывают условия по ширине окна и другим свойствам среды. Материалы MDN по этим ссылкам на английском.