Не знаете, как работают элементы CSS? Пора освоить все виды селекторов и позиционирование на странице. Разбираем наглядные примеры.
Введение в CSS
CSS (аббревиатура от Cascading Style Sheets – каскадные таблицы стилей) – язык, который используем для оформления стиля HTML-файла и сообщения браузеру, как отображать элементы на странице.
Речь пойдёт исключительно о стилях документов HTML, хотя CSS применяют и для других XML-документов.
Файл CSS содержит правила CSS.
Каждое правило состоит из 2 частей:
- селектор
- блок объявлений
Селектор CSS – строка, которая идентифицирует элементы (один или несколько) на странице в соответствии со специальным синтаксисом, о котором скоро поговорим.
Блок объявлений содержит одно или несколько объявлений, которые состоят из свойства и значения.
Больше в CSS ничего нет.
Как выглядит CSS
Набор правил CSS состоит из cелектора и объявления.
Объявление содержит правила, каждое из которых состоит из свойства и значения.
В этом примере селектор p
применяет одно правило, которое устанавливает значение 20px
для свойства font-size
:
p { font-size: 20px; }
Правила следуют одно за другим:
p { font-size: 20px; } a { color: blue; }
Селектор распространяется на один или больше элементов:
p, a { font-size: 20px; }
и на теги HTML, как указано выше, или элементы HTML, которые содержат конкретный атрибут class
– .my-class
, или элементы HTML с конкретным атрибутом id
– #my-id
.
Продвинутые селекторы CSS выбирают элементы, атрибут которых соответствует конкретному значению, и элементы, которые отвечают псевдоклассам (подробнее об этом позже).
Точка с запятой
Каждое правило CSS заканчивается точкой с запятой. Точки с запятой обязательны только для последнего правила. Для последовательности рекомендуем использовать их после каждого правила. Тогда не столкнётесь с ошибкой, если добавите другое свойство и забудете добавить точку с запятой в предыдущей строке.
Добавление CSS на страницу HTML
CSS прикрепляется к HTML-странице тремя способами.
1: Использование тега link
С помощью тега link
подключаем файл CSS. Это предпочтительный способ использования CSS. Один файл CSS распространяется на все страницы сайта. Поэтому изменение одной строки в этом файле влияет на представление всех страниц сайта.
Для использования этого метода добавляем тег link
с атрибутом href
, который указывает на нужный файл CSS. Делаем это внутри тега head
, а не внутри тега body
:
<link rel="stylesheet" type="text/css" href="myfile.css">
Атрибуты rel
и type
также обязательные, поскольку они сообщают браузеру, на какой тип файла ссылаться.
2: Использование тега style
Вместо того, чтобы использовать тег link
для указания отдельной таблицы стилей, которая содержит наш CSS, добавляем CSS непосредственно внутри тега style
. Синтаксис такой:
<style> ...наш CSS... </style>
Когда используем этот метод, избегаем создания отдельного файла CSS. Это хороший способ поэкспериментировать перед «формализацией» CSS в отдельном файле.
3: Встроенные стили
Встроенные стили – третий способ добавления CSS на страницу. Добавляем атрибут style
к любому тегу HTML и включаем в него CSS.
<div style="">...</div>
Пример:
<div style="background-color: yellow">...</div>
Селекторы
Селектор связывает одно и более объявлений с одним или несколькими элементами на странице.
Базовые селекторы
Предположим, отобразим слова в элементе p
на странице жёлтым цветом.
Для указания этого элемента используем селектор p
, который охватывает все теги p
на странице. С помощью несложного правила CSS достигаем цели:
p { color: yellow; }
Каждому тегу HTML соответствует селектор, например: div
, span
, img
.
Если селектор CSS соответствует нескольким элементам, изменение затронет все элементы на странице.
Для привязки стиля к необходимому элементу на странице используются два атрибута HTML-элементов: class
и id
.
Различие между ними состоит в том, что внутри HTML-документа одно и то же значение class
используется для одного или нескольких элементов, а id
только один раз. Как следствие, с использованием классов CSS выбираются элементы с двумя и более конкретными именами классов, что невозможно с помощью идентификаторов.
Классы обозначаются с помощью символа .
, в то время как для идентификаторов используется символ #
.
Пример использования класса:
<p class="dog-name"> Роджер </p> .dog-name { color: yellow; }
Пример использования идентификатора:
<p id="dog-name"> Роджер </p> #dog-name { color: yellow; }
Сочетание селекторов
Выбор элемента с помощью класса CSS или идентификатора
Выберем целевые элементы, к которым прикрепляется класс или идентификатор.
Пример использования класса:
<p class="dog-name"> Роджер </p> p.dog-name { color: yellow; }
Пример использования идентификатора:
<p id="dog-name"> Роджер </p> p#dog-name { color: yellow; }
Ориентация на составные классы
Уже в курсе, как выбрать целевой элемент с помощью конкретного класса с использованием .class-name
. Теперь отметим элемент с двумя или более классами: объединим имена классов и разделим точкой, без пробелов.
Пример:
<p class="dog-name roger"> Роджер </p> .dog-name.roger { color: yellow; }
Объединение классов и идентификаторов
Таким же образом объединяем класс и идентификатор.
Пример:
<p class="dog-name" id="roger"> Роджер </p> .dog-name#roger { color: yellow; }
Группировка селекторов
Скомбинируем селекторы, чтобы применять одни и те же объявления к нескольким селекторам. Для этого разделяем их запятой.
Пример:
<p> Мою собаку зовут: </p> <span class="dog-name"> Роджер </span> p, .dog-name { color: yellow; }
Добавим отступы в этих объявлениях для понятности:
p, .dog-name { color: yellow; }
Следование по дереву документа с помощью селекторов
Создадим конкретный селектор из комбинации элементов, чтобы следовать древовидной структуре документа. Например, тег span
вложен в тег p
. Теперь выберем его без применения стиля к тегу span
, который не включён в тег p
:
<span> Здравствуйте! </span> <p> Мою собаку зовут: <span class="dog-name"> Роджер </span> </p> p span { color: yellow; }
Посмотрите, как использовали пробел между двумя токенами p
и span
.
Это работает даже при многоуровневой вложенности элемента справа.
Для определения зависимости первого уровня используем символ >
между двумя токенами:
p > span { color: yellow; }
В этом случае, если span
не первый потомок элемента p
, новый цвет не применяется. Стиль будет применяться к прямым потомкам:
<p> <span> Это жёлтый </span> <strong> <span> Это не жёлтый </span> </strong> </p>
Одноуровневые селекторы стилизуют элемент, только если ему предшествует конкретный элемент. Делаем это с помощью оператора +
.
Пример:
p + span { color: yellow; }
Это назначит жёлтый цвет элементам span
, которым предшествует элемент p
:
<p>Это абзац</p> <span>Это жёлтый промежуток</span>
Селекторы атрибутов
В этом разделе проанализируем селекторы атрибутов. Поговорим о селекторах псевдоклассов и селекторах псевдоэлементов в следующих двух разделах.
Селектор присутствия атрибута
Первый тип селектора – атрибут присутствия атрибута.
Проверим, содержит ли элемент атрибут, используя синтаксис []
. p[id]
выберет все теги p
на странице, которые имеют атрибут id
, независимо от значения:
p[id] { /* ... */ }
Точные селекторы значений атрибутов
Внутри скобок проверяем значение атрибута с помощью =
, и CSS будет применяться только в том случае, если атрибут соответствует указанному значению:
p[id="my-id"] { /* ... */ }
Соответствие части значения атрибута
Хотя =
проверяет точное значение, существуют другие операторы для проверки:
*=
содержит ли атрибут часть^=
начинается ли атрибут с части$=
заканчивается ли атрибут частью|=
начинается ли атрибут с части и после него идёт тире (например, в классах) или просто содержит часть~=
содержится ли часть в атрибуте, но отделена пробелами от остальных
Все упомянутые проверки чувствительны к регистру.
Если добавите i
непосредственно перед закрывающей скобкой, проверка не будет чувствительна к регистру. Это поддерживается многими браузерами, но не всеми, проверьте.
Псевдоклассы
Псевдоклассы – предопределенные ключевые слова, которые используются для выбора элемента на основании его состояния или для определения целевого дочернего элемента.
Начинаются с одного двоеточия :
.
Используются как часть селектора, и полезны для стилизации активных или посещённых ссылок. Например, для изменения стиля при наведении, фокусе или выборе первого потомка или нечётных строк.
Рассмотрим рядовой пример. Вы хотите стилизовать ссылку, поэтому создаёте правило CSS для элемента a
:
a { color: yellow; }
Это, кажется, работает, пока не нажмёте одну ссылку. Ссылка возвращается к предопределенному цвету (синему) при нажатии на неё. Затем, когда открываете ссылку и возвращаетесь на страницу, ссылка синего цвета.
Почему это происходит?
Потому что ссылка при нажатии изменяет состояние: переходит в состояние :active
. И когда ссылку посетили, она становится :visited
. Навсегда, пока пользователь не очистит историю просмотров.
Итак, чтобы правильно сделать ссылку жёлтой во всех состояниях, напишем
a, a:visited, a:active { color: yellow; }
:nth-child()
заслуживает отдельного упоминания. Применяется для обозначения нечётных или чётных потомков: :nth-child(odd)
и :nth-child(even)
.
Часто это используется в списках для отличия нечётных линий от чётных:
ul:nth-child(odd) { color: white; background-color: black; }
Псевдоэлементы CSS
Псевдоэлементы используются для стилизации определённой части элемента.
Начинаются с двойного двоеточия ::
.
Иногда встречаются с одним двоеточием, но этот синтаксис поддерживается по причине обратной совместимости. Используйте два двоеточия, чтобы отличить их от псевдоклассов.
::before
и ::after
, вероятно, самые используемые псевдоэлементы.
Применяются для добавления содержимого до или после элемента, например, иконки.
Теперь пример. Допустим, хотим, чтобы размер первой строки абзаца увеличился, что типично для типографии:
p::first-line { font-size: 2rem; }
Или, может быть, хотим, чтобы первая буква была жирнее:
p::first-letter { font-weight: bolder; }
::after
и ::before
менее интуитивны. Указываем свойство content
для вставки содержимого любого типа после или перед элементом:
p::before { content: url(/myimage.png); } .myElement::before { content: "Эй, эй!"; }
Позиционирование
Позиционирование – это то, с помощью чего в CSS мы определяем, где элементы появляются на экране и как они появляются.
Статическое позиционирование
Это значение по умолчанию для элемента. Статически расположенные элементы отображаются в нормальном потоке страниц.
Относительное позиционирование
Если установите position: relative
для элемента, то сможете изменить его расположение со смещением, используя свойства
top
right
bottom
left
которые называются свойствами смещения. Принимают значение длины или процент.
Смотрите пример на Codepen. Создали родительский контейнер, дочерний контейнер и внутреннее поле с текстом:
<div class="parent"> <div class="child"> <div class="box"> <p>Test</p> </div> </div> </div>
и CSS, который добавляет цвета и поля, но не затрагивает позиционирование:
.parent { background-color: #af47ff; padding: 30px; width: 300px; } .child { background-color: #ff4797; padding: 30px; } .box { background-color: #f3ff47; padding: 30px; border: 2px solid #333; border-style: dotted; font-family: courier; text-align: center; font-size: 2rem; }
вот результат:
Попробуйте добавить любое из свойств, которые упоминали раньше (top
, right
, bottom
, left
), в .box
, и ничего не произойдёт. Положение static
.
Теперь, если установим position: relative
в блок, сначала кажется, что ничего не изменилось. Но теперь элемент перемещается с использованием свойств top
, right
, bottom
, left
. И теперь положение изменяется относительно элемента, содержащего его.
Например:
.box { /* ... */ position: relative; top: -60px; }
Отрицательное значение для top
заставит блок двигаться вверх относительно контейнера.
Или же
.box { /* ... */ position: relative; top: -60px; left: 180px; }
Обратите внимание, как пространство, которое занимает блок, сохраняется в контейнере, как будто ещё на месте.
Ещё одно свойство, которое теперь работает, это z-index
, и изменяет размещение по оси z.
Абсолютное позиционирование
Установка position: absolute
для элемента удалит его из потока документа.
Помните наблюдение при относительном позиционировании, что пространство, первоначально занимаемое элементом, сохраняется даже при перемещении элемента?
При абсолютном позиционировании как только устанавливаем position: absolute
в .box
, его исходное пространство теперь разрушено, и только исходная точка (координаты x, y) остаётся прежней.
.box { /* ... */ position: absolute; }
Теперь перемещаем блок по своему усмотрению, используя свойства top
, right
, bottom
, left
:
.box { /* ... */ position: absolute; top: 0px; left: 0px; }
или
.box { /* ... */ position: absolute; top: 140px; left: 50px; }
Координаты указаны относительно ближайшего контейнера, который не static
.
Это означает, что если добавим position: relative
для элемента .child
и установим top
и left
в 0, блок появится не в верхней левой границе окна, а на координатах 0, 0 элемента .child
:
.child { /* ... */ position: relative; } .box { /* ... */ position: absolute; top: 0px; left: 0px; }
Как уже видели, .child
статический по умолчанию:
.child { /* ... */ position: static; } .box { /* ... */ position: absolute; top: 0px; left: 0px; }
Как и для относительного позиционирования, используется z-index
, чтобы изменить положение по оси z.
Фиксированное позиционирование
Как и в случае абсолютного позиционирования, когда элементу назначается position: fixed
, он удаляется из потока страницы.
Отличие от абсолютного позиционирования CSS заключается в следующем: элементы теперь всегда расположены относительно окна, а не первого нестатического контейнера.
.box { /* ... */ position: fixed; }
.box { /* ... */ position: fixed; top: 0; left: 0; }
Другое отличие состоит в том, что прокрутка не влияет на элементы. Если поместить «липкий» элемент где-нибудь, прокрутка страницы не удалит его из видимой части страницы.
Липкое позиционирование
Несмотря на то, что предыдущие значения вводили уже давно, это добавили недавно. И оно по-прежнему относительно не поддерживается (смотрите caniuse.com).
Компонент iOS UITableView – то, что приходит на ум, когда думаешь о position: sticky
. Знаете, когда прокручиваешь список контактов, и первая буква закреплена сверху, чтобы знать, что просматриваешь контакты на эту конкретную букву?
Раньше использовали JavaScript для подобной имитации, а теперь этот подход поддерживается в CSS нативно.
Обтекание и его отмена
Обтекание было важной темой в прошлом.
Использовалось в куче хаков и творческих приёмов, потому что этот способ, вместе с таблицами, на самом деле давал реализовать некоторые макеты. Раньше использовали обтекание боковой панели слева, например, чтобы показывать её в левой части экрана. И добавляли отступы к основному контенту.
К счастью, времена изменились, и сегодня Flexbox и Grid помогают с макетом. float
вернулся к первоначальному назначению: размещение содержимого на одной стороне элемента контейнера и отображение одноуровневых элементов вокруг него.
Свойство float
поддерживает три значения:
left
right
none
(по умолчанию)
Скажем, блок содержит абзац с некоторым текстом, а абзац также содержит изображение.
Вот код:
<div class="parent"> <div class="child"> <div class="box"> <p>This is some random paragraph and an image. <img src="https://via.placeholder.com/100x100" /> The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. </p> </div> </div> </div> .parent { background-color: #af47ff; padding: 30px; width: 500px; } .child { background-color: #ff4797; padding: 30px; } .box { background-color: #f3ff47; padding: 30px; border: 2px solid #333; border-style: dotted; font-family: courier; text-align: justify; font-size: 1rem; }
и внешний вид:
Как видите, нормальный поток по умолчанию считает изображение встроенным и освобождает место для него в самой строке.
Если добавим float: left
к изображению и некоторые поля:
img { float: left; padding: 20px 20px 0px 0px; }
результат такой:
а это то, что получаем, когда применяем float: right
и соответственно корректируем поля:
img { float: right; padding: 20px 0px 20px 20px; }
Плавающий элемент удаляется из нормального потока страницы, а остальное содержимое обтекает его.
Не ограничиваемся плавающими изображениями. Здесь заменим изображение на элемент span
:
<div class="parent"> <div class="child"> <div class="box"> <p>This is some random paragraph and an image. <span>Some text to float</span> The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. The image is in the middle of the text. </p> </div> </div> </div> span { float: right; margin: 20px 0px 20px 20px; padding: 10px; border: 1px solid black }
и вот результат:
Отмена обтекания
Что происходит, когда плавающий элемент не один?
Если сталкиваются два плавающих изображения, по умолчанию они складываются одно за другим, горизонтально. Пока не закончится место, и они начнут укладываться на новую линию.
Скажем, было три встроенных изображения внутри тега p
:
Если добавим float: left
к этим изображениям:
img { float: left; padding: 20px 20px 0px 0px; }
вот что будет:
если добавите clear: left
к изображениям, они разместятся вертикально, а не горизонтально:
Это перевод части справочника CSS.
Комментарии