Больше года назад я опубликовал 12 малоизвестных фактов о CSS (перевод на хабре), и по сей день это была одна из самых популярных статей на SitePoint. С тех пор я собирал больше интересностей и маленьких советов по CSS для новой публикации. Мы же все знаем, что каждый успешный фильм должен способствовать выходу новомодного сиквела, верно?
![](https://habrastorage.org/files/f50/157/c62/f50157c62f3444ae8e82acdea5745673.png)
Автор иллюстрации SitePoint/Natalia Balska.
Итак, давайте посмотрим на подборку уже этого года дюжины малоизвестных фактов о CSS. Я уверен, что многим из вас известны, по крайней мере, некоторые из них, но вы можете дать мне знать в комментариях сколько из фактов оказались для вас новыми.
1. Оригинальная статья изобилует рабочими демонстрациями с CodePen. Хабр, к сожалению, не поддерживает вставки с подобных ресурсов, а заменять рабочие динамические примеры статичными картинками, думаю, не имеет смысла. Поэтому статья получилась немного «лысой» простыней, но, я надеюсь, заинтересованные читатели будут открывать недостающие примеры по ссылкам в новом окне.
2. Хотя я имею непосредственное отношение к верстке, перевод получился большим и не таким простым, как показался поначалу. Замечания по ошибкам, опечаткам, терминологии и т.п. просьба присылать личным сообщением в хабрапочту.
1. В свойстве border-radius
можно использовать «слэш» синтаксис
Об этом я уже писал на SitePoint больше четырех лет назад, но я думаю, что многие начинающие и даже некоторые опытные разработчики не знают о такой возможности.
Верьте или нет, но следующий код валидный:
.box { border-radius: 35px 25px 30px 20px / 35px 25px 15px 30px; }
Если вы никогда не видели подобного синтаксиса, он может показаться немного запутанным, поэтому приведу объяснение из спецификации:
Если значения указаны до и после слэша, то значения перед слэшем устанавливают горизонтальный радиус, а значения после слеша — вертикальный. Если слэш не используется — значения обоих радиусов (и горизонтального и вертикального) считаются одинаковыми.
В спецификации также приведена следующая схема:
![](https://habrastorage.org/files/c81/5db/719/c815db7190ae46db8b55930e6526644e.png)
В пояснении к картинке сказано: «Два значения border-top-left-radius: 55pt 25pt
определяют кривизну угла».
Таким образом, использование слэша в значениях свойства border-radius
позволяет создавать несимметрично изогнутые углы (прим. переводчика: скруглы). Если вы хотите более подробно разобраться в этом, прочтите мою статью (ссылка на которую выше приводилась), или лучше посмотрите удобную интерактивную демонстрацию от MDN.
Большинство border-radius
генераторов не позволяют использовать эти необязательные значения. Из тех, что я нашел, генератор от MDN единственный поддерживает «слэш» синтаксис.
2. Свойство font-weight
поддерживает ключевые слова относительности
Обычно, когда вы видите описание свойства font-weight
, значение в нем либо normal
, либо bold
. Вы также могли видеть целые значения с инкрементом в сотню: 100
, 200
, и т.д. вплоть до 900
.
Однако, есть два значения, о которых часто забывают: bolder
и lighter
.
Согласно спецификации, эти ключевые слова делают шрифт жирнее или тоньше относительно наследуемого значения. Самое главное — это действует, когда вы имеете дело со шрифтом, в котором поддерживаются несколько степеней «жирности», где поддерживается начертания толще, чем обычный bold
, и тоньше, чем просто нормальный текст.
В синтаксисе, основанном на целых значениях, 700
означает bold
и 400
значит normal
. Итак, если ваш шрифт поддерживает толщину 300
, но не меньше, значение lighter
будет использовать толщину 300
, если наследуемая толщина шрифта 400
. Если же шрифт не поддерживает более тонкого начертания (т.е. значение по умолчанию 400
является самым тонким), то толщина так и останется 400
, и значение lighter
не произведет никакого эффекта на текст.
Посмотрите на следующий пример.
В этом примере я использую шрифт Exo 2, который поддерживает 18 разных начертаний. В моем демо не используются курсивные начертания, но шрифт их поддерживает для каждого значения от 100
до 900
.
Пример включает в себя 12 вложенных элементов «box» с различными значениями font-weight
, включая bolder
и lighter
, чтобы вы могли видеть как это влияет на «жирность» текста в разных случаях наследования. Ниже под спойлером приведен CSS из примера. Обратите внимание на комментарии в коде, и помните, что каждый следующий элемент «box» вложен в предыдущий:
.box { font-weight: 100; } .box-2 { font-weight: bolder; /* переключает на 400 */ } .box-3 { font-weight: bolder; /* переключает на 700 */ } .box-4 { font-weight: 400; } .box-5 { font-weight: bolder; /* переключает на 700 */ } .box-6 { font-weight: bolder; /* переключает на 900 */ } .box-7 { font-weight: 700; } .box-8 { font-weight: bolder; /* переключает на 900 */ } .box-9 { font-weight: bolder; /* переключает на 900 */ } .box-10 { font-weight: lighter; /* переключает на 700 */ } .box-11 { font-weight: lighter; /* переключает на 400 */ } .box-12 { font-weight: lighter; /* переключает на 100 */ }
В этом случае ключевые сова «bolder» и «lighter» устанавливают font-weight
на значения 100
, 400
, 700
и 900
. С девятью разными стилями эти ключевые слова никогда не приведут к значениям 200
, 300
, 500
, 600
и 800
.
Так получается потому что вы говорите браузеру выбрать следующий шрифт в серии, который «жирнее» или «тоньше». Но браузер выбирает не просто следующий вариант жирнее или тоньше, а вариант начертания жирнее или толще относительно текущего. Однако, если самое тонкое начертание шрифта начинается со значения 300
(как у шрифта Open Sans), а значение по умолчанию 400
, то использование ключевого слова «lighter» установит font-weight
на значение 300
.
Это может показаться запутанным, но вы можете поиграться с примером, чтобы понять как работают эти ключевые слова.
3. Свойство outline-offset
Свойство outline
хорошо известно благодаря своему удобству при отладке верстки (контур элемента никак не влияет на окружающие его элементы). В спецификации, однако, также добавлено свойство outline-offset
, которое осуществляет именно то, что следует из его названия — оно позволяет задать отступ контура от элемента.
В этом примере подвигайте слайдер вправо/влево, чтобы увидеть как это влияет на отступ контура от элемента. В данном случае отступ меняется от 0px
до 30px
, но в CSS вы можете задать любой отступ. Следует помнить, что хоть outline
и универсальное свойство (одновременно устанавливающее цвет, стиль и толщину внешней границы), оно не включает в себя outline-offset
. Поэтому при необходимости outline-offset
каждый раз нужно прописывать отдельно.
Единственный минус outline-offset
— он поддерживается всеми браузерами, кроме Internet Explorer (не поддерживает даже IE 11).
4. В CSS есть свойство table-layout
Вы, наверное, скажете: «Ха, старо как мир. Я знаю о display:table
. Простейший способ вертикального центрирования». Но это не то, о чем я хочу рассказать. Заметьте, я сказал свойство table-layout
, а не display
.
Свойство table-layout
не самая простая CSS фича, чтобы объяснить как оно работает. Поэтому давайте заглянем в спецификацию, а потом рассмотрим пример. Спецификация гласит:
При этом (быстром) алгоритме горизонтальная разбивка таблицы не зависит от контента в ячейках; зависит только от ширины таблицы, ширины колонок и бордюров или расстояния между ячейками.
Это, похоже, первый раз, когда в W3C спецификации что-то трудно понять… Хах, прост шутканул (прим. переводчика: в оригинале «LOL JK»).
А если серьезно, как всегда нам поможет живой пример. В этом демо таблице в CSS добавлено table-layout: fixed
. Кликайте по кнопке, чтобы выключать/включать это свойство.
На этом примере вы можете видеть преимущество использования table-layout: fixed
над table-layout: auto
. Такой подход не всегда будет лучшим выбором и не всегда необходим, но не плохо бы о нем знать, когда речь идет о таблицах с клетками непостоянной ширины.
В прошлом году Крис Коер (Chris Coyier) написал отличную статью о table-layout
, поэтому если вы хотите больше узнать об этом свойстве — советую почитать.
5. Свойство vertical-align
в ячейках таблицы работает по-другому, нежели в других элементах
Если вы занимались созданием сайтов в середине 2000-х и раньше или часто верстаете HTML письма для email рассылок, вы, наверное, предполагаете, что CSS свойство vertical-align
является аналогом старого HTML4 атрибута valign
, который в HTML5 уже не поддерживается.
Но CSS свойство vertical-align
работает не так-же, особенно с таблицами. Это, на мой взгляд, странновато, но все же лучше, чем если бы свойство вообще не работало в таблицах.
Так в чем же разница между применением свойства к обычным элементам и к ячейкам таблиц?
Если vertical-align
применяется не к ячейкам таблиц, то следует этим простым правилам:
- работает только с
inline
иinline-block
элементами; - не влияет на соседние элементы в контенте, но влияет на выравнивание элемента относительно соседних
inline
иinline-block
элементов; - на свойство влияют настройки шрифта, такие как
line-height
, и размер соседнихinline
иinline-block
элементов.
В этом примере свойство vertical-align
присвоено элементу input
. Нажимая на кнопки вы можете устанавливать свойству значения, написанные на кнопках. Обратите внимание, как каждое значение меняет позицию элемента input
.
В целом, это довольно простенькая демонстрация работы свойства. Для более глубокого анализа прочтите прошлогоднюю статью Кристофера Оуе (Christopher Aue).
Когда дело доходит до таблиц, vertical-align
работает совсем по-другому. В этом случае вы применяете свойство к одной и более ячейкам, и выравнивание контента ячеек зависит от выбранного значения. Пример на CodePen.
Как показано в примере, только 4 значения свойства vertical-align
применимы к ячейкам таблиц. Кроме того, значение baseline
влияет не только на ячейку, к которой проставляется, но и на соседние ячейки в строке таблицы.
6. Псевдоэлемент ::first-letter
умнее, чем вы думали
Псевдоэлемент ::first-letter
позволяет стилизовать первую букву любого элемента и дает возможность реализовать эффект буквицы (прим. переводчика: позволил себе сослаться на русскоязычную страницу wiki), который был распространен в печати в течение многих лет.
Хорошая новость в том, что, похоже, браузеры имеют одинаковое представление о «первой букве» элемента. Впервые я прочел об этом в твите Мэта Эндрюса (Matt Andrews), хотя, такое поведение браузеров ему явно не понравилось. Вы можете посмотреть его пример на CodePen.
![](https://habrastorage.org/files/0a8/0a2/8e8/0a80a28e848d49dca50d0ebdd9539c26.png)
Мне кажется, что большая четверка браузеров работает с этим свойством одинаково, и это круто, так как я считаю, что это правильное поведение. Было бы немного странно, если бы открывающая скобка считалась первой буквой. В таком случае это было бы похоже на «first character» (первый символ), который мог бы стать самостоятельным псевдоклассом.
7. В HTML вы можете использовать недопустимые символы в качестве разделителя в списке классов элемента
Этот подход обсуждался в 2013 году Бэном Эвардом (Ben Everard), и, я думаю, стоит подробнее рассмотреть эту тему.
В публикации Бэна говорилось об использовании символа слэша ("/") для разделения в HTML списков классов на группы, чтобы сделать код легче для прочтения и понимания. Автор указывает на то, что хотя слеш является недопустимым символом, браузеры не споткнутся на нем, а просто его проигнорируют.
Предположим, у вас такой HTML:
<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"> <div class="col col-4 col-8 && c-list && bx bx--rounded bx--transparent">
Все подобные конструкции отлично работают, можете протестировать на этом демо.
Конечно, эти разделители не могут быть использованы в качестве классов, поэтому я называю их «недопустимыми». Следующий код будет нерабочим и не применит стили к элементу:
./ { color: blue; }
Если вы хотите использовать подобные символы в именах классов, сохраняя их работоспособность, вы можете экранировать их, воспользовавшись этим инструментом. Предыдущий пример будет работать, только если CSS будет выглядеть так:
.\/ { color: blue; }
Углубляясь в подробности скажу, что символы юникода не нужно экранировать, поэтому вы можете использовать подобные безумные конструкции:
<div class="♥ ★"></div>
С таким CSS:
.♥ { color: hotpink; } .★ { color: yellow; }
Есть так же возможность экранировать и символы данного типа, вместо их непосредственной вставки. Следующий код эквивалентен предыдущему:
.\2665 { color: hotpink; } .\2605 { color: yellow; }
8. Количество повторов анимации может принимать дробные значения
Вероятно вы в курсе, что при использовании keyframe-анимаций вы можете использовать свойство animation-iteration-count
, чтобы установить количество повторов анимации:
.example { animation-iteration-count: 3; }
Целое значение в данном случае говорит о том, что анимацию нужно повторить 3 раза. Но, возможно, вы не в курсе, что можно устанавливать и дробные значения:
.example { animation-iteration-count: .5; }
В данном случае будет запущена только половина анимации (она остановится на половине первой итерации). Давайте посмотрим на пример, в котором анимируются два шарика. У верхнего шарика счетчик повторов установлен на «1», у нижнего на «0.5».
Что интересно, счетчик повторов не зависит от свойства/значения, которые анимируются. Другими словами, если вы анимируете какие-то 100 пикселей, это не значит, что на половине повтора анимация остановится на 50 пикселях. Предыдущий пример использует тайминг-функцию linear
, что гарантирует остановку второго мячика на половине пути.
Вот еще две анимации, но тут уже используется тайминг-функция ease
: пример. Обратите внимание, что сейчас второй мячик также прошел до остановки половину анимации. Повторю, так получается из-за различных тайминг-функций.
Если вы понимаете тайминг-функции, вы поймете, почему при ease-in-out
мячик остановится в той-же позиции, что и при linear
. Поиграйтесь с различными дробными значениями и тайминг-функциями чтобы увидеть, как это влияет на результат.
9. Animation
может не работать из-за имени анимации
Некоторые разработчики обнаружили это случайно на своем опыте, хотя в спецификации на этот счет есть предупреждение. Предположим, у вас есть следующий код анимации:
@keyframes reverse { from { left: 0; } to { left: 300px; } } .example { animation: reverse 2s 1s; }
Заметьте, для анимации я использую имя reverse
. На первый взгляд код выглядит рабочим, но обратите внимание что произойдет, если мы используем его на живом примере.
Анимация не работает, так как «reverse» — это зарезервированное ключевое слово для свойства animation-direction
. Это произойдет с любой анимацией, имя которой совпадает с зарезервированными ключевыми словами, используемыми в универсальном (кратком) способе записи. При подробной форме записи, с раздельным указанием animation-name
и других параметров, анимация будет работать.
Имена анимации, которые могут сломать краткую форму записи, включают в себя имена тайминг-функций, таких как 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)
. В ночных сборках WebKit такого бага нет, поэтому со временем и в Safari подобная конструкция будет работать нормально.
Этот код использует связку псевдоклассов с выражениями. Хотя выражения могут показаться запутанными, вы можете видеть выделяемый диапазон элементов в числах, использованных в этих выражениях.
Как это работает: В первой части связки выражение говорит «выбрать 7-ой элемент и каждый после него». Во второй части говорится «выбрать 14-ый элемент и каждый до него». Но так как селекторы в связке — каждый ограничивает область выборки другого. Так вторая часть связки не дает первой выбраться за пределы 14-ого элемента, а первая часть не дает второй опуститься в выборке ниже 7-ого элемента.
Для более детального изучения этих типов селекторов и выражений вы можете прочитать мой старый пост на эту тему.
11. Псевдоэлементы могут быть применены к некоторым одиночным тегам
Возможно вы, как и я, в какой-то момент пытались применить псевдоэлементы к изображениям или элементам форм. Этого сделать не получится, потому что псевдоэлементы не работают с заменяемыми элементами. Я думаю, многие разработчики предполагают, что это касается всех одиночных тегов (не имеющих закрывающего тега). Но это не так.
Вы можете применить псевдоэлементы к некоторым одиночным тегам, которые не являются заменяемыми элементами. Это касается и элемента hr
, как видно из этого примера.
Закрашенная область в этом примере — это горизонтальный очерк (элемент hr
), и к нему применены оба псевдоэлемента ::before
и ::after
. Интересно, но мне не удалось получить тот-же результат с br
, хотя он и является незаменяемым однотеговым элементом.
Вы также можете добавить псевдоэлементы к элементам meta
и 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
не чувствительны к регистру. Тут нет никакого открытия, но, возможно, вы не знали об этом.
Народ, пора закругляться
В этот момент опускается занавес, и надеюсь-не-слишком-дрянной сиквел заканчивается.
Чувствуется, что каждую неделю я натыкаюсь на небольшие CSS интересности и изучаю их, и, я надеюсь, что что-то из описанного выше оказалось познавательным для большинства из вас. Какие у вас любимые малоизвестные CSS трюки или техника? Знаете ли вы свойства или возможности CSS, которые вы считаете малоизвестными, но хорошо поддерживаемыми браузерами? Поделитесь ими в комментариях.
ссылка на оригинал статьи http://habrahabr.ru/post/262783/
Добавить комментарий