За последние несколько лет в CSS-технологию введено множество новых функций. Одни позволяют анимировать и преобразовать элементы, другие дают возможность создавать фоновые изображения, эффекты градиентов, масок и фильтров, а третьи позволяют оживлять SVG-элементы.
Все эти возможности будут рассматриваться в следующих нескольких главах. Я думаю, что в первую очередь было бы полезно изучить ряд основ CSS, претерпевших изменения за несколько последних лет: порядок выбора элементов на странице, единицы измерения, доступные для изменения стиля и размеров наших элементов, и способы, благодаря которым существующие (и будущие) псевдоклассы и псевдоэлементы повышают эффективность использования CSS-таблиц. Кроме того, мы рассмотрим способ разветвления в коде CSS, позволяющий задействовать возможности, поддерживаемые в различных браузерах.
В этой главе будут рассмотрены следующие вопросы:
• анатомия правил CSS (что определяет правило, объявления и пары «свойство — значение»);
• простые и полезные CSS-трюки для адаптивных конструкций (использование нескольких столбцов, перенос слов на новые строки, усечение текста с использованием многоточия, создание областей прокрутки);
• предоставление возможности разветвления функций в CSS (способы применения одних правил в одних браузерах, а других правил — в других браузерах);
• способы применения селекторов по соответствующим подстрокам значений атрибутов с целью выбора HTML-элементов;
• что такое селекторы на основе порядковых номеров и как ими пользоваться;
• что такое псевдоклассы и псевдоэлементы (:empty, ::before, ::after, :target, :scope);
• новые селекторы в модуле CSS Level 4 Selectors (:has);
• что такое переменные CSS и пользовательские свойства и как они записываются;
• что такое CSS-функция calc и как ею можно воспользоваться;
• использование единиц измерения, относящихся к окнам просмотра (vh, vw, vmin и vmax);
• как пользоваться шрифтовым веб-оформлением с помощью @font-face;
• режимы цветовых настроек RGB и HSL с альфа-прозрачностью.
Абсолютными знаниями не обладает никто. Я работаю с CSS на протяжении 10 лет и каждую неделю открываю для себя что-то новое (или хорошо забытое старое). Поэтому я не думаю, что стоит гнаться за усвоением каждого возможного сочетания свойств и значений CSS. Разумнее выработать общее представление об имеющихся возможностях.
Исходя из этого, в данной главе я собираюсь сосредоточиться на технологиях, единицах измерения и селекторах, которые, на мой взгляд, наиболее полезны при создании адаптивных веб-конструкций. Надеюсь, после изучения главы вы получите тот объем знаний, который будет необходим для решения большинства проблем, встречающихся на пути разработки адаптивного веб-дизайна.
Перед исследованием всего арсенала средств, предлагаемого CSS3, и во избежание путаницы установим терминологию, которой будем придерживаться для описания правила CSS. Рассмотрим следующий пример:
.round { /* селектор */
border-radius: 10px; /* объявление */
}
Это правило состоит из селектора (.round), после которого следует объявление (border-radius: 10px;). В свою очередь, объявление определяется свойством (border-radius:) и значением (10px;). Наши мнения совпали? Отлично, теперь давайте ускоримся.
Не забудьте проверить наличие поддержки для ваших пользователей
По мере углубления в CSS3 не забудьте посещать сайт /, если, конечно, вам интересно, каков текущий уровень браузерной поддержки конкретной возможности CSS3 или HTML5. Кроме отображения сведений о поддержке различными версиями браузеров (которые можно найти в отношении конкретной возможности), на сайте также приведены текущие статистические данные об уровнях использования браузеров, взятые с сайта /.
Я пришел к выводу, что в своей повседневной работе постоянно использую одни возможности CSS3 и весьма редко применяю другие. Я подумал, что было бы полезно поделиться знаниями о тех возможностях, которые использую наиболее часто. В CSS3 имеется множество полезных вещей, способных облегчить жизнь, особенно тем, кто занимается адаптивным веб-дизайном. С их помощью довольно легко решаются проблемы, которые раньше вызывали головную боль.
Вам когда-нибудь хотелось, чтобы текстовый блок появлялся в нескольких колонках? Эту задачу можно решить, разложив содержимое по разным элементам разметки и задав им соответствующие стилевые настройки. Но внесение изменений в разметку ради достижения определенного стилевого оформления — далеко не идеальное решение. Способ совсем не сложного разнесения одного или нескольких фрагментов содержимого по нескольким колонкам описывается в CSS-спецификации многоколоночной разметки. Рассмотрим следующую разметку:
<main>
<p>lloremipsimLoremipsum dolor sit amet, consectetur
<!-- БОЛЬШОЙ ОБЪЕМ ТЕКСТА -->
</p>
<p>lloremipsimLoremipsum dolor sit amet, consectetur
<!-- БОЛЬШОЙ ОБЪЕМ ТЕКСТА -->
</p>
</main>
Используя CSS-свойство, позволяющее выводить содержимое в нескольких колонках, можно применить несколько способов распределения содержимого по нескольким колонкам. Можно сделать колонки определенной ширины (например, 12 em) или указать, что содержимое должно распределяться по конкретному количеству колонок (например, по трем).
Посмотрим на код, необходимый для выполнения каждого из этих сценариев. Для колонок заданной ширины используется следующий синтаксис:
main {
column-width: 12em;
}
Это будет означать, что независимо от ширины окна просмотра содержимое будет распределяться по колонкам шириной 12 em. При изменении размеров окна просмотра количество выводимых на экран колонок будет динамически изменяться. Можно посмотреть все это в браузере, загрузив в него пример из файла каталога example_05-01 (или из репозитория GitHub — ).
Посмотрим, как эта страница выводится на экран iPad в портретной ориентации (при ширине окна просмотра 768 пикселов).
А теперь посмотрим на нее в браузере Chrome на экране настольного компьютера (с шириной окна просмотра около 1100 пикселов).
Вот вам и простые адаптируемые текстовые колонки, полученные при минимуме усилий. Лично мне это нравится!
Если нужно получить неизменное количество колонок при изменяемой их ширине, можно написать следующее правило:
main {
column-count: 4;
}
Можно пойти еще дальше и добавить определенный промежуток между колонками, а также разделитель колонок:
main {
column-gap: 2em;
column-rule: thin dotted #999;
column-width: 12em;
}
При этом будет получен следующий результат.
Спецификацию, касающуюся модуля CSS3 Multi-Column Layout Module, можно найти по адресу /.
На данный момент, несмотря на объявленный W3C статус CR, при объявлении колонок вам для максимальной совместимости, скорее всего, понадобится указать префиксы производителей.
Единственное предостережение, которое мне хотелось бы дать в отношении применения свойств CSS, задающих использование нескольких колонок, касается того, что при растянутом по колонкам тексте впечатление пользователей от страницы может быть подпорчено, поскольку, возможно, для чтения колонок им придется прокручивать страницу вверх-вниз, а это может стать весьма утомительным занятием.
Сколько раз вы впадали в уныние, когда приходилось вводить длинный URL-адрес, имея для этого весьма узкое поле ввода? Посмотрите на пример, находящийся по адресу rwd.education/code/example_05-04. Проблему можно разглядеть и в следующей копии экрана, заметив, что URL-адрес выходит за пределы выделенного ему пространства.
Данная проблема решается довольно легко путем простого CSS3-объявления, которое, как нарочно, работает точно так же и в устаревших версиях Internet Explorer вплоть до версии 5.5! Просто добавьте:
word-wrap: break-word;
к элементу-контейнеру — и получите эффект, показанный в следующей копии экрана.
Вуаля, теперь длинные URL-адреса отлично переносятся на новую строку!
По укоренившейся традиции усечение текста всегда было прерогативой технологий на серверной стороне. Но сегодня можно произвести усечение текста с добавлением многоточия с помощью только лишь кода CSS. Посмотрим, как это делается.
Рассмотрим следующую разметку (в Интернете этот пример можно найти по адресу rwd.education/code/ch5/example_05-03/):
<p class="truncate">OK, listen up, I've figured out the key eternal
happiness. All you need to do is eat lots of scones.</p>
А нам нужно произвести усечение текста до ширины 520 пикселов, чтобы он имел следующий вид.
Этого эффекта можно добиться с помощью следующего кода CSS:
.truncate {
width: 520px;
overflow: hidden;
text-overflow: ellipsis;
white-space: no-wrap;
}
совет
Спецификацию, касающуюся свойства text-overflow, можно найти по адресу /.
Когда ширина содержимого превышает ширину, заданную в определении (которую можно также задать как 100 %, если содержимое находится в подстраиваемом под экран контейнере), оно будет усечено. Пара «свойство — значение» white-space: no-wrap используется для обеспечения отключения переноса внутри элемента-контейнера.
Надеюсь, вы понимаете, о чем речь? Панели с прокруткой по горизонтали широко представлены в магазине iTunes и в Apple TV и используются как демонстрационные панели соответствующего содержимого (фильмы, альбомы и т. д.). Когда горизонтального пространства вполне хватает, в поле зрения попадают все объекты. Когда пространство ограничено (например, на мобильных устройствах), панель можно прокручивать из стороны в сторону.
Прокручиваемые панели особенно хорошо работают на современных устройствах под управлением Android и iOS. Если у вас есть современное iOS- или Android-устройство, посмотрите следующий пример на нем, а также в браузере настольного компьютера типа Safari или Chrome: rwd.education/code/ch5/example_05-02/.
Я создал панель для лучших фильмов 2014 года, которая имеет на iPhone следующий вид (см. стр. 121).
Сильно стараться мне не пришлось. Ключевым в данной технологии является свойство white-space, которое появилось еще в версии CSS 2.1 (). Но я собираюсь использовать его совместно с новым механизмом разметки Flexbox, ведь вы же не станете мне возражать?
Чтобы проявился эффект, положенный в основу данной технологии, нам нужно иметь окружающее пространство шириной меньше суммарной ширины содержащейся информации, а также настроить ширину по оси X на автоматически выбираемое значение. Тогда прокрутка будет работать только при дефиците пространства:
.Scroll_Wrapper {
width: 100%;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
}
.Item {
display: inline-flex;
}
Используя объявление white-space: nowrap, мы предписываем браузеру не переносить эти элементы на новую строку при обнаружении пробельного символа. Затем, чтобы все оставалось в одной строке, для всех первых дочерних элементов этого контейнера задаем линейное отображение. Здесь мы воспользовались значением inline-flex, но точно так же могли бы применить inline, inline-block или inline-table.
Псевдоэлементы ::before и ::after
Если посмотреть на код, выложенный в качестве образца, можно увидеть, что для отображения номера рекламного плаката применяется псевдоэлемент ::before. При использовании псевдоэлементов следует помнить, что для отображения ::before или ::after у них должно иметься значение содержимого, даже если это просто пробел. Когда эти псевдоэлементы отображаются на экране, они начинают вести себя соответственно как первый и последний дочерние элементы того элемента, в отношении которого применяются.
Чтобы все выглядело немного эстетичнее, я собираюсь скрыть полосу прокрутки там, где это возможно сделать. К сожалению, в силу специфики браузеров код придется дополнять вручную (Autoprefixer с этим не справится, поскольку на эти свойства распространяются права собственности). Я также собираюсь добавить инерционность прокрутки, необходимую для сенсорных устройств с браузерами на движке WebKit (обычно это устройства под управлением iOS). Теперь обновленное правило .Scroll_Wrapper будет иметь следующий вид:
.Scroll_Wrapper {
width: 100%;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
/* Придание инерционности прокрутке на
сенсорных устройствах на базе WebKit */
-webkit-overflow-scrolling: touch;
/* Удаление полос прокрутки в поддерживающих
это свойство версиях IE */
-ms-overflow-style: none;
}
/* Предотвращение появления полосы прокрутки в браузерах с движком WebKit */
.Scroll_Wrapper::-webkit-scrollbar {
display: none;
}
При дефиците пространства мы получаем симпатичную горизонтальную панель без полосы прокрутки. В противном случае на экране помещается сразу все содержимое.
Но в отношении данной модели нужно сделать два предостережения. Во-первых, на момент написания книги в браузере Firefox не было свойства, позволяющего скрывать полосы прокрутки. Во-вторых, старые Android-устройства не способны выполнять горизонтальную прокрутку (так оно и есть). Поэтому я, как правило, дополняю данную модель вспомогательным средством обнаружения возможностей. Как это работает, мы рассмотрим в следующем разделе.
При создании адаптивных веб-конструкций и стремлении получить единую конструкцию, работающую повсеместно на любом устройстве, часто приходится сталкиваться с ситуациями, при которых те или иные функции или технологии не поддерживаются какими-либо устройствами. В таких случаях вам, скорее всего, захочется создать в коде CSS соответствующее разветвление: если браузер поддерживает функцию, предоставить один фрагмент кода, а если не поддерживает — другой. В JavaScript такие ситуации разрешаются с помощью инструкций if-else или switch.
На данный момент имеется два возможных подхода. Один из них полностью основан на применении CSS, но не очень широко поддерживается браузерами, а другой можно воплотить в жизнь только с помощью библиотеки JavaScript, но зато он пользуется значительно более широкой поддержкой браузеров. Рассмотрим их по очереди.
Решением по разветвлению кода в CSS, присущим самой этой технологии, является использование запросов возможностей (feature queries), представляющих собой составную часть условных правил — CSS Conditional Rules Module Level 3 (/). Но на данный момент условные правила CSS не имеют поддержки в Internet Explorer (применительно к версии 11) и Safari (включая устройства под управлением iOS вплоть до версии 8.1), то есть они не пользуются достаточно широкой поддержкой.
Синтаксис у запросов возможностей такой же, как и у медиазапросов. Рассмотрим следующий код:
@supports (flashing-sausages: lincolnshire) {
body {
sausage-sound: sizzling;
sausage-color: slighty-burnt;
background-color: brown;
}
}
В данном случае стили будут применены только в том случае, если браузер поддерживает свойство flashing-sausages. Я абсолютно уверен в том, что ни один браузер никогда не будет поддерживать свойство под названием flashing-sausages, поэтому ни один из стилей внутри блока @supports применяться не будет.
Рассмотрим более практичный пример. Зададим использование Flexbox в случае его поддержки браузером и предусмотрим резервную технологию разметки на случай, если Flexbox не поддерживается. Рассмотрим следующий пример:
@supports (display: flex) {
.Item {
display: inline-flex;
}
}
@supports not (display: flex) {
.Item {
display: inline-block;
}
}
Здесь один блок кода определяется на случай поддержки возможности, а другой блок — на случай отсутствия такой поддержки. Эта модель подойдет в том случае, если браузер поддерживает @supports (я понимаю, что в этом довольно легко запутаться), но если он не обеспечивает такой поддержки, не будет применен ни один из этих стилей.
Если нужно обеспечить работу на устройствах, не поддерживающих @supports, лучше сначала написать исходное объявление и уже после него — то объявление, которое обусловлено запросом @supports, чтобы предыдущее правило отменялось в случае поддержки @supports и блок @supports игнорировался, если его поддержка отсутствует. Поэтому предыдущий пример требует следующей переработки:
.Item {
display: inline-block;
}
@supports (display: flex) {
.Item {
display: inline-flex;
}
}
Условия также можно комбинировать. Предположим, нам нужно применить некоторые правила лишь при одновременной поддержке Flexbox и pointer: coarse (если вы пропустили соответствующий материал, то связанное с взаимодействием со страницей медиасвойство pointer рассматривалось в главе 2). Комбинированное условие может иметь следующий вид:
@supports ((display: flex) and (pointer: coarse)) {
.Item {
display: inline-flex;
}
}
Здесь мы воспользовались ключевым словом and, но можно было использовать также or или заменить одно слово другим. Например, если стили нужно применить при условии поддержки двух предыдущих пар «свойство — значение» или при поддержке 3D-преобразований:
@supports ((display: flex) and (pointer: coarse)) or
(transform:translate3d(0, 0, 0)) {
.Item {
display: inline-flex;
}
}
Обратите в предыдущем примере внимание на дополнительный набор круглых скобок, отделяющих условия для flex и pointer от условия для transform.
К сожалению, как уже говорилось, до широкой поддержки @supports пока еще слишком далеко. А что же тогда делать разработчику адаптивного веб-дизайна? Не впадать в уныние, ведь у нас есть великолепное JavaScript-средство, позволяющее легко преодолеть подобные трудности.
Пока @supports не получит более широкую реализацию в браузерах, мы можем воспользоваться JavaScript-средством под названием Modernizr. На данный момент это самый надежный способ реализации ветвлений в вашем коде.
Когда ветвление требуется в CSS, я стараюсь воспользоваться подходом, предполагающим постепенное усложнение, что означает применение сначала простого и доступного кода, который будет предоставлять на крайний случай функциональный дизайн для устройств с самыми скромными возможностями. Затем этот код постепенно усложняется для устройств с более развитыми возможностями.
совет
Тема постепенного усложнения будет раскрыта в главе 10.
Посмотрим, как можно реализовать постепенное усложнение и ветвление нашего кода CSS с использованием Modernizr.
Обнаружение возможностей с помощью Modernizr. Если вы занимаетесь веб-разработкой, то, скорее всего, уже слышали о Modernizr, даже если и не пользовались этим средством. Оно представляет собой библиотеку JavaScript, включаемую в страницу и тестирующую браузер на наличие определенных возможностей. Чтобы приступить к использованию Modernizr, нужно просто включить ссылку на загруженный файл в раздел заголовка страницы:
<script src="/js/libs/modernizr-2.8.3-custom.min.js"></script>
Этот код при загрузке браузером страницы запускает всевозможные тесты из состава библиотеки. Если браузер проходит тест, Modernizr добавляет соответствующий класс к корневому тегу HTML, что вполне сообразуется с нашими целями.
Например, после того, как Mondernizr выполнит свои задачи, классы в теге HTML могут приобрести следующий вид:
<html class="js no-touch cssanimations csstransforms csstransforms3d
csstransitions svg inlinesvg" lang="en">
В данном случае тестированию подверглись только несколько возможностей: анимация, преобразования, применение SVG, линейной SVG и поддержка сенсорных экранов. При наличии этих классов код может подвергнуться ветвлению:
.widget {
height: 1rem;
}
.touch .widget {
height: 2rem;
}
В предыдущем примере элемент widget в обычных условиях получает высоту 1rem, но если в HTML присутствует класс touch (благодаря работе Modernizr), то widget получит высоту 2rem.
Можно также поменять логику на противоположную:
.widget {
height: 2rem;
}
.no-touch .widget {
height: 1rem;
}
Таким образом, исходной для элементов будет высота 2rem, и она будет уменьшена, если присутствует класс no-touch.
Какая бы структура вам ни понадобилась, Modernizr предоставляет широкую поддержку ветвления при наличии возможностей. Особая польза от применения этого средства проявится при потребности в использовании таких возможностей, как transform3d, с сохранением предоставления работоспособной подмены для тех браузеров, которые не в состоянии справиться с такими возможностями.
совет
Modernizr может предоставить точные тесты практически для всего, что вы можете пожелать использовать в качестве основы для ветвления кода, но есть и исключения. Например, общеизвестны трудности точного тестирования возможности overflow-scrolling. В тех ситуациях, когда класс устройств не может быть успешно определен, вероятно, будет разумнее выполнить ветвление кода на результате тестирования другой возможности. Например, старые версии Android испытывают трудности с горизонтальной прокруткой, а ветвление можно организовать по результатам появления класса no-svg (поскольку Android 2-2.3 не поддерживает и SVG). И наконец, можно объединить тесты для создания собственного пользовательского теста. Эта тема слегка выходит за рамки вопросов, рассматриваемых в книге, но если она вас заинтересует, обратитесь к материалам по адресу /.
В CSS3 имеются очень эффективные средства выбора элементов внутри страницы. Может, это прозвучит для вас слишком оптимистично, но уж поверьте, они смогут облегчить вашу жизнь и заставят полюбить CSS3! И я готов ответить за столь смелое утверждение.
Возможно, вы уже пользовались селекторами атрибутов CSS для создания правил. Рассмотрим, к примеру, следующее правило:
img[alt] {
border: 3px dashed #e15f5f;
}
Оно будет нацелено на каждый использованный в разметке тег изображения, у которого имеется атрибут alt. Или же предположим, что нам нужно выбрать все элементы с атрибутом data-sausage:
[data-sausage] {
/* Стили */
}
Для указания атрибута понадобятся всего лишь квадратные скобки.
совет
Атрибут типа data-* был введен в HTML5 для предоставления места пользовательским данным, которые не могут быть должным образом сохранены с помощью других механизмов. Описание спецификации можно найти по адресу 01019/elements.html.
Можно сузить область выбора, указав значение атрибута. Рассмотрим, к примеру, следующее правило:
img[alt="sausages"] {
/* Стили */
}
Оно будет нацелено только на те изображения, которые имеют атрибут alt со значением sausages, например:
<img class="oscarMain" src="img/sausages.png" alt="sausages" />
До сих пор мы довольствовались тем, что предоставлялось спецификацией CSS2. Интересно, а что же нового появилось с выходом спецификации CSS3?
CSS3 позволяет выбирать элементы на основе подстрок значений их атрибутов. Хотя данная формулировка воспринимается с трудом, но ничего сложного здесь нет! Вариантов соответствия подстроке значения атрибута всего три:
• подстрока находится в начале значения;
• значение содержит экземпляр подстроки;
• значение заканчивается подстрокой.
Посмотрим, как они выглядят.
Рассмотрим следующую разметку:
<img src="img/ace-film.jpg" alt="film-ace">
<img src="img/rubbish-film.jpg" alt="film-rubbish">
Оба указанных в ней изображения можно выбрать по подстроке, находящейся в начале значения их атрибута:
img[alt^="film"] {
/* Стили */
}
Ключевым здесь выступает символ ^ (который называется «карет», также его часто называют колпаком), означающий «начинается с». Поскольку оба атрибута alt начинаются с film, селектор выбирает оба тега img.
Селектор значения атрибута по имеющемуся в нем экземпляру подстроки имеет следующий синтаксис:
[атрибут*="значение"] {
/* Стили */
}
Если нужно, этот селектор, как и все селекторы атрибутов, может использоваться в сочетании с селектором типа (который ссылается на фактически используемый элемент HTML), хотя лично я поступлю таким образом только в случае крайней необходимости (в том случае, если понадобится сменить тип используемого элемента).
Обратимся к примеру и рассмотрим следующую разметку:
<p data-ingredients="scones cream jam">Will I get selected?</p>
Этот элемент можно выбрать следующим образом:
[data-ingredients*="cream"] {
color: red;
}
Ключевым здесь выступает символ *, который в данном контексте означает «содержит».
Селектор «начинается с» с этой разметкой работать не будет, поскольку строка, являющаяся значением атрибута, не начинается с "cream". Но в ней содержится "cream", следовательно, селектор значения атрибута, работающий по принципу «содержит экземпляр», данный элемент обязательно найдет.
Селектор значения атрибута по подстроке, находящейся в его конце, имеет следующий синтаксис:
[атрибут$="значение"] {
/* Стили */
}
Разобраться в нем поможет следующий пример. Рассмотрим его разметку:
<p data-ingredients="scones cream jam">Will I get selected?</p>
<p data-ingredients="toast jam butter">Will I get selected?</p>
<p data-ingredients="jam toast butter">Will I get selected?</p>
Предположим, нам нужно выбрать тот элемент, в значении атрибута data-ingredients которого имеются слова scones, cream и jam (то есть первый элемент). Мы не можем воспользоваться селектором подстроки значения атрибута, работающим по принципу «содержит экземпляр» (он выберет все три варианта) или «начинается с» (он выберет только последний элемент). Но мы можем воспользоваться селектором подстроки значения атрибута, работающим по принципу «заканчивается подстрокой»:
[data-ingredients$="jam"] {
color: red;
}
Ключевым символом здесь является знак доллара ($), означающий «заканчивается подстрокой».
Важно уяснить, что у выбора по атрибутам есть одна особенность: значения атрибутов рассматриваются как цельные строковые значения. Рассмотрим следующее правило CSS:
[data-film^="film"] {
color: red;
}
Как ни странно, этот селектор в отношении следующего значения атрибута не сработает, даже притом что одно из слов внутри атрибута начинается с сочетания film:
<span data-film="awful moulin-rouge film">Moulin Rouge is dreadful</span>
Причина в том, что в данном случае атрибут data-film начинается не с film, а с awful (и если вы видели фильм «Мулен Руж», то знаете, что у него также жуткое начало, так и не переходящее затем в более позитивное русло).
Кроме применения недавно рассмотренных селекторов на совпадение с подстрокой есть еще несколько способов обхода этой проблемы. Можно воспользоваться селектором списка значений, разделенных пробелами (обратите внимание на символ тильды), пользующимся поддержкой даже старых браузеров вплоть до Internet Explorer 7:
[data-film~="film"] {
color: red;
}
Можно выбрать весь атрибут:
[data-film="awful moulin-rouge film"] {
color: red;
}
Или же, если нужно сделать выбор только при наличии в значении атрибута двух строк, можно объединить эту пару (или столько строк, сколько нужно) в селекторах подстрок атрибутов, работающих по принципу «содержит экземпляр»:
[data-film*="awful"][data-film*="moulin-rouge"] {
color: red;
}
Правильного варианта действий на все случаи жизни не существует, все зависит от сложности структуры той строки, на основании которой вы пытаетесь осуществить свой выбор.
До появления HTML5 разметка, в которой идентификаторы и имена классов начинаются с цифр, считалась недопустимой. В HTML5 эти ограничения устранены. Что касается идентификаторов (ID), нужно по-прежнему учитывать некоторые обстоятельства. В идентификаторе не должно быть пробелов, и для страницы он должен быть уникальным. Дополнительные сведения можно найти по адресу .
Теперь, несмотря на то что значения идентификаторов и классов в HTML5 могут начинаться с цифр, спецификация CSS по-прежнему не позволяет использовать селекторы идентификаторов и классов, начинающиеся с цифр ().
К счастью, этот запрет легко обойти, воспользовавшись селектором атрибутов, например [id="10"].
В CSS3 предоставляется более эффективный механизм выбора элементов на основе их местоположения в структуре DOM.
Рассмотрим обработку весьма распространенной конструкции, при которой ведется работа над панелью навигации для более широкого окна просмотра и нам требуется, чтобы в левой стороне экрана были все ссылки, кроме последней.
Согласно сложившейся практике нам понадобилось бы решать эту задачу путем добавления к последней ссылке имени класса, что дало бы возможность выбрать именно эту ссылку:
<nav class="nav-Wrapper">
<a href="/home" class="nav-Link">Home</a>
<a href="/About" class="nav-Link">About</a>
<a href="/Films" class="nav-Link">Films</a>
<a href="/Forum" class="nav-Link">Forum</a>
<a href="/Contact-Us" class="nav-Link nav-LinkLast">Contact Us</a>
</nav>
Но такое решение само по себе может стать проблематичным. Например, иногда весьма трудно даже получить такую систему управления содержимым, которая может добавить класс к последнему элементу списка. К счастью, подобные обстоятельства больше не вызывают опасений. Эту задачу, как и многие другие, теперь можно решить с помощью структурных псевдоклассов CSS3.
В CSS 2.1 уже был селектор, применяющийся для выбора первого элемента списка:
div:first-child {
/* Стили */
}
А в CSS3 добавился селектор, который также может соответствовать последнему элементу:
div:last-child {
/* Стили */
}
Посмотрим, как с помощью этого селектора решается наша предыдущая задача:
@media (min-width: 60rem) {
.nav-Wrapper {
display: flex;
}
.nav-Link:last-child {
margin-left: auto;
}
}
Есть также селекторы для тех случаев, когда имеется только один элемент :only-child и только один элемент заданного типа :only-of-type.
Селекторы nth-child позволяют решать куда более трудные задачи. Давайте с той же разметкой, что и прежде, посмотрим, как селекторы nth-child позволяют выбрать любую ссылку (или ссылки) внутри списка.
Прежде всего посмотрим, как можно выбрать каждый второй элемент списка. Это можно сделать с помощью следующего кода:
.nav-Link:nth-child(odd) {
/* Стили */
}
А так можно выбрать каждый первый элемент:
.nav-Link:nth-child(even) {
/* Стили */
}
Непосвященные могут проявить излишнюю настороженность по отношению к селекторам на nth-основе. Но, как только вы усвоите логику и синтаксис, вы будете удивлены тому, на что они способны. Взглянем на предоставляемые ими возможности.
CSS3 обеспечивает невероятную гибкость, позволяя нам использовать ряд правил на nth-основе:
• nth-child(n);
• nth-last-child(n);
• nth-of-type(n);
• nth-last-of-type(n).
Мы уже видели, как в выражениях на nth-основе можно использовать значения (odd) или (even), а вот параметр (n) может использоваться следующими двумя способами:
• в виде целого числа, например :nth-child(2), что приведет к выбору второго элемента;
• в виде числового выражения, например :nth-child(3n+1), благодаря чему выбор начнется с первого элемента и продолжится выбором каждого третьего элемента.
Разобраться со свойством на основе целого числа нетрудно, нужно просто ввести номер того элемента, который следует выбрать.
Версия селектора с числовым выражением может немного озадачить неискушенных в ее использовании. Если у вас с математикой проблем нет, то я извиняюсь за следующий раздел, а всем остальным советую как следует изучить его.
Разбираемся с математикой. Рассмотрим десять линейных блоков span на странице (посмотреть их в работе можно, запустив пример из файла каталога example_05-05):
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
Изначально им будет задан следующий стиль:
span {
height: 2rem;
width: 2rem;
background-color: blue;
display: inline-block;
}
Нетрудно представить, что в результате мы получим выстроенные в линию десять квадратов.
А теперь посмотрим, как можно выбрать различные элементы с помощью селекции на nth-основе.
Из соображений практичности при разборе выражения в скобках я начну с правого края. К примеру, если я хочу определить, что будет выбрано с помощью выражения (2n + 3), то начинаю с крайнего справа числа (число 3 указывает на третий элемент слева) и знаю, что наряду с ним, начиная с его позиции, будет выбран каждый второй элемент. Поэтому добавление правила:
span:nth-child(2n+3) {
color: #f90;
border-radius: 50%;
}
даст на экране браузера следующий результат.
Как видите, наш nth-селектор нацелен на третий элемент списка, а также на каждый последующий второй элемент после него (если бы в списке было 100 элементов, то продолжался бы выбор каждого второго из них).
А как выбрать каждый последующий элемент, начиная со второго? Хотя можно воспользоваться кодом :nth-child(1n+2), первая цифра вообще-то не нужна, поскольку, если не утверждается ничто иное, переменная n равна единице. Поэтому можно просто написать :nth-child(n+2). По аналогии с этим, если нам нужно выбрать каждый третий элемент, вместо записи :nth-child(3n+3) можно просто указать :nth-child(3n), поскольку каждый третий элемент все равно будет начинаться с третьего элемента и нет необходимости указывать именно на него. В выражении могут применяться также отрицательные числа. Например, при использовании выражения :nth-child(3n-2) выбор начинается с -2, а затем выбирается каждый третий элемент.
Можно также изменить направление. По умолчанию, как только найдена первая часть заданного выбора, последующие части ищутся вниз по элементам в DOM-дереве (и поэтому выбор в нашем примере идет слева направо). Но направление можно изменить на обратное, поставив минус, например:
span:nth-child(-2n+3) {
background-color: #f90;
border-radius: 50%;
}
В этом примере также ищется третий элемент, но затем поиск идет в обратном направлении с целью выбора каждого второго элемента (вверх по DOM-дереву, поэтому в нашем примере — справа налево).
Надеюсь, теперь-то вы усвоили логику выражений на nth-основе?
Разница между nth-child и nth-last-child заключается в том, что вариант nth-last-child работает в противоход распространению дерева документа. Например, :nth-last-child(-n+3) начинает выбор с 3 с конца, а затем выбирает все элементы после него. Результат применения данного правила будет иметь на экране браузера следующий вид.
И в заключение рассмотрим селекторы :nth-of-type и :nth-last-of-type. В предыдущих примерах вычисление шло в отношении всех дочерних элементов независимо от их типа (следует твердо усвоить, что селектор nth-child нацеливается на все дочерние элементы одного и того же DOM-уровня независимо от их классов), а вот селекторы :nth-of-type и :nth-last-of-type позволяют указывать тип подлежащих выбору элементов. Рассмотрим следующую разметку (файл с которой можно найти в каталоге example_05-06):
<span class="span-class"></span>
<span class="span-class"></span>
<span class="span-class"></span>
<span class="span-class"></span>
<span class="span-class"></span>
<div class="span-class"></div>
<div class="span-class"></div>
<div class="span-class"></div>
<div class="span-class"></div>
<div class="span-class"></div>
Если воспользоваться следующим селектором:
.span-class:nth-of-type(-2n+3) {
background-color: #f90;
border-radius: 50%;
}
то независимо от наличия у всех элементов одного и того же класса span-class нацеливание произойдет только на span-элементы (поскольку они относятся к выбираемому типу). В результате будут выбраны следующие элементы.
Вскоре мы увидим, как эта же задача решается с помощью селекторов из спецификации CSS4.
Счетчики в CSS3 работают не так, как в JavaScript и jQuery!
Если вы привыкли пользоваться JavaScript и jQuery, то должны быть в курсе, что подсчет там ведется с нуля и выше (используется индексация, начинающаяся с нуля). Например, при выборе элемента в JavaScript или jQuery целочисленное значение 1 будет фактически указывать на второй по счету элемент. Но в CSS3 счет начинается с 1, поэтому значение 1 соответствует первому элементу.
Просто для того, чтобы завершить этот небольшой раздел, хочу проиллюстрировать реальную проблему адаптивного веб-дизайна и способ применения выбора на nth-основе для ее решения.
Помните горизонтальную прокручиваемую панель, файлы для создания которой можно найти в каталоге example_05-02? Посмотрим, как это может выглядеть в той ситуации, при которой осуществить горизонтальную прокрутку невозможно. Используя ту же разметку, поместим верхнюю десятку самых кассовых фильмов 2014 года в решетку grid-системы. Для некоторых окон просмотра решетка будет шириной всего в два элемента, по мере увеличения окна просмотра будут показаны три элемента, при еще более крупных размерах — четыре элемента. Но при этом возникает проблема. Независимо от размера окна просмотра нам бы не хотелось, чтобы у самой нижней строки элементов имелась нижняя граница. Файл с соответствующим кодом можно найти в каталоге example_05-09.
Результат при ширине четыре элемента можно увидеть на следующей странице.
Видите эту совершенно ненужную границу ниже последних двух элементов? Именно ее и следует удалить. Но мне нужно получить надежное решение, чтобы граница удалялась и при другом составе элементов последней строки. Теперь, поскольку при различных окнах просмотра в каждой строке содержится разное количество элементов, нам также нужно для разных окон просмотра изменить выбор на nth-основе. Для краткости я покажу вам выбор, соответствующий четырем элементам в строке (для самого большого из окон просмотра). Чтобы увидеть измененный выбор при различных окнах просмотра, можете просмотреть образец кода:
@media (min-width: 55rem) {
.Item {
width: 25%;
}
/* Получить каждый четвертый элемент, а из них
взять только тот, который находится в составе
последних четырех элементов */
.Item:nth-child(4n+1):nth-last-child(-n+4),
/* Теперь получить каждый элемент, следующий
за той же самой коллекцией. */
.Item:nth-child(4n+1):nth-last-child(-n+4) ~ .Item {
border-bottom: 0;
}
}
примечание
Как видите, здесь выстроена цепочка из селекторов псевдоклассов на nth-основе. Важно понимать, что предыдущие селекторы не фильтруют выбор для следующих, а элемент должен соответствовать каждому из выборов. Для предыдущего примера первым должен быть элемент из четырех, он должен быть также одним из четырех последних.
Отлично! Благодаря выбору на nth-основе у нас получился стойкий набор правил для удаления самой нижней границы независимо от размера окна просмотра или количества показываемых на экране элементов.
Еще одним полезным селектором является селектор псевдокласса отрицания. Он пригодится для выбора всего, что не подпадает под какой-либо другой выбор. Рассмотрим следующий код:
<div class="a-div"></div>
<div class="a-div"></div>
<div class="a-div"></div>
<div class="a-div not-me"></div>
<div class="a-div"></div>
И вот эти стили:
div {
display: inline-block;
height: 2rem;
width: 2rem;
background-color: blue;
}
.a-div:not(.not-me) {
background-color: orange;
border-radius: 50%;
}
Последнее правило предписывает каждому элементу, имеющему класс .a-div, быть оранжевого цвета и иметь скругление, за исключением div-контейнера, у которого также имеется класс .not-me. Файл с этим кодом находится в каталоге example_05-07 образцов кода (напоминаю, что все образцы можно взять на сайте /).
совет
До сих пор мы рассматривали в основном то, что называется структурными псевдоклассами (вся информация о них доступна по адресу /). Но в CSS3 имеется гораздо больше селекторов. При работе над веб-приложением стоит просмотреть полный перечень элементов пользовательского интерфейса, относящихся к псевдоклассам (/), поскольку они могут, к примеру, нацеливать правила на основе того, выбраны некоторые элементы или нет.
Мне приходилось сталкиваться с ситуациями, когда элемент, включающий внутренние отступы, получает динамически вставляемое в него содержимое. Иногда он получает содержимое, а иногда — нет. Проблема в том, что, даже когда он не включает содержимое, я все равно вижу отступ. Рассмотрим код HTML и код CSS, которые находятся в файле каталога example_05-08:
<div class="thing"></div>
.thing {
padding: 1rem;
background-color: violet;
}
При отсутствии в этом div-контейнере содержимого все равно виден его фоновый цвет, задаваемый свойством background-color. К счастью, его нетрудно спрятать:
.thing:empty {
display: none;
}
Но все же селектор :empty нужно применять с оглядкой. Например, можно подумать, что данный контейнер пуст:
<div class="thing"> </div>
Но ведь это не так! Обратите внимание на пробел в контейнере. Пробельный символ не означает пустоту!
И чтобы не запутаться, следует знать, что комментарий не влияет на наличие или отсутствие пробельного символа в элементе. Например, этот элемент-контейнер все равно будет считаться пустым:
<div class="thing"><!--I'm empty, honest I am--></div>
Дополнение к псевдоэлементам
Псевдоэлементы используются со времен появления CSS2, но в спецификации CSS3 синтаксис их использования был слегка пересмотрен. Чтобы освежить вашу память, скажу, что до сих пор p:first-line указывал на первую строку тега <p> или p:first-letter указывал на первую букву. А CSS3 требует отделять эти псевдоэлементы от псевдоклассов, таких как nth-child(). Поэтому теперь нужно использовать запись p::first-letter. Но следует заметить, что Internet Explorer 8 и предыдущие версии не понимают синтаксис с двойным двоеточием, они понимают только синтаксис с одним двоеточием.
Одно из качеств псевдоэлемента :first-line, которое может вам особенно пригодиться, заключается в его работе с учетом специфики окна просмотра. Например, если написать следующее правило:
p::first-line {
color: #ff0cff;
}
то, как и ожидалось, первая строка будет выведена на экран в ужасном розовом оттенке. Но при другом размере окна просмотра в ней будет выведена другая подборка текста.
Следовательно, при реализации адаптивного дизайна вам предоставляется удобный способ визуального отображения первой строки в стиле, отличающемся от стиля других строк, без необходимости внесения изменений в разметку (браузер выведет ее на экран, не считаясь с тем, как она обозначена в разметке).
Благодаря популярности препроцессоров CSS-таблиц эти таблицы стали приобретать все больше функций, присущих программированию. Первыми из таких функций стали пользовательские свойства. Нам они больше известны как переменные, хотя это не является их обязательным и единственным предназначением. Полную спецификацию можно найти по адресу /. Но имейте в виду, что на начало 2015 года реализация этой функции в браузерах была весьма скудной — ограничивалась браузером Firefox.
Пользовательские свойства CSS позволяют хранить в таблицах стилей информацию, которая затем может использоваться в таблице стилей или, возможно, оказывать влияние на сценарий JavaScript. Очевидным вариантом использования будет хранение имени семейства шрифтов с последующей ссылкой на него:
:root {
--MainFont: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
Здесь с целью хранения пользовательского свойства в корне документа используется псевдокласс :root (хотя эти свойства можно хранить в любом выбранном вами правиле).
совет
В структуре документа псевдокласс :root всегда ссылается на самый верхний родительский элемент. В HTML-документе им всегда будет тег HTML, но в SVG-документе, который рассматривается в главе 7, он будет ссылаться на другой элемент.
Пользовательское свойство всегда начинается с двух дефисов, за которыми следует выбранное пользователем имя, а его окончание обозначается, как и любое другое свойство в CSS, точкой с запятой.
Сослаться на значение этого свойства можно с помощью записи var():
.Title {
font-family: var(--MainFont);
}
Очевидно, таким образом вы можете хранить любое количество пользовательских свойств. Основным преимуществом такого хранения является возможность изменения значения внутри переменной, и каждое использующее эту переменную правило получает новое значение без его непосредственного изменения.
Предусматривается, что в будущем эти свойства смогут проходить синтаксический анализ и использоваться кодом JavaScript. Более подробную информацию о такого рода невероятных вещах можно найти в описании нового модуля CSS Extensions: /.
Сколько раз приходилось создавать код разметки и думать о чем-нибудь вроде следующего: «Нужно от половины ширины родительского элемента отнять точно 10 пикселов». Возможность выполнять подобные вычисления особенно пригодилась бы при разработке адаптивного веб-дизайна, поскольку нам никогда заранее не известен размер экрана, на котором будут просматриваться наши веб-страницы. К счастью, в CSS теперь есть способ решения этой задачи. Он называется функцией calc(). Рассмотрим пример CSS-кода:
.thing {
width: calc(50% - 10px);
}
В этой функции поддерживаются сложение, вычитание, деление и умножение, что позволяет решить множество проблем, которые ранее решались только с применением JavaScript.
Эта функция пользуется весьма неплохой поддержкой со стороны браузеров, но заметным исключением являются Android 4.3 и более ранние версии. Соответствующую спецификацию можно найти по адресу /.
В спецификации CSS Selectors Level 4, последней доступной версией которой была редакторская правка от 14 декабря 2014 года (/), имелось несколько новых типов селекторов. Но пока шла работа над книгой, их реализация в браузерах так и не появилась. Поэтому мы рассмотрим только один пример, поскольку спецификация еще может претерпеть всяческие изменения. Им будет селектор реляционного псевдокласса (Relational Pseudo-Class) из раздела «Логические комбинации» (/) самой последней правки.
Этот селектор имеет следующий формат:
a:has(figcaption) {
padding: 1rem;
}
Он предписывает добавление отступа к любому элементу a-тега, содержащему figcaption. Выбор можно инвертировать, если задать его в сочетании с псевдоклассом отрицания:
a:not(:has(figcaption)) {
padding: 1rem;
}
Отступ будет добавлен в том случае, если элемент a-тега не будет содержать figcaption.
Буду честен и скажу: в данной правке не так уж много новых селекторов, которые произвели на меня впечатление. Но кто знает, как все обернется к тому моменту, когда они станут пригодны к использованию в браузерах.
Давайте сменим направление. Мы рассматривали тему выбора элементов в нашем адаптивном мире. А как насчет задания их размеров? В CSS Values and Units Module Level 3 (/) вводятся единицы измерения, выражаемые относительно размеров окна просмотра. Для адаптивного веб-дизайна это очень полезное нововведение, поскольку каждая единица измерения представляет собой процентное отношение к длине окна просмотра:
• vw — для ширины окна просмотра;
• vh — для высоты окна просмотра;
• vmin — для минимального размера окна просмотра, равна самому малому значению — либо vw, либо vh;
• vmax — для максимального размера окна просмотра, равна самому большому значению — либо vw, либо vh.
Все эти меры длины пользуются неплохой поддержкой браузеров (/).
Хотите окно, высота которого задается как 90 % от высоты окна браузера? Проще некуда:
.modal {
height: 90vh;
}
При всей пользе, ожидаемой от использования единиц измерения относительно окон просмотра, в некоторых браузерах их применение реализовано довольно странно. К примеру, в Safari под управлением iOS 8 при изменении просматриваемой области в ходе прокрутки с верхней части страницы адресная строка сжимается, но никакие изменения в декларируемую высоту окна просмотра не вносятся.
Но, наверное, более полезно применять эти единицы измерения в сочетании с шрифтовыми настройками. Например, создать текст, масштабирующийся в зависимости от размеров окна просмотра, не так-то просто.
Я могу показать вам решение этой задачи прямо сейчас. Но мне хотелось бы использовать вполне определенный шрифт, чтобы независимо от того, в какой системе просматривается пример, Windows, Mac или Linux, мы видели одно и то же.
Хорошо, сознаюсь вам, что это будет простой трюк, позволяющий мне проиллюстрировать возможности использования веб-шрифтов с помощью CSS3.
Многие годы в веб-приложениях приходилось довольствоваться скучным выбором «безопасных» шрифтов. Когда для дизайна были важны какие-то особые шрифты, приходилось подставлять графический элемент, а для смещения текста от границ окна просмотра применять правило отступа text-indent. Это была та еще работенка!
Но кроме этого, для добавления на страницу особого типографского оформления имелось несколько оригинальных методов. В sIFR (/) и Cufуn (/) для переделки текстовых элементов с целью их появления в виде шрифтов, для которых они предназначались, использовались технологии Flash и JavaScript соответственно. К счастью, в CSS3 предоставляются средства пользовательского шрифтового оформления, уже готовые к завоеванию широкой популярности.
CSS-правило @font-face появилось еще в CSS2 (но затем из CSS 2.1 оно было удалено). Оно даже пользовалось частичной поддержкой Internet Explorer 4 (кроме шуток!). А как обстоят дела, когда речь заходит о CSS3?
Как выясняется, правило @font-face было снова введено для модуля шрифтов CSS3 Fonts Module (). Из-за исторически сложившейся правовой тяжбы, касающейся использования шрифтов в веб-приложениях, серьезные подвижки в фактическом признании данного решения для шрифтового оформления начались только в последние годы.
Как обычно, когда в веб-мире речь идет о привлечении каких-либо ресурсов, единого формата файлов не существует. Точно так же, как изображения могут приходить в JPG, PNG, GIF и других форматах, у шрифтов имеется собственный набор форматов на выбор. Для Internet Explorer (и больше никакого другого браузера) в качестве наиболее предпочтительных были выбраны шрифты формата Embedded OpenType с расширениями имен файлов .eot. Для других браузеров предпочтение отдавалось более распространенным шрифтам формата TrueType с расширениями имен файлов .ttf. В то же время существуют шрифты форматов SVG-графики и Web Open Font Format с расширениями имен файлов .woff или .woff2.
Сейчас, чтобы охватить различные браузерные реализации, необходимо обслуживать несколько файловых версий одного и того же шрифта.
Но есть и хорошая новость: добавление каждого пользовательского шрифта для любого браузера не составляет особого труда. Посмотрим, как это делается!
CSS предоставляет так называемое эт-правило (по названию символа @ — «эт») @font-face, позволяющее ссылаться на онлайн-шрифты, которые затем можно будет использовать для отображения текста.
Существует большое количество великолепных источников, позволяющих просматривать и получать веб-шрифты, среди которых как бесплатные, так и платные. Что касается источников бесплатных шрифтов, то я отдаю предпочтение Font Squirrel (/), хотя Google также предоставляет бесплатные веб-шрифты, которые в конечном счете подаются с помощью правила @font-face (). Существуют также отличные платные сервисы от Typekit (/) и Font Deck (/).
Для данного упражнения я собираюсь загрузить Roboto. Это шрифт, используемый последними Android-телефонами, и если у вас имеется такой телефон, он должен быть вам знаком. В противном случае все, что вам нужно знать о нем, сводится к тому, что это весьма привлекательный шрифт интерфейса, разработанный для обеспечения высокой разборчивости на небольших экранах. Вы сами можете его получить по адресу .
примечание
Если есть возможность загрузить поднабор своего шрифта, применяемый для языка, который вы собираетесь использовать, именно так и нужно сделать. Это означает, что в результате будет получен файл, намного меньший по размеру, чем тот файл, в котором содержатся образы символов для языков, которые вы не собираетесь использовать.
После загрузки набора @font-face загляните в ZIP-файл, где обнаружатся папки различных шрифтов Roboto. Я выбираю версию Roboto Regular. Внутри этой папки шрифт присутствует в различных файловых форматах (WOFF, TTF, EOT и SVG), вдобавок там имеется файл stylesheet.css, содержащий стек шрифтов. Например, правило для Roboto Regular имеет следующий вид:
@font-face {
font-family: 'robotoregular';
src: url('Roboto-Regular-webfont.eot');
src: url('Roboto-Regular-webfont.eot?#iefix') format('embedded-opentype'),
url('Roboto-Regular-webfont.woff') format('woff'),
url('Roboto-Regular-webfont.ttf') format('truetype'),
url('Roboto-Regular-webfont.svg#robotoregular')
format('svg');
font-weight: normal;
font-style: normal;
}
Во многом по такому же принципу, как и при работе с префиксами производителей, браузер будет применять стили из этого перечня свойств (начиная с имеющего приоритет самого нижнего свойства, если оно применимо), игнорируя те из них, которые ему непонятны. Поэтому, какой бы браузер ни применялся, использоваться будет тот шрифт, которым он сможет воспользоваться.
Теперь, несмотря на то что этот блок кода вполне достоин копирования и вставки, важно обратить внимание на пути, по которым можно найти сохраненные шрифты. Например, я склонен копировать шрифты из ZIP-файла и сохранять их в папке с незатейливым названием fonts, находящейся на том же уровне, что и моя папка css. Следовательно, поскольку я обычно копирую это правило со стеком шрифтов в свою основную таблицу стилей, мне нужно изменить пути. И тогда правило приобретет следующий вид:
@font-face {
font-family: 'robotoregular';
src: url('../fonts/Roboto-Regular-webfont.eot');
src: url('../fonts/Roboto-Regular-webfont.eot?#iefix')
format('embedded-opentype'),
url('../fonts/Roboto-Regular-webfont.woff') format('woff'),
url('../fonts/Roboto-Regular-webfont.ttf')
format('truetype'),
url('../fonts/Roboto-Regular-webfont.svg#robotoregular')
format('svg');
font-weight: normal;
font-style: normal;
}
Затем наступает время установки для соответствующего правила стилевого оформления нужного шрифта и его плотности (если необходимо). Посмотрите на файл примера из каталога example_05-10 — там такая же разметка, как и в файле примера из каталога example_05-09, мы просто объявляем это семейство шрифтов в качестве исходного:
body {
font-family: robotoregular;
}
Дополнительное преимущество веб-шрифтов проявляется в том, что, если в комплексе используются те же шрифты, что и в вашем коде, вы можете подключить размеры непосредственно из файла комплекса. Например, если в Photoshop размер шрифта составляет 24 пиксела, мы либо подключаем это значение в неизменном виде, либо переводим его в более гибкую единицу измерения, такую как rem (при условии, что размер основного шрифта составляет 16 пикселов, 24 / 16 = 1,5 rem).
Но, как упоминалось ранее, теперь в нашем распоряжении есть размеры, задаваемые относительно размеров окна просмотра. Здесь ими можно воспользоваться для масштабирования текста относительно размеров окна просмотра:
body {
font-family: robotoregular;
font-size: 2.1vw;
}
@media (min-width: 45rem) {
html,
body {
max-width: 50.75rem;
font-size: 1.8vw;
}
}
@media (min-width: 55rem) {
html,
body {
max-width: 78.75rem;
font-size: 1.7vw;
}
}
Если открыть этот пример в браузере и изменить размеры окна просмотра, можно увидеть, что благодаря всего лишь нескольким строкам кода CSS мы получили текст, масштабируемый под доступное пространство. Великолепно!
В целом метод шрифтового оформления веб-приложений @font-face представляется весьма эффективным средством. Единственное предостережение, касающееся использования этой технологии с адаптивными конструкциями, относится к размеру файла шрифта. Если устройство, на экран которого выводится наш пример, требует для шрифта Roboto Regular формата SVG, то по сравнению с применением стандартных веб-безопасных шрифтов, например Arial, необходимо извлечь дополнительные 34 Кбайт данных. Нами в примере использовался английский поднабор символов, что сократило размер файла, но такая возможность предоставляется далеко не всегда. Если нужно добиться от сайта наивысшей производительности, следует контролировать размеры пользовательских шрифтов и разумно подходить к их использованию.
До сих пор в данной главе рассматривались вопросы предоставляемых CSS3 новых эффективных возможностей выбора элементов и добавления к нашим конструкциям пользовательского шрифтового оформления. Теперь будут рассмотрены обеспечиваемые CSS3 способы работы с цветом, которые раньше были просто недоступны.
Прежде всего, CSS3 предоставляет два новых способа объявления цвета: RGB и HSL. Кроме того, эти два формата позволяют нам использовать вместе с ними альфа-канал (соответственно RGBA и HSLA).
Красный, зеленый и синий — Red, Green и Blue (RGB) — это система задания цвета, которая существует уже не одно десятилетие. Она работает путем определения значений для красного, зеленого и синего компонентов цвета. Например, красный цвет может быть определен в CSS в виде шестнадцатеричного значения (HEX-значения) #fe0208:
.redness {
color: #fe0208;
}
совет
Если хотите получить описание способа более интуитивно понятного восприятия значений, выраженных шестнадцатеричными числами, я могу порекомендовать следующую статью в Smashing Magazine: /.
Но с помощью CSS3 этот цвет может быть указан также в виде RGB-значения:
.redness {
color: rgb(254, 2, 8);
}
Большинство приложений редактирования изображений показывают цвета на панели их выбора в виде как HEX-, так и RGB-значений. У панели выбора цвета программы Photoshop имеются R-, G- и B-области, показывающие значения для каждого из этих каналов. Например, значение R может выражаться числом 254, G — числом 2, а B — числом 8. Все это весьма просто преобразуется в значение цвета для CSS. В CSS после определения режима задания цвета (например, RGB) значения для красного, зеленого и синего цветов отделяются друг от друга запятыми и записываются внутри скобок именно в таком порядке, как показано в предыдущем примере кода.
Кроме формата RGB, CSS3 позволяет использовать для объявления цвета значения в формате «тон, насыщенность и яркость» — Hue, Saturation и Lightness (HSL).
Не нужно путать HSL и HSB!
Не следует ошибочно полагать, что значение в формате Hue, Saturation и Brightness (HSB), показанное на панели выбора цвета в таких приложениях редактирования изображений, как Photoshop, — это то же самое, что и HSL. Это не так!
Востребованность формата HSL объясняется относительной простотой понимания того, какой именно цвет будет представлен при заданных им значениях. Например, если вы не обладаете какими-то сверхспособностями по подбору цвета, держу пари, что вам не удастся с ходу сказать, какой это цвет: rgb(255, 51, 204). Есть желающие? Только не я. А вот покажите мне HSL-значение hsl(315, 100%, 60%), и я могу высказать догадку, что это где-то между пурпурным и красным цветом (хотя это ярко выраженный розовый цвет). Как я догадался? Да очень просто.
HSL-формат основан на цветовом диске в 360°. Вот как он выглядит.
Первая цифра в цветовом определении формата HSL представляет собой тон — Hue. Глядя на диск, можно понять, что желтый (Yellow) находится на отметке 60°, зеленый (Green) — 120°, светло-голубой (Cyan) — 180°, синий (Blue) — 240°, малиновый (Magenta) — 300° и, наконец, красный (Red) — 360°. Следовательно, если вышеупомянутый цвет в формате HSL имеет тон 315, нетрудно понять, что он будет располагаться между малиновым (Magenta), который находится на отметке 300°, и красным (Red), находящимся на отметке 360°.
Следующие два значения в HSL-определении задают насыщенность и яркость и указываются в процентах. Ими просто задается изменение базовой насыщенности. Для более насыщенного, красочного вида во втором значении указывается более высокий процент. Последнее значение управляет яркостью (Lightness) и может варьироваться от 0 для чистого черного цвета до 100 % для абсолютно белого цвета.
Следовательно, если цвет определен в виде HSL-значений, проще будет создать и его вариации, изменяя процентные показатели насыщенности и яркости. Например, красный цвет может быть определен в HSL-значениях следующим образом:
.redness {
color: hsl(359, 99%, 50%);
}
Если нужен чуть более темный цвет, можно воспользоваться теми же HSL-значениями, изменив всего лишь процентный показатель яркости (последнее из значений):
.darker-red {
color: hsl(359, 99%, 40%);
}
В заключение, если вы в состоянии запомнить для цветового диска HSL мнемоническое правило Young Guys Can Be Messy Rascals (или любое другое удобное для вас выражение), то сможете приблизительно задать значение цвета в формате HSL, для чего не придется обращаться к панели выбора цвета, а кроме этого, задать еще и его оттенок. Покажите этот трюк на корпоративной вечеринке в обществе парней и девушек из компании разработчиков на Ruby, Node или .NET и сможете быстро набрать очки, повысив свой престиж!
До сих пор мне приходилось терпеть ваше едва сдерживаемое удивление по поводу того, к чему вся эта возня вокруг HSL или RGB и почему нужно отдавать им предпочтение над старым, годами проверенным форматом с использованием HEX-значений. Основное отличие HSL и RGB от HEX заключается в том, что эти два формата позволяют использовать канал альфа-прозрачности. Это дает возможность видеть то, что находится под верхним элементом.
Объявление цвета в формате HSLA похоже по синтаксису на стандартное HSL-правило. Но дополнительно нужно указать значение как hsla, а не просто как hsl и добавить показатель прозрачности, задаваемый между 0 (полная прозрачность) и 1 (полная непрозрачность), например:
.redness-alpha {
color: hsla(359, 99%, 50%, .5);
}
Синтаксис RGBA следует тому же соглашению, что и его HSLA-эквивалент:
.redness-alpha-rgba {
color: rgba(255, 255, 255, 0.8);
}
А почему бы просто не воспользоваться свойством opacity?
В CSS3 элементам также позволяется иметь установку непрозрачности, задаваемую объявлением свойства opacity. Значение устанавливается между 0 и 1 с десятичным шагом (например, непрозрачность, установленная в .1, означает 10 %). Но данное свойство отличается от RGBA и HSLA тем, что с его помощью устанавливается непрозрачность для всего элемента. А установка значения для HSLA или RGBA позволяет иметь уровень альфа-прозрачности конкретной части элемента. Например, у элемента может быть HSLA-значение для фона, а для текста внутри него задан сплошной цвет.
Несмотря на то что эта функциональная возможность находится на весьма ранних стадиях спецификации, возможно, в скором будущем вы сможете получить удовольствие от работы над цветовым оформлением в CSS с помощью функции color(). А пока для нее не появится широкая браузерная поддержка, с подобными манипуляциями неплохо справляются пре- и постпроцессоры CSS (сделайте себе приятное и купите прямо сейчас книгу по этой теме, я рекомендую остановить выбор на Sass and Compass for Designers Бена Фрэйна).
Проследить за ходом разработки спецификации CSS Color Module Level 4 можно по адресу /.
В данной главе были изучены способы, позволяющие легко выбирать практически все, что нам нужно на странице, с помощью новых селекторов CSS3. Были также рассмотрены способы создания за рекордно короткие сроки адаптивных колонок и прокручиваемых панелей с содержимым, а также решения часто возникающих и весьма неприятных проблем с не помещающимися в области ввода длинными URL-адресами путем организации их многострочного вывода. Кроме того, теперь мы получили представление о новом цветовом модуле CSS3 и о том, как применять цвета с RGB и HSL, дополненные прозрачными альфа-слоями, для получения интересных эстетических эффектов.
В данной главе также был рассмотрен вопрос добавления к веб-конструкциям шрифтового оформления с помощью правила @font-face, которое наконец-то освободило нас от оков рутинного выбора веб-безопасных шрифтов. Несмотря на все эти впечатляющие новые возможности и технологии, мы из всего, что можно будет сделать с CSS3, коснулись лишь того, что лежит на поверхности. Продолжим наш путь и расширим круг изучаемых способов, позволяющих CSS3 максимально ускорить работу, повысить эффективность и возможности сопровождения адаптивной конструкции с помощью имеющихся в CSS3 текстовых и блочных теней, градиентов и возможностей применения многочисленных фонов.