В будущем CSS есть много того, чего нам стоит ожидать с нетерпением: с одной стороны, там будет целый спектр новых методов, которые произведут революцию в вёрстке; с другой стороны — новый набор графических эффектов, которые позволят создавать на лету фильтры и шейдеры. Людям всё это страшно нравится, в журналах и блогах пишется огромное количество статей об этих нововведениях.
Но если эти инструменты можно назвать выставочными лошадками CSS, тогда, думается мне, стоит обратить немного внимания и на рабочих лошадей: на те компоненты языка, которые являются его составными частями: селекторы, единицы измерения, функции. Я частенько называю их «скучными мелочами» — хотя на самом деле я это говорю с большой теплотой, и вам стоит, мне кажется, разделить моё доброе к ним отношение.
Почему? Давайте пробежимся по парочке лучших нововведений в CSS из разряда скучных мелочей — тех мелочей, над которыми работали в плохо освещенных лабораториях, вдали от блеска новых глянцевых штучек на витринах. Некоторые из этих мелочей уже какое-то время с нами, но заслуживают того, чтобы больше людей о них знали; другие, напротив, только начинают появляться в браузерах. Но тем не менее они произведут революцию в том, как мы работаем — причем тихо, скромно и без претензий.
Относительные единицы измерения Скопировать ссылку
Скорее всего, вы, умный и предусмотрительный веб-разработчик, работаете с относительными единицами измерения — то есть с em
или процентами — так что эта проблема вам должна быть знакома: вам наверняка приходится сидеть за калькулятором, чтобы вычислить размеры — из-за наследования. Например, сейчас вполне обычный прием — установить базовый размер шрифта для документа, а потом использовать относительные единицы, чтобы установить размер шрифта для всех остальных элементов на странице. В CSS это выглядит примерно так:
html { font-size: 10px; }
p { font-size: 1.4em; }
Здесь всё отлично, и никакой проблемы нет, пока у вас не появляется дочерний элемент, которому вы хотите установить какой-нибудь другой размер шрифта. Например, в такой разметке:
А и Б сидели на <span>трубе</span>.
Если вы хотите, чтобы этот <span>
было меньшего размера шрифта, например, 1.2em
, то что вам делать? Берите калькулятор и считайте, сколько будет 1,2 поделить на 1,4, и в итоге у вас получится:
p span { font-size: 0.85714em; }
И проблема не ограничивается использованием em
. Если вы разрабатываете тянущийся сайт с использованием ширин в процентах, то знаете, что эти проценты соотносятся с размерами контейнера элемента, так что если у вас есть элемент, которому вы хотите поставить ширину в 40% от его родительского элемента, ширина которого — 75%, тогда придется устанавливать ширину этого элемента в 53,33333%.
Мягко говоря, не идеально.
Размеры относительно корневого элемента Скопировать ссылку
Чтобы побороть эту проблему с размерами шрифтов, теперь нам доступна новая единица измерения — rem
(корневой em
). Это всё ещё относительная единица измерения, но она всегда соотносится с фиксированным базовым значением, а именно — с размером шрифта корневого элемента документа (в случае HTML это всегда элемент <html>
). Если предположить, что мы используем тот же самый размер шрифта для корневого элемента, что и в прошлый раз (10px
), то нам потребуются для этого случая следующие CSS-правила:
p { font-size: 1.4rem; }
p span { font-size: 1.2rem; }
Теперь оба правила соотносятся с размером шрифта корневого элемента — это куда более элегантно, да и работать с этим удобнее, особенно если у вас простое базовое значение, например, 10px
или 12px
. Это как если вернуться назад и использовать значения в пикселях, только с возможностью их масштабировать.
Это одна из функций, перечисленных в этой статье, которая поддерживается браузерами очень хорошо: все современные браузеры, включая IE9, поддерживают эту единицу, нет её пока только в Opera Mobile.
Размеры относительно вьюпорта Скопировать ссылку
Если вам кажется, что единица rem
— крутая (а я так думаю!), то вы будете в восторге от того, что узнаете, что существует ещё и новый набор единиц измерения, который поможет победить проблему с процентами. Эти единицы работают примерно так же, как rem
, за исключением того, что они соотносятся не с установленным пользователем значением на корневом элементе документа, а с самим вьюпортом, или областью просмотра устройства.
Две базовых единицы здесь — vh
и vw
; они соотносятся (соответственно) с высотой и шириной вьюпорта. Каждая единица является числом, и это число равняется соответствующему проценту от указанного измерения (ширины или высоты). Пока я ещё помню уроки в школе сценаристов, давайте я лучше не буду объяснять, а покажу:
div { height: 50vh; }
В этом примере высота блока будет равна точно половине высоты вьюпорта; 1vh
— это 1% от высоты вьюпорта, так что равенство 50vh
= 50% от этой высоты выглядит вполне логичным.
Если размер окна просмотра изменяется, то изменяется и значение соответствующих единиц, и при этом вам не нужно беспокоиться о вложенных элементах: элемент с шириной 10vw
всегда будет этой ширины, вне зависимости от ширины его родительского элемента.
Также есть единица vmin
, которая соответствует меньшему значению — vh
или vw
; кроме того, недавно стало известно, что в спецификацию добавится и соответствующая единица vmax
(хотя на момент написания статьи этого пока не случилось).
Сейчас эти единицы поддерживаются в IE9+, Chrome и Safari 6.
Рассчитываемые значения Скопировать ссылку
Если вы будете работать с тянущимся или адаптивным дизайном, вы, без сомнения, столкнетесь с проблемой смешивания единиц измерения — когда вы хотите, чтобы у вас на странице была сетка, ширина у которой задается в процентах, но при этом с фиксированными полями. Например:
div {
margin: 0 20px;
width: 33%;
}
Если в вашей верстке указаны только padding
и border
, тогда, в принципе, можно решить проблему с помощью box-sizing
, но с margin
это не поможет. Есть лучший и более гибкий подход — использовать для значения функцию calc()
, которая позволяет вам производить математические действия с разными единицами, скажем:
div {
margin: 0 20px;
width: calc(33% - 40px);
}
Вы можете применяться её где угодно, не только для ширин, но и везде, где вам нужны единицы изменения. А если вы хотите зайти совсем далеко, то вы тоже можете даже использовать calc()
внутри calc()
.
В IE9+ эта функция поддерживается без префикса(!), в Firefox — с префиксом -moz-
(в релизе 16 или 17 он должен быть отброшен), а в Chrome и Safari — с префиксом -webkit-
. В мобильный WebKit он, увы, пока не включен.
Загрузка подмножества символов Скопировать ссылку
Быстрая загрузка веб-страниц всегда была важна — но сейчас, с появлением на рынке широкого спектра мобильных устройств (с каждым из которых понятие «скорость соединения» становится всё более изменчивым и неопределенным) это, пожалуй, особенно важно. Один из способов ускорить загрузку страницы — сократить размер внешних подгружаемых файлов, и поэтому новое свойство внутри @font-face
, которое позволяет делать именно это — весьма полезное добавление.
Свойство, о котором идет речь — unicode-range
, и в качестве значения оно принимает набор ссылок на юникод-символы. При загрузке внешних ресурсов из файла шрифта будут загружаться только эти символы, а не все символы, присутствующие в шрифте. Приведенный код показывает, как загрузить только три символа из файла foo.ttf:
@font-face {
font-family: foo;
src: url('foo.ttf');
unicode-range: U+31-33;
}
Особенно это полезно в том случае, если вы используете иконки внутри шрифта и хотите показывать на конкретной странице не все из них, а только конкретные. В одном тесте, который я провел, использование unicode-range
сократило общее время загрузки файла шрифта в среднем на 0,85 секунды — а это вполне существенно. Конечно, у вас могут получиться и другие цифры.
Это свойство на данный момент поддерживается в IE9+ и браузерах на движке WebKit: Chrome и Safari.
Новые псевдоклассы Скопировать ссылку
Единицы измерения и значения — это всё прекрасно, но особенно меня радуют селекторы и псевдоклассы. Когда у меня получается выдумать замысловатый селектор, даже если он в итоге будет запрятан там, где только немногие избранные смогут его найти, я всегда чувствую себя мастером своего дела. Перефразируя отца Стива Джобса: ты должен сделать так, чтобы забор со стороны твоего дома выглядел так же хорошо, как со стороны улицы, даже если больше никто не будет знать, что это так — ведь ты будешь.
Для меня стало откровением, когда я впервые использовал :nth-of-type()
, это было словно я вышиб ногой двери восприятия… Окей, я чуть-чуть преувеличиваю. Но есть несколько новых CSS-псевдоклассов, относительно которых действительно стоит испытывать энтузиазм.
Псевдокласс отрицания Скопировать ссылку
Вы наверняка не поймете, насколько в действительности полезен новый (относительно) псевдокласс отрицания :not()
, пока сами его не попробуете. В качестве аргумента :not()
передается простой, а не составной селектор. Когда список элементов создается селектором, включающим :not()
, все элементы, которые соответствуют аргументу, исключаются из этого списка. Знаю, звучит сложно, мне тоже так кажется. Но на самом деле всё довольно просто.
Представьте себе: у вас есть список, и вы хотите применить правило ко всем нечётным элементам в списке, но не к последнему. Вам придётся написать что-то вроде такого:
li { color: #00f; }
li:nth-child(odd) { color: #f00; }
li:last-child { color: #00f; }
С псевдоклассом отрицания вы можете исключить последний элемент из списка, используя в качестве аргумента :last-child
. Таким образом количество правил уменьшится, и с кодом станет легче работать:
li { color: #00F; }
li:nth-child(odd):not(:last-child) { color: #F00; }
Ничего принципиально нового здесь нет, и, как я показал, вполне можно работать и без него, но — это довольно-таки полезно. У меня была возможность применить этот псевдокласс в проекте, где использовался встроенный WebKit, и я раз за разом убеждался в его пользе. Честно, это один из моих любимых псевдоклассов.
Всё верно, у меня есть любимые псевдоклассы.
Из всех функций, рассмотренных в этой статье, это самая широко поддерживаемая; её поддерживают IE9+ и все современные браузеры — без префикса. Если вы работаете с jQuery, вполне возможно, что вы уже привыкли использовать этот синтаксис — в jQuery он есть начиная с версии 1.0, как и метод not()
, который делает то же самое.
Псевдокласс соответствия Скопировать ссылку
Псевдокласс соответствия :matches()
принимает в качестве аргумента простой селектор, составной селектор, список, разделенный запятой, или любую комбинацию этих пунктов. Отлично! Но что же он делает?
Лучше всего он подходит для того, чтобы срезать лишнее с повторяющихся селекторов. В качестве сценария использования представьте себе, что у вас есть несколько элементов <p>
в разных контейнерах, но вы хотите выбрать только некоторые из них; тогда правило в стилях будет выглядеть примерно так:
.home header p,
.home footer p,
.home aside p {
color: #f00;
}
С селектором :matches()
вы можете значительно сократить его, найдя сходство в селекторах; в нашем примере у нас везде в начале стоит .home
, а конце — p
, так что мы можем использовать :matches()
для того чтобы собрать все элементы между ними. Непонятно? Это выглядит вот так:
.home :matches(header,footer,aside) p { color: #f00; }
В действительности это уже часть CSS4 (если быть совсем точными, спецификации CSS-селекторов уровня 4), и ещё в этой спецификации сказано, что вы сможете использовать такой же синтаксис — составные селекторы, разделенные запятой — в будущих версиях :not()
. Здорово-то как!
На сегодняшний день :matches()
есть в Chrome и Safari с префиксом -webkit-
, а в Firefox он проходит под своим старым названием, :any()
, с префиксом -moz-
.
Ну как, уже полюбили рабочих лошадок? Скопировать ссылку
Самое лучшее во всех этих новых возможностях — они решают совершенно реальные проблемы, от маленького, но раздражающего повторения селекторов до новых и появляющихся в настоящее время сложных задач, связанных с разработкой высокопроизводительных адаптивных сайтов. На самом деле, я могу легко представить, что регулярно использую каждое из этих нововведений.
Может быть, про новые возможности вроде фильтров больше пишут, но вы с гораздо большей вероятностью обнаружите, что именно те мелочи, которые представлены в этой статье, будут вам полезны в разработке.
Каждая из них сделает вашу профессиональную жизнь немножко проще, и в то же время расширит пространство ваших возможностей — а в этом ничего скучного, поверьте, нет.