Верстка интернет-магазина: список товаров


403df77cd5384b729a9721a3eb9fbd05.png

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


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


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


Адаптивная сетка


Итак, начнем с создания адаптивных плиток — будущих карточек товаров. У нас будет 8 комнатных растений:



Оберткой для товаров послужат блоки, занимающие 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, весь список имеет нежелательный отступ справа.


c340566ef0c145f9bfb92f261f5d8beb.png

Исправим это с помощью отрицательного значения margin-right у родителя.


.products {
	list-style: none;
	margin: 0 -20px 0 0;
	padding: 0;
}

Теперь все в порядке. Посмотреть на получившуюся сетку можно на страничке демо. Для наглядности блокам в демо задана фиксированная высота.


Фото товаров


Следующим интересным моментом является верстка блоков с фотографиями растений. Разметка в данном случае будет такой:



Сделаем родителя тега 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);
}

Как все это работает можно посмотреть на примере демо.


Описание товара


6feadff0a9dd4b34aad10d2f6335c6b0.pngНам нужно, во-первых, задать описанию товара высоту в четыре строки, а во-вторых, сделать конец последней строки слегка размытым.

Первую задачу можно решить, задав высоту параграфа с описанием, равную четырем 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));
}

Перечеркнутые цены


6a64d984d3224db9b48b8bd81e3abcc7.png

Чтобы перечеркнуть цену линией отличной по цвету от текста, задаем блоку с ценой значение color равное #ff3535 и text-decoration — line-through. При этом устанавливаем для вложенных элементов серый цвет текста.


.product-price-old b,
.product-price-old small {
	color: #888;
}

Всплывающие кнопки


97bf0cdc80d74622bfb2ef7920efb687.png

Что касается кнопки «Быстрый просмотр», ее реализация сравнительно проста. Кнопка абсолютно позиционирована относительно блока с классом .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 занимает всю площадь карточки.


96ff90000d044466bf13098d9d382271.png

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


Переключение вида карточек товаров


a265a2c67ae844c6a044b208987b6c56.png

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



По клику на кнопки у списка товаров удаляется и добавляется класс .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);
}

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

Комментарии (3)

  • 11 января 2017 в 11:43

    0

    При ховере есть неприятный скачёк — видимо из-за тени.
    В версии для телефона невозможно нажать на кнопки — их просто нет.
  • 11 января 2017 в 11:45

    0

    При масштабе 150% и наведении мышки на плитку:
    Скриншот с Оперы
    image
  • 11 января 2017 в 11:47

    0

    Я одного не пойму, почему как только нужна группа каких-то однородных элементов, так сразу непременно используется ul и его друзья? В каждой второй верстке обязательно ul. Особенно на плагинах, которые должны выдавать иерархию, будь то меню или дерево — обязательно висит ul. Да в половине сладеров-крутилок — обязательно ul. Сидишь и наблюдаешь, как дерево с точками красиво трансформируется в то что надо.

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

    Загадка…

© Habrahabr.ru