Si quieres crear un portfolio y poder filtrarlo por categorías, puedes hacerlo solo utilizando CSS y jQuery. Además podrás crear unos efectos animados que le van a encantar a los visitantes de la página web.

En este artículo te propongo dos diferentes para que puedas escoger el que prefieras.

 

MixItUp

Para ello tienes que crear el archivo html, el css y añadir el jQuery mediante el plugin MixItUp.

 

HTML

Tendrá el siguiente código:

<header class="cd-header">
<h1>Content Filter</h1>
</header>

<main class="cd-main-content">

<div class="cd-tab-filter-wrapper">

<div class="cd-tab-filter">

<ul class="cd-filters">

<li class="placeholder">
<a data-type="all" href="#0">All</a> <!-- selected option on mobile -->
</li>

<li class="filter"><a class="selected" href="#0" data-type="all">All</a></li>

<li class="filter" data-filter=".color-1"><a href="#0" data-type="color-1">Color 1</a></li>

<li class="filter" data-filter=".color-2"><a href="#0" data-type="color-2">Color 2</a></li>

</ul> <!-- cd-filters -->

</div> <!-- cd-tab-filter -->

</div> <!-- cd-tab-filter-wrapper -->


<section class="cd-gallery">

<ul>
<li class="mix color-1 check1 radio2 option3"><img src="img/img-1.jpg" alt="Image 1"></li>
<li class="mix color-2 check2 radio2 option2"><img src="img/img-2.jpg" alt="Image 2"></li>
<li><!-- ... --></li>
<li class="gap"></li>
</ul>

<div class="cd-fail-message">No results found</div>

</section> <!-- cd-gallery -->

<div class="cd-filter">

<form>
<div class="cd-filter-block">
<h4>Block title</h4>
<div class="cd-filter-content">
<!-- filter content -->
</div> <!-- cd-filter-content -->
</div> <!-- cd-filter-block -->
</form>

<a href="#0" class="cd-close">Close</a>

</div> <!-- cd-filter -->

<a href="#0" class="cd-filter-trigger">Filters</a>

</main> <!-- cd-main-content -->

 

Es importante que respetes los estilos, si los cambias tenlo en cuenta para cambiarlos también en el archivo css.

 

CSS

En estos estilos podrás ver muchas transiciones y transformaciones que son necesarias para conseguir que filtre correctamente nuestro contenido.

Aquí te dejo el código del css:

.cd-tab-filter-wrapper {

 background-color: #ffffff;
 z-index: 1;

}

.cd-filter {

position: absolute;
top: 0;
left: 0;
width: 280px;
height: 100%;
background: #ffffff;
z-index: 2;
transform: translateX(-100%);
transition: transform 0.3s, box-shadow 0.3s;

} 

.cd-filter-trigger {

position: absolute;
top: 0;
left: 0;
height: 50px;
width: 60px;
z-index: 3;

}

.cd-main-content.is-fixed .cd-tab-filter-wrapper {

position: fixed;
top: 0;
left: 0;
width: 100%;

}

.cd-main-content.is-fixed .cd-filter {

position: fixed;
height: 100vh;
overflow: hidden;

}

.cd-main-content.is-fixed .cd-filter-trigger {

position: fixed;

}

 

 

El resultado

filtrar-contenido-css-jquery

En la página web del autor puedes ver una demo donde se filtran los contenidos por colores. También te puedes descargar todos los archivos (html, css y jQuery) gratis.

 

 

Blueprint: Filterable Product Grid

Es otro plugin para filtrar contenido. Igual que el anterior te lo divido por partes: en html, en css, javascript y el resultado.

 

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;
	}
}

 

Javacript

/**
 * 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);

 

El resultado

Después de todo el código viene el resultado final:

Filtrar contenido con CSS y jQuery

Igual que en el ejemplo anterior, en la página web del autor puedes ver una demo, así como también descargar todos los archivos.

 

Y con esto, este artículo se ha acabado. ¿Te animas a poner en práctica alguno de estos plugins?