Concevoir un portfolio responsive avec filtre via Isotope.js sous WordPress

Un thème premium qui se respecte comporte des modèles de pages de type portfolio, très utile pour mettre en valeur vos créations artistiques notamment. La plupart d’entre eux sont dotés d’un système de filtre basé sur les termes d’une taxonomie spécialement créée pour l’occasion et le redimensionnement de la fenêtre réajuste automatiquement les éléments avec une transition en CSS3. Ce tutoriel va vous apprendre comment mettre en place un tel système sous WordPress et sans avoir recours à un plugin.

Avant-propos

Ce tutoriel est réservé à des utilisateurs avertis. Elle requiert de multiples connaissances de base en termes d’intégration, de développement Web et plus. Il serait impossible de tout expliquer ligne par ligne d’où cet avertissement. Les utilisateurs peu à l’aise avec le code préféreront le recours à un plugin.

Résultat final / démonstration

Une démonstration est disponible sur mon site Neticpro et une variante sur le site de ddesign.

Les sites ayant subi une refonte, seules les captures d’écran ci-dessous illustrent le propos.

wpchannel-isotope-portfolio-1
Mon portfolio (pas mis à jour) avec ouverture d’une détaillée
wpchannel-isotope-portfolio-2
Le portfolio de Christèle & Déborah avec effet fancyBox

Étape n°1 – Création du custom post type ‘Portfolio’

Il nous faut dans un premier temps générer un type de contenu sur-mesure qui sera entièrement dédié à la saisie des éléments du portfolio.

Récupérez donc ce code à insérer dans votre fichier functions.php (ou dans un fichier dédié pour ceux qui veulent aller plus loin) :

/* Portfolio */
function cpt_ntp_portfolio() {
$labels = array(
 'name' => _x( 'Portfolio', 'Post Type General Name', 'ntp_framework' ),
 'singular_name' => _x( 'Portfolio', 'Post Type Singular Name', 'ntp_framework' ),
 'menu_name' => __( 'Portfolio', 'ntp_framework' ),
 'parent_item_colon' => __( 'Portfolio parent :', 'ntp_framework' ),
 'all_items' => __( 'Tous les portfolios', 'ntp_framework' ),
 'view_item' => __( 'Voir le portfolio', 'ntp_framework' ),
 'add_new_item' => __( 'Ajouter un portfolio', 'ntp_framework' ),
 'add_new' => __( 'Nouveau portfolio', 'ntp_framework' ),
 'edit_item' => __( 'Editer un portfolio', 'ntp_framework' ),
 'update_item' => __( 'Mettre à jour le portfolio', 'ntp_framework' ),
 'search_items' => __( 'Rechercher des produits', 'ntp_framework' ),
 'not_found' => __( 'Aucun portfolio trouvé', 'ntp_framework' ),
 'not_found_in_trash' => __( 'Aucun portfolio trouvé dans la corbeille', 'ntp_framework' ),
 );
 $rewrite = array(
 'slug' => 'portfolio',
 'with_front' => true,
 'pages' => false,
 'feeds' => false,
 );
 $args = array(
 'label' => __( 'portfolio', 'ntp_framework' ),
 'description' => __( 'Les créations de votre entreprise', 'ntp_framework' ),
 'labels' => $labels,
 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', ),
 'taxonomies' => array( 'type' ),
 'hierarchical' => false,
 'public' => true,
 'show_ui' => true,
 'show_in_menu' => true,
 'show_in_nav_menus' => true,
 'show_in_admin_bar' => true,
 'menu_position' => 20,
 'menu_icon' => '',
 'can_export' => true,
 'has_archive' => true,
 'exclude_from_search' => true,
 'publicly_queryable' => true,
 'query_var' => 'portfolio',
 'rewrite' => $rewrite,
 'capability_type' => 'page',
 );
 register_post_type( 'portfolio', $args );
}
add_action( 'init', 'cpt_ntp_portfolio', 0 );

Vous pouvez changer le textdomain par le vôtre, à la place de ntp_framework.

Vérifiez que le type de contenu apparaît bien dans votre administration WordPress puis ajoutez quelques éléments d’exemples.

Aucun champ particulier n’a été ajouté, notez que l’image à la une nous servira pour afficher les vignettes dans la galerie.

Étape n°2 – Création de la taxonomie personnalisée ‘Type’

Il s’agit ni plus ni moins que des catégories liées au items du portfolio. Je l’ai nommé Type pour l’exemple :

/* Type */
function ct_ntp_type() {
$labels = array(
 'name' => _x( 'Types', 'Taxonomy General Name', 'ntp_framework' ),
 'singular_name' => _x( 'Type', 'Taxonomy Singular Name', 'ntp_framework' ),
 'menu_name' => __( 'Types', 'ntp_framework' ),
 'all_items' => __( 'Tous les types', 'ntp_framework' ),
 'parent_item' => __( 'Type parent', 'ntp_framework' ),
 'parent_item_colon' => __( 'Type parent :', 'ntp_framework' ),
 'new_item_name' => __( 'Nouveau type', 'ntp_framework' ),
 'add_new_item' => __( 'Ajouter un type', 'ntp_framework' ),
 'edit_item' => __( 'Editer un type', 'ntp_framework' ),
 'update_item' => __( 'Mettre à jour', 'ntp_framework' ),
 'separate_items_with_commas' => __( 'Séparer les types par des virgules', 'ntp_framework' ),
 'search_items' => __( 'Rechercher des types', 'ntp_framework' ),
 'add_or_remove_items' => __( 'Ajouter ou supprimer des types', 'ntp_framework' ),
 'choose_from_most_used' => __( 'Choisir parmi les types les plus utilisés', 'ntp_framework' ),
 );
 $rewrite = array(
 'slug' => 'type',
 'with_front' => true,
 'hierarchical' => true,
 );
 $args = array(
 'labels' => $labels,
 'hierarchical' => true,
 'public' => true,
 'show_ui' => true,
 'show_admin_column' => true,
 'show_in_nav_menus' => true,
 'show_tagcloud' => true,
 'query_var' => 'type',
 'rewrite' => $rewrite,
 );
 register_taxonomy( 'type', 'portfolio', $args );
}
add_action( 'init', 'ct_ntp_type', 0 );

Étape n°3 – Création de la page d’archive du portfolio

A présent que les données sont saisies dans le back-office de WordPress, il nous faut les afficher. Avec les types de contenu personnalisé, on reprend simplement la hiérarchie des thèmes WordPress, à savoir :

  • archive-portfolio.php : la page qui affichera la liste complète des éléments dont le lien correspondra au nom du type de contenu (à moins que vous n’ayez passé des règles de réécriture) ;
  • single-portfolio.php : pour afficher le détail d’un item du portfolio ;

Le premier fichier est le plus important, le second facultatif si bien que nous ne l’utiliserons pas dans ce tutoriel afin de simplifier.

Voici un exemple de fichier archive-portfolio.php, je dis un exemple dans la mesure où vous devrez l’adapter en fonction de votre thème en reprenant la même structure HTML / CSS.

Notez que le code est basé sur le framework Bootstrap 2.3 pour les aspects responsive. Je compte le passer en Bootstrap 3.0 prochainement.

/* Page d’archive du portfolio */

<?php get_header(); ?>
<div id="content" class="container">
	<div class="row">
		<div id="main" class="span12" role="main">

			<div class="page-header">
				<h1 class="archive_title h2">
					<?php post_type_archive_title(); ?> - <small><?php _e('Some of our best work', 'ntp_framework'); ?></small>
				</h1>
			</div>

			<?php 
				$terms = get_terms("type"); 
				$count = count($terms); 
				echo '<ul id="portfolio-filter" class="filter">'; 
				echo '<li class="active-tag btn btn-small"><a href="#all" data-filter="*" title="Tout">Tout</a></li>'; 
				if ( $count > 0 ) { 
					foreach ( $terms as $term ) { 
						$termname = ($term->slug); 
						echo ' <li class="btn btn-small"><a href="#'.$termname.'" title="" data-filter=".'.$termname.'" rel="'.$termname.'">'.$term->name.'</a></li>'; 
					} 
				} 
				echo "</ul>"; 
			?>

			<div id="portfolio-wrapper">
				<ul id="portfolio-list" class="thumbnails isotope">

				<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

					<li id="post-<?php the_ID(); ?>" <?php post_class('item-portfolio'); ?> role="article">
						<?php
							$image_id = get_post_thumbnail_id();
							$image_url = wp_get_attachment_image_src($image_id, 'large');
							$image_url = $image_url[0];
						?>

						<a class="fancybox thumbnail" id="post-<?php the_ID(); ?>" href="<?php echo $image_url ?>" title="<?php the_title_attribute(); ?>"><?php the_post_thumbnail('medium', array('class' => 'aligncenter photo')); ?></a>
					</li>

				<?php endwhile; ?> 

				<?php else : ?>

					<article id="post-not-found">
						<header>
							<h1><?php _e("No portfolio yet", "ntp_framework"); ?></h1>
						</header>

						<section class="post_content">
							<p><?php _e("Sorry, What you were looking for is not here.", "ntp_framework"); ?></p>
						</section>
					</article>

				<?php endif; ?>

				</ul>
			</div>
		</div> 
	</div> 
</div>
<?php get_footer(); ?>

Étape n°4 – Intégration des scripts JavaScript

Nous aurons recours au script Isotope qui dispose de nombreux paramètres de personnalisation pour celles et ceux qui voudront aller plus loin.

Nous devons enregistrer le script et l’appeler sur la page d’archive de notre portfolio de façon optimale. Toujours dans le fichier functions.php :

/* Ajout des scripts JavaScript */
function ntp_js() {
wp_register_script('isotope', get_template_directory_uri().'/inc/js/jquery.isotope.min.js', array('jquery'), '1.5.19', true);if (is_post_type_archive('portfolio')) {
wp_enqueue_script('isotope');
}
}
add_action('wp_enqueue_scripts', 'ntp_js');

Il nous faut également récupérer les slugs des termes de la taxonomie liée au portfolio pour les insérer automatiquement dans la galerie. C’est de cette manière que le système de filtrage opère via Isotope.

/* Ajout des termes dans les classes CSS des éléments du portfolio */
function ntp_item_portfolio_class( $classes, $class, $ID ) {
 $taxonomy = 'type';
 $terms = get_the_terms( (int) $ID, $taxonomy );
 if( !empty( $terms ) ) {
 foreach( (array) $terms as $order => $term ) {
 if( !in_array( $term->slug, $classes ) ) {
 $classes[] = $term->slug;
 }
 }
 }
 return $classes;
}
add_filter('post_class', 'ntp_item_portfolio_class', 10, 3);

Comme vous l’aurez remarqué, nous aurons recours au transformations et animations via le CSS de niveau 3 que la plupart des navigateurs supportent dorénavant et non pas à jQuery.

Il nous maintenant initialiser le script et activer les différents effets sur la page concernée :

/* Ajout du JavaScript isotope sur le portfolio */
function ntp_isotope_js() { 
 if (!is_admin() && is_post_type_archive('portfolio')) { ?>
 <script> 
 jQuery(function($) {
 $(window).load(function() {

 /* Code principal */
 function ntp_portfolio_isotope() {
 var $container = $('#portfolio-list');
 $container.imagesLoaded(function(){
 $container.isotope({
 itemSelector: '.item-portfolio',
 layoutMode: 'masonry' 
 });
 });
 } ntp_portfolio_isotope();

 /* Filtre */
 $('.filter a').click(function() {
 var selector = $(this).attr('data-filter');
 $('#portfolio-list').isotope({ filter: selector });
 $(this).parents('ul').find('a').removeClass('active');
 $(this).addClass('active');
 return false;
 });

 /* Redimensionnement */
 var isIE8 = $.browser.msie && +$.browser.version === 8;
 if (isIE8) {
 document.body.onresize = function () {
 ntp_portfolio_isotope();
 };
 } else {
 $(window).resize(function () {
 ntp_portfolio_isotope();
 });
 }

 /* Orientation */
 window.addEventListener("orientationchange", function() {
 ntp_portfolio_isotope();
 });

 });
 });
</script> 
<?php } }
add_action ('wp_footer', 'ntp_isotope_js');

Étape n°5 – Ajout des classes CSS

Pour un rendu correct, il nous faut ajouter quelques lignes de code CSS. Attention à ne pas modifier le nom des classes CSS précédemment ajoutées dans les fichiers PHP.

/*--------------------------------------------------------------
    Portfolio
-------------------------------------------------------------- */

/* Grille portfolio */
ul#portfolio-list { 
    margin-top: 20px;    
}
ul#portfolio-list h2 { 
    font-weight: lighter;
}
.thumbnail { 
    width: 85%;
}
.isotope, .isotope .isotope-item {
    -webkit-transition: all 0.6s ;
    -moz-transition: all 0.6s ;
    -ms-transition: all 0.6s ;
    -o-transition: all 0.6s ;
    transition: all 0.6s ;
}
.isotope {
    transition-property: height, width;
}
.isotope .isotope-item {
    transition-property: transform, opacity;
}
.isotope.no-transition, .isotope.no-transition .isotope-item, .isotope .isotope-item.no-transition {
    transition-duration: 0s;
}
ul#portfolio-filter {
    margin-top: 20px;
}
a.thumbnail:hover, a.thumbnail:focus {
    border-color: #27AAE2;
    box-shadow: none;
    outline: 0 none;
}
.thumbnail {
    border: 1px solid #EEEEEE;
    border-radius: 0 0 0 0;
    box-shadow: none;
}
.single-portfolio header {
    text-align: center;
}
.single-portfolio h1 {
    margin: 50px auto 0;
}
.single-portfolio h2 {
    font-family: Georgia, serif;
    font-size: 18px;
    font-style: italic;
    font-weight: lighter;
    margin: 0;
}
#bg-portfolio {
    background: rgb(69,72,77); /* Old browsers */
    background: -moz-linear-gradient(top,  rgba(69,72,77,1) 0%, rgba(0,0,0,1) 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(69,72,77,1)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top,  rgba(69,72,77,1) 0%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top,  rgba(69,72,77,1) 0%,rgba(0,0,0,1) 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top,  rgba(69,72,77,1) 0%,rgba(0,0,0,1) 100%); /* IE10+ */
    background: linear-gradient(to bottom,  rgba(69,72,77,1) 0%,rgba(0,0,0,1) 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#45484d', endColorstr='#000000',GradientType=0 ); /* IE6-9 */
    border-bottom: 1px solid #D4D4D4;
    border-top: 1px solid #D4D4D4;
    margin: 20px 0;
    padding: 50px 0;
}
ul#project-details li {
    margin: 10px 0;
}
.single-portfolio .carousel img {
    height: auto;
    left: 0;
    margin: 0 auto;
    min-width: inherit;
    position: relative;
    top: 0;
}

Étape n°6 – Vérifier le résultat final

Pour terminer, il nous faut ajouter un lien d’accès au portfolio. Sous Apparence puis Menus, rajoutez un Lien avec l’URL du portfolio typiquement : http://neticpro.fr/portfolio/

Pour aller plus loin

#1 – Augmenter le nombre d’éléments affichés dans la galerie

Le nombre d’éléments affichés est limité au paramètre défini dans les réglages de lecture de WordPress. Vous pouvez rajouter ce bout de code dans le fichier de fonctions pour en afficher 99 bien que je ne vous conseille pas de dépasser 50 éléments avec ce type de script.

/* Nombre d'items à afficher dans le portfolio */
function ntp_cpt_item( $query ) {
 if ( is_post_type_archive( 'portfolio' ) ) {
 $query->set( 'posts_per_page', 99 );
 return;
 }
}
add_action( 'pre_get_posts', 'ntp_cpt_item', 1 );

#2 – Ajouter un effet fancyBox sur les éléments

Si vous ne souhaitez pas ouvrir une page détaillée pour décrire l’item, vous pouvez tout aussi bien afficher l’image en plus grand via un effet fancyBox.

Pour ce faire, intégrer le script fancyBox puis appelez en se basant sur les mêmes méthodes décrites ci-dessus pour Isotope. Je n’irais pas plus loin ici car cela pourrait faire l’objet d’un autre tutoriel.

#3 – Activer le responsive si absence de Twitter Bootstrap

Dans mes exemples, les images disposent d’une taille en pourcentage ce qui autorise une adaptation en fonction de la résolution de la fenêtre. Si vous n’utilisez pas une telle solution, vous devriez lire la documentation relative à ce sujet sur le site Isotope.

Vous disposez à présent d’un portfolio de vos plus belles créations avec un code optimisé, adaptatif et entièrement conçu pour WordPress. Des suggestions d’améliorations ?