Construire une galerie d'images avec une amélioration progressive

Qui n'aime pas truquer complètement leur site Web avec des fonctionnalités soignées? Mais que se passe-t-il lorsque vos téléspectateurs n'utilisent pas la dernière version du navigateur ou que JavaScript est désactivé? Dans le tutoriel d'aujourd'hui, vous apprendrez à créer une galerie d'images qui fonctionnera dans presque tous les environnements, en utilisant des techniques d'amélioration progressive..


introduction

En quoi consiste exactement l'amélioration progressive? Formellement, c'est ceci:

L'amélioration progressive est une stratégie de conception Web qui met l'accent sur l'accessibilité, le balisage sémantique et les technologies de feuille de style et de script externes. L’amélioration progressive utilise les technologies Web en couches pour permettre à tous d’accéder au contenu et aux fonctionnalités de base d’une page Web, à l’aide de n’importe quel navigateur ou connexion Internet, tout en offrant à ceux qui disposent d’une meilleure bande passante ou d’un logiciel de navigation plus avancé une version améliorée de la page. (Wikipédia).

L’amélioration progressive est le contraire de la dégradation progressive, où vous construisez votre site / application avec toutes les fonctionnalités, puis vous assurez qu’il est beau et qu'il fonctionne correctement dans les navigateurs plus anciens. Avec l’amélioration progressive, nous jetterons une base solide pour notre galerie d’images qui fonctionnera quel que soit le lieu où vous la regardez. Ensuite, nous allons nous concentrer sur la fonctionnalité et les yeux jusqu'à ce que nous ayons une belle galerie d'images qui fonctionne bien. Commençons!

Ce que nous sommes après

Voici ce que nous voulons en arriver à faire: si tous les cloches et sifflets sont activés, nous pourrons faire glisser nos images pour les visionner; ce sera une simulation très basique d'une pile de photos sur votre table basse. Lorsque vous cliquez sur l'un d'eux, il s'ouvre pour révéler certains détails de l'image. Si JavaScript est désactivé, nous aurons une belle grille d'images à choisir; en cliquant dessus nous mènera à une page avec une version agrandie de l'image et des détails. S'il n'y a pas de support CSS, nous aurons une liste laide (mais fonctionnelle) des images.

Voici une capture d'écran de notre produit final:

Poser les fondations: POSH

Nous commençons avec du vieux HTML sémantique. C’est notre fondement, car tous les navigateurs sont bons pour l’analyse HTML..

index.htm

     Galerie d'images progressivement améliorée   

Cliquez sur une image ci-dessous pour la voir!

  • 3dOcean
  • AudioJungle
  • ActiveDen
  • GraphicRiver
  • Thème Forêt
  • VideoHive

C'est tout; trucs assez basiques, hein? Aucun navigateur digne de ce titre ne devrait poser problème. Et ceci est notre première couche finie. Non, ce n'est pas joli, mais ce n'était pas notre objectif: nous voulions quelque chose qui fonctionnera partout, peu importe le problème. Quelques points à noter à propos de ce code: d’abord, c’est la sémantique, comme nous l’avons dit. Vous pourriez vous interroger sur les divs dans les éléments de la liste. Quoi de neuf avec eux? Même si nous commençons avec le principe de base, nous prévoyons que la plupart de nos téléspectateurs verront que JavaScript est activé, auquel cas nous aurons besoin de ces divs. Nous pourrions les insérer avec jQuery, mais puisque nous faire Attendez-vous à ce qu'ils soient utilisés la plupart du temps, il est plus facile de les coder en dur. L'autre chose à noter, c'est que c'est utilisable. Essayez de le visualiser dans Lynx, ou un autre navigateur en mode texte uniquement:

Par ailleurs, les pages liées au HTML ci-dessus seront disponibles dans la source téléchargeable; ils sont tous semblables à ceci:

     Themeforest MarketPlace par Envato   

Thème Forêt

Thème Forêt

Offres Themeforest: Modèles HTML, WordPress, Joomla, Sites Flash, Modèles PSD, Javascript, Scripts PHP

Sur un site réel, vous encercleriez ceci avec le modèle de votre site, mais cela convient parfaitement à nos besoins..

Habiller la structure: CSS

Bien que le HTML sémantique soit agréable, il semble un peu dépouillé. Habillons-le avec du CSS. Bien sûr, nous devons d’abord faire référence à la feuille de style:

  

Nous allons d'abord niveler le terrain de jeu avec une réinitialisation Meyer simplifiée:

 / * Réinitialisation de Meyer * / html, body, div, h1, h2, h4, p, a, img, ul, li margin: 0; rembourrage: 0; bordure: 0; contour: 0; poids de police: hériter; style de police: hériter; taille de police: 100%; famille de polices: hériter; alignement vertical: ligne de base;  / * n'oubliez pas de définir les styles de focus! * /: focus contour: 0;  body line-height: 1; la couleur noire; fond blanc;  ol, ul list-style: none;  / * END Meyer Reset * / 

Maintenant, nous devons styliser notre galerie pour une utilisation sans JavaScript. Nous allons commencer par quelques éléments généraux et un style d'arrière-plan:

 body font: 13px / 1.5 'Helvetica Neue', Arial, 'Liberation Sans', FreeSans, sans-serif; / * <-- from 960.gs text.css */ background: #36b4dd;  h1  font-size: 30px;  #container > h1 padding: 10px; h4 taille de la police: 20px; padding-bottom: 10px;

Maintenant nous allons nous occuper de notre rubrique et lister les éléments.

 #container h1 padding: 10px;  #images li float: left; arrière-plan: #ecec; bordure: 1px solide #ccc; marge: 10px; largeur: 256px; rembourrage: 10px; débordement caché;  #images li div width: 512px; débordement caché;  #images li a float: left;  #images li div.info width: 246px; remplissage: 0 0 0 10px; float: gauche;  

Vous remarquerez que nous avons défini une largeur sur notre liste d'éléments. Nous devons le faire pour notre fonctionnalité JavaScript; c'est aussi pourquoi débordement: masqué est défini. C'est facile dans notre cas, car toutes les images ont la même largeur. Si vos largeurs sont différentes, vous devrez probablement définir la largeur de chaque élément de la liste avec JavaScript. Cela fonctionnera car la version uniquement CSS ne nécessite pas la largeur. La div directement dans notre élément de liste (qui englobe tout le contenu) est large de 512px, avec débordement masqué. Nous avons flotté notre ancre à gauche pour pouvoir placer le div.info à gauche, comme vous le verrez plus loin..

Alors, voici les fruits de nos travaux jusqu'à présent:

Nous reviendrons sur CSS dans un peu; mais maintenant, passons au JavaScript!

Ajout de la fonctionnalité: JavaScript

Nous allons utiliser jQuery ici; Commencez donc par l’importer à partir du CDN de Google. Nous aurons également besoin de la bibliothèque jQueryUI. Nous pourrions également obtenir cela de Google, mais nous n’avons pas besoin de toute la bibliothèque. J'ai téléchargé une copie du site jQueryUI, avec uniquement les composants principaux et déplaçables, ce dont nous avons besoin. Vous pouvez faire ce que vous préférez.

   

Avant de commencer à coder, déterminons ce que nous devons faire..

  • Le code h1 que nous avons codé en dur fournit des instructions pour la version non JavaScript. Nous allons supprimer cela et ajouter des instructions différentes.
  • Nous devons configurer le glisser sur les éléments de la liste; nous ajouterons une touche d'amusement: lorsque l'utilisateur relâche l'élément de la liste, il glisse un peu plus loin et ralentit (sonne comme un effet). Comme nous l'avons dit plus tôt, c'est censé être un peu comme une pile de photos sur une table.
  • Lorsqu'un élément de la liste est cliqué, il devrait «glisser ouvert» et doubler de largeur. Avant cela, toutefois, nous envoyons un appel Ajax pour obtenir la page à laquelle l'utilisateur accédera si JavaScript n'est pas activé. Ensuite, nous obtiendrons les valeurs souhaitées sur cette page et les brancherons à notre élément de liste dans un div. Nous allons vérifier cette div avant de passer l'appel, cependant, si l'utilisateur a déjà cliqué dessus, nous n'enverrons pas d'autre demande..

Bon, ouvrez une balise de script et codons!

 var imgs; $ (document) .ready (fonction () ); $ (fenêtre) .load (fonction () );

Nous allons commencer par créer une variable globale: un tableau des éléments de la liste (enfin, ce sera un tableau prochainement). Ensuite, nous configurons les gestionnaires d’événements pour a) lorsque le DOM est prêt et b) lorsque le chargement de la fenêtre est terminé. L'effet que nous ferons lors du chargement de la fenêtre (dont je ne vous ai pas encore parlé) n'exige pas d'attendre jusqu'à cette date, mais je pense que ce sera plus agréable lorsque les images auront été chargées..

Maintenant, ce code va dans notre fonction document.ready:

 var drag = ; $ ('h1'). remove (); $ ('# images'). append ('
  • Mélanger les images autour; si vous en voyez une que vous aimez, cliquez dessus!

  • '); imgs = $ ('# images li');

    Devrait être simple: nous créons un objet qui contiendra quelques détails sur le glissement; puis nous supprimons le h1, ajoutons un élément de la liste avec de nouvelles instructions à notre liste et mettons tous les éléments de la liste dans notre variable imgs.

    Maintenant, nous allons construire notre fonctionnalité de glissement. Vraiment c'est aussi simple que cela:

     imgs.draggable (); 

    Mais nous allons ajouter quelques options. Voici le code; le poursuivre vous-même et ensuite nous allons nous y promener.

     imgs.draggable (stack: group: '#images li', min: 1, début: function () $ this = $ (this); if ($ this.attr ("id") === ' instructions ') $ this.fadeOut (). remove (); imgs.each (fonction () var $ ceci = $ (ceci); if ($ this.width ()! == 256) $ this. stop (). animate (width: 256). removeClass ('top');); drag.startTime = new Date (); drag.startPos = $ this.position ();, stop: function ( ) var $ this = $ (this), haut, gauche, heure; drag.endTime = new Date (); drag.endPos = $ this.position (); drag.leftOffset = drag.endPos.left - drag.startPos .left; drag.topOffset = drag.endPos.top - drag.startPos.top; time = (drag.endTime.getTime () - drag.startTime.getTime ()) / 60; top = (drag.topOffset / time) .toString (); left = (drag.leftOffset / time) .toString (); $ this.animate (en haut: '+ =' + en haut, à gauche: '+ =' + à gauche)); 

    Nous avons ajouté trois propriétés à notre objet options déplaçables: stack, start et stop. Stack contrôle l'index z d'un groupe d'objets et prend un objet avec deux propriétés qui lui sont propres: group et min. Le groupe est un sélecteur jQuery; dans notre cas, ce sont les éléments de la liste. Min est l'indice z minimal que tout élément du groupe peut prendre. Alors maintenant, lorsque vous faites glisser un élément, il arrive en haut de la pile.

    La fonction de démarrage est exécutée lorsque vous commencez à faire glisser un élément. Nous commençons par mettre en cache $ (this). Ensuite, nous vérifions si l'élément de la liste que nous avons récupéré a un identifiant 'instructions'. Si c'est le cas, nous le supprimons et le fondons. Ensuite, nous passons en boucle sur chaque élément de la liste et si nous en trouvons des dont la largeur n’est pas de 256 pixels, nous animons la largeur à 256 pixels et supprimons la classe de "top". Qu'est-ce que 'top' fait? Nous allons le nommer dans quelques minutes, mais cela donne simplement à l'utilisateur un retour visuel lorsqu'il clique sur un élément. Après cela, nous faisons quelque chose de très important: nous définissons deux propriétés sur notre objet glisser. L'un (heure de début) est l'heure à laquelle le glissement a commencé et l'autre (startPos) est la position à laquelle l'élément a commencé. Nous allons utiliser cette information pour créer notre effet lorsque le glissement s'arrête.

    Enfin, nous avons la fonction stop, qui s’exécute de manière prévisible lorsque l’utilisateur arrête de glisser. Encore une fois, nous commençons par mettre en cache $ (this), ainsi que de créer quelques autres variables auxquelles nous donnerons des valeurs dans un instant. Ensuite, nous plaçons notre heure de fin et notre position dans drag.endTime et drag.endPosition. Ensuite, nous calculons notre décalage gauche et supérieur en soustrayant où nous étions de où nous sommes; nous pouvons le faire avec les propriétés top et left de l'objet position. Passons maintenant à la logique de ralentissement de l'animation: vous pourriez devenir très compliqué avec cet algorithme, mais nous allons simplement garder les choses simples. Nous trouverons le temps que la traînée a pris en soustrayant notre heure de début de notre heure de fin; La méthode getTime renvoie le nombre de milles depuis le 01/01/01, la différence est donc en milles. Ensuite, nous divisons cette valeur par 60, valeur que j'ai établie par essais et erreurs. En moyenne, cela fixe notre variable temporelle entre 2 et 3. Ensuite, nous divisons notre décalage haut et gauche par le temps et convertissons ces valeurs en chaîne, en les enregistrant en haut et à gauche. Enfin, nous animons l’élément de liste déplacé en incrémentant (c’est ce que «+ =» fait) la valeur en haut ou à gauche. À ce stade, vous devriez pouvoir faire glisser les images et obtenir notre effet.

    Cependant, en cliquant sur les images, vous accédez à une nouvelle page. Alors configurons notre gestionnaire d'événements click.

     imgs.click (function () var $ this = $ (this); if ($ this.attr ('id') === 'instructions') $ this.fadeOut (). remove (); else  if ($ this.width ()! == 256) $ this.stop (). animate (width: 256). removeClass ('top'); else if (! ($ this.find (' .info '). length)) $ .ajax (url: $ this.find (' a '). attr (' href '), dataType:' html ', success: function (data) var $ d = $ (data), head = $ d.filter ('h1'), para = $ d.filter ('p'); $ this.children ('div'). append ('
    ') .find (". info"). append (tête, para); , erreur: function () var msg = '

    Oops!

    Il semble y avoir eu un problème. nous ne pouvons pas obtenir cette information maintenant.

    '; $ this.children ('div'). append ('
    ') .find (". info"). html (msg); ); $ this.css ('zIndex': 8) .stop () .animate (width: 512) .addClass ('top') .siblings (). removeClass ('top') .stop (). animate (width: 256) .filter (function () return $ (this) .css ('zIndex') === '8'). css ('zIndex': 7); return false; );

    Procédure opératoire standard aujourd'hui: commencez par mettre en cache $ (this). Une fois encore, nous vérifions l'identifiant des instructions; si elle est là, nous fadeOut et supprimons l'élément. Si ce n'est pas là, nous vérifions la largeur de l'élément: s'il n'est pas 256px, cela signifie que cet élément a déjà été cliqué, nous animons donc la largeur jusqu'à 256 et supprimons notre première classe (oui, nous y arriverons ). Si l'élément a une largeur de 256 pixels, nous recherchons un élément enfant avec la classe info. Nous pouvons faire cela en appelant la méthode find sur l'élément, passer le sélecteur que nous recherchons et obtenir la propriété length. Si cet élément n'existe pas, le résultat sera 0, ce qui est une valeur fausse. Nous le plaçons donc entre parenthèses et utilisons un! pour passer le booléen. Maintenant, s'il n'y a pas d'éléments enfants avec une classe d'informations, nous entrerons dans ce bloc, qui est notre appel ajax.

    $ .ajax () prend un paramètre d'objet, et nous utiliserons quatre propriétés: url, type de données, success et error. L'URL et le type de données sont évidents: nous trouvons simplement l'ancre dans notre élément de liste et définissons url sur son href; notre type de données est html. Si notre appel ajax aboutit, nous prenons les données que nous avons obtenues, c'est-à-dire l'intégralité du contenu HTML de la page, et les transformons en objet jQuery. Ensuite, nous pouvons filtrer le titre et le paragraphe que nous savons avoir ici. Ensuite, nous obtenons simplement le div à l'intérieur de notre élément de liste, ajoutons un div.info, ainsi que l'en-tête et le paragraphe. Si notre demande échoue, nous afficherons un message d'erreur par un processus similaire, à l'aide de la fonction error. Après notre appel ajax, nous voulons effectuer un certain style et une animation sur notre élément de la liste. Tout d'abord, nous voulons définir l'index z sur 8, ou tout nombre supérieur au nombre d'éléments déplaçables que nous avons. Ensuite, nous voulons arrêter toutes les animations en cours sur cet élément de la liste et animer la largeur à 512px. Enfin, nous allons ajouter cette classe supérieure. Ensuite, nous obtenons tous les frères et sœurs, qui sont les autres éléments de la liste. Nous allons arrêter toute animation sur eux, puis les animer à 256 pixels de large. Enfin, nous filtrerons uniquement les éléments avec un indice z égal à 8 et changerons leur indice z en 7. Cela permet à l'élément de la liste cliqué de s'afficher en haut de la liste. A la fin, nous renvoyons false, nous restons donc sur notre page actuelle (car même s'il s'agit d'une fonction de clic sur un élément de la liste, les utilisateurs cliqueront probablement sur notre image enveloppée d'ancres dans l'élément de la liste)..

    Voilà donc notre gestionnaire de clic; Il ne reste qu'un morceau de JavaScript. Si vous donnez à notre exemple un essai maintenant, vous verrez que cela fonctionne… en quelque sorte. Chaque fois que vous cliquez sur un élément de la liste pour l'ouvrir, celui-ci s'ouvre, mais vous remarquerez un problème plutôt sournois. C'est parce que les éléments de la liste sont flottants à gauche; prenons soin de cela dans notre gestionnaire de prêt de fenêtre.

     $ (fenêtre) .load (fonction () var $ w = $ (fenêtre); imgs.css (position: 'absolute', à gauche: $ w.width () / 2 - imgs.width (), en haut: $ w.height () / 2- imgs.height ()); pour (var i = 0; imgs [i]; i ++) $ (imgs [i]). animate (left: '+ =' + Math.random () * 150, en haut: '+ =' + Math.random () * 150);); 

    Si vous avez assez bien suivi jusqu'à présent, vous n'aurez pas peur ici: nous utilisons simplement la méthode CSS de jQuery pour définir le positionnement sur absolu et empiler toutes les images de sorte que leurs bords droits soient alignés au centre de la fenêtre d'affichage. les bords inférieurs sont alignés sur le centre vertical. Ensuite, nous utilisons une boucle for pour recurse sur chaque élément de la liste et l’animons aléatoirement de bas en haut. Cela crée l'effet d'une pile d'images dispersées.

    Alors c'est tout pour le JavaScript! Maintenant, quand un utilisateur charge la page, il devrait voir quelque chose comme ceci (après animation):

    Touches finales: CSS3

    Nous pourrions nous arrêter là, mais nous voulons récompenser ceux qui utilisent des navigateurs avant-gardistes. Nous revenons donc au CSS pour quelques minutes. Et, oui, nous allons regarder la classe supérieure.

    La première chose à faire est d’ajouter des coins arrondis au sélecteur #images li.

     border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; 

    Ensuite, la classe supérieure, qui contient uniquement les éléments de la liste lorsqu'ils sont «ouverts», se présente comme suit:

     .top box-shadow: 0 0 10px # 000; -moz-box-shadow: 0 0 10px # 000; -webkit-box-shadow: 0 0 30px # 000;  

    Rien d’incroyablement chic, mais quelques raffinements quand même.

    Commentaires de clôture

    Eh bien c'est ça. Nous devrions maintenant avoir une galerie d'images qui fonctionne correctement sans CSS ni JavaScript, mais en tire pleinement parti lorsque ces technologies sont disponibles. Alors, comment amélioreriez-vous notre galerie? Écoutons cela dans les commentaires!