×

产品网格布局-Filterable Product Grid

产品网格布局-Filterable Product Grid
This Blueprint is a responsive Isotope-powered product grid layout where each grid item is a Flickity image slider. A small cart icon animation indicates that a product was added to the shopping cart. The product filter utilizes the Isotope filter functionality. Some example media queries are used to show how to make the layout adaptive.
这个是一个敏感的同位素动力产品网格布局,每个网格项目是一个flickity图像滑块,一个小型车图标动画表明一个产品被添加到购物车,产品过滤器利用同位素过滤器功能,可以点击下面查看演示。

查看演示 下载资源

HTML

<!-- Bottom bar with filter and cart info -->
<div class="bar">
    <div class="filter">
        <span class="filter__label">Filter: </span>
        <button class="action filter__item filter__item--selected" data-filter="*">All</button>
        <button class="action filter__item" data-filter=".jackets">
            <i class="icon icon--jacket"></i>
            <span class="action__text">Jackets</span>
        </button>
        <button class="action filter__item" data-filter=".shirts">
        	<i class="icon icon--shirt"></i>
        	<span class="action__text">Shirts</span>
        </button>
        <button class="action filter__item" data-filter=".dresses">
        	<i class="icon icon--dress"></i>
        	<span class="action__text">Dresses</span>
        </button>
        <button class="action filter__item" data-filter=".trousers">
        	<i class="icon icon--trousers"></i>
        	<span class="action__text">Trousers</span>
        </button>
        <button class="action filter__item" data-filter=".shoes">
        	<i class="icon icon--shoe"></i>
        	<span class="action__text">Shoes</span>
        </button>
    </div>
    <button class="cart">
        <i class="cart__icon fa fa-shopping-cart"></i>
        <span class="text-hidden">Shopping cart</span>
        <span class="cart__count">0</span>
    </button>
</div>
<!-- Main view -->
<div class="view">
    <!-- Grid -->
    <section class="grid">
	<!-- Loader -->
	<img class="grid__loader" src="images/grid.svg" width="60" alt="Loader image" />
        <!-- Grid sizer for a fluid Isotope (Masonry) layout -->
        <div class="grid__sizer"></div>
        <!-- Grid items -->
        <div class="grid__item shirts">
            <div class="slider">
                <div class="slider__item"><img src="images/product1/1.png" alt="product1_1" /></div>
                <div class="slider__item"><img src="images/product1/2.png" alt="product1_2" /></div>
                <div class="slider__item"><img src="images/product1/3.png" alt="product1_3" /></div>
            </div>
            <div class="meta">
                <h3 class="meta__title">Miriam Classic</h3>
                <span class="meta__brand">Miriam</span>
                <span class="meta__price">$79</span>
            </div>
            <button class="action action--button action--buy">
                <i class="fa fa-shopping-cart"></i>
                <span class="text-hidden">Add to cart</span>
            </button>
        </div>
        <div class="grid__item grid__item--size-a jackets">
            <!-- ... -->
        </div>
        <div class="grid__item shoes">
            <!-- ... -->
        </div>
        <div class="grid__item dresses">
            <!-- ... -->
        </div>
        <div class="grid__item trousers">
            <!-- ... -->
        </div>
    </section>
    <!-- /grid-->
</div>
<!-- /view -->
<script src="js/isotope.pkgd.min.js"></script>
<script src="js/flickity.pkgd.min.js"></script>
<script src="js/main.js"></script>

CSS

/* Product grid */

.grid {
	position: relative;
	overflow: hidden;
	max-width: 1300px;
	margin: 0 auto;
	padding: 1.5em 0 8em;
	text-align: center;
}

/* Loader */
.grid__loader {
	display: none;
	margin: 3em auto 0;
}

.grid--loading .grid__loader {
	display: block;
}

/* Clearfix */

.grid:after {
	content: '';
	display: block;
	clear: both;
}

/* Grid items */

.grid__sizer,
.grid__item {
	position: relative;
	float: left;
	width: 20%;
	padding: .75em;
}

.no-touch .grid__sizer,
.no-touch .grid__item {
	padding: .75em .75em 1.25em;
}

.grid--loading .grid__item {
	visibility: hidden;
}

.grid__item--size-a {
	width: 40%;
}

/* Gallery */

.slider {
	padding: 0;
	border-radius: 5px;
	background: #24252a;
}

.no-touch .slider {
	padding: 0 0 1.25em;
}

.slider__item {
	width: 100%;
	padding: 1em;
}

.slider__item img {
	width: 100%;
}
/* Flickity page dots */

.slider .flickity-page-dots {
	bottom: 20px;
	opacity: 0;
	-webkit-transition: opacity .3s;
	transition: opacity .3s;
}

.no-touch .slider:hover .flickity-page-dots {
	opacity: 1;
}

.slider .flickity-page-dots .dot {
	background: #131417;
}

/* Product meta */

.meta {
	position: relative;
	margin: 10px 0 0;
	padding: 0 60px 0 0;
	text-align: left;
}

.meta__brand {
	font-size: .85em;
	font-weight: bold;
	display: block;
	color: #595b64;
}

.meta__title {
	font-size: .95em;
	font-weight: bold;
	margin: 0;
	padding: .4em 0 .1em;
}

.meta__price {
	font-size: .95em;
	font-weight: bold;
	position: absolute;
	top: .45em;
	right: .25em;
	color: #595b64;
}

/* Action style */

.action {
	font-family: Avenir, 'Helvetica Neue', 'Lato', 'Segoe UI', Helvetica, Arial, sans-serif;
	font-size: 1.05em;
	position: relative;
	overflow: hidden;
	margin: 0;
	padding: .25em;
	cursor: pointer;
	color: #fff;
	border: none;
	background: none;
}

.action:focus {
	outline: none;
}

.action--button {
	color: #5c5edc;
}

.no-touch .action--button:hover {
	color: #fff;
	outline: none;
}

.text-hidden {
	position: absolute;
	top: 200%;
}

/* Add to cart button */

.action--buy {
	position: absolute;
	top: 0;
	right: 0;
	padding: 1.85em 2.35em;
	-webkit-transition: opacity .3s, -webkit-transform .3s;
	transition: opacity .3s, transform .3s;
	-webkit-transform: translate3d(-5px, 0, 0);
	transform: translate3d(-5px, 0, 0);
}

.no-touch .action--buy {
	opacity: 0;
}

.no-touch .grid__item:hover .action--buy {
	opacity: 1;
	-webkit-transform: translate3d(0, 0, 0);
	transform: translate3d(0, 0, 0);
}

/* Fixed bottom bar */

.bar {
	position: fixed;
	z-index: 100;
	bottom: 0;
	left: 0;
	width: 100%;
	padding: 1.75em 5em;
	text-align: center;
	background: #191a1b;
	-webkit-transform: translate3d(0, 0, 0);
	/* Fix for Chrome flicker on Mac ...party like we're in 2012! */
}

.flexbox .filter {
	display: -webkit-flex;
	display: flex;
	-webkit-align-items: center;
	align-items: center;
	-webkit-justify-content: center;
	justify-content: center;
}

/* Filter */

.filter__label {
	font-size: .85em;
	display: inline-block;
	margin: 0 2%;
	font-weight: bold;
	color: #393A3F;
}

.filter__item {
	font-weight: bold;
	margin: 0 2%;
	padding: .1em;
	vertical-align: middle;
	color: #a3a3b3;
	border-bottom: 2px solid transparent;
}

.filter__item--selected {
	color: #5c5edc;
	border-color: #5c5edc;
}

.filter__item .icon {
	font-size: 1.75em;
	display: none;
}

/* Shopping cart */

.cart {
	font-size: 1.5em;
	position: absolute;
	top: 0;
	right: 0;
	overflow: hidden;
	height: 100%;
	padding: 0 1.195em;
	cursor: pointer;
	color: #abacae;
	border: none;
	background-color: #131415;
}

.no-touch .cart:focus,
.no-touch .cart:hover {
	color: #fff;
	outline: none;
}

.cart--animate .cart__icon {
	-webkit-animation: cartAnim .4s forwards;
	animation: cartAnim .4s forwards;
}

@-webkit-keyframes cartAnim {
	50% {
		opacity: 0;
		-webkit-transform: translate3d(50px, 0, 0);
		transform: translate3d(50px, 0, 0);
	}
	51% {
		opacity: 0;
		-webkit-transform: translate3d(-50px, 0, 0);
		transform: translate3d(-50px, 0, 0);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0);
		transform: translate3d(0, 0, 0);
	}
}

@keyframes cartAnim {
	50% {
		opacity: 0;
		-webkit-transform: translate3d(50px, 0, 0);
		transform: translate3d(50px, 0, 0);
	}
	51% {
		opacity: 0;
		-webkit-transform: translate3d(-50px, 0, 0);
		transform: translate3d(-50px, 0, 0);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0);
		transform: translate3d(0, 0, 0);
	}
}

.cart__count {
	font-size: 9px;
	font-weight: bold;
	line-height: 15px;
	position: absolute;
	top: 50%;
	right: 20px;
	width: 15px;
	height: 15px;
	margin: -16px 0 0 0;
	text-align: center;
	color: #fff;
	border-radius: 50%;
	background: #5c5edc;
}

.cart--animate .cart__count {
	-webkit-animation: countAnim .4s forwards;
	animation: countAnim .4s forwards;
}

@-webkit-keyframes countAnim {
	50% {
		opacity: 0;
		-webkit-transform: translate3d(0, 80px, 0);
		transform: translate3d(0, 80px, 0);
	}
	51% {
		opacity: 0;
		-webkit-transform: translate3d(0, -80px, 0);
		transform: translate3d(0, -80px, 0);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0);
		transform: translate3d(0, 0, 0);
	}
}

@keyframes countAnim {
	50% {
		opacity: 0;
		-webkit-transform: translate3d(0, 80px, 0);
		transform: translate3d(0, 80px, 0);
	}
	51% {
		opacity: 0;
		-webkit-transform: translate3d(0, -80px, 0);
		transform: translate3d(0, -80px, 0);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0);
		transform: translate3d(0, 0, 0);
	}
}
/* Resize grid items on smaller screens */

@media screen and (max-width: 65em) {
	.grid__sizer,
	.grid__item,
	.grid__item--size-a {
		width: 33.333%;
	}
}

@media screen and (max-width: 50em) {
	.grid__sizer,
	.grid__item,
	.grid__item--size-a {
		width: 50%;
	}
	.bar {
		padding-left: 0;
		text-align: left;
	}
}

@media screen and (max-width: 40em) {
	.bar {
		padding: .5em 4.5em .5em 0;
	}
	.flexbox .filter {
		-webkit-justify-content: space-around;
		justify-content: space-around;
	}
	.filter__item {
		height: 100%;
		padding: .5em .1em;
		border: none;
	}
	.filter__item .icon {
		display: inline-block;
	}
	.filter__label,
	.action__text {
		display: none;
	}
	.cart {
		padding: 0 1em;
	}
}

@media screen and (max-width: 25em) {
	.grid {
		max-width: 75%;
	}
	.grid__loader {
		margin: 0 auto;
	}
	.grid__sizer,
	.grid__item,
	.grid__item--size-a {
		width: 100%;
	}
	.action--buy {
		font-size: 1.5em;
		padding: 1.15em 1.5em;
		-webkit-tap-highlight-color: transparent;
	}
}

JavaScript

/**
 * main.js
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2015, Codrops
 * http://www.codrops.com
 */
;(function(window) {

	'use strict';

	var support = { animations : Modernizr.cssanimations },
		animEndEventNames = { 'WebkitAnimation' : 'webkitAnimationEnd', 'OAnimation' : 'oAnimationEnd', 'msAnimation' : 'MSAnimationEnd', 'animation' : 'animationend' },
		animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],
		onEndAnimation = function( el, callback ) {
			var onEndCallbackFn = function( ev ) {
				if( support.animations ) {
					if( ev.target != this ) return;
					this.removeEventListener( animEndEventName, onEndCallbackFn );
				}
				if( callback && typeof callback === 'function' ) { callback.call(); }
			};
			if( support.animations ) {
				el.addEventListener( animEndEventName, onEndCallbackFn );
			}
			else {
				onEndCallbackFn();
			}
		};

	// from http://www.sberry.me/articles/javascript-event-throttling-debouncing
	function throttle(fn, delay) {
		var allowSample = true;

		return function(e) {
			if (allowSample) {
				allowSample = false;
				setTimeout(function() { allowSample = true; }, delay);
				fn(e);
			}
		};
	}

	// sliders - flickity
	var sliders = [].slice.call(document.querySelectorAll('.slider')),
		// array where the flickity instances are going to be stored
		flkties = [],
		// grid element
		grid = document.querySelector('.grid'),
		// isotope instance
		iso,
		// filter ctrls
		filterCtrls = [].slice.call(document.querySelectorAll('.filter > button')),
		// cart
		cart = document.querySelector('.cart'),
		cartItems = cart.querySelector('.cart__count');

	function init() {
		// preload images
		imagesLoaded(grid, function() {
			initFlickity();
			initIsotope();
			initEvents();
			classie.remove(grid, 'grid--loading');
		});
	}

	function initFlickity() {
		sliders.forEach(function(slider){
			var flkty = new Flickity(slider, {
				prevNextButtons: false,
				wrapAround: true,
				cellAlign: 'left',
				contain: true,
				resize: false
			});

			// store flickity instances
			flkties.push(flkty);
		});
	}

	function initIsotope() {
		iso = new Isotope( grid, {
			isResizeBound: false,
			itemSelector: '.grid__item',
			percentPosition: true,
			masonry: {
				// use outer width of grid-sizer for columnWidth
				columnWidth: '.grid__sizer'
			},
			transitionDuration: '0.6s'
		});
	}

	function initEvents() {
		filterCtrls.forEach(function(filterCtrl) {
			filterCtrl.addEventListener('click', function() {
				classie.remove(filterCtrl.parentNode.querySelector('.filter__item--selected'), 'filter__item--selected');
				classie.add(filterCtrl, 'filter__item--selected');
				iso.arrange({
					filter: filterCtrl.getAttribute('data-filter')
				});
				recalcFlickities();
				iso.layout();
			});
		});

		// window resize / recalculate sizes for both flickity and isotope/masonry layouts
		window.addEventListener('resize', throttle(function(ev) {
			recalcFlickities()
			iso.layout();
		}, 50));

		// add to cart
		[].slice.call(grid.querySelectorAll('.grid__item')).forEach(function(item) {
			item.querySelector('.action--buy').addEventListener('click', addToCart);
		});
	}

	function addToCart() {
		classie.add(cart, 'cart--animate');
		setTimeout(function() {cartItems.innerHTML = Number(cartItems.innerHTML) + 1;}, 200);
		onEndAnimation(cartItems, function() {
			classie.remove(cart, 'cart--animate');
		});
	}

	function recalcFlickities() {
		for(var i = 0, len = flkties.length; i < len; ++i) {
			flkties[i].resize();
		}
	}

	init();

})(window);

人已赞赏
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索