Книга: HTML5 и CSS3. Разработка сайтов для любых браузеров и устройств. 2-е изд.
Назад: 7. Использование SVG для достижения независимости от разрешения
Дальше: 9. Обуздание форм с помощью HTML5 и CSS3

8. Переходы, преобразования и анимация

Исторически сложилось так, что перемещение элементов по экрану или применение к ним эффектов анимации было исключительной прерогативой JavaScript. Сегодня с основной частью задач по перемещению может справиться код CSS с использованием для этого трех своих основных агентов: CSS-переходов (transitions), CSS-преобразований (transforms) и CSS-анимации (animations). Фактически к перемещению имеют непосредственное отношение только переходы и анимация, а преобразование просто позволяет изменять элементы, но, как мы вскоре увидим, оно часто встраивается и в весьма впечатляющие эффекты перемещений.

Чтобы четко разобраться в том, за что отвечает каждая из этих трех составля­ющих, хочу предложить, возможно, несколько упрощенное описание.

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

• CSS-преобразование используется, когда нужно обеспечить визуальное преобразование элемента, не оказывая при этом никакого влияния на разметку страницы.

• CSS-анимация используется, когда нужно применить к элементу серию изменений с различными ключевыми точками, определяемыми по времени.

Итак, мы уловили смысл и получили представление о том, как всем этим можно воспользоваться, а теперь узнаем, что в этой главе будут рассматриваться следующие вопросы:

что такое CSS3-переходы и как ими можно воспользоваться;

• как создать код CSS3-перехода и что собой представляет его сокращенный синтаксис;

• что такое функции развития процесса CSS3-перехода во времени (ease, cubic-bezier и т. д.);

• как можно развлечься с переходами на адаптивных сайтах;

• что такое CSS3-преобразования и как ими можно воспользоваться;

• что представляют собой различные 2D-преобразования (scale, rotate, skew, translate и т. д.);

• что такое 3D-преобразования;

как средствами CSS3 осуществлять анимацию, используя keyframes.

Что такое CSS3-переходы и как ими можно воспользоваться

Переходы между двумя состояниями являются простейшим способом создания с помощью CSS визуального эффекта. Рассмотрим простой пример перехода элемента из одного состояния в другое при прохождении над ним указателя мыши.

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

Традиционно при использовании одного лишь кода CSS с помощью состояний, связанных с нахождением указателя мыши над элементом, CSS-правила могут только включаться или выключаться. У элемента есть один исходный набор свойств и значений, и когда указатель проходит над элементом, свойства и значения тут же изменяются. Но CSS3-переходы, как следует из их названия, позволяют обеспечивать переход от одних или нескольких свойств и значений к другим свойствам и значениям.

Sovet.tif совет

Сначала нужно предупредить вас о двух весьма важных обстоятельствах. Во-первых, переход от состояния display: none; невозможен. Если для элемента установлено свойство display: none;, то его прорисовка на экране отсутствует, следовательно, отсутствует и реальное состояние, с которого можно было бы осуществить переход. Чтобы создать процесс постепенного появления элемента, нужно задавать переход в отношении непрозрачности или позиции элемента. Во-вторых, не все свойства подвергаются переходам. Чтобы убедиться в том, что вы не пытаетесь добиться невозможного, обратитесь к перечню доступных для переходов свойств, который можно найти по адресу /.

Если открыть файл из каталога example_08-01, то в нем, в контейнере nav, можно увидеть несколько ссылок. Разметка имеет следующий вид:

<nav>

    <a href="#">link1</a>

    <a href="#">link2</a>

    <a href="#">link3</a>

    <a href="#">link4</a>

    <a href="#">link5</a>

</nav>

А вот соответствующий ей код CSS:

a {

    font-family: sans-serif;

    color: #fff;

    text-indent: 1rem;

    background-color: #ccc;

    display: inline-flex;

    flex: 1 1 20%;

    align-self: stretch;

    align-items: center;

    text-decoration: none;

    transition: box-shadow 1s;

}

 

a + a {

    border-left: 1px solid #aaa;

}

 

a:hover {

    box-shadow: inset 0 -3px 0 #CC3232;

}

И два состояния: первое, исходное.

08_01.tif 

И второе, при наведении указателя мыши.

08_02.tif 

В данном примере при наведении указателя на элемент к нижней границе этого элемента добавляется красная блочная тень (мой выбор пал на блочную тень, поскольку она не влияет на разметку ссылки, как это может случиться при использовании границы элемента). Обычно проведение указателя мыши над ссылкой переводит ее из первого состояния (без красной линии) во второе (с красной линией) по принципу включения-выключения. Но вот эта строка:

transition: box-shadow 1s;

добавит к блочной тени переход от обычного состояния к состоянию наведения указателя за одну секунду.

Sovet.tif совет

В предыдущем примере кода CSS можно заметить использование селектора примыкающего одноуровневого элемента +. Это означает, что заключенные в него стили будут применены в том случае, если за одним выбранным тегом (в нашем случае это <a>) тут же следует другой выбранный тег (еще один тег <a>). Здесь этот селектор применяется из тех соображений, что левая граница у первого элемента нам не нужна.

Учтите, что свойство перехода применяется в CSS к исходному состоянию элемента, а не к тому состоянию, в котором он в конечном итоге окажется. Короче говоря, объявление перехода применяется не к конечному, а к начальному состоянию. Это объясняется тем, что различные состояния, такие как :active, также могут иметь различные стилевые установки и подвергаться такому же переходу.

Свойства перехода

При объявлении перехода можно воспользоваться четырьмя свойствами:

transition-property — название CSS-свойства, подвергаемого переходу (например, background-color, text-shadow или название любого другого доступного для применения переходов свойства);

• transition-duration — время, за которое должен произойти переход (определенное в секундах, например .3s, 2s или 1.5s);

• transition-timing-function — порядок изменения скорости в процессе перехода (например, ease, linear, ease-in, ease-out, ease-in-out или cubic-bezier);

• transition-delay — дополнительное значение для указания задержки до начала перехода. Как вариант, может использоваться отрицательное значение для немедленного начала перехода, но уже с того момента, до которого переход дошел бы за указанное время. Определяется в секундах, например .3s, 1s или 2.5s.

Используемые по отдельности различные свойства могут быть задействованы для создания следующего перехода:

.style {

    /*...(дополнительные стилевые настройки)...*/

    transition-property: all;

    transition-duration: 1s;

    transition-timing-function: ease;

    transition-delay: 0s;

}

Краткая форма записи перехода с помощью свойства transition

Показанные ранее отдельные объявления можно свести в одну краткую форму:

transition: all 1s ease 0s;

Но при этом следует сделать одно важное замечание: при записи краткой версии первое значение, связанное со временем, всегда применяется для свойства transition-duration. Второе значение, также связанное со временем, относится к свойству transition-delay. Я склоняюсь к использованию именно сокращенной формы, поскольку обычно мне нужно лишь определить продолжительность перехода и те свойства, к которым он должен быть применен.

Конечно, это мелочь, но постарайтесь указывать только то свойство или свойства, к которым действительно нужно применить переход. Безусловно, удобно установить значение all, имея в виду все свойства, но если переход нужен применительно лишь к непрозрачности, то свойству transition нужно указать только opacity. В противном случае браузер будет перегружен ненужной работой. В большинстве случаев это не создаст проблем, но если питать надежды на получение от сайта наивысшей производительности, особенно на не самых новых устройствах, то тут пригодится любая мелочь.

Sovet.tif совет

Переходы пользуются весьма широкой поддержкой, но, как всегда, не поленитесь установить такое средство, как Autoprefixer, чтобы добавить префиксы производителей, нужные браузерам, от которых требуется поддержка вашего сайта. Можно также зайти на сайт caniuse.com и проверить, какие возможности какими браузерами поддерживаются.

Короче говоря, переходы и 2D-преобразования работают практически везде, кроме IE9 и более ранних версий, 3D-преобразования работают везде, кроме IE9 и более ранних версий, Android 2.3 и более ранних версий и Safari 3.2 и более ранних версий.

Переходы различных свойств за разные периоды времени

Когда в правиле содержатся несколько объявленных свойств, то не обязательно реализовывать переходы их всех за одно и то же время. Рассмотрим следующее правило:

.style {

    /* ...( дополнительные стилевые настройки)... */

    transition-property: border, color, text-shadow;

    transition-duration: 2s, 3s, 8s;

}

Здесь с помощью объявления transition-property указаны свойства, подвергаемые переходу: border, color и text-shadow. А затем с помощью объявления transition-duration указано, что свойство border будет подвергнуто переходу за две секунды, color — за три секунды, а text-shadow — за восемь секунд. Указания продолжительностей переходов, разделенные запятыми, соответствуют порядку указания подвергаемых переходу свойств, при перечислении которых в качестве разделителей также применялись запятые.

Основные сведения о функциях развития процесса по времени

Понять при объявлении перехода, что такое свойства, продолжительность и задержка, нетрудно. Но вот понять, что делает каждая функция развития процесса по времени, намного труднее. Чем же занимаются ease, linear, ease-in, ease-out, ease-in-out и cubic-bezier? Каждая из них фактически является предопределенной кривой Безье третьего порядка (cubic-bezier curve) и, по сути, аналогична функции плавности. Или, проще говоря, является математическим описанием того, как должен выглядеть процесс перехода. Нагляднее будет показать эти кривые, поэтому я рекомендую вам заглянуть по адресам / и /.

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

08_03.tif 

Но даже если вы способны записать собственную кривую Безье вслепую, скорее всего, на практике в большинстве ситуаций это мало что изменит. Причина, как и в случае со многими другими улучшениями, заключается в том, что при применении эффектов переходов следует проявлять определенную сдержанность. При реальной работе переходы, длящиеся слишком долго, создают впечатление заторможенности сайта. К примеру, навигационные ссылки с переходами по пять секунд способны скорее навредить работе, чем впечатлить ваших пользователей. Ощущение скорости играет весьма важную роль для наших пользователей, поэтому и вы и я должны сконцентрироваться на создании сайтов и приложений, скорость работы которых ощущается как можно более высокой.

Поэтому, если для иного нет веских причин, зачастую наилучшим выбором будет использование исходного развития процесса перехода (ease) за короткий промежуток времени, который, на мой взгляд, не должен быть более одной секунды.

Развлечение с переходами  на адаптивных сайтах

Бывало ли у вас в детстве такое, что один из родителей куда-то уезжал на целый день, а другой, чтобы завоевать ваше расположение, говорил что-нибудь вроде: «Пока мамы (папы) нет дома, мы будем сыпать сахар во все сухие завтраки, но ты должен пообещать, что не скажешь об этом, когда она (он) вернется»? Каюсь, я тоже проделывал нечто подобное со своими малышами. В этом-то все и дело: когда никто не видит, можно немного порезвиться. Я не собираюсь советовать внедрение этого в серьезные приложения, но попробуйте следующий код в своем проекте по разработке адаптивного веб-приложения:

* {

    transition: all 1s;

}

Здесь используется универсальный CSS-селектор *, предназначенный для выбора абсолютно всего, а затем устанавливается переход всех свойств за одну секунду (1s). Поскольку функция развития процесса по времени не указана, то по умолчанию станет использоваться ease, а задержки не будет, так как если дополнительно ее значение не указано, то по умолчанию принимается значение 0. Каков будет эффект? А вы попробуйте изменить размер окна вашего браузера, и большинство того, что в нем находится (ссылки, состояния прохода указателя мыши и т. п.), будет вести себя вполне предсказуемо. Но, поскольку под переходы подпадает абсолютно все, сюда включаются и любые правила внутри медиазапросов, поэтому при изменении размеров окна элементы некоторым образом переходят из одного состояния в другое. Важно ли это? Конечно, нет! Забавно наблюдать за этим и развлекаться? Конечно, да! А теперь уберите это правило, пока мама не увидела!

CSS3 2D-преобразования

Несмотря на схожесть названий, CSS-преобразования (transforms) не имеют ничего общего с CSS-переходами (transitions). Их нужно рассматривать в следующем ключе: переходы сглаживают изменения, происходящие при перетекании одного состояния в другое, а преобразования определяют, во что элемент превратится. Лично я запоминаю разницу абсолютно по-детски: представляю себе робот-трансформер, например, Optimus Prime. Когда он превращается в грузовик, это пре­образование. Но фаза между роботом и грузовиком является переходом (он переходит из одного состояния в другое).

Разумеется, если вам невдомек, кто или что такое Optimus Prime, можете мысленно отбросить несколько последних предложений. Надеюсь, вскоре все станет ясно и понятно.

Доступны две группы CSS3-преобразований: 2D и 3D. 2D-варианты реализованы намного шире, браузеры в них неплохо разбираются, и их, конечно же, легче записывать, поэтому с них и начнем. Модуль CSS3 2D Transforms позволяет воспользоваться следующими преобразованиями:

scale — используется для масштабирования элемента (его увеличения или уменьшения);

• translate — перемещает элемент по экрану (вверх, вниз, влево и вправо);

• rotate — вращает элемент на определенную величину, указанную в градусах;

• skew — используется для наклона элемента по его координатам x и y;

matrix — позволяет выполнять перемещения и придавать форму преобразованиям с точностью до пиксела.

Sovet.tif совет

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

Попробуем применить различные 2D-преобразования, которые можно посмотреть в действии, открыв в браузере файл каталога example_08-02. Здесь, чтобы вы могли лучше разобраться со всем, что происходит, ко всем преобразованиям применяются переходы.

Масштабирование (scale)

Для масштабирования, scale, используется следующий синтаксис:

.scale:hover {

    transform: scale(1.4);

}

Проход указателя мыши над ссылкой, имеющей класс scale, произведет следующий эффект.

08_04.tif 

Браузеру указывается, что нам нужно, чтобы при наведении на элемент указателя мыши этот элемент увеличивался в 1,4 раза от исходного размера.

Кроме тех значений, которые уже использовались для увеличения элементов, использование значений меньше единицы приведет к сжатию элементов. Следу­ющий код приведет к сжатию элемента до половины его размера:

transform: scale(0.5);

Перемещение (translate)

Для перемещения, translate, используется следующий синтаксис:

.translate:hover {

    transform: translate(-20px, -20px);

}

В нашем примере это правило приведет к следующему эффекту.

08_05.tif 

Свойство translate указывает браузеру на необходимость перемещения элемента на расстояние, определяемое либо в пикселах, либо в процентах. Первое значение относится к перемещению по оси X, второе — по оси Y. Положительные значения, заданные в скобках, приводят к перемещению элемента вправо и вниз, а отрицательные соответственно влево и вверх.

Если передается только одно значение, то оно применяется к оси X. Если нужно указать для перемещения элемента значение только для одной оси, можно также воспользоваться объявлениями translateX или translateY.

Использование перемещения для центрирования элементов с абсолютным позиционированием. Перемещение обеспечивает весьма полезный способ центрирования элементов с абсолютным позиционированием внутри контейнера с относительным позиционированием. Пример кода можно найти в файле каталога example_08-03.

Рассмотрим разметку:

<div class="outer">

    <div class="inner"></div>

</div>

И этот код CSS:

.outer {

    position: relative;

    height: 400px;

    background-color: #f90;

}

 

.inner {

    position: absolute;

    height: 200px;

    width: 200px;

    margin-top: -100px;

    margin-left: -100px;

    top: 50%;

    left: 50%;

}

Возможно, вам самим приходилось делать нечто подобное. Когда известны размеры элемента с абсолютным позиционированием (в данном случае это 200 × 200 пикселов), для «подталкивания» элемента обратно в центр можно воспользоваться отступами с отрицательными значениями. А как быть, если вам понадобится включить содержимое и будет совершенно непонятно, насколько высоким оно окажется? На помощь придет перемещение.

Добавим к внутреннему блоку какое-нибудь произвольное содержимое.

08_06.tif 

Очевидно, у нас возникла проблема! Хорошо, разберемся с этим беспорядком с помощью перемещения:

.inner {

    position: absolute;

    width: 200px;

    background-color: #999;

    top: 50%;

    left: 50%;

    transform: translate(-50%, -50%);

}

И вот результат.

Здесь top и left позиционируют внутренний блок внутри его контейнера таким образом, что вначале левый верхний угол внутреннего блока находится в точке 50 % длины и 50 % высоты внешнего контейнера. Объявление transform работает в отношении внутреннего элемента и позиционирует его в обратную сторону по этим осям на половину (-50%) его собственной ширины и высоты. Превосходно!

08_07.tif 

Вращение (rotate)

Преобразование rotate позволяет вращать элемент. Для него используется следующий синтаксис:

.rotate:hover {

    transform: rotate(30deg);

}

А в окне браузера произойдет следующее.

08_08.tif 

Значение в скобках всегда задается в градусах (например, 90deg). Положительные значения задают вращение по часовой стрелке, а отрицательные — против часовой стрелки. Можно также сойти с ума и задать элементу вращение, указав следующее значение:

transform: rotate(3600deg);

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

Наклон (skew)

Если вам приходилось работать в программе Photoshop, то чем занимается наклон, вы уже представляете. Он позволяет наклонить элемент по какой-либо из его осей или по двум осям сразу. Вот код нашего примера:

.skew:hover {

    transform: skew(40deg, 12deg);

}

Установка этого правила для ссылки с псевдоклассом hover приведет при наведении указателя мыши на элемент к следующему эффекту.

08_09.tif 

Первое значение задает наклон применительно к оси X (в нашем примере это 40deg), а второе значение (12deg) предназначено для задания наклона по оси Y. Если опустить второе значение, то единственное имеющееся значение будет просто применено к оси X (горизонтальной оси), например:

transform: skew(10deg);

Матрица (matrix)

Кто-нибудь вспомнил одноименный и весьма переоцененный фильм? Нет? Что, простите? Вам хочется узнать о CSS3-матрице, а не о фильме? Ну что ж, хорошо.

Я не собираюсь вас обманывать. Думаю, что синтаксис матричного преобразования выглядит несколько страшновато. Рассмотрим пример кода:

.matrix:hover {

    transform: matrix(1.678, -0.256, 1.522, 2.333, -51.533, -1.989);

}

По сути, матрица позволяет объединять в одно объявление сразу несколько видов преобразований (масштабирование, вращение, наклон и т. д.). Предыдущее объявление реализуется в окне браузера в эффект, показанный на следующей странице.

Теперь мне нравятся сложные задачи, но я уверен, что нельзя не согласиться с тем, что этот синтаксис требует исследований. Лично я расстроился, глядя на спецификацию и понимая, что математические знания, требующиеся для полного осмысления, выходят за рамки моего рудиментарного уровня: /.

08_10.tif 

Sovet.tif совет

Если вам удается работать с анимацией в JavaScript, не прибегая к помощи анимационных библиотек, то, наверное, стоит поближе познакомиться и с матрицей. В ее синтаксисе вычисляются все остальные преобразования, поэтому, если вам удается осмысливать текущие представления о создании анимации с помощью JavaScript, нужно проверить на деле, сможете ли вы так же легко разобраться со значениями матрицы.

Матричные преобразования для ловкачей и остолопов. Представить меня математиком можно только с очень большой натяжкой, поэтому, сталкиваясь с необходимостью создания преобразований на основе матрицы, я немного жульничаю. Если ваши математические навыки также оставляют желать лучшего, рекомендую обратиться по адресу /.

Сайт Matrix Construction Set позволяет перетаскивать элемент, придавая ему в точности тот вид, который вас устраивает, после чего по старой доброй традиции забирать код с уже включенными в него префиксами производителей для вставки в свой файл CSS.

Свойство transform-origin

Обратите внимание на то, что при использовании CSS исходная точка пре­образования, которую браузер использует в качестве центра, находится посередине — в 50 % протяженности элемента по оси X и в 50 % его протяженности по оси Y. Здесь прослеживаются существенные отличия от SVG-технологии, в которой такая точка по умолчанию находится в левом верхнем углу с координатами (0; 0).

Используя свойство transform-origin, можно изменить точку, в которой будет начинаться преобразование.

Рассмотрим наше прежнее матричное преобразование. По умолчанию точка начала преобразования transform-origin устанавливается в позицию '50% 50%' (в центре элемента). Средства разработчика Firefox показывают, как это преобразование применяется.

08_11.tif 

Теперь, если перенастроить значение transform-origin таким образом:

.matrix:hover {

    transform: matrix(1.678, -0.256, 1.522, 2.333, -51.533, -1.989);

    transform-origin: 270px 20px;

}

то можно увидеть следующий эффект.

08_12.tif 

Первое значение задает смещение по горизонтали, а второе — по вертикали. Можно использовать ключевые слова. Например, left задает 0 % по горизонтали, right — 100 % по горизонтали, top — 0 % по вертикали и bottom — 100 % по вертикали. Вместо этого можно воспользоваться длиной, задавая для нее любые единицы измерения, используемые в CSS.

Если для значений свойства transform-origin используются проценты, то горизонтальное и вертикальное смещение задаются относительно высоты и ширины контейнера, содержащего элементы.

Если используется длина, то значения отмеряются от левого верхнего угла контейнера, содержащего элементы.

Полная информация о свойстве transform-origin может быть найдена на сайте /.

Мы рассмотрели основы 2D-преобразований. Они намного более широко реализованы, чем их 3D-собратья, и предоставляют более эффективные средства для перемещения элементов по экрану, чем прежние методы, например абсолютное позиционирование.

Полная спецификация CSS3 2D Transforms Module Level 3 находится по адресу /.

Sovet.tif СОВЕТ

Более полно преимущества перемещения элементов с помощью преобразований рассмотрены в замечательной статье Пола Айриша (Paul Irish) (/), в которой представлен ряд весьма ценных данных.

А в качестве просто фантастического обзора того, как браузеры справляются с переходами и анимацией, и объяснения, почему преобразования могут быть столь эффектными, я настоятельно рекомендую следующую публикацию в блоге: /.

CSS3 3D-преобразования

Рассмотрим наш первый пример — элемент, который переворачивается, когда на него наводится указатель мыши. Состояние наведения указателя используется здесь для инициирования изменения просто в целях иллюстрации, но переворот может быть легко вызван изменением класса (через код JavaScript) или получением элементом фокуса.

У нас будет два таких элемента: один с горизонтальным переворотом, другой — с вертикальным. Полный пример можно найти в файле каталога example_08-04. Изображения не могут обеспечить полное восприятие сути этой технологии, для этого лучше подойдет переворот элемента со сменой лицевой стороны с зеленой на красную с полной иллюзией того, что это происходит в трехмерном пространстве с привлечением перспективы. Посмотрите на копию экрана, сделанную на промежуточной фазе перехода от зеленого к красному, которая, надеюсь, в какой-то мере передает суть эффекта.

08_13.tif 

Sovet.tif совет

Следует также иметь в виду, что при абсолютном позиционировании элемента с заданием значений top, left, bottom, right в пикселах промежуточные значения преобразований могут вычисляться по субпиксельным позициям.

Разметка для элемента, подвергаемого перевороту, имеет следующий вид:

<div class="flipper">

    <span class="flipper-object flipper-vertical">

        <span class="panel front">The Front</span>

        <span class="panel back">The Back</span>

    </span>

</div>

Единственным отличием в разметке горизонтального переворота является использование вместо класса flipper-vertical класса flipper-horizontal.

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

Прежде всего нам нужно задать объекту с классом .flipper, внутри которого будет осуществляться переворот, определенную перспективу. Воспользуемся для этого свойством perspective. Ему задается длина, предназначенная для имитации расстояния от экрана просмотра до края 3D-пространства элементов.

Если для перспективы задать небольшое значение, например 20 пикселов, 3D-пространство элемента будет простираться только на эти 20 пикселов от плоскости экрана и в результате получится слишком явно выраженный 3D-эффект. А чересчур большое значение будет означать, что край воображаемого 3D-пространства находится намного дальше, и получится менее выраженный 3D-эффект:

.flipper {

    perspective: 400px;

    position: relative;

}

Внешний элемент имеет относительное позиционирование, которое предназначено для того, чтобы создать содержимое для flipper-object, позиционируемое внутри него:

.flipper-object {

    position: absolute;

    transition: transform 1s;

    transform-style: preserve-3d;

}

Кроме абсолютного позиционирования .flipper-object в левом верхнем углу его ближайшего родительского элемента с относительным позиционированием (что является позицией по умолчанию для абсолютно позиционированных элементов), у нас имеется установка перехода для преобразования. В данном случае ключевым объявлением, касающимся 3D-эффекта, является transform-style: preserve-3d. Тем самым браузеру сообщается, что при преобразовании этого элемента мы хотим, чтобы 3D-эффект сохранялся для всех дочерних элементов.

Если для .flipper-object не указать preserve-3d, обратную сторону (красную часть) переворачиваемого элемента мы никогда не увидим. Спецификацию для этого свойства можно найти по адресу 90320/.

Каждая панель переворачиваемого элемента должна получить позиционирование в верхней части своего контейнера, но мы также хотим, чтобы при вращении обратная сторона элемента была не видна (в противном случае мы никогда не увидим зеленую панель, поскольку она располагается «позади» красной). Для этого используется свойство backface-visibility. Его значение устанавливается в hidden, чтобы, как вы догадались, скрыть обратную сторону элемента:

.panel {

    top: 0;

    position: absolute;

    backface-visibility: hidden;

}

Sovet.tif совет

Обнаружилось, что в некоторых браузерах у свойства backface-visibility имеется ряд не­ожиданных побочных эффектов. Особенно полезно будет повысить эффективность работы элементов с фиксированной позицией на не самых новых Android-устройствах. Более по­дробные сведения и описание причин происходящего можно найти в публикациях по адресам / и /.

Затем нам нужно заставить заднюю панель быть в исходном состоянии перевернутой, чтобы при переворачивании всего элемента она оказалась в правильном положении. Для этого применяется преобразование вращения:

.flipper-vertical .back {

    transform: rotateX(180deg);

}

.flipper-horizontal .back {

    transform: rotateY(180deg);

}

Теперь все на своих местах и все, что мы хотим сделать, — это перевернуть весь внутренний элемент, когда на внешний элемент наводится указатель мыши:

.flipper:hover .flipper-vertical {

    transform: rotateX(180deg);

}

.flipper:hover .flipper-horizontal {

    transform: rotateY(180deg);

}

Как вы можете представить, существует несметное количество (кстати, это преувеличение, я проверял) способов применения главных компонентов этой конструкции. Чтобы поинтересоваться с точки зрения перспективы, как выглядит забавный навигационный эффект или меню, которое оказывается за пределами основного холста, я рекомендую посетить сайт Codrops: .

Sovet.tif совет

Самые последние наработки консорциума W3C в отношении CSS Transforms Module Level 1 можно найти по адресу /.

Свойство transform3d

Вдобавок к использованию перспективы я выявил немалую пользу от применения значения transform3d. Только одно это свойство и его значение позволяют перемещать элемент по осям X (влево-вправо), Y (вверх-вниз) и Z (вперед-назад). Внесем коррективы в последний пример и воспользуемся преобразованием translate3d. Код этого примера можно найти в файле каталога example_08-06.

Кроме установки элементов с небольшим отступом, изменения по сравнению с предыдущим примером можно найти только здесь:

.flipper:hover .flipper-vertical {

    transform: rotateX(180deg) translate3d(0, 0, -120px);

    animation: pulse 1s 1s infinite alternate both;

}

 

.flipper:hover .flipper-horizontal {

    transform: rotateY(180deg) translate3d(0, 0, 120px);

    animation: pulse 1s 1s infinite alternate both;

}

Мы по-прежнему применяем преобразование, но на этот раз добавили к вращению translate3d. Синтаксис включает в себя помещаемые внутрь объявления translate3d аргументы, отделенные друг от друга запятыми и задающие перемещение по осям X, Y и Z.

В наших двух примерах я не перемещал элемент по осям X или Y (слева направо или вверх и вниз), зато с вашей точки наблюдения перемещал его по на правлениям к вам и от вас.

Если вы посмотрите на верхний пример, то увидите, что переворот элемента происходит за нижней кнопкой и завершается в позиции, находящейся на 120 пикселов ближе к плоскости экрана (отрицательные значения приведут к отдалению элемента от вас).

08_14.tif 

В то же время нижняя кнопка переворачивается по горизонтали и в итоге оказывается отстоящей от вас на 120 пикселов.

08_15.tif 

Sovet.tif совет

Спецификацию, касающуюся translate3d, можно найти по адресу /.

Использование преобразований при постепенном усложнении

Область, в которой, на мой взгляд, свойство transform3d проявило себя с наилучшей стороны, — это выдвигаемые на экран и задвигаемые за его пределы панели, в частности модели, располагающие элементы навигации за пределами холста. Если вы откроете файл, находящийся в каталоге example_08-07, то увидите, что мною создана основная постепенно усложняемая модель за пределами холста.

При создании системы взаимодействия с помощью JavaScript и с использованием современных свойств CSS, подобных преобразованиям, появляется смысл испытывать компоненты, начиная с требующих поддержки устройств с самыми скромными возможностями. А что делать в расчете на тех, у кого нет JavaScript (да, попадаются еще и такие), или на тех, кто испытывает проблемы с загрузкой или выполнением кода JavaScript? А что делать, если чьи-нибудь устройства не поддерживают преобразования (устройства, использующие, к примеру, Opera Mini)? Не волнуйтесь, вы можете без особых усилий обеспечить работоспособный интерфейс для любой возможности.

Я пришел к выводу, что при создании таких моделей интерфейсов полезнее всего начинать с самого скромного набора возможностей и выполнять усложнение, начиная с этой исходной позиции. Сначала установим, что увидят те, у кого недоступен JavaScript. Как бы там ни было, если метод для отображения меню зависит от наличия JavaScript, то вывод меню за пределы экрана не используется. В таком случае для размещения области навигации в обычном потоке элементов документа мы полагаемся на разметку. В худшем случае независимо от ширины окна просмотра пользователи смогут просто прокрутить страницу, добравшись до самого низа, и щелкнуть на ссылке.

08_16.tif 

Если JavaScript доступен, то при меньших экранах мы убираем меню влево. При щелчке на кнопке меню мы добавляем класс к тегу body (с помощью JavaScript) и используем его в качестве зацепки для возвращения навигационной панели в поле зрения с помощью CSS.

08_17.tif 

Для более крупных окон просмотра мы прячем кнопку меню и просто располагаем панель навигации слева, а основное содержимое перемещаем так, чтобы им было занято все остальное пространство.

08_18.tif 

Затем эффект скрытия-показа панели навигации постепенно усложняется. Здесь свое вполне заслуженное место занимает средство Modernizr: добавляя классы к HTML-тегу, мы можем использовать их как зацепки для стилевого оформления (Modernizr более подробно рассматривается в главе 5).

Сначала для браузеров, поддерживающих только преобразования, связанные с перемещениями (например, старые Android-браузеры), используется простое свойство translateX:

.js .csstransforms .navigation-menu {

    left: auto;

    transform: translateX(-200px);

}

Для браузеров, поддерживающих трехмерные преобразования, используется свойство translate3d. При этом там, где оно поддерживается, ожидается существенный прирост производительности, поскольку на большинстве устройств выполнение решаемых при его объявлении задач возлагается на графические процессоры:

.js .csstransforms3d .navigation-menu {

    left: auto;

    transform: translate3d(-200px, 0, 0);

}

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

Создание эффектов анимации средствами CSS3

Если вам приходилось работать с приложениями Flash, Final Cut Pro или After Effects, то вы сразу же почувствуете преимущества, получаемые при работе с CSS3-анимацией. В CSS3 применяется методика анимации с использованием ключевых кадров, встречающаяся в приложениях, построенных на использовании шкалы времени.

Анимация весьма широкой реализуется в браузерах и поддерживается Fire­fox 5+, Chrome, Safari 4+, Android (всеми версиями), iOS (всеми версиями) и Internet Explorer 10+. Анимация в CSS3 содержит два компонента: прежде всего это объявление ключевых кадров, а затем их использование в свойстве animation. Посмотрим, как все это работает.

В предыдущем примере создавался простой эффект переворачивания элементов путем сочетания преобразований и переходов. Давайте соберем воедино все технологии, изученные в этой главе, и добавим к этому примеру анимацию. В следующем примере, код которого можно найти в файле каталога example_08-05, добавим анимационный эффект пульсации в процессе переворачивания элемента.

Сначала создадим правило @keyframes:

@keyframes pulse {

    100% {

        text-shadow: 0 0 5px #bbb;

        box-shadow: 0 0 3px 4px #bbb;

    }

}

Как видите, за написанием @keyframes для определения нового эт-правила keyframes следует имя конкретной анимации (в данном примере pulse).

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

Здесь мы использовали только один селектор ключевого кадра — 100%. Но в правиле keyframes таких селекторов можно указать сколько угодно, определив их в виде процентных отметок. Эти отметки нужно представлять себе находящимися на шкале времени. Например, на 10 % следует сделать фон синим, на 30 % — лиловым, а на 60 % элемент должен стать полупрозрачным и т. д., как вы сочтете нужным. Имеется также ключевое слово from, эквивалентное 0 %, и to, эквивалентное 100 %. Их можно использовать следующим образом:

@keyframes pulse {

    to {

        text-shadow: 0 0 5px #bbb;

        box-shadow: 0 0 3px 4px #bbb;

    }

}

Но следует иметь в виду, что браузеры, основанные на движке WebKit (iOS, Safari), не всегда понимают значения from и to, предпочитая им 0% и 100%, поэтому я рекомендую остановить свой выбор на процентном обозначении селекторов ключевых кадров.

Как вы заметили, мы не стали определять стартовое положение. Дело в том, что оно совпадает с тем состоянием, в котором уже находится каждое из этих свойств. Ту часть спецификации, в которой все это объясняется, можно найти по адресу /.

Primechanie.tif примечание

Если не определен ключевой кадр для 0 % или from, то агент пользователя создает ключевой кадр для 0 %, используя вычисленные значения анимируемых свойств. Если не определен ключевой кадр для 100 % или to, то агент пользователя создает ключевой кадр для 100 %, используя вычисленные значения анимируемых свойств. Если в селекторе ключевого кадра указано отрицательное процентное значение или значение, превышающее 100 %, то ключевой кадр будет проигнорирован.

В эт-правиле keyframes мы добавили к селектору 100 % свойства text-shadow и box-shadow, после чего ожидаем, что ключевые кадры, будут применены к элементу для анимации text-shadow и box-shadow до определенной величины. Но сколько будет длиться анимация? Как заставить ее повториться, пойти вспять и продемонстрировать другие возможности, по поводу которых я надеюсь получить ответ? Вот как происходит применение анимации на основе ключевых кадров:

.flipper:hover .flipper-horizontal {

    transform: rotateY(180deg);

    animation: pulse 1s 1s infinite alternate both;

}

Здесь для краткой формы записи ряда связанных с анимацией свойств используется свойство animation. В данном примере объявляются (по порядку) имя используемого объявления ключевых кадров (pulse), продолжительность анимации (одна секунда), задержка перед началом анимации (одна секунда, чтобы дать нашей кнопке время на первый переворот), количество запусков анимации (бесконечно — infinite), направление анимации (чередование — alternate, то есть анимация сначала идет в одном направлении, а затем его меняет), а затем нам нужно, чтобы свойство animation-fill-mode сохраняло значения, определенные в ключевых кадрах, когда анимация собирается идти вперед или назад (both).

Сокращенная запись может фактически принять все семь свойств анимации. Вдобавок к тому что было использовано в предыдущем примере, можно указать значение свойства animation-play-state. Для эффективного проигрывания или остановки анимации ему может быть присвоено значение состояния работы — running или состояния на паузе — paused. Разумеется, использовать сокращенную запись совсем не обязательно, иногда имеет смысл установить каждое свойство по отдельности, что поможет разобраться в коде при его последующем изучении. Далее показаны отдельные свойства и там, где это возможно, их альтернативные значения, отделенные друг от друга вертикальной чертой:

.animation-properties {

    animation-name: warning;

    animation-duration: 1.5s;

    animation-timing-function: ease-in-out;

    animation-iteration-count: infinite;

    animation-play-state: running | paused;

    animation-delay: 0s;

    animation-fill-mode: none | forwards | backwards | both;

    animation-direction: normal | reverse | alternate | alternate-reverse;

}

Primechanie.tif примечание

Полное определение каждого из этих свойств анимации можно найти по адресу /.

Как уже упоминалось, объявленные ключевые кадры использовать в отношении других элементов и с совершенно другими установками довольно просто:

.flipper:hover .flipper-vertical {

    transform: rotateX(180deg);

    animation: pulse 2s 1s cubic-bezier(0.68, -0.55, 0.265, 1.55) 5

    alternate both;

}

Здесь pulse-анимация запустится на две секунды и будет использовать функцию развития процесса по времени ease-in-out-back, определенную в виде кривой Безье третьего порядка. Анимация будет повторяться в обе стороны пять раз. Это объявление применено в файле примера к вертикально переворачиваемому элементу.

Это всего лишь один простой пример использования CSS-анимации. Так как на ключевые кадры можно разложить практически все, перед нами открываются, по сути, безграничные возможности. О последних разработках в области CSS3-анимации можно узнать по адресу /.

Свойство animation-fill-mode property. Свойство animation-fill-mode заслуживает специального упоминания. Рассмотрим анимацию, начинающуюся с фона желтого цвета, который переходит в фон красного цвета за три секунды. Код этого примера можно увидеть в файле каталога example_08-08.

Здесь применяется следующая анимация:

.background-change {

    animation: fillBg 3s;

    height: 200px;

    width: 400px;

    border: 1px solid #ccc;

}

 

@keyframes fillBg {

    0% {

        background-color: yellow;

    }

    100% {

        background-color: red;

    }

}

Но как только анимация завершится, фон контейнера div вернется к бесцветному состоянию. Это потому, что по умолчанию все, что происходит за пределами анимации, остается за ее пределами! Чтобы изменить такое поведение, у нас есть свойство animation-fill-mode. В данном примере мы можем воспользоваться следующим кодом:

animation-fill-mode: forwards;

Тогда элемент сможет сохранить любые значения, примененные в конце анимации. В нашем случае в контейнере div сохранится фон красного цвета, которым заканчивается анимация. Дополнительные сведения о свойстве animation-fill-mode можно найти по адресу .

708085.png 

Резюме

Описаниям преобразований, переходов и анимации средствами CSS можно посвятить целые книги. Но надеюсь, что даже поверхностное ознакомление в этой главе с данным вопросом позволит вам усвоить основы и приступить к практическому использованию этих эффектов. В конечном счете освоение новейших возможностей и технологий CSS нацелено на придание адаптивной конструкции еще большей компактности и изысканности путем использования средств CSS, а не кода JavaScript и внесение в нее ряда более привлекательных эстетических усовершенствований.

Из этой главы мы узнали, что такое CSS3-преобразования и как создается код для их реализации. Мы научились пользоваться функциями развития процесса по времени ease и linear, а затем применили их для создания простых, но весьма интересных эффектов. Затем было изучено все, что касается 2D-преобразований, в том числе масштабирование и наклон, после чего рассмотрены способы их использования в связке с переходами. Вкратце были рассмотрены 3D-преобразования, а затем изучено все, что касается эффективности и относительной простоты CSS-анимации. И трудно не согласиться с тем, что ваши возможности по части использования CSS3 существенно возросли!

Но есть одна область в разработке сайтов, которую я всеми силами стараюсь обойти стороной, — это создание форм. Не знаю почему, но мне всегда казалось, что их создание является весьма нудной и зачастую не приносящей полного удовлетворения работой. Представьте себе, как я обрадовался, когда узнал, что HTML5 и CSS3 могут как никогда ранее упростить процесс создания, стилевого оформления и даже проверки правильности заполнения форм. У меня появилось желание заняться этим вопросом. Подобный прилив энтузиазма в части создания веб-форм можете испытать и вы. Этими знаниями я готов поделиться с вами в следующей главе.

Назад: 7. Использование SVG для достижения независимости от разрешения
Дальше: 9. Обуздание форм с помощью HTML5 и CSS3