Есть много способов создать анимированную галерею: JavaScript, PHP, Flash и т.д. Но в большинстве случаев все, что вам надо – простой код CSS с семантической разметкой.
Часть 1.
Чтобы выполнить это упражнение, вам понадобятся три миниатюры, в идеале одинакового размера, и три увеличенных версии этих изображений. Для ясности сохраните крупные версии как alladin.jpg, а миниатюры - как alladin-thumb.jpg.
Разобравшись с контентом, вы должны решить, какую разметку лучше всего к нему применить. Наша цель – создать серию миниатюр, при взаимодействии с которыми открываются их увеличенные версии, включая объяснение их контекста и значения. Здесь нам на помощь приходит невероятно полезный (и недооцененный) список определений: по сути, речь идет о ряде терминов (которые могут быть словами, изображениями, ссылками или чем-либо еще), которые уточняются определением.
Базовая разметка довольно проста:
<dl class="cartoon">
<dt><img src="alladin-thumb.jpg" alt="">
<dd><img src="alladin.jpg" alt="Алладин">
<dt><img src="mermaid-thumb.jpg" alt="">
<dd><img src="mermaid.jpg" alt="Румалочка">
<dt><img src="mulan-thumb.jpg" alt="">
<dd><img src="mulan.jpg" alt="Мулан">
</dl>
(В целях данного упражнения я предположил, что все миниатюры одинакового размера, чтобы их ширину и высоту можно было включить в объявление .cartoon dt img {}
в таблице стилей. Если бы все миниатюры были разного размера, мы бы определили ширину и высоту как отдельные встроенные стили для каждой фотографии, как мы обычно делаем для крупных изображений.)
При просмотре страницы в браузере мы тут же сталкиваемся с рядом проблем. Первая заключается в том, что увеличенные изображения отображаются сразу, тогда как они должны появляться только при наведении мышкой на миниатюру.
Существует множество свойств CSS, с помощью которых можно заставить «исчезнуть» элементы на странице: display, visibility, выталкивание элементов за границы окна (margin или left) и т.д. Мы воспользуемся таким свойством, как прозрачность opacity:
.cartoon dd { opacity: 0; }
Таким образом, мы спрячем увеличенные изображения, но оставим нетронутым пространство, которые они занимают на экране. Чтобы добиться этого, нужно абсолютно спозиционировать элементы dd:
.cartoon dd { opacity: 0; position: absolute; }
Применение абсолютного позиционирования удаляет элементы из потока документа: страница отображается без объявления определений, из-за чего рушится вся остальная структура документа. (Конечно же, элементы <dd>
и фотографии, которые они содержат, до сих пор присутствуют – они просто спрятаны с помощью параметра opacity: 0
. Чтобы посмотреть, где находятся изображения, просто удалите или закомментируйте эту часть объявления стиля.)
Position: absolute
– очень полезное, но опасное свойство. При неправильном использовании оно может привести к абсолютному позиционированию всех элементов на странице, особенно если дизайнер помешан на том, чтобы разметка сайта была отлажена пиксель в пиксель, или к нарушению структуры кода из-за удаления абсолютно спозиционированных элементов из потока документа. Следует избегать применения position: absolute
и использовать это свойство, только когда без него действительно нельзя обойтись – и при этом четко знать, зачем вы его используете.
В нашем случае применение position: absolute
полностью оправдано: мы хотим, чтобы все увеличенные изображения появлялись в одном и том же месте. На данном этапе это не так (опять же, временно отключите opacity: 0, чтобы посмотреть, где они находятся). К тому же, мы хотим, чтобы положение увеличенных изображений соизмерялось с их отношением к списку определений. Это двухшаговый процесс. Сначала код для самого списка определений:
.simple-gallery { position: relative; }
Эта строчка объясняется простым правилом: абсолютно спозиционированные элементы располагаются напротив начала тела документа (то есть, в верхнем левом углу страницы), если только они не находятся в границах другого абсолютно или относительно спозиционированного элемента.
По сути, мы настроили абсолютно спозиционированные элементы <dd>
так, чтобы их положение соотносилось со списком определений, а не с телом документа. Мы можем увидеть это, еще раз прокомментировав видимость элементов <dd>
и добавив больше CSS в объявление стиля.
.cartoon dd {
/* opacity: 0; */
position: absolute;
top: 20px;
left: 200px;
}
Значения для верхней и левой границы я взял, что называется, с потолка; вы сами должны скорректировать их в соответствии с конкретным дизайном страницы, прежде чем снова включать visibility: hidden
.
Предпоследний шаг – сделать так, чтобы элементы <dd>
появлялись только при наведении мышкой на миниатюры. Взглянув на нашу разметку, мы увидим, что каждому элементу <dd>
предшествует тег dt. Следовательно, нам нужна комбинация со смежным селектором.
.cartoon dt:hover + dd { opacity: 1; }
Этот код CSS – отличное решение за исключением одного «но»: чтобы показать увеличенное изображение, вы должны переместить мышку вправо от миниатюры, где <dt>
до сих пор активен. Так происходит потому, что <dt>
относится к классу блок-тегов и поэтому по умолчанию растягивается на всю страницу. Но если это блок-тег, для него можно установить ширину. Если предположить, что ширина всех наших миниатюр составляет 75 пикселей, получаем:
.cartoon dt { width: 75px; }
Наш окончательный CSS код:
.cartoon { position: relative; }
.cartoon dt { width: 75px; }
.cartoon dd { opacity: 0; position: absolute; top: 20px; left: 200px; }
.cartoon dt:hover + dd { opacity: 1; }
А вот 1й пример анимированной галереи на CSS3 в живую.
Часть 2.
Предыдущая галерея вышла просто потрясающей, портило ее лишь одно - экран просмотра увеличенной фотографии при первоначальной загрузке оставался пустым. Давайте исправим это упущение. В этом нам очень сильно поможет HTML5:
- элементы
input
отображаются в любом месте страницы и не обязательно должны быть связаны с формой;
- метка
label
с правильным значением атрибута for может заменить радиокнопку, к которой она привязана;
- для установления этого отношения радиокнопка необязательно должна быть отображена на странице, пока работает код
- содержание элементов
<label>
чаще представлено изображениями, чем текстом;
- статус радиокнопки можно отслеживать через псевдо-селектор
:checked
Чтобы все это заработало, код HTML должен быть корректным и валидным. На этом я и сосредоточусь в первую очередь.
Миниатюры
<label for="alladin"><img src="alladin-thumb.jpg" alt="Алладин"></label>
<input type="radio" id="alladin" name="churchy">
<label for="mermaid"><img src="mermaid-thumb.jpg" alt="Русалочка"></label>
<input type="radio" id="mermaid" name="churchy">
<label for="mulan"><img src="mulan-thumb.jpg" alt="Мулан"></label>
<input type="radio" id="mulan" name="churchy">
Для удобства использования, миниатюрные изображения все относительно небольшие с одними и теми же пропорциями.
При составлении вышеуказанной разметки нужно следовать всего трем правилам:
- Значения атрибута for на каждой метке должно совпадать со значением id, связанного с радиокнопкой – так же, как и в случае с обычной формой.
- Каждое значение id должно быть уникальным
- Все элементы радиокнопки должны иметь одинаковый атрибут name, чтобы при работе отключать друг друга.
Для начала неплохо добавить на страницу код миниатюр, чтобы убедиться, что радиокнопки (которые все еще видны на этой стадии) отключают друг друга при их нажатии.
Изображения галереи
Разметка для больших изображений еще проще:
<div class="cartoon">
<figure id="f-alladin">
<img alt src="alladin.jpg">
<figcaption>Алладин (IMDB 8,0/10)</figcaption>
</figure>
...
<figure id="f-beauty">
<img alt src="beauty.jpg">
<figcaption>Красавица и чудовище (IMDB 8,1/10)</figcaption>
</figure>
</div>
Я оставил значения атрибута alt
для этих изображений пустыми, чтобы не усложнять для этот пример. Единственным требованием является то, что каждое изображение должно иметь уникальный идентификатор. Изображения, которые я выбрал для нашей галереи - обои на рабочий стол из популярных диснеевских мультфильмов.
Основной CSS тоже довольно прост:
.cartoon-container {
background: #111111;
overflow: hidden;
position: relative;
}
.cartoon-container input[type="radio"] {
display: none;
}
.cartoon-container label img {
border-right: 40px solid #111111;
clear: left;
display: block;
float: left;
width: 17%;
}
.cartoon-container label:hover {
cursor: pointer;
}
.cartoon {
margin-left: 22.5%;
position: relative;
width: 70%;
}
.cartoon figure {
margin: 0;
opacity: 0;
position: absolute;
transform: scale(0.8);
-webkit-transform: scale(0.8);
transition: all 0.5s linear 0s;
width: 100%;
}
.cartoon figure img {
box-shadow: 0 0 15px rgba(0, 0, 0, 0.6);
width: 100%;
}
Объявления скрывают радиокнопки и устанавливают размеры изображений в зависимости от ширины экрана, при этом миниатюры расположены слева. Я добавил тег border-right
, чтобы отодвинуть крупные фотографии подальше от миниатюр, но есть много других способов добиться того же результата. Увеличенные изображения невидимы по умолчанию и отображаются на 80% от своего нормального размера.
Теперь добавим интерактивности:
#alladin:checked ~ .cartoon #f-alladin {opacity: 1; transform: scale(1);}
#mermaid:checked ~ .cartoon #f-mermaid {opacity: 1; transform: scale(1);}
#mulan:checked ~ .cartoon #f-mulan {opacity: 1; transform: scale(1);}
#beauty:checked ~ .cartoon #f-beauty {opacity: 1; transform: scale(1);}
Здесь использованы более сложные селекторы: я удалил произвольные компоненты, предшествующие большинству элементов id, чтобы сделать код проще. Проще говоря, объявления будут прочитаны так, будто «пользователь выбрал радиокнопку с конкретным id (кликнув на саму кнопку или привязанную к ней метку). Теперь присмотритесь к элементу, содержащему id мультфильма. Если этот элемент содержит изображение с конкретным id, установите его прозрачность на 1 и выберите нормальное значение для параметра scale».
Хотя в этом случае вам придется прописать объявление CSS для каждой пары миниатюра – герой, тот факт, что применяемые стили всегда идентичны, позволяет сделать код более эффективным с помощью комбинатора группы:
#alladin:checked ~ .cartoon #f-alladin,
#mermaid:checked ~ .cartoon #f-mermaid,
#mulan:checked ~ .cartoon #f-mulan,
#beauty:checked ~ .cartoon #f-beauty {
opacity: 1;
transform: scale(1);
-webkit-transform: scale(1);
}
Вот 2й пример анимированной галереи на CSS3 в живую.
Заключение
Как отобразить фотографию героя по умолчанию? Добавить атрибут checked в код привязанной к изображению радиокнопки.
<input type="radio" id="mermaid" name="churchy" checked>
Вот и все. Крупномасштабные изображения всегда будут отображаться по умолчанию, и при желании пользователь сможет перейти к просмотру другой фотографии, кликнув на метку миниатюры. Еще одно преимущество этой системы – то, что информация сохранится при обновлении и перезагрузке страницы, поскольку браузер запоминает опции формы.
Конечно, это не предел: я усовершенствовал код, использованный в демо, добавив всплывающие надписи к картинкам.