Bygg et bildegalleri med progressiv forbedring

Hvem elsker ikke å helt lure ut deres nettside med ryddige funksjoner? Men hva skjer når seerne ikke bruker den nyeste nettleseren, eller de har JavaScript slått av? I dagens veiledning lærer du hvordan du lager et bildegalleri som vil fungere i nesten alle miljøer, ved hjelp av progressive forbedringsmetoder.


Introduksjon

Så hva er progressiv forbedring? Formelt er det dette:

Progressiv forbedring er en strategi for webdesign som legger vekt på tilgjengelighet, semantisk markering og ekstern stilark og skriptingsteknologi. Progressiv forbedring bruker webteknologi på en lagdelt måte som gjør det mulig for alle å få tilgang til det grunnleggende innholdet og funksjonaliteten til en nettside, ved hjelp av en hvilken som helst nettleser eller Internett-tilkobling, samtidig som de gir bedre båndbredde eller mer avansert nettleser en forbedret versjon av siden. (Wikipedia).

Progressiv forbedring er motsatt av grasiøs nedbrytning, hvor du bygger ditt nettsted / app med alle funksjonene, og sørg for at det ser bra ut og fungerer greit i eldre nettlesere. Med progressiv forbedring legger vi et solid fundament for vårt bildegalleri som vil fungere uansett hvor du ser det. Da lagrer vi øye-godteri og funksjonalitet til vi har et godt, velfungerende bilgalleri. La oss begynne!

Hva vi er etter

Her er det vi vil ende opp med: hvis alle klokkene og fløyter er slått på, kan vi dra våre bilder rundt for å se dem; det vil være en veldig grunnleggende simulering av en stabel med bilder på salongbordet ditt. Når du klikker på en, vil den glide åpen for å avsløre noen detaljer om bildet. Hvis JavaScript er slått av, har vi et fint rutenett for å velge mellom; ved å klikke på dem, tar vi oss til en side med en større versjon av bildet og detaljene. Hvis det ikke er CSS-støtte, får vi en stygg (men arbeider) liste over bildene.

Her er et skjermbilde av vårt endelige produkt:

Legge til stiftelsen: POSH

Vi starter med noen vanlig gammel semantisk HTML. Dette er vårt fundament, siden alle nettlesere der ute er gode til å analysere HTML.

index.htm

     Progressivt forbedret bildegalleri   

Klikk på et bilde under for å se det!

  • 3dOcean
  • AudioJungle
  • ActiveDen
  • GraphicRiver
  • Themeforest
  • VideoHive

Det er det; ganske grunnleggende ting, eh? Ingen nettleser verdt den tittelen skal ha et problem med det. Og dette er vårt ferdige første lag. Nei, det er ikke pent, men det var ikke vårt mål: Vi ønsket noe som vil fungere overalt, uansett hva. Noen ting å legge merke til om denne koden: For det første er det semantisk, som vi sa det burde være. Du lurer kanskje på divsene i listepostene. Hva skjer med dem? Selv om vi starter med de bare beinene, forventer vi at de fleste av våre seere vil ha JavaScript aktivert, i så fall trenger vi de divene. Vi kunne sette dem inn med jQuery, men siden vi gjøre Forvent at de skal brukes mesteparten av tiden, det er lettere å kode hardt inn. Den andre tingen å legge merke til er at den er brukbar. Prøv å vise den i Lynx, eller en annen nettleser som bare er i tekst:

Forresten, sidene som er koblet til i HTML-koden ovenfor, vil være tilgjengelige i nedlastbar kilde; de ligner alle på dette:

     Themeforest MarketPlace av Envato   

Themeforest

Themeforest

Themeforest tilbyr: HTML-maler, WordPress, Joomla, Flash-sider, PSD-maler, Javascript, PHP-skript

På et ekte nettsted, vil du omgjøre dette med nettstedet mal, men det er bare bra for våre formål.

Klær på strukturen: CSS

Selv om semantisk HTML er fint, ser det litt ut. La oss kle det med noen CSS. Selvfølgelig må vi først referere stilarket:

  

Vi planlegger nivået først med en tilbaketrukket Meyer reset:

 / * Meyer Tilbakestill * / html, kropp, div, h1, h2, h4, p, a, img, ul, li margen: 0; polstring: 0; grense: 0; oversikt: 0; font-weight: arv; font-style: arv; skriftstørrelse: 100%; font-familie: arv; vertikaljustering: basislinje;  / * Husk å definere fokus stiler! * /: fokus disposisjon: 0;  kropp linjehøyde: 1; farge svart; bakgrunn: hvit;  ol, ul listestil: ingen;  / * End Meyer Reset * / 

Nå må vi stille inn vårt galleri for bruk uten JavaScript. Vi begynner med noen generelle elementer og bakgrunnsstyling:

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

Nå tar vi vare på våre overskrifter og listeposter.

 #container h1 polstring: 10px;  #images li float: left; bakgrunn: #ececec; grense: 1px solid #ccc; margin: 10px; bredde: 256px; polstring: 10px; overløp: skjult;  #images li div width: 512px; flow: hidden;  #images li a float: left;  #images li div.info width: 246px; polstring: 0 0 0 10px; float: venstre;  

Du vil legge merke til at vi har satt en bredde på listelementene våre. Vi må gjøre det for vår JavaScript-funksjonalitet; det er også hvorfor overløp: skjult er satt. Dette er lett i vårt tilfelle, fordi jeg har laget alle bildene i samme bredde. Hvis dine er forskjellige bredder, må du sannsynligvis sette bredden for hvert listepost med JavaScript. Det vil fungere fordi CSS-versjonen ikke krever bredden. Diven som ligger direkte innenfor vårt listepost (som bryter alt innholdet) er 512px bredt, med overlap gjemt. Vi har floppet vårt anker til venstre slik at vi kan flyte div.info til venstre ved siden av det, som du ser videre på.

Så her er frukten av vårt arbeid så langt:

Vi kommer tilbake til CSS på litt; men nå, la oss gå til JavaScript!

Legge til funksjonaliteten: JavaScript

Vi bruker jQuery her; så start med å importere det fra Googles CDN. Vi trenger også jQueryUI-biblioteket. Vi kan også få det fra Google, men vi trenger ikke hele biblioteket. Jeg har lastet ned en kopi fra jQueryUI-siden, med bare kjerne og de trekkbare komponentene, som er alt vi trenger. Du kan gjøre det du foretrekker.

   

Før vi begynner koding, la oss bestemme hva vi trenger å gjøre.

  • H1 vi har hardkodd gir instruksjon for ikke-JavaScript-versjonen. Vi fjerner dette og legger til forskjellige instruksjoner.
  • Vi må konfigurere dra på listelementene; Vi legger til et morsomt: Når brukeren slipper listeposten, vil den skyve litt lenger og senke (lyder som en iEffect). Som vi sa tidligere, skulle det være litt som en bunke med bilder på et bord.
  • Når et listepunkt er klikket, skal det "skyve åpent," dobling i bredde. Før det gjør, sender vi imidlertid et Ajax-anrop for å få siden som brukeren ville gå til hvis JavaScript ikke var aktivert. Deretter får vi verdiene vi ønsker fra den siden og kobler dem til vår liste i en div. Vi sjekker for denne diven før du ringer, men hvis brukeren allerede har klikket på den, sender vi ikke en annen forespørsel..

Ok, åpne et skript og la oss kode!

 var imgs; $ (dokument) .ready (funksjon () ); $ (vindu) .load (funksjon () );

Vi starter med å opprette en global variabel: en rekke listeposter (vel, det vil snart være en matrise). Deretter setter vi opp hendelsesbehandlere for a) når DOM er klar, og b) når vinduet er ferdig lastet. Effekten vi skal gjøre når vinduet laster (som jeg ikke har fortalt deg om ennå) krever ikke at vi venter til da, men jeg tror det blir bedre når bildene er lastet.

Nå går denne koden i vår document.ready funksjon:

 var dra = ; $ ( 'H1') fjerne (.); $ ( '# Bilder'). Append ('
  • Kast bildene rundt; Hvis du ser en du liker, klikker du på den!

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

    Bør være grei: Vi lager et objekt som vil holde noen detaljer om uttrekking; da fjerner vi h1, legger til en liste med nye instruksjoner til listen vår, og legger alle listepostene i vår imgs-variabel.

    Nå bygger vi vår slepefunksjonalitet. Virkelig er det så enkelt som dette:

     imgs.draggable (); 

    Men vi skal legge til noen få alternativer. Her er koden; persue det selv og da vil vi spasere gjennom den.

     imgs.draggable (stack: group: '#images li', min: 1, start: funksjon () $ this = $ (dette); hvis ($ this.attr ("id") === ' instruksjoner ') $ this.fadeOut (). fjern (); imgs.each (funksjon () var $ this = $ (dette); hvis ($ this.width ()! == 256) $ dette. stop (): drag.startPos = $ this.position ();, stop: function ((bredde: 256). FjernClass ('top');); drag.startTime = nytt Dato ) var $ this = $ (dette), topp, venstre, tid; drag.endTime = nytt 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 = (dra.topOffset / tid) .toString (); left = (drag.leftOffset / time) .toString (); $ this.animate (top: '+ =' + topp, venstre: '+ =' + venstre);); 

    Vi har lagt til tre egenskaper i vårt trekkbare alternativobjekt: stable, start og stopp. Stack kontrollerer z-indeksen for en gruppe objekter, og tar et objekt med to egenskaper av seg selv: gruppe og min. Gruppen er en jQuery-velger; i vårt tilfelle er det listepostene. Min er den minste z-indeksen noen elementer i gruppen kan ta. Så nå, når du drar et element, kommer det til toppen av haugen.

    Start-funksjonen kjøres når du begynner å dra et element. Vi starter med å cache $ (dette). Deretter sjekker vi for å se om listen elementet vi grep har et ID-instruksjon. Hvis det gjør det, forsvinner vi det og fjerner det. Deretter løper vi over hvert listeelement, og hvis vi finner noen som ikke er 256px bred, animerer vi bredden til 256px og fjerner klassen "topp". Hva er 'topp'? Vi stiler det om noen få minutter, men det gir bare brukeren visuell tilbakemelding når de klikker på et element. Deretter gjør vi noe veldig viktig: vi setter to egenskaper på vårt dragobjekt. One (startTime) er den tiden draget startet, og den andre (startPos) er posisjonen som varen startet på. Vi bruker denne informasjonen til å skape vår effekt når draringen stopper.

    Til slutt har vi stoppfunksjonen, som forutsigbar kjører når brukeren slutter å dra. Igjen begynner vi å cache $ (dette), samt å skape noen andre variabler, vi gir verdier til i et øyeblikk. Deretter setter vi sluttiden og posisjonen inn i drag.endTime og drag.endPosition. Deretter beregner vi vår venstre og toppforskyvning ved å trekke fra hvor vi var fra hvor vi er; Vi kan gjøre dette med topp- og venstre egenskaper som posisjonsobjektet har. Nå for å redusere animasjonslogikken: Du kan bli svært komplisert med denne algoritmen, men vi skal bare holde det enkelt. Vi finner den tiden draen tok ved å trekke vår starttid fra vår endTime; GetTime-metoden returnerer antall millesekunder siden 1970/01/01, så forskjellen er i millesekunder. Da deler vi den verdien med 60, som jeg kom opp med gjennom prøving og feiling. Med en gjennomsnittlig dra, setter dette vår tidsvariabel et sted mellom 2 og 3. Da deler vi vår topp og offset etter tid, og konverterer disse verdiene til streng, og lagrer dem i topp og venstre. Til slutt, animerer vi det slepede listeposten, øker (det er hva '+ =' gjør) verdien ved toppen eller til venstre. På dette tidspunktet bør du kunne trekke bildene rundt og få vår effekt.

    Men ved å klikke på bildene kommer du til en ny side. Så la oss sette opp vår klikkhendelseshåndterer.

     imgs.click (funksjon () var $ this = $ (dette); hvis ($ this.attr ('id') === 'instruksjoner') $ this.fadeOut (). remove (); else  if ($ this.width ()! == 256) $ this.stop (). animate (bredde: 256). removeClass ('top'); annet hvis (! ($ this.find (' .info '). lengde)) $ .ajax (url: $ this.find (' a '). attr (' href '), dataType:' html ', suksess: funksjon (data) var $ d = $ (data), hode = $ d.filter ('h1'), para = $ d.filter ('p'); $ this.children ('div').
    ') .find (". info"). legge til (hode, para); , feil: funksjon () var msg = '

    Oops!

    Det ser ut til at det har vært et problem; Vi kan ikke få denne informasjonen akkurat nå.

    '; $ This.children ( 'div'). Append ('
    . ') .Finn ( "info") html (msg); ); $ this.css ('zIndex': 8) .stop () .animate (width: 512) .addClass ('top') .siblings (). removeClass ('top') .stop (). animere (bredde: 256) .filter (funksjon () return $ (dette) .css ('zIndex') === '8'). css ('zIndex': 7); returnere false; );

    Standard operasjonsprosedyre i dag: Begynn med å cache $ (dette). Igjen, vi sjekker for id av instruksjoner; hvis det er der, vi fade ut og fjerne elementet. Hvis det ikke er der, kontrollerer vi elementets bredde: Hvis det ikke er 256px, betyr det at dette elementet allerede er klikket, så vi animerer bredden ned til 256 og fjerner vår toppklasse (ja, vi kommer dit ). Hvis elementet er 256px bredt, ser vi etter et barnelement med klassen av info. Vi kan gjøre dette min ringer finnmetoden på elementet, passere i selgeren vi leter etter, og få lengden på eiendommen. Hvis dette elementet ikke eksisterer, blir resultatet 0, som er en falsk verdi, så vi pakker det i parentes og bruker en! å bytte boolsk. Nå, hvis det ikke er noen barnelementer med en klasse med info, kommer vi inn i denne blokken, som er vårt ajax-anrop.

    $ .ajax () tar en objektparameter, og vi bruker fire egenskaper: URL, datatype, suksess og feil. Url og datatype er åpenbare: vi finner bare ankeret i vår liste element og sett url til sin href; Datatypen vår er html. Hvis vårt ajax-anrop lykkes, tar vi dataene vi får, som er hele HTML-innholdet på siden, og gjør det til et jQuery-objekt. Deretter kan vi filtrere ut overskriften og avsnittet som vi vet at vi har der. Da får vi bare div i vår liste element, legger til div.info, og legger til overskriften og avsnittet til det. Hvis vår forespørsel mislykkes, viser vi en feilmelding ved hjelp av en lignende prosess, ved hjelp av feilfunksjonen. Etter vår ajax-samtale, ønsker vi å utføre noen styling og animasjon på vår liste element. Først vil vi sette z-indeksen til 8, eller et hvilket som helst tall som er høyere enn antall trekkbare elementer vi har. Da vil vi stoppe alle nåværende animasjoner på dette listeposten og animere bredden til 512px. Til slutt legger vi til toppklassen. Deretter får vi alle søsken, som er de andre listepostene. Vi stopper animasjonen på dem og animerer dem til 256px bred. Til slutt vil vi bare filtrere ut elementene med en z-indeks på 8 og endre deres z-indeks til 7. Dette gjør det mulig for den nåværende cliked-listen å komme over toppen. På slutten returnerer vi falske, så vi holder oss på vår nåværende side (fordi selv om dette er en klikkfunksjon på en liste element, vil brukerne mest sannsynlig klikke på vårt ankerinnpakket bilde inne i listeposten).

    Så det er vår klikkbehandler; bare ett stykke JavaScript igjen. Hvis du gir vårt eksempel et forsøk nå, ser du det fungerer ... slags. Når du klikker på et listeelement for å åpne det, åpnes det, men du ser et ganske skittent problem. Det er fordi listepostene er floated til venstre; la oss ta vare på det i vår vindu klare handler.

     $ (vindu) .load (funksjon () var $ w = $ (vindu); imgs.css (posisjon: 'absolutt', venstre: $ w.width () / 2 - imgs.width $ w.height () / 2- imgs.height ()) for (var i = 0; imgs [i]; i ++) $ (imgs [i]). animate (left: '+ =' + Math.random () * 150, topp: '+ =' + Math.random () * 150);); 

    Hvis du har fulgt ganske bra så langt, vil du ikke flinke her: vi bruker bare jQuery's css-metode for å sette posisjoneringen til absolutt og stable alle bildene, slik at deres høyre kanter er justert til midten av visningsporten, og deres Bunnkanter er justert til den vertikale midten. Deretter bruker vi en for-løkke til å rekursere over hver liste element og tilfeldig passe den rett og ned. Dette skaper effekten av en stabel bilder som er spredt.

    Så det er det for JavaScript! Nå, når en bruker laster inn siden, bør de se noe slikt (etter animasjon):

    Final Touches: CSS3

    Vi kan ende der, men vi vil belønne de som bruker fremtidsrettet nettlesere, så det er tilbake til CSS i noen få minutter. Og ja, vi vil se på toppklassen.

    Det første vi skal gjøre er å legge avrundede hjørner til velgeren #images li.

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

    Deretter ser toppklassen, hvilke listeposter bare når de er 'åpne', slik ut:

     .topp boks-skygge: 0 0 10px # 000; -moz-boks-skygge: 0 0 10px # 000; -webkit-boks-skygge: 0 0 30px # 000;  

    Ingenting utrolig fancy, men noen fine raffinementer likevel.

    Avsluttende kommentarer

    Vel, det er det. Vi bør nå ha et bildegalleri som fungerer anstendig uten CSS eller JavaScript, men tar full nytte av dem der teknologiene er tilgjengelige. Så, hvordan ville du forbedre vårt galleri? La oss høre det i kommentarene!