Галерея с асинхронной загрузкой средствами CSS3
Занимаясь вёрсткой галерей, я искал простое и оригинальное решение для просмотра фотографий.
Экспериментируя, написалпример , которым хочу поделиться с сообществом Хабра.
В разметке галереи есть принципиальный момент: списки preview и photoboxes разделены, что позволяет независимо использовать любое позиционирование и оформление для превью (далее лента миниатюр) и блоков с фотографиями (далее фотобоксы).

Заголовок центрирован посредством margin: auto. Он имеет относительный размер шрифта и ширину в %, пропорциональную ширине экрана, а так же минимальную ширину в em, что не даёт ему деформироваться при малой ширине окна.
Аналогичное форматирование характерно для других блочных элементов с текстом.

Предварительный просмотр реализован в виде списка, элементы которого вытянуты в строку с помощью table-cell. При переполнении миниатюрами у нижней границы ленты образуется прокрутка. Внутри ячеек блочные ссылки и изображения миниатюр.
Список фотобоксов центрирован в блоке галереи при помощи inline-block.
Такое выравнивание позволяет ему обтекать и центрировать содержимое.
Сначала в потоке форматирования только центрированный счётчик. Размер обёртки равен размеру блока счётчика.

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

Изначально фотобокс скрыт и выведен из нормального потока форматирования с помощью абсолютного позиционирования.
В нужный момент он проявляется и позиционируется статично, возвращаясь в поток.
В нормальном потоке фотобоксы идут друг за другом вертикально. Если мы будем проявлять их, не сложив предварительно в «колоду», то каждый будет отображаться в своей статичной позиции, порой далеко внизу.
Для подсчёта номера и числа фотографий счётчик (photo) ставится в списке фотобоксов на значение 0.
В каждом следующем фотобоксе значение счётчика на 1 больше, чем в предыдущем.
В элементе, удалённом из потока нет инкремента счётчика. По этому фотобоксы скрываются (visibility: hidden), а не удаляются (display: none).
Общее число фотографий сохраняется в списке фотобоксов и выводится в его псевдоэлемент.
Счётчик порядкового номера фотографии печатается в псевдоэлементе фотобокса, в нижнем правом углу.
Прежде всего, создаётся псевдоэлемент, в который будет загружаться фотография.
Чтобы размеры фотобокса не изменялись в процессе загрузки, у псевдоэлемента прописываются ширина и высота фотографии.
Схема загрузки фотографии следующая: активируем ссылку миниатюры, она синхронизируется с соответствующим фотобоксом по#photobox-id через :target, фотобокс вынимается из общей стопки и проявляется, далее в псевдоэлемент вверху него загружается фотография.
Ссылка на#photobox-id перемещает фокус по якорю на фотобокс при его статичном/относительном позиционировании. Когда элементы галереи умещаются в окне этого не видно.
Аргументом в пользу ссылок такого типа является возможность использования браузерной навигации на странице (next/prev/reload). В принципе, фотографии в данной галерее можно загружать, используя лишь адресную строку. При этом они будут загружаться в фотобокс.
Приведённый пример корректно и идентично поддерживается всеми вышеупомянутыми браузерами. В Internet Explorer не работает, т. к. IE 6 и 7 не поддерживают псевдоэлементы, свойство content и счётчики. Ключевой псевдокласс :target не поддерживает даже IE 8.
Реализация для IE возможна через AJAX или эмуляцию псевдоклассов со вставкой элементов.
Максим Милованов (alemiks) написал пример эмуляции псевдокласса :target , и целую статью по эмуляции CSS для IE .
Если требуется эффектное JS-решение для проекта с поддержкой IE — вполне подойдётклон Lightbox .
СпасибоАлександру Макарову (SamDark) за фотографии и хост для публикации примера.
P. S. Если не понравилось выделение ссылок — посмотритепример с полупрозрачностью (используется свойство opacity).
Экспериментируя, написал
- Разметка: XHTML 1.0 Strict [Valid].
- Оформление и управление: CSS3 [Valid].
- Поддержка устройствами группы: screen.
- Поддержка браузерами: Opera 9.6, 10; Firefox 3.0, 3.5; Chrome 1—4; Safari 3.2, 4.0.
- Асинхронная загрузка, счётчик изображений.
- Корректная ссылка вида
#photobox-id. - Вывод гипертекста с заголовком, описанием, ссылками.
- Центрированный «эластичный» макет с сохранением пропорций.
- Горизонтальная навигация с прокруткой миниатюр.
- Выделение/подсветка ссылок.
Разметка
В разметке галереи есть принципиальный момент: списки preview и photoboxes разделены, что позволяет независимо использовать любое позиционирование и оформление для превью (далее лента миниатюр) и блоков с фотографиями (далее фотобоксы).
<div id="gallery"> <h1>CSS-Галерея</h1> <ul class="preview"> <li> <a href="#photobox-id" title="Изображение"> <img src="thumb.jpeg" alt="Изображение" /> </a> </li> <!-- и т. д. элементы ленты миниатюр --> </ul> <ul class="photoboxes"> <li id="photobox-id"> <h2>Наименование изображения</h2> <p>Описание изображения</p> </li> <!-- и т. д. элементы списка фотобоксов --> </ul> </div>
Текст

Заголовок центрирован посредством margin: auto. Он имеет относительный размер шрифта и ширину в %, пропорциональную ширине экрана, а так же минимальную ширину в em, что не даёт ему деформироваться при малой ширине окна.
/* заголовок галереи */
#gallery > h1 {
width: 25%;
min-width: 7.5em;
padding: 0.25em;
margin: 0.25em auto;
text-align: center;
font-size: 175%;
}Аналогичное форматирование характерно для других блочных элементов с текстом.
/* наименование фотографии */
.photoboxes > li > h2 {
max-width: 10em;
margin: 0.25em auto;
text-align: center;
font-size: 125%;
}
/* описание фотографии */
.photoboxes > li > p {
max-width: 20em;
margin: 0 auto;
font-size: 100%;
}Превью

Предварительный просмотр реализован в виде списка, элементы которого вытянуты в строку с помощью table-cell. При переполнении миниатюрами у нижней границы ленты образуется прокрутка. Внутри ячеек блочные ссылки и изображения миниатюр.
/* лента миниатюр */
.preview {
width: 50%;
min-width: 17.5em;
overflow: auto;
margin: 0.75em auto;
}
/* ячейка с миниатюрой */
.preview > li { display: table-cell; /* ячейки в строку */ }
/* ссылка миниатюры */
.preview > li > a {
display: block;
margin: 0.5em;
padding: 0.5em;
}
/* изображение миниатюры */
.preview > li > a > img {
display: block; /* без лишнего поля снизу */
width: 75px;
height: 75px;
}Фотобоксы
Список фотобоксов центрирован в блоке галереи при помощи inline-block.
/* блок галереи */
#gallery { text-align: center; /* центрирует список фотобокcов */ }
/* список фотобокcов */
.photoboxes { display: inline-block; /* обёртывает содержимое */ }Такое выравнивание позволяет ему обтекать и центрировать содержимое.
Сначала в потоке форматирования только центрированный счётчик. Размер обёртки равен размеру блока счётчика.

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

Изначально фотобокс скрыт и выведен из нормального потока форматирования с помощью абсолютного позиционирования.
/* фотобокc */
.photoboxes > li {
position: absolute; /* «колода» фотобокcов */
visibility: hidden; /* невидимые фотобокcы */
display: block; /* без маркера */
padding: 0.75em;
}В нужный момент он проявляется и позиционируется статично, возвращаясь в поток.
/* фотобокc синхронизированный со ссылкой */
.photoboxes > li:target {
position: static; /* достаём фотобокc из «колоды» */
visibility: visible; /* проявляем фотобокc */
}В нормальном потоке фотобоксы идут друг за другом вертикально. Если мы будем проявлять их, не сложив предварительно в «колоду», то каждый будет отображаться в своей статичной позиции, порой далеко внизу.
Счётчики
Для подсчёта номера и числа фотографий счётчик (photo) ставится в списке фотобоксов на значение 0.
/* список фотобокcов */
.photoboxes { counter-reset: photo; /* счётчик установлен на 0 */ }В каждом следующем фотобоксе значение счётчика на 1 больше, чем в предыдущем.
/* список фотобокcов */
.photoboxes > li { counter-increment: photo; /* +1 к счётчику с каждым фотобокcом */ }В элементе, удалённом из потока нет инкремента счётчика. По этому фотобоксы скрываются (visibility: hidden), а не удаляются (display: none).
Общее число фотографий сохраняется в списке фотобоксов и выводится в его псевдоэлемент.
/* псевдоэлемент со счётчиком общего числа фотографий */
.photoboxes:after {
display: block;
width: 5em;
padding: 0.125em;
margin-left: auto; /* смещает к правому краю */
margin-top: 0.25em; /* отступ от фотобокса */
content: counter(photo) " фото"; /* вывод числа фотографий */
text-align: center;
font-size: 115%;
}Счётчик порядкового номера фотографии печатается в псевдоэлементе фотобокса, в нижнем правом углу.
/* псевдоэлемент со счётчиком порядкового номера фотографии */
.photoboxes > li:after {
display: block; /* счётчик под описанием */
content: "№" counter(photo); /* вывод номера фотографии */
text-align: right; /* номер в нижнем правом углу */
font-size: 105%;
}Загрузка
Прежде всего, создаётся псевдоэлемент, в который будет загружаться фотография.
/* псевдоэлемент с фотографией */
.photoboxes > li:before {
display: block;
padding: 0.75em;
margin: 0 auto; /* центрирует блок */
text-align: center; /* центрирует фотографию */
}Чтобы размеры фотобокса не изменялись в процессе загрузки, у псевдоэлемента прописываются ширина и высота фотографии.
/* горизонтальные фотографии */
#photobox-id:before {
width: 300px;
height: 225px;
}
Схема загрузки фотографии следующая: активируем ссылку миниатюры, она синхронизируется с соответствующим фотобоксом по
/* загрузка фотографий в соответствующие фотобоксы при активации ссылки */
#photobox-id:target:before { content: url("photo.jpeg"); }Ссылки
Ссылка на
Аргументом в пользу ссылок такого типа является возможность использования браузерной навигации на странице (next/prev/reload). В принципе, фотографии в данной галерее можно загружать, используя лишь адресную строку. При этом они будут загружаться в фотобокс.
Поддержка
Приведённый пример корректно и идентично поддерживается всеми вышеупомянутыми браузерами. В Internet Explorer не работает, т. к. IE 6 и 7 не поддерживают псевдоэлементы, свойство content и счётчики. Ключевой псевдокласс :target не поддерживает даже IE 8.
Реализация для IE возможна через AJAX или эмуляцию псевдоклассов со вставкой элементов.
Если требуется эффектное JS-решение для проекта с поддержкой IE — вполне подойдёт
Благодарности
Спасибо
P. S. Если не понравилось выделение ссылок — посмотрите



комментарии (71)