Een afbeeldingengalerij bouwen met Progressive Enhancement

Wie houdt er niet van om hun website compleet te misleiden met nette functies? Maar wat gebeurt er wanneer uw kijkers de nieuwste browser niet gebruiken of is JavaScript uitgeschakeld? In de tutorial van vandaag leert u hoe u een afbeeldingsgalerij maakt die in bijna alle omgevingen werkt, met behulp van progressieve verbeteringstechnieken.


Invoering

Dus wat is precies een progressieve verbetering? Formeel is het dit:

Progressive Enhancement is een strategie voor webdesign met de nadruk op toegankelijkheid, semantische markup en externe stylesheet- en scriptingtechnologieën. Progressive Enhancement maakt gebruik van webtechnologieën op een gelaagde manier waarmee iedereen toegang heeft tot de basisinhoud en -functionaliteit van een webpagina, via elke browser of internetverbinding, terwijl deze ook betere versies biedt voor de bandbreedte of meer geavanceerde browsersoftware. (Wikipedia).

Progressieve verbetering is het tegenovergestelde van sierlijke degradatie, waarbij u uw site / app met alle functies bouwt, en er vervolgens voor zorgt dat het er goed uitziet en fatsoenlijk functioneert in oudere browsers. Met vooruitstrevende verbeteringen leggen we een solide basis voor onze afbeeldingengalerij, die werkt, ongeacht waar u deze bekijkt. Daarna leggen we de nadruk op eye-candy en functionaliteit totdat we een goed uitziende, goed functionerende afbeeldingengalerij hebben. Laten we beginnen!

Wat we zijn na

Dit is wat we willen bereiken: als alle toeters en bellen zijn ingeschakeld, kunnen we onze afbeeldingen slepen om ze te bekijken; het is een zeer eenvoudige simulatie van een stapel foto's op uw salontafel. Wanneer u op een knop klikt, wordt deze open geschoven om enkele details over de afbeelding te onthullen. Als JavaScript is uitgeschakeld, hebben we een mooi raster met afbeeldingen om uit te kiezen; Als u hierop klikt, gaan we naar een pagina met een grotere versie van de afbeelding en de details. Als er geen CSS-ondersteuning is, krijgen we een lelijke (maar werkende) lijst met afbeeldingen.

Dit is een screenshot van ons eindproduct:

De stichting leggen: POSH

We beginnen met enkele eenvoudige oude semantische HTML. Dit is onze basis, aangezien elke browser die er is goed is in het ontleden van HTML.

index.htm

     Geleidelijk verbeterde afbeeldingengalerij   

Klik op een afbeelding hieronder om het te bekijken!

  • 3dOcean
  • AudioJungle
  • ActiveDen
  • GraphicRiver
  • ThemeForest
  • VideoHive

Dat is het; vrij eenvoudig spul, toch? Geen browser die deze titel waard is, zou er een probleem mee moeten hebben. En dit is onze afgewerkte eerste laag. Nee, het is niet mooi, maar dat was niet ons doel: we wilden iets dat overal werkt, wat er ook gebeurt. Een paar dingen om op te merken over deze code: ten eerste is het semantisch, zoals we al hadden gezegd. Je kunt je afvragen wat de div's in de lijstitems zijn. Wat is er met hen aan de hand? Hoewel we beginnen met de kale botten, verwachten we dat de meeste van onze kijkers JavaScript hebben ingeschakeld, in welk geval we deze div's nodig hebben. We kunnen ze invoegen met jQuery, maar sinds wij do Verwacht dat ze het grootste deel van de tijd worden gebruikt, het is gemakkelijker om het hard in te coderen. Het andere dat opvalt is dat het bruikbaar is. Probeer het in Lynx of een andere alleen-tekstbrowser te bekijken:

Overigens zijn de pagina's waarnaar in de bovenstaande HTML is gelinkt beschikbaar in de downloadbare bron; ze lijken allemaal op dit:

     Themeforest MarketPlace door Envato   

ThemeForest

ThemeForest

Themeforest-aanbiedingen: HTML-sjablonen, WordPress, Joomla, Flash-sites, PSD-sjablonen, Javascript, PHP-scripts

Op een echte site zou je dit omringen met je sitesjabloon, maar het is prima voor onze doeleinden.

De structuur aankleden: CSS

Hoewel semantische HTML leuk is, ziet het er een beetje kaal uit. Laten we het aankleden met wat CSS. Natuurlijk moeten we eerst naar de stylesheet verwijzen:

  

We zullen eerst het speelveld nivelleren met een uitgeklede Meyer-reset:

 / * Meyer's Reset * / html, body, div, h1, h2, h4, p, a, img, ul, li margin: 0; opvulling: 0; rand: 0; overzicht: 0; font-weight: inherit; lettertype-stijl: erven; tekengrootte: 100%; font-family: inherit; vertical-align: basislijn;  / * Vergeet niet om focusstijlen te definiëren! * /: focus overzicht: 0;  body line-height: 1; de kleur zwart; achtergrond: wit;  ol, ul lijststijl: geen;  / * EINDE Meyer's Reset * / 

Nu moeten we onze galerij opmaken voor gebruik zonder JavaScript. We beginnen met enkele algemene elementen en achtergrondstyling:

 lichaam 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 opvulling: 10px; h4 font-size: 20px; padding-bottom: 10px;

Nu zorgen we voor onze kop- en lijstitems.

 #container h1 opvulling: 10px;  #images li float: left; achtergrond: #ececec; border: 1px solid #ccc; margin: 10px; breedte: 256 px; opvulling: 10px; overloop verborgen;  #images li div width: 512px; overloop verborgen;  #images li a float: left;  #images li div.info width: 246px; opvulling: 0 0 0 10px; float: left;  

U zult merken dat we een breedte hebben ingesteld op onze lijstelementen. We moeten dat doen voor onze JavaScript-functionaliteit; dat is ook waarom overflow: hidden is ingesteld. Dit is gemakkelijk in ons geval, omdat ik alle afbeeldingen op dezelfde breedte heb gemaakt. Als de uwe verschillende breedten heeft, moet u waarschijnlijk de breedte voor elk lijstitem instellen met JavaScript. Dat zal werken omdat de CSS-versie alleen de breedte niet nodig heeft. De div direct in ons lijstitem (dat alle inhoud bevat) is 512 px breed, met overloop verborgen. We hebben ons anker naar links gedreven, zodat we de div.info naast je kunnen laten zweven, zoals je verderop kunt zien.

Dus, hier zijn de vruchten van onze inspanningen tot nu toe:

We komen een beetje terug bij CSS; maar nu gaan we naar het JavaScript!

De functionaliteit toevoegen: JavaScript

We zullen hier jQuery gebruiken; dus begin met het importeren van dat van het CDN van Google. We hebben ook de jQueryUI-bibliotheek nodig. We zouden dat ook van Google kunnen krijgen, maar we hebben niet de hele bibliotheek nodig. Ik heb een kopie gedownload van de jQueryUI-site, met alleen de kern en de versleepbare componenten, en dat is alles wat we nodig hebben. Je kunt doen wat je wilt.

   

Voordat we beginnen met coderen, laten we bepalen wat we moeten doen.

  • De h1 die we hebben gecodeerd, geeft instructies voor de niet-JavaScript-versie. We zullen dit verwijderen en andere instructies toevoegen.
  • We moeten het slepen configureren op de lijstelementen; We zullen een sprankje plezier toevoegen: wanneer de gebruiker het lijstitem vrijgeeft, zal het een beetje verder schuiven en vertragen (klinkt als een iEffect). Zoals we eerder al zeiden, het zou een beetje op een stapel foto's op een tafel moeten lijken.
  • Wanneer op een lijstitem wordt geklikt, moet het 'open schuiven', dat in breedte verdubbelt. Voordat dit gebeurt, sturen we echter een Ajax-aanroep om de pagina te krijgen waarnaar de gebruiker zou gaan als JavaScript niet was ingeschakeld. Vervolgens krijgen we de gewenste waarden van die pagina en koppelen we ze aan ons lijstitem in een div. We zullen deze div controleren voordat we de oproep plaatsen, dus als de gebruiker er al op heeft geklikt, sturen we geen nieuw verzoek.

Oke, open een scripttag en laten we code!

 var imgs; $ (document) .ready (function () ); $ (window) .load (function () );

We beginnen met het maken van een globale variabele: een array van de lijstitems (wel, het wordt binnenkort een array). Vervolgens stellen we event-handlers in voor a) wanneer de DOM gereed is en b) wanneer het venster klaar is met laden. Het effect dat we zullen hebben als het venster wordt geladen (waarover ik je nog niet heb verteld) vereist niet dat we tot dan wachten, maar ik denk dat het leuker zal zijn als de afbeeldingen zijn geladen.

Nu gaat deze code in onze document.ready-functie:

 var drag = ; $ ( 'H1') te verwijderen ().; $ ( '# Afbeeldingen'). Toevoegen ('
  • Gooi de afbeeldingen rond; als je er een ziet die je leuk vindt, klik er dan op!

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

    Moet rechttoe rechtaan zijn: we maken een object dat informatie bevat over slepen; vervolgens verwijderen we de h1, voegen we een lijstitem met nieuwe instructies toe aan onze lijst en plaatsen we alle lijstitems in onze imgs-variabele.

    Nu gaan we onze sleepfunctionaliteit bouwen. Eigenlijk is het zo simpel als dit:

     imgs.draggable (); 

    Maar we gaan een paar opties toevoegen. Hier is de code; volg het zelf en dan zullen we er doorheen wandelen.

     imgs.draggable (stack: group: '#images li', min: 1, start: function () $ this = $ (this); if ($ this.attr ("id") === ' instructions ') $ this.fadeOut (). remove (); imgs.each (function () var $ this = $ (this); if ($ this.width ()! == 256) $ this. stop (). animeren (width: 256). removeClass ('top');); drag.startTime = new Date (); drag.startPos = $ this.position ();, stop: function ( ) var $ this = $ (this), top, left, time; 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 = (sleep.topOffset / time) .toString (); left = (drag.leftOffset / time) .toString (); $ this.animate (top: '+ =' + top, left: '+ =' + left);); 

    We hebben drie eigenschappen aan ons draggable opties-object toegevoegd: stack, start en stop. Stack bestuurt de z-index van een groep objecten en neemt een object met twee eigen eigenschappen: groep en min. Groep is een jQuery-selector; in ons geval zijn dit de lijstitems. Min is de minimale z-index die items in de groep kunnen hebben. Dus nu, wanneer u een item sleept, komt het naar de top van de stapel.

    De startfunctie wordt uitgevoerd wanneer u een item begint te slepen. We beginnen met het cachen van $ (dit). Vervolgens controleren we of het lijstitem dat we hebben gepakt een id van 'instructies' heeft. Als dat zo is, vervagen we het en verwijderen we het. Vervolgens doorlopen we elk lijstitem en als we er een vinden die niet 256 px breed zijn, animeren we de breedte tot 256 px en verwijderen we de klasse 'top'. Wat is 'top' doen? We zullen het in een paar minuten stylen, maar het geeft de gebruiker gewoon visuele feedback wanneer ze op een item klikken. Daarna doen we iets heel belangrijks: we plaatsen twee eigenschappen op ons drag-object. Eén (startTime) is de tijd waarop het slepen begon en de andere (startPos) is de positie waarmee het item begon. We zullen deze informatie gebruiken om ons effect te creëren wanneer het slepen stopt.

    Ten slotte hebben we de stop-functie, die voorspelbaar wordt uitgevoerd wanneer de gebruiker stopt met slepen. Nogmaals, we beginnen met het cachen van $ (dit), evenals het creëren van een paar andere variabelen waaraan we in een moment waarden zullen geven. Vervolgens zetten we onze eindtijd en positie in drag.endTime en drag.endPosition. Vervolgens berekenen we onze linker en bovenste offset door af te trekken waar we waren van waar we zijn; we kunnen dit doen met de eigenschappen boven en links die het positieobject heeft. Nu voor de vertragende animatielogica: je zou heel ingewikkeld kunnen worden met dit algoritme, maar we houden het simpel. We zullen de tijd vinden die de sleep duurde door onze startTime af te trekken van onze EndTime; de getTime-methode retourneert het aantal milleseconden sinds 1970/01/01, dus het verschil is in milleseconden. Vervolgens verdelen we die waarde met 60, die ik met vallen en opstaan ​​heb bedacht. Bij gemiddeld slepen stelt dit onze tijdvariabele ergens tussen 2 en 3 in. Vervolgens verdelen we onze top en linker offset met de tijd en zetten die waarden om in string, waardoor ze boven en links worden bewaard. Ten slotte animeren we het gesleepte lijstitem, verhogen (dat is wat '+ =' doet) de waarde bovenaan of links. Op dit punt zou je in staat moeten zijn om de afbeeldingen te slepen en ons effect te krijgen.

    Als u op de afbeeldingen klikt, wordt u naar een nieuwe pagina geleid. Laten we onze klikgebeurtenishandler instellen.

     imgs.click (function () var $ this = $ (this); if ($ this.attr ('id') === 'instructions') $ this.fadeOut (). remove (); else  if ($ this.width ()! == 256) $ this.stop (). anim (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"). toevoegen (head, para); , error: function () var msg = '

    Oops!

    Het lijkt erop dat er een probleem is geweest; we kunnen deze informatie nu niet krijgen.

    '; $ This.children ( 'div'). Toevoegen ('
    . ') .Vind (. "Info") html (msg); ); $ this.css ('zIndex': 8) .stop () .anim (width: 512) .addClass ('top') .siblings (). removeClass ('top') .stop (). animeren (width: 256). filter (function () return $ (this) .css ('zIndex') === '8'). css ('zIndex': 7); return false; );

    Standaardwerkwijze vandaag: begin met het cachen van $ (dit). Nogmaals, we controleren de id van de instructies; als het er is, vervagen we en verwijderen we het item. Als het er niet is, controleren we de breedte van het element: als het geen 256 px is, betekent dit dat er al op dit item is geklikt, dus we animeren de breedte tot 256 en verwijderen onze topklasse (ja, we komen er wel aan ). Als het element 256 px breed is, controleren we op een onderliggende element met de klasse van info. We kunnen dit doen door de methode find op het element aan te roepen, de selector door te geven waarnaar we op zoek zijn en de eigenschap length te krijgen. Als dit element niet bestaat, is het resultaat 0, wat een valse waarde is, dus we verpakken dit tussen haakjes en gebruiken een! om de boolean te veranderen. Nu, als er geen onderliggende elementen zijn met een categorie informatie, zullen we in dit blok stappen, wat onze ajax-oproep is.

    $ .ajax () neemt een objectparameter en we gebruiken vier eigenschappen: url, datatype, succes en fout. Url en datatype liggen voor de hand: we vinden eenvoudig het anker in ons lijstitem en stellen url in op zijn href; ons datatype is html. Als onze ajax-oproep succesvol is, nemen we de gegevens die we ontvangen, de volledige HTML-inhoud van de pagina, en veranderen deze in een jQuery-object. Dan kunnen we de kop en alinea wegfilteren waarvan we weten dat we die hebben. Dan krijgen we gewoon de div in ons lijstitem, voeg een div.info toe en voeg daar de kop en paragraaf aan toe. Als ons verzoek mislukt, geven we een foutmelding door een vergelijkbaar proces, met behulp van de foutfunctie. Na onze ajax-oproep willen we wat styling en animatie uitvoeren op ons lijstitem. Ten eerste willen we de z-index instellen op 8 of een hoger nummer dan het aantal versleepbare items dat we hebben. Vervolgens willen we alle huidige animaties op dit lijstitem stoppen en de breedte animeren tot 512 px. Ten slotte voegen we die topklasse toe. Vervolgens krijgen we alle broers en zussen, de andere lijstitems. We stoppen alle animaties en animeren ze vervolgens naar 256 px breed. Ten slotte filteren we alleen de elementen uit met een z-index van 8 en wijzigen ze hun z-index in 7. Hiermee kan het huidige geklikte lijstitem bovenaan komen. Helemaal aan het einde geven we false terug, dus we blijven op onze huidige pagina (want ook al is dit een klikfunctie op een lijstitem, de gebruikers zullen hoogstwaarschijnlijk in het item op ons anker ingekapseld klikken).

    Dus dat is onze click handler; er is nog maar één stuk JavaScript over. Als u ons voorbeeld nu probeert, zult u zien dat het werkt ... een beetje. Telkens wanneer u op een lijstitem klikt om het te openen, wordt het geopend, maar u zult een nogal vaag probleem opmerken. Dit komt omdat de lijstitems naar links worden verplaatst; laten we daar voor zorgen in onze raamklare afhandelaar.

     $ (venster) .load (function () var $ w = $ (venster); imgs.css (positie: 'absoluut', links: $ w.width () / 2 - imgs.width (), bovenaan: $ w.height () / 2- imgs.height ()); for (var i = 0; imgs [i]; i ++) $ (imgs [i]). animeren (left: '+ =' + Math.random () * 150, bovenaan: '+ =' + Math.random () * 150);); 

    Als je tot nu toe redelijk goed hebt gevolgd, zul je hier niet terugdeinzen: we gebruiken eenvoudigweg de css-methode van jQuery om de positionering in te stellen op absoluut en alle afbeeldingen te stapelen zodat hun rechterranden zijn uitgelijnd met het midden van de viewport en hun de onderranden zijn uitgelijnd met het verticale midden. Vervolgens gebruiken we een for-lus om over elk lijstitem te recurse ren en willekeurig willekeurig naar rechts en naar beneden te animeren. Hierdoor ontstaat het effect van een stapel afbeeldingen die worden verspreid.

    Dus dat is het voor JavaScript! Nu, wanneer een gebruiker de pagina laadt, zouden ze zoiets moeten zien (na animatie):

    Laatste details: CSS3

    Daar kunnen we een einde aan maken, maar we willen degenen belonen die vooruitstrevende browsers gebruiken, dus het is een paar minuten terug bij de CSS. En, ja, we zullen naar de topklasse kijken.

    Het eerste wat we zullen doen is het toevoegen van afgeronde hoeken aan de selector # afbeeldingen li.

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

    Dan ziet de topklasse, die de lijst met items alleen heeft als ze 'open' zijn, er als volgt uit:

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

    Niets ongelooflijk moois, maar toch een paar mooie verfijningen.

    Opmerkingen sluiten

    Nou, dat is het dan. We zouden nu een afbeeldingengalerij moeten hebben die fatsoenlijk werkt zonder CSS of JavaScript, maar maakt daar volledig gebruik van waar die technologieën beschikbaar zijn. Dus, hoe zou je onze galerij verbeteren? Laten we het horen in de reacties!