
Требования к верстке каталогов интернет-магазинов имеют свойство повторяться из проекта в проект. Поэтому у меня выработался набор стандартных приемов, которыми я хочу поделиться в этой статье.
Некоторые приемы уже были рассмотрены в различных статьях. Однако у меня возникло желание объединить их и проиллюстрировать отдельными демо. Надеюсь, в таком виде наработки окажутся полезны верстальщикам, которым часто приходится работать над интернет-магазинами.
В качестве примера мы будем верстать список товаров для интернет-магазина комнатных растений. Демо готового каталога можно посмотреть по ссылке. В результате должен получиться список растений с фото, описаниями и всплывающими кнопками. Кроме того, вид списка можно будет переключать: товары будут выглядеть либо как плитка, либо как таблица.
Адаптивная сетка
Итак, начнем с создания адаптивных плиток — будущих карточек товаров. У нас будет 8 комнатных растений:
<ul class="products clearfix"> <li class="product-wrapper"> <a href="" class="product"></a> </li> <li class="product-wrapper"> <a href="" class="product"></a> </li> <li class="product-wrapper"> <a href="" class="product"></a> </li> <li class="product-wrapper"> <a href="" class="product"></a> </li> <li class="product-wrapper"> <a href="" class="product"></a> </li> <li class="product-wrapper"> <a href="" class="product"></a> </li> <li class="product-wrapper"> <a href="" class="product"></a> </li> <li class="product-wrapper"> <a href="" class="product"></a> </li> </ul>
Оберткой для товаров послужат блоки, занимающие 100% ширины родителя на мобильных устройствах.
.product-wrapper { display: block; width: 100%; float: left; transition: width .2s; }
Теперь используем медиа-запросы, чтобы разместить по две, три и четыре плитки в ряд при больших разрешениях монитора.
@media only screen and (min-width: 450px) { .product-wrapper { width: 50%; } } @media only screen and (min-width: 768px) { .product-wrapper { width: 33.333%; } } @media only screen and (min-width: 1000px) { .product-wrapper { width: 25%; } }
И зададим стили карточек товаров.
.product { display: block; border: 1px solid #b5e9a7; border-radius: 3px; position: relative; background: #fff; margin: 0 20px 20px 0; text-decoration: none; color: #474747; z-index: 0; height: 300px; }
Из-за того, что карточки имеют margin-right равный 20px, весь список имеет нежелательный отступ справа.

Исправим это с помощью отрицательного значения margin-right у родителя.
.products { list-style: none; margin: 0 -20px 0 0; padding: 0; }
Теперь все в порядке. Посмотреть на получившуюся сетку можно на страничке демо. Для наглядности блокам в демо задана фиксированная высота.
Фото товаров
Следующим интересным моментом является верстка блоков с фотографиями растений. Разметка в данном случае будет такой:
<div class="product-photo"> <img src="images/roses/1.jpg" alt=""> </div>
Сделаем родителя тега img квадратом с помощью свойства padding-bottom со значением 100%. Вот все стили для данного блока.
.product-photo { position: relative; padding-bottom: 100%; overflow: hidden; }
В указанном блоке расположим картинку таким образом, чтобы при любых размерах она не выходила за пределы родителя, и отцентрируем ее горизонтально и вертикально.
.product-photo img { position: absolute; top: 0; bottom: 0; left: 0; right: 0; max-width: 100%; max-height: 100%; margin: auto; transition: transform .4s ease-out; }
Осталось немного увеличивать фото при наведении.
.product:hover .product-photo img { transform: scale(1.05); }
Как все это работает можно посмотреть на примере демо.
Описание товара
Нам нужно, во-первых, задать описанию товара высоту в четыре строки, а во-вторых, сделать конец последней строки слегка размытым.Первую задачу можно решить, задав высоту параграфа с описанием, равную четырем line-heigth.
.product p { position: relative; margin: 0; font-size: 1em; line-height: 1.4em; height: 5.6em; overflow: hidden; }
А эффекта размытия последних букв четвертой строки мы добьемся с помощью псевдоэлемента :after с линейным градиентом в качестве фона.
.product p:after { content: ''; display: inline-block; position: absolute; bottom: 0; right: 0; width: 4.2em; height: 1.6em; background: linear-gradient(to left top, #fff, rgba(255, 255, 255, 0)); }
Перечеркнутые цены

Чтобы перечеркнуть цену линией отличной по цвету от текста, задаем блоку с ценой значение color равное #ff3535 и text-decoration — line-through. При этом устанавливаем для вложенных элементов серый цвет текста.
.product-price-old b, .product-price-old small { color: #888; }
Всплывающие кнопки

Что касается кнопки «Быстрый просмотр», ее реализация сравнительно проста. Кнопка абсолютно позиционирована относительно блока с классом .product-photo, скрыта с помощью opacity: 0 и немного сдвинута вниз за счет transition: translateY(2em). При наведении курсора на карточку товара стили кнопки меняются следующим образом.
.product:hover .product-preview { transform: translateY(0); opacity: 1; }
Несколько сложнее дело обстоит с кнопками «В корзину» и «Купить в 1 клик». Здесь внешний контейнер .product-buttons-wrap абсолютно позиционирован в блоке .product и равен родителю по ширине и высоте.
.product-buttons-wrap { position: absolute; top: 0; left: -1px; right: -1px; bottom: 0; visibility: hidden; opacity: 0; transform: scaleY(.8); transform-origin: top; transition: transform .2s ease-out; z-index: -1; backface-visibility: hidden; }
Далее мы стилизуем псевдоэлемент .product-buttons-wrap:before таким образом, чтобы он вытеснял любой контент блока вниз, под нижнюю границу, блока-родителя.
.product-buttons-wrap:before { content: ""; float: left; height: 100%; width: 100%; }
Теперь можно добавить собственно контент — кнопки, размещенные в блоке .buttons.
.buttons { position: relative; top: -1px; padding: 20px; background: #fff; box-shadow: 0 0 20px rgba(0, 0, 0, .5); border: 1px solid #56bd4b; border-radius: 3px; }
Благодаря правилу float: left у псевдоэлемента .product-buttons-wrap:before, кнопки расположены ниже основного контента, и блок .buttons занимает всю площадь карточки.

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

Для переключения между плиткой и табличным видом каталога мы создаем две кнопки.
<div class="layout-buttons"> <span class="active icon icon-list"></span> <span class="icon icon-table"></span> </div>
По клику на кнопки у списка товаров удаляется и добавляется класс .table-layout.
$productList.toggleClass('table-layout');
Таким образом, прописав стили для карточек-дочерних элементов блока ul.table-layout, мы можем «превратить» список в таблицу только с помощью CSS, без перезагрузки страницы. Для этого задается ширина карточек равная 100%. А вложенные блоки теперь займут только часть ширины карточки, например:
.table-layout .product-main { width: 50%; float: left; background: #fff; }
Далее абсолютно позиционированные элементы занимают свое «естественное» положение. Например, так происходит с кнопками.
.table-layout .product-buttons-wrap { position: static; visibility: visible; opacity: 1; transform: scaleY(1); }
Это был последний момент, которым хотелось с вами поделиться. С праздниками и всего доброго.
