Pull to refresh

12 малоизвестных фактов о CSS

Reading time 9 min
Views 60K
Предлагаю читателям «Хабрахабра» перевод статьи «12 Little-Known CSS Facts (The Sequel)». Она совсем недавно была упомянута в дайджесте интересных материалов из мира веб-разработки и IT.

Update: немного «шлифанул» перевод напильником. Выражаю благодарность всем неравнодушным читателям.
Внимание! Под катом почти 1.5 Мб картинок и много интересных ссылок.

Итак, начнём-с…

1. В свойстве border-radius можно использовать slash-синтаксис.


Об этом уже писалось 4 года назад, но многие новички и даже некоторые опытные разработчики не знают о существовании этой «фишки».

Верите или нет, но следующий код валиден:

.box {
  border-radius: 35px 25px 30px 20px / 35px 25px 15px 30px;
}


Такой подход немного обескураживает в первый раз. Вот объяснение из спецификации:
Если значения указаны и «до», и «после» слеша, то значения «до» устанавливают горизонтальный радиус, а значения «после» « вертикальный.
Если slash отсутствует, то значения обоих радиусов считаются одинаковыми.

В спецификации также приводится следующая диаграмма:



Использование slash-а при указании значений позволит вам создавать несимметричные скругленные углы. Если хотите более подробно изучить эту тему, то почитайте указанную выше статью или, даже лучше, попробуйте интерактивное демо от MDN.

Большинство генераторов border-radius-ов не позволяют устанавливать дополнительные значения. Из всех найденных таких генераторов только MDN-овский это умеет.

2. Свойство font-weight может принимать «относительные» значения.


Чаще всего свойство font-weight принимает значение normal или bold. Иногда встречаются и целочисленные значения, кратные ста, такие как 100, 200 и т.д. до 900.

Но два возможных значения часто забывают — bolder и lighter.

Согласно спецификации, эти ключевые слова устанавливают шрифта жирнее или тоньше по сравнению с унаследованным. Такая возможность работы с отображением текста важна, если используемый шрифт имеет несколько вариантов «веса», а не только «жирный» и «нормальный».

В значениях веса, кратным ста, «жирный» равен 700, а «нормальный» — 400. Таким образом, если вы хотите установить вес в 300, то значение lighter, примененное к тексту, который унаследовал нормальный вес 400, установит как раз нужный вес. Если более «легкого» варианта шрифта нет (т.е. 400 — самый тонкий вариант шрифта), то те же 400 и останется, и от использования lighter эффекта не будет.

В примере используется шрифт Exo 2, который имеет 18 различных стилей, но из них нужны только некурсивные варианты шрифта — этого достаточно для всех числовых весовых значений.

В демке используется 12 вложенных box-элементов с различными значениями font-weight включая bolder и lighter, так что эффект от применения этих ключевых слов очевиден. Ниже приведены использованные стили. Обратите внимание на комментарии в коде и учтите, что каждый следующий элемент находится внутри предыдущего.
Много css-кода из демки
.box {
  font-weight: 100;
}
 
.box-2 {
  font-weight: bolder; /* maps to 400 */
}
 
.box-3 {
  font-weight: bolder; /* maps to 700 */
}
 
.box-4 {
  font-weight: 400;
}
 
.box-5 {
  font-weight: bolder; /* maps to 700 */
}
 
.box-6 {
  font-weight: bolder; /* maps to 900 */
}
 
.box-7 {
  font-weight: 700;
}
 
.box-8 {
  font-weight: bolder; /* maps to 900 */
}
 
.box-9 {
  font-weight: bolder; /* maps to 900 */
}
 
.box-10 {
  font-weight: lighter; /* maps to 700 */
}
 
.box-11 {
  font-weight: lighter; /* maps to 400 */
}
 
.box-12 {
  font-weight: lighter; /* maps to 100 */
}


В данном примере bolder и lighter, в конечном итоге, устанавливают следующие значения веса: 100, 400, 700 и 900. С девятью различными css-стилями при использовании этих ключевых слов не получится добиться значений 200, 300, 500, 600 и 800.

Это происходит из-за того, что вы указываете браузеру выбрать следующий вариант шрифта, который «жирнее» или «легче». А браузер выбирает не просто «следующий более жирный» или «следующий более тонкий» вариант, а «жирный» и «легкий» по отношению к текущему унаследованному варианту. Но, если самый «легкий» вариант шрифта имеет вес 300, например, как у Open Sans, а унаследованное значение равнялось 400, то при использовании «lighter» получится 300.

Такое поведение может сбивать с толку, но если вы «поиграетесь» с демо-примером, то всё встанет на свои места.

3. Существует свойство outline-offset


Свойство outline довольно широко известно из-за использования при дебагинге (из-за него страница не «расползается»). В спецификации, однако, добавлено свойство outline-offset, которые делает ровно то, что и означает — указывает сдвиг внешней границы от элемента.

В демо при изменении положения ползунка меняется и величина сдвига границы. В примере указаны значения от 0px до 30px, но вы можете изменить пределы на своё усмотрение. Обратите внимание, на то, что свойство outline — сокращенное свойство и не включает в себя outline-offset и его придется указывать отдельно.

Главным недостатком свойства outline-offset является тот факт, что оно поддерживается всеми браузерами кроме Internet Explorer (даже в IE 11 его нет).

4. Существует свойство table-layout


Не стоит путать это свойство с display: table.
Т.к. table-layout — не самая простая «фишка» CSS для понимания, давайте сначала обратимся к спецификации, а потом посмотрим на демо:
При таком подходе вертикальное выравнивание таблицы зависит не от содержимого ячейки, а от ширины таблицы, ширины колонки и границ или отступов между ячейками.

Возможно, это первый раз в истории спецификации W3C, когда что-то так сложно понять.

Но, если серьёзно, использование демо поможет.



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

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

5. Свойство vertical-align работает по разному в ячейках таблиц и других элементах


Если вы занимаетесь разработкой сайтов с середины двухтысячных или раньше или знаете достаточно много о HTML и email-письмах, то вы, возможно, предполагаете, что свойство vertical-align является обычным улучшением старого HTML4-аттрибута valign, который сайчас указан как устаревший и несоответствующий стандарту HTML5.
Но свойство vertical-align в CSS работает не совсем так. Но не в таблицах. Что, по-моему, достаточно странно, но я полагаю, это лучше, чем свойство, вообще не работающее в таблицах.

Итак, какова разница при использовании этого свойства в обычных элементах и ячейках таблиц?

Если vertical-align применяется НЕ к ячейкам таблиц, то оно работает по следующим правилам:
  • Применимо только к inline или inline-block элементам;
  • Не влияет на содержимое элемента, а только меняет его положение относительно других inline и inline-block элементов
  • На свойсто могут влиять настройки текста или шрифта, такие как line-height и размер смежных inline и inline-block элементов.

Демо.



Свойство vertical-align установлено у поля ввода input. При нажатии на кнопки значение свойства меняется. Обратите внимание, что все эти значения различны.
Примите во внимание, что данная демка — лишь поверхностный взгляд на vertical-align. Более глубокое его рассмотрение можно изучить тут.

Когда vertical-align применяется к ячейке таблицы, то оно работает совсем по-другому. В частности, данное свойство применяется и к содержимому ячеек.
Демо.



Как показано в примере, для vertical-align есть только 4 варианта значения, которые применимы к ячейкам таблицы, кроме того значение baseline влияет и на ячейки того же уровня, что и ячейка, к которой свойство применено.

6. Псевдо-элемент ::first-letter умнее, чем вы думаете


Псевдо-элемент ::first-letter позволяет вам стилизовать первую букву элемент (примечание переводчика — привет, капитан!), например, красиво выделить её как в печатных книгах много лет назад.

Браузеры достаточно хорошо поддерживают стандарт относительно этой «первой буквы». Впервые этот псевдо-элемент я увидел в твите Matt Andrews, хотя он явно подразуемевает, что это всё таки плохая «фишка». Демо.


Это здорово, что 4 крупных браузера отображают этот псевдо-элемент одинаково, потому что, по-моему, это и есть правильный вариант отображения. Выглядело бы странным, если бы какой-нибудь символ, такой как одиночная скобочка, воспринимался как «первая буква» — это скорее можно было бы считать «первым символом», который достоин собственного нового псевдо-класса.

7. Вы можете использовать «невалидные» символы в качестве разделителей в перечне классов элемента


Этот подход обсуждал Ben Edvard в 2013 году, и, я думаю, стоит подробнее рассмотреть этот вопрос.
Ben писал об использование slash («/») в качестве разделителя HTML-классов по группам для того, чтобы сделать код более читаемым и проще сканируемым. Автор указывает, что несмотря на то, что неэкранированный slash является «невалидным» символом, браузеры его просто игнорируют, а не выдадут ошибку.
Допустим, у вас такой HTML-код:
<div class="col col-4 col-8 c-list bx bx--rounded bx--transparent">

При использовании slash-ей получается следующее:
<div class="col col-4 col-8 / c-list / bx bx--rounded bx--transparent">

Вы можете использовать любой символ (валидный или не очень) для получения того же эффекта:
<div class="col col-4 col-8 ** c-list ** bx bx--rounded bx--transparent">
<div class="col col-4 col-8 || c-list || bx bx--rounded bx--transparent">
<div class="col col-4 col-8 && c-list && bx bx--rounded bx--transparent">

Все перечисленные варианты работают нормально, в чем можно убедится, посмотрев демо
Конечно же, эти разделители не могут быть использованы в css-стилях как классы. Следующий код является неправильным и не применится к элементу:
./ {
  color: blue;
}

Если вы вынуждены использовать подобные символы в названиях своих css-классов, то можно использовать вот этот инструмент. Таким образом, вышеуказанный код будет работать, если его преобразовать до такого:
.\/ {
  color: blue;
}

Если продолжать эту тему, то Unicode-символы вообще не должны быть экранированы и можно творить разные безумные вещи:
. {
  color: hotpink;
}
 
.★ {
  color: yellow;
}

  <div class=" ★"></div>

Кроме того, вы можете «экранировать» и эти символы тоже, вместо того чтобы использовать их напрямую. Следующие css-строки аналогичны предыдущим:
.\2665 {
  color: hotpink;
}
 
.\2605 {
  color: yellow;
}


8. Количество повторов анимации может принимать дробные значения


При описании анимации можно использовать свойство animation-itereation-count для того, чтобы указать, какое количество раз анимация будет проиграна:
.example {
  animation-iteration-count: 3;
}

Вышеуказанный код говорит, что анимация будет проигрываться 3 раза. Но, возможно, вы не знали, что можно указывать и дробные значения:
.example {
  animation-iteration-count: .5;
}

В этом случае анимация будет проиграна лишь на половину первой итерации. В демо на CodePen верхнему кружку указано количество итераций 1, а нижнему — .5



Длительность итерации определяется не по изменению значений свойств во течение анимации, а именно по времени и с учетом сглаживания. В вышеупомянутом примере используется функция с линейной зависимостью от времени — linear.

Но в этом примере уже применяется сглаживание:



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

Если вы разбираетесь в различных функциях сглаживания, то заметите, что при использовании ease-in-out второй кружок займет то же итоговое положение, что и при использовании linear.

9. Анимация, записанная в краткой форме может не работать из-за своего названия


Некоторые разработчики заметили это случайно, хотя в спецификации есть соответствующее предупреждение. Давайте рассмотрим следующую анимацию:
@keyframes reverse {
  from {
      left: 0;
    }
 
    to {
      left: 300px;
    }
}
 
.example {
    animation: reverse 2s 1s;
}

Заметьте, я использую название анимаци reverse. На первый взгляд, всё хорошо, но давайте посмотрим на живой пример.

Анимация не работает, т.к. reverse — валидное ключевое слово для свойства animation-direction. Так же анимация не будет работать при использовании в краткой форме в названии других ключевых слов. Но всё работает хорошо при использовании «полной» формы описания.

К ключевым словам-значениям animation-direction, «ломающими» анимации, стоит отнести и ключевые слова, относящиеся к функциям сглаживания, а так же infinite, alternate, running, paused и так далее.

10. В селекторе можно указать диапазон элементов.


Не знаю, кто начал это первым использовать, но первым я увидел это демо от Gunnar Bittersmann. Допустим, у вас есть список из 20 элементов и нужно выбрать элементы с 7 по 14 включительно. Это можно сделать вот так:
ol li:nth-child(n+7):nth-child(-n+14) {
  background: lightpink;
}


Демо.



В Safari из-за бага такой приём работать не будет. Однако, решение всё таки есть — Matt Pomaski починил это. Нужно всего лишь перечислить элементы выборки в другом порядке:
ol li:nth-child(-n+14):nth-child(n+7) {
  background: lightpink;
}

Этот код использует цепочку связанных псевдо-классов. Хотя выражение немного запутанное, ключевые числа 7 и 14 в нём используются без изменений.
Постараюсь объяснить, как это работает. Первая часть выражения говорит: «выбрать седьмой элемент, а потом все ПОСЛЕ него». А вторая часть — «выбрать четырнадцатый элемент, а потом все ДО него». Т.к. части связаны, то на пересечении запросов получается требуемый диапазон.

Для более детального рассмотрения этой темы рекомендуется почитать более раннюю статью.

11. Псевдо-элементы могут быть применены к некоторым «пустым» элементам


Наверняка вы пробовали использовать псевдо-элементы с изображениями или input-ами. Но это не работает с «замещаемыми» элементами (примечание переводчика — в комментариях к этому переводу SelenIT2 постарался объяснить, что же это за зверь такой). Я думаю, многие разработчики предполагают, что пустые элементы (те, у которых нет закрывающего тега) так же попадают в эту категорию. Но это не так.

Вы можете использовать псевдо-элементы вместе с некторыми пустыми элементами, которые не являются «замещаемыми». Например, <hr> в этом демо.



Цветная область является тегом <hr> и его двумя псевдо-элементами ::before и ::after. Интересно, что подобного результата не получилось добиться от тега <br>, который тоже не является «замещаемым».

Так же, вы можете использовать псевдо-элементы вместе с мета-тегами или <link>, если, конечно, готовы применить к ним свойство display: block как в этом демо.

12. Некоторые значения атрибутов регистро-зависимы при использовании в селекторах


Наконец-то, что-то непонятное. Допустим, есть такой HTML:
<div class="box"></div>
<input type="email">

Можно стилизовать оба этих элемента следующим образом:
div[class="box"] {
  color: blue;
}
 
input[type="email"] {
  border: solid 1px red;
}

Это замечательно работает. А как на счёт такого?
div[class="BOX"] {
  color: blue;
}
 
input[type="EMAIL"] {
  border: solid 1px red;
}


Значения обоих атрибутов написаны в верхнем регистре. В этом случае .box-элемент не получит стилизации, т.к. атрибут class регистрозависим. Поле ввода email, однако, будет стилизовано, т.к. аттрибут type регистронезависим. В этом нет ничего новаторского, но, возможно, вы это не замечали раньше.
Tags:
Hubs:
+69
Comments 21
Comments Comments 21

Articles