Новое в блогах


Техноблог HTTPS и Amiro.CMS  1
Техноблог Обновление цен в каталоге интернет-магазина через CSV-файл 
Техноблог Подключаем и используем модуль «SEO Шаблоны»  1
Техноблог Использование модуля «Валюты» в интернет-магазине импортных товаров 
Личный опыт История от «Интер Электрик», #ОбновлениеЗаРассказ 
Личный опыт История от АвтоТехЦентр Субару Медведково, #ОбновлениеЗаРассказ 

Теги



Многослайдовый баннер на гаджете Лента изображений без JavaScript (только CSS)

С начала разработки каскадных таблиц стилей третьей версии, возможности верстальщика растут экспоненциально. Всё больше функционала можно реализовать на «чистом» CSS. В данной работе предлагается разработка интерактивного слайдера без единой строчки какой бы то ни было реализации ECMAScript (например, JavaScript или JScript – сокращённо JS). Автоматическая ротация, интерактивный выбор любого слайда с плавным переходом – всё это реализовано на «чистом» CSS.

Введение

Свойства transition, animation и transform уже давно, в том или ином виде, реализованы во всех популярных браузерах. 6 июня 2012 года консорциум W3C объявил, что эта часть разрабатываемого стандарта CSS 3.0 кардинально меняться не будет, и рекомендовал реализовать её всем браузерам уже сегодня.

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

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

Устаревшие версии Internet Explorer, к которым скоро можно будет отнести даже 9 версию, не поддерживают transition, animation и transform ни в каком виде. Но их доля всё ещё значительна и превышает 10%.В данной работе для основного функционала для IE7-9 предлагается js-«заглушка», а для дополнительного функционала – эффекта плавного переключения между слайдами, согласно принципу graceful degradation – ничего.

CSS против JS

Есть множество задач, которые можно решить при помощи CSS: интерактивные галереи, многоуровневые выпадающие меню, построение и анимация трёхмерных диаграмм... Вопрос: зачем использовать CSS, когда можно все сделать на JS? Ответ каждый должен дать себе сам, принимая во внимание следующие аргументы:

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

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

БЭМ

Итак, для именования CSS классов использовалась методология Блок Элемент Модификатор (БЭМ https://github.com/bem). Суть в том, что вёрстка основана на компоновке страницы из независимых блоков. Согласно БЭМ у блока могут быть элементы, но только внутри блока. Вот CSS классы данной работы:

.image-tape /* Блок, содержащий ленту изображений */
.image-tape__radio /* Радиокнопка */
.image-tape__item /* Слайд */
.image-tape__img /* Картинка внутри слайда */
.image-tape__number-list /* Контейнер с кнопками переключения */
.image-tape__number /* Кнопка включения связанного с ней слайда */
.image-tape__number-after /* внедрён для поддержки IE7 и IE8, которые не поддерживают псевдоэлементы :after и ::after соответственно */
.image-tape_count_X /* Модификатор, определяющий количество слайдов X */

Особенности использования анимации

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

@keyframes image-tape__item-autoplay_count_3
{
	0%{opacity:0;}
	10%{opacity:1;}
	33% {opacity:1;}
	43% {opacity:0;}
	100%{opacity:0;}
}

Главная особенность реализации слайдера в том, что всем слайдам и всем кнопкам присваивается одна и та же анимация:

image-tape_count_3 .image-tape__item,
image-tape_count_3 .image-tape__number-after
{
	-moz-animation: image-tape__item-autoplay_count_3 15s infinite;
	-webkit-animation: image-tape__item-autoplay_count_3 15s infinite;
	-o-animation: image-tape__item-autoplay_count_3 15s infinite; 
	animation: image-tape__item-autoplay_count_3 15s infinite;
}

Такой подход позволяет серьезно сократить объем кода, ведь все анимации пока ещё приходится дублировать их префиксными версиями (@-webkit-keyframes, @-moz-keyframes и @-o-keyframes), а каждую такую «стопку» правил надо отдельно описывать для каждого требуемого (заказчиком) числа слайдов. Если отдельно описывать анимацию ещё и для каждого слайда, то объем кода может составить десятки килобайт.

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

.image-tape__item:nth-of-type(2),
.image-tape__number:nth-of-type(2) > .image-tape__number-after
{
	-moz-animation-delay:5s;
	-webkit-animation-delay:5s;
	-o-animation-delay:5s;
	animation-delay:5s;
}
.image-tape__item:nth-of-type(3),
.image-tape__number:nth-of-type(3) > .image-tape__number-after
{
	-moz-animation-delay:10s;
	-webkit-animation-delay:10s;
	-o-animation-delay:10s;
	animation-delay:10s;
}
...

Для первой пары остаётся значение по-умолчанию – нулевое смещение.

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

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

Пауза при наведении курсора

Есть целый ряд CSS «событий», переключающих состояние html элемента. Если говорить о клике мыши, то это появление псевдоклассов :focus, :target, или :checked у одного из элементов страницы. Псевдокласс :focus может быть не более чем у одного элемента на страницу единовременно; псевдокласс :target засоряет «хистори» браузера и требует наличие тега «a»; псевдокласс :checked запоминает состояние до ухода со страницы, плюс, в случае радиокнопок, является дискретным переключателем, когда выбран может быть только один элемент конкретной группы – а это то, что нужно.

.image-tape__radio {стили не выбранной радиокнопки}
.image-tape__radio:checked {стили выбранной радиокнопки}

В селекторах CSS уровня ниже 4.0 переключить состояние произвольного элемента (например, opacity слайда) можно только в связке с радиокнопкой, при помощи селекторов соседей + и ~. Переключить можно как стили соседа, так и стили потомков соседа, но в любом случае сосед должен находиться после радиокнопки.

/* Стиль первого слайда в состоянии «не выбран» */
.image-tape__radio:nth-of-type(1) ~ .image-tape__item:nth-of-type(1) {
	opacity: 0.0;
}
/* Стиль первого слайда в состоянии «выбран» */
.image-tape__radio:nth-of-type(1):checked ~ .image-tape__item:nth-of-type(1) {
	opacity: 1.0;
}

Было использовано переключение opacity слайда – контейнера, который содержит картинку. Это более универсальный способ, чем переключение свойств картинки, поскольку в div-контейнер, в отличие от пустого элемента img, можно поместить любую дополнительную информацию (например, название слайда, или связанное описание, включая ссылки).

Для слайдов указаны свойства transition, которые позволяют сделать переключение между ними плавным.

.image-tape__item 
{
	-moz-transition: opacity 0.2s linear; 	
	-webkit-transition: opacity 0.2s linear; 	
	-o-transition: opacity 0.2s linear; 
	transition: opacity 0.2s linear;
}

Остановка ротации при выборе слайда

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

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

<input class="image-tape__radio" id="1" type="radio">
<input class="image-tape__radio" id="2" type="radio">
<input class="image-tape__radio" id="3" type="radio">
...
<div class="image-tape__item">...</div>

Более того, все кнопки (лейблы радиокнопок) надо группировать в отдельном блоке и помещать после радиокнопок, иначе могут возникнуть проблемы с универсальным позиционированием лейблов для произвольного числа слайдов.

Остановка анимации всех слайдов и кнопок при выборе любого слайда задаётся следующим образом:

.image-tape__radio:checked ~ .image-tape__item,
.image-tape__radio:checked ~ .image-tape__number-list > .image-tape__number-after
{
	opacity: 0.0;
	-moz-animation: none;
	-webkit-animation: none;
	-o-animation: none;
	animation: none;
}

Произвольное число слайдов

Сделать универсальный слайдер под любое число слайдов невозможно, потому что под каждое число требуется своя «стопка» CSS-правил анимации. Каждую такую «стопку» (если она описана) можно подключать через модификатор блока image-tape:

.image-tape_count_X

Для поддержки некоторых старых браузеров первый слайд не анимируется. По этой причине контейнер первой картинки имеет opacity всегда равный 1.0. Возникает проблема: при плавном переключении двух других слайдов между собой, первый просвечивает (это может быть и background родителя блока image-tape). Для удаления эффекта просвечивания устанавливается задержка transition-delay для всех слайдов, кроме выбранного; для выбранного же устанавливается z-index больше, чем у всех остальных:

.image-tape__item {
	opacity: 1.0;
	position: relative;
	-moz-transition: opacity 0.0s linear 0.2s;
	-webkit-transition: opacity 0.0s linear 0.2s;
	-o-transition: opacity 0.0s linear 0.2s;
	transition: opacity 0.0s linear 0.2s;
}

.image-tape__radio:nth-of-type(1):checked ~ .image-tape__item:nth-of-type(1),
.image-tape__radio:nth-of-type(2):checked ~ .image-tape__item:nth-of-type(2),
.image-tape__radio:nth-of-type(3):checked ~ .image-tape__item:nth-of-type(3),
.image-tape__radio:nth-of-type(4):checked ~ .image-tape__item:nth-of-type(4),
.image-tape__radio:nth-of-type(5):checked ~ .image-tape__item:nth-of-type(5){
	-moz-transition: opacity 0.2s linear;
	-webkit-transition: opacity 0.2s linear;
	-o-transition: opacity 0.2s linear;
	transition: opacity 0.2s linear;
	z-index: 6;
}

Чтобы слайды не конфликтовали с другими элементами сайта (например, не перекрывали выпадающее меню с z-index менее или равным 6), создаём свой контекст (stacking context) для блока путём задания минимально, необходимого для видимости, z-index`а:

.image-tape
{
z-index: 0;
}

Теперь все элементы блока будут "конфликтовать" только между собой.

Реализация на Amiro.CMS

Весь CSS необходимо добавить во вкладку Пользовательские стили CSS при редактировании любого макета. После сброса кэша браузера этот код будет присутствовать на всех страницах сайта. Впрочем, частично, или даже полностью, CSS можно вставить непосредственно в шаблон imagetape.tpl в тег style. Это уменьшает объём подключаемого на каждую страницу сайта CSS файла, работает во всех браузерах, валидно в html5 при наличии атрибута scoped, а в условиях вёрстки независимыми блоками не влияет на другие части страницы.

При попытке вывода требуемого html кода посредством шаблона imagetape.tpl возникает две проблемы:

1. 1. В сете image, в котором заключен html код одного слайда, отсутствует счетчик (переменная, принимающая значения от 1 до количества слайдов N), который необходим для связки между собой радиокнопок и лейблов.

2. 2. Требуется группировка радиокнопок до всех слайдов, и лейблов после всех слайдов, но их количество должно однозначно соответствовать количеству слайдов.

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

##setglobalvar @imagetape_radioid = (imagetape_radioid)?imagetape_radioid + 1:1##

Здесь символ @ означает, что справа от него находится php выражение (не рекомендуется его использовать слишком часто). Весь php код, в отличие от условных конструкций if-else-endif, выполняется ещё на этапе набора html кода из сетов , поэтому счетчик будет работать.

Для группировки списка лейблов и радиокнопок используется такой код:

##setglobalvar @imagetape_radios = imagetape_radios . ' '##
##setglobalvar @imagetape_labels = imagetape_labels . ' '##

В итоге, у нас получается html код, в котором сначала идёт список радиокнопок, затем список слайдов с баннерами, а затем блок с списокм лейблов:

<div class="image-tape image-tape_type_slideshow image-tape_count_##imagetape_radioid##" id="image-tape-##group##">
	##imagetape_radios##
	##imageset##
	<div class="image-tape__number-list">
		##imagetape_labels##
	</div>
</div>

Вывод

Уже сегодня, без навыков программирования и специализированных библиотек, до своей окончательной стандартизации, CSS 3.0 позволяет реализовывать сложный и интересный функционал. Предложенный интерактивный слайдер, на текущий момент, полностью работоспособно у 80% пользователей рунета. Для большей части оставшихся пользователей, а именно для пользователей браузеров IE7-9, можно использовать js-«заглушку», которая реализует основной функционал слайдера.

Шаблон с предложенным решением включен в шаблоны версии 5.14.6

[12.09.12]  
Рейтинг: 3.6 (голосов: 10)
Комментировать

Теги: инструкцияинтеграциягаджетыAPIhow-toCSS
 
Вернуться к списку
Комментарии (7)

 (Партнер)  05.09.12 14:47
0


Да-а, ребята, вы любите IE так же, как люблю его я.

Отличная работа.
Мне в принципе нравятся такие смелые решение "без js" и особенно приятно видеть такой подход в своей основной cms.

 (Партнер)  05.09.12 15:18
0

Хочу добавить свои 5 копеек о стеке свойств с вендорными префиксами. Думаю лучше писать W3C оригинал последним, что бы актуальным всегда была версия из спецификации, а не из браузера.
-webkit-transition:
-moz-transition:
-o-transition:
transition:

   17.01.14 04:54
0

Классный слайдовый баннер!

Подскажите, пожалуйста, как:

1. Изменить скорость слайд-шоу (сделать чуть медленнее)
2. Уменьшить (увеличить) количество слайдов (с 3 на 2 или с 3 на 4-5)
3. Убрать отображение кнопок-номеров слайдов.

Заранее благодарен за ответ.

   17.01.14 08:20
0

1. В шаблоне imagetape_slideshow.tpl за скорость отвечают CSS-стили
с значениями 5s, 10s, 15s и т.д. то есть второй слайд появляется через
5 секунд, третий через 10 и т.д. Их нужно настраивать вручную.
В принципе, это довольно просто - в поле найти пишем 5s, в поле "замена
на" 8s и нажимаем "заменить все". Затем 10s на 13s и т.д. последовательно.

2. Максимальное число слайдов - 5. Если нужно больше, придется настраивать
шаблон imagetape_slideshow.tpl

Чтобы уменьшить с 3 до 2 слайдов, нужно просто зайти в настройки гаджета
через Менеджер сайта, в визуальном редакторе нажать двойным щелчком по
гаджету, и в открывшемся окне оставить два изображения, третье удалить.

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

3. В этом поможет CSS-стиль .image-tape__number-list{display: none}
Его можно добавить в конец "CSS пользователя" в макетах страниц.

Еще информация о гаджете:
http://manual.amiro.ru/doc/menedzher-sajta/vizualnyj-redaktor/gadzhety/#lenta_gadget
http://www.amiro.ru/blog/review/tape-of-images

   17.01.14 08:48
0

Спасибо за информативный и оперативный ответ!

   20.12.14 16:11
0

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

   05.02.15 12:25
0

Возможно, у разработчиков есть решение.
Попробуйте в саппорт написать.

Ваш комментарий