Вертикальные поля
Что станет с элементом, если назначить ему свойство
padding-top: 50%
? Интуитивно понятно, что подобное свойство устанавливает размер поля от верхнего края содержимого элемента, размер которого составляет 50%… От чего берутся эти 50%? Собственно говоря, в определённый момент интуиция при разборе особенностей этого свойства оказывается бесполезной. Дело в том, что эти вот 50% берутся от ширины родительского элемента того элемента, которому назначают верхнее поле.Вот пример, подготовленный средствами CodePen. Такие примеры вы найдёте и во многих других разделах этого материала.
Вышесказанное справедливо и для нижнего поля, задаваемого свойством
padding-bottom
. Знание этой особенности, в частности, позволяет создавать отзывчивые элементы, сохраняющие соотношение сторон:.square {
width: 100%;
height: 0;
padding-bottom: 100%;
}
О непостоянном схлопывании отступов
Расстояние между следующими элементами будет
20px
, а не 40px
:<div style="margin-bottom:20px">foo</div>
<div style="margin-top:20px">foo</div>
> Пример
Однако так бывает не всегда. Отступы не схлопываются при работе со следующими элементами:
- Плавающие элементы.
- Абсолютно позиционированные элементы.
- Строчно-блочные (inline-block) элементы.
- Элементы с параметром
overflow
, установленным в любое значение кромеvisible
(они не схлопывают отступы со своими элементами-потомками). - Элементы, к которым применено правило
clear
(их верхние отступы не схлопываются с нижними отступами их родительских блоков). - Корневой элемент дерева документа.
Уровень прозрачности и порядок наложения элементов
Предположим, что имеются три элемента
<div>
, каждый из них позиционирован абсолютно. Они содержат другие элементы, которым назначено свойство z-index
со значениями от 1 до 3. Каждый следующий такой элемент выводится поверх предыдущего. Если теперь назначить z-index: 10
самому нижнему элементу, он будет выведен поверх двух других, порядок расположения которых не изменится. Пока всё выглядит так, как и ожидается. Если теперь назначить первому элементу <div>
, тому, который теперь находится выше других, свойство opacity: 0.99
, то он окажется под двумя другими.> Пример
Подробности о том, почему это происходит, можно найти здесь.
Кастомные свойства и переменные CSS
Используя SASS или LESS, можно решить, что кастомные свойства и переменные CSS эквивалентны возможностям, доступным в этих препроцессорах. Однако, тут имеются несколько отличий, на которые стоит обратить внимание.
Сначала рассмотрим основы:
// задавать и использовать кастомные свойства можно так
:root {
--foo: #000;
}
button {
background-color: var(--foo); //чёрный фон
}
Кастомные свойства, кроме того, наследуемы, то есть, если переназначить локальную переменную, это подействует на все элементы-потомки, и, в отличие от препроцессора, браузер, когда подобное происходит, пересчитывает все выражения, где применяются такие переменные.
При применении кастомных свойств резервные значения можно перечислить через запятую. В список резервных значений могут входить и другие переменные.
.foo {
color: var(—-my-var, 'blue');
}
Это приводит нас к основной разнице с препроцессорами: переменные CSS знают о структуре DOM и об изменениях, которые там происходят.
::root {
--default-color: #000000;
}
header {
--primary-color: #ff0000;
}
a {
color: var(--primary-color, --default-color);
}
<a href="">this is black</a>
<header>
<a href="">this is red.</a>
</header>
В отличие от первого примера, демонстрирующего наследование, этот пример полагается на резервные значения, на которые влияет то, было ли задано кастомное свойство в родительском элементе DOM или нет.
> Пример
Более того, их легко можно менять, используя средства JavaScript:
// получить переменную из inline-стиля
element.style.getPropertyValue("--my-var");
// установить переменную в inline-стиле
element.style.setProperty("--my-var", jsVar + 4);
Эта возможность поддерживается начиная с Edge 15.
Конструкция vertical align: top | middle | bottom
Конструкция
vertical align: top | middle | bottom
работает только для inline-элементов (в том числе и для inline-block
) и элементов table-cell
. Этот способ не подходит для выравнивания элементов внутри их родительских элементов. Для этого нужно использовать средства flexbox-вёрстки, или то, что известно как «douchebag vertical align» (ниже мы об этом поговорим).Свойство height: 100% может не давать ожидаемого эффекта
То, о чём мы говорили в предыдущем разделе, справедливо и для свойства
height: 100%
. Во многих случаях установка этого свойства не приводит к тому, чего ожидает разработчик. Причина подобного кроется в том, что не задана высота родительского элемента. Рассмотрим пример:<html>
<body>
<div style="height:100%;background:red;"></div>
</body>
</html>
Показанный здесь элемент
<div>
не закрасит всю страницу в красный цвет. Для того чтобы этого добиться, нужно установить свойство height
в 100%
и для элемента <body>
, и для элемента <html>
.Стили идентификаторов и стили классов
Стили идентификаторов переопределяют стили, заданные на уровне классов. Происходит это из-за того, что id-селекторы точнее, чем селекторы классов. Так, например, правило, заданное для
.foo.bar
переопределит правила, заданные отдельно для .foo
и для .bar
.#foo { color: red; }
.bar { color: green; }
<h1 id="foo" class="bar">this will be red not green</h1>
Выбор элементов с определённым атрибутом
Средствами CSS можно выбирать элементы на основе конкретных атрибутов и их содержимого. Например, это может быть содержимое атрибутов
src
или href
.// выбираем все ссылки на zip-файлы (нечувствительно к регистру)
a[href$=".zip" i] { }
// сделаем красными ссылки на google.com
[href*="google.com"] { color: red; }
Этот приём может оказаться полезным при отладке, например, для выделения всех элементов
img
с пустым атрибутом alt
:img:not([alt]) {
border: 2px dashed red;
}
img[alt=""] {
border: 2px dashed red;
}
Если вы используете Angular, этот подход, кроме того, может быть полезен для выбора элементов, которые содержат
[ng-click]
. Или, если надо, так можно визуально разделить ссылки на локальные ресурсы, и ссылки, которые начинаются с http
или https
.> Пример
О порядке следования свойств при указании значений параметров по горизонтали и вертикали
Когда задают некие значения, имеющие отношения к горизонтальной и вертикальной осям, первое число обычно задаёт вертикальное значение, а второе — горизонтальное. Например, в выражении
padding: 10px 20px; 10px
— это верхнее и нижнее поле, 20px
— это правое и левое поле. Именно так это выглядит при настройке полей, отступов, границ, в целом — это так практически для всего, за исключением свойства border-spacing
в таблицах, где значения расположены с точностью до наоборот: первое число устанавливает значение по горизонтали, второе — по вертикали.Несколько фоновых изображений для одного элемента
Одному и тому же элементу можно назначать несколько фоновых изображений, разделив их запятой. При этом каждое из них можно по-разному настраивать, например — позиционировать.
background: url(example1.png’) no-repeat center 50px, url(‘example2.jpg’) no-repeat bottom top;
Эта возможность поддерживается начиная с IE11.
Наложение CSS-анимаций
Так же, как и при работе с фонами, можно накладывать друг на друга CSS-анимации:
@keyframes foo {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes bar {
0% { transform: translateX(-100px); }
100% { transform: translateX(0px); }
}
.element {
animation: foo 2s 0s, bar 1s 0s;
}
О странном поведении position: fixed при использовании трансформации translateZ
Добавление трансформации
translateZ(0);
к контейнеру, который включает в себя элемент со свойством position: fixed;
приводит к выравниванию элемента относительно контейнера, а не относительно окна.> Пример
Стилизация элементов, на которые осуществляется переход по адресам, содержащим символ решётки (/#foo)
Псевдо-класс
:target
можно использовать для стилизации элементов, на которые осуществляется переход при щелчке по ссылке с символом решётки. Так, например, щелчок по ссылке вида <a href="#foo">Go to Foo</a>
прокрутит страницу до элемента <div id="foo">foo</div>
. Теперь, если вы включили в CSS правило вида #foo:target { color: red; }
, элемент <div> #foo
будет окрашен в красный цвет. Выделение таких элементов может оказаться полезным для тех посетителей сайта, которые попали на страницу по внешней ссылке вроде
www.example.com/#foo
. При таком подходе браузер прокрутит страницу к нужному элементу и этот элемент окажется выделенным. В наши дни так поступают редко, но этот приём способен улучшить впечатления пользователей от работы с сайтом.> Пример
Малоизвестные возможности content: ‘foo’;
?Атрибуты данных
Атрибуты данных можно использовать для динамического CSS-содержимого. Например:
<div data-text="foo"></div>
div:before {
content: attr(data-text);
}
> Пример
Этот приём может оказаться полезным, если, например, нужно перевести текст псевдо-класса (скажем, используя его для всплывающих подсказок). Сейчас с помощью
attr()
можно работать лишь с контентом. Хотя не исключено появление поддержки этой конструкцией других свойств. Более того, значения, получаемые из attr()
— это строки, поэтому они предназначены, в первую очередь, для контента и не могут использоваться для свойств, задающих размеры (например — font-size
), или для ссылок (например, content: url()
). Кстати, поговорим об этом.?Content: url()
Данную конструкцию можно использовать для многих видов данных (изображения, звуки, видео). Например:
<div></div>
div:before {
content: url(image.jpg);
}
> Пример
Однако если из DOM в CSS надо передавать произвольные данные, придётся обратиться к вышеописанным кастомным свойствам:
<div style="--background-image: url('http://via.placeholder.com/150x150');"></div>
div:after {
content: '';
background-image: var(--background-image);
}
?Инкрементальный счётчик
Конструкцию
content: counter()
можно использовать для инкрементной нумерации псевдо-элементов:p {
counter-increment: myIndex;
}
p:before {
content:counter(myIndex);
}
<p>foo</p>
<p>bar</p>
> Пример
?Открывающие и закрывающие кавычки
Свойство
content
псевдо классов вроде :before
и :after
может быть использовано для добавления к элементам открывающих и закрывающих кавычек:q:before {
content: open-quote;
}
q:after {
content: close-quote;
}
Если говорить о кавычках, то скомбинировав этот приём с ранее упомянутым выбором атрибутов данных, можно даже использовать CSS для задания специфического локализованного стиля кавычек, основанного на языке сайта, с применением одного лишь свойства
quotes
:html[lang="fr"] q {
Quotes: "«" "»";
}
Использование свойства font
Свойство
font
позволяет, в сокращённом формате, задавать параметры шрифтов:h1 {
font-weight: bold;
font-style: italic;
font-size: 1rem;
//etc…
}
// комбинированный вариант
h1 {
font: italic lighter 1rem/150% Verdana, Helvetica, sans-serif;
}
// синтаксис
// font: font-style font-variant font-weight font-size/line-height font-family;
Директива supports
Директиву
@supports
можно использовать для проверки того, поддерживает ли браузер возможности, интересующие разработчика. Скажем, если display:flex
планируется использовать только в том случае, если есть уверенность в поддержке этой возможности браузером, можно применить следующую конструкцию:@supports (display: flex) {
div {
display: flex;
}
}
Двоеточия в именах классов
Использование двоеточий в именах классов может оказаться полезным для создания более понятных имён, которые, при чтении, легче делить на части. Так, например, некоторые CSS UI-фреймворки (вроде Tailwind) используют следующие соглашения по именованию:
<div class="justify-start sm:justify-center md:justify-end lg:justify-between xl:justify-around">
<button class="bg-blue hover:bg-blue-dark text-white hover:text-blue-light">Button</button>
Задавать специфические классы для стилей, применяемых к элементам, над которыми находится указатель мыши, возможно, в большинстве случаев не особенно полезно, но такой подход позволяет чётко отличать соответствующие состояния от других, что улучшает читаемость кода.
Для использования двоеточий в CSS их нужно экранировать:
.sm\:justify-center { }
Трёхэлементный селектор
Все, кто читают этот материал, должны знать о CSS-селекторе, состоящем из трёх элементов, который обычно называют «lobotomized owl selector». Вот как он выглядит:
* + * {
margin-top: 2rem;
}
Он придётся кстати в ситуациях, когда имеется множество элементов одного вида, между которыми должен быть отступ, причём, после последнего элемента такого списка отступ не нужен:
li + li {
margin-top: 1rem;
}
// вместо
li {
margin-bottom: 1rem;
}
li:last-of-type {
margin-bottom: 0;
}
Вертикальное выравнивание методом «douchebag vertical align»
Раз уж мы заговорили о необычных селекторах — вспомним и о методике вертикального выравнивания, называемой «douchebag vertical align»:
.element {
position: relative;
top: 50%;
transform: translateY(-50%);
}
Свойство font-feature-settings для шрифтов OpenType
Шрифты OpenType поддерживают настройку свойств. Эту особенность можно использовать для подгонки шрифта под нужды конкретного проекта благодаря свойству font-feature-settings.
Один из вариантов применения этой возможности открывается в ситуации, когда нужен красивый шрифт, не являющийся моноширинным, для таймера обратного отсчёта. Без специальной настройки ширина последовательности цифр будет постоянно меняться. Выглядит это непрофессионально. Вот решение этой проблемы:
font-feature-settings: "tnum";
font-variant-numeric: tabular-nums;
Обрезка текста с добавлением окончания в виде многоточия, "…"
Тут всё предельно просто:
p {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
> Пример
Итоги
Мы рассмотрели некоторые малоизвестные возможности CSS, которые, надеемся, пригодятся веб-разработчикам. Кстати, вот ещё одна интересная штука, не относящаяся, правда, к CSS. Это — HTML-элемент wbr, который позволяет отмечать места разрывов слов.
Уважаемые читатели! Знаете ли вы о каких-нибудь возможностях CSS, полезных, но не получивших широкой известности?
Комментарии (12)
kartvladek
07.03.2018 15:31Да почему не возможно — это всего лишь вопрос времени, а время как известно — относительно. Да и есть ли оно вообще — еще разобраться надо
Akdmeh
07.03.2018 18:00Ну обычно подобные статьи действительно страдают тем, что трудно найти необходимую аудиторию — кому-то большинство пунктов известно, кому-то нет…
Хотя однозначно польза в подобных статьях есть — например, я не знал раньше о «lobotomized owl selector» (точнее, не задумывался, что так удобнее) — а ведь действительно, на одну директиву меньше. Думаю, другие разработчики тоже найдут один-два пункты, о которых не знали — уже польза!
Для меня, кстати, довольно неочевидным было то, что для inline-block указывать вертикальное позиционирование нужно для собственно тех элементов, которые их используют, хотя по логике казалось, что это нужно делать для родительского контейнера.
kshuric
09.03.2018 10:46А я вот про *+* впервые узнал, так что польза от таких статей всегда есть. Кто-то начинающий загуглит и найдет что ему надо.
В статью я бы добавил еще где поддерживается, а где нет.
yurch-html
09.03.2018 13:30О странном поведении position: fixed при использовании трансформации translateZ
При любой трансформации будет фиксед вести себя как абсолют.
Вертикальное выравнивание методом «douchebag vertical align»
К слову о неизвестной высоте, при релетиве, top: 50%, не сработает
yurch-html
09.03.2018 14:07Мне нравятся подобного рода статьи, какая-то новая инфа да проскочит.
Так что автору спасибо.
(надо бы сюда еще про белый полупрозрачный бордер, на белом фоне написать)
spmbt
Наборчик — так себе: рассчитан на начинающе-средних верстальщиков, чтобы восхитить и усилить интерес к профессии. Много свойств, которые уже давно знают и немного намешано новых правил (font-feature-settings, Двоеточия в именах классов (тут не знаю, насколько ново, но в самом деле не встречается в обиходе)), counter-increment). И есть, наконец, хаки типа translateZ и прозрачности с absolute.
Совет: про целевую аудиторию переводчикам хорошо было бы писать 2 строчки в начале: «Для начинающих, но кое-что редкое есть во второй половине». Это не составит трудов, но сразу сориентирует.
dom1n1k
Нормальный наборчик. Есть действительно неочевидные и малоизвестные вещи. А сказать что-то принципиально новое по теме CSS уже практически невозможно.
vintage
Неочевидный момент — чтобы элементы во флексбоксе не выпирали за пределы контейнера своим содержимым, нужно этому контейнеру задать
overflow:hidden
.Synoptic
А мне понравилось, многое не применял.
parmactep
Типичная ошибка интерполировать "мне известно" на "всем известно".