From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
In this tutorial we will create a bubbly image gallery that shows your images in a unique way. The idea is to show the thumbnails of albums in a rounded fashion allowing the user to scroll them automatically by moving the mouse. Clicking on a thumbnail will zoom in a big circle and the full image which will be automatically resized to fit into the screen. Navigating through the images will slide the current image to the side and make the new one appear in a zoom like fashion.
We will be using Manos Malihu’s brilliant thumbnail scroller which you can find here: Manos Malihu’s thumbnail scroller
The beautiful images are by talented geishaboy500 and you can find more amazing photographs on his flickr photostream:
Photos by geishaboy500
Ok, let’s get started!
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
The Markup
Let’s start by creating our HTML structure. We will have quite a few elements, so we will begin with the top menu that appears when we view the full image:
<div class="top_menu" id="top_menu"> <span id="description" class="description"></span> <a id="back" href="#" class="back"><span></span>back</a> <div class="info"> <span class="album_info">Album 1</span> <span class="image_info"> / Shot 1</span> </div> </div>
We need an option to go back to the thumbnails view, a description area and an information area that shows us which image we are currently viewing. So, this element is just going to show up when we click on a thumbnail. The empty span will be used to add a little back arrow.
We also need a loader element:
<div id="loader" class="loader"></div>
Now, let’s take a look at the heading element where we will put our main h1 element for the gallery title:
<div class="header" id="header" style="top:-90px;"><!--top 30 px to show--> <h1>Bubbleriffic<span>jQuery Image Gallery</span></h1> </div>
We want to slide this element in from the top when we load the page, so we initially set the top value to -90 pixels. In the JavaScript we will then animate it to 30 pixels. You can also add this style to the stylesheet instead of having an inline style.
The next element will be the thumbnails wrapper that will have all the thumbnail albums. Since we will use Manos’ thumbnail scroller, we will base our markup on that structure. There will be three scrolling containers for the three albums which will have the class “tshf_container”:
<div id="thumbnails_wrapper" class="thumbnails_wrapper" style="top:-255px;"> <!-- top:110px to show--> <div id="tshf_container1" class="tshf_container"> <div class="thumbScroller"> <div class="container"> <div class="content"> <div> <a href="#"> <img src="images/albums/album1/thumbs/1.jpg" alt="Description" class="thumb" /> </a> <span></span> </div> </div> <div class="content"> ... </div> </div> </div> </div> <div id="tshf_container2" class="tshf_container"> ... </div> <div id="tshf_container3" class="tshf_container"> ... </div> </div>
The empty span inside of the div that holds the image will be used for overlaying an image with a hole in it, making the thumbnails appear like little bubbles.
Now we will add the yellow bubble that will be used to create the bubble like tunnel effect when we want to view a full image:
<div class="bubble"> <img id="bubble" src="images/bubble.png" alt=""/> </div>
The preview container for the full image view with the navigation will have the following structure:
<div id="preview" class="preview"> <a id="prev_image" href="#" class="prev_image"></a> <a id="next_image" href="#" class="next_image"></a> </div>
The footer can be used to add some information:
<div class="footer"> <!-- Add something here --> </div>
Let’s take a look at the style!
The CSS
First, we will reset the style and define some general properties for links, lists and the body:
*{ margin:0; padding:0; } a{ text-decoration:none; outline:none; } ul{ list-style:none; } body{ background:#222 url(../bg.jpg) repeat top left; font-family:"Trebuchet MS", "Myriad Pro", Helvetica, sans-serif; font-size:13px; color: #fff; text-transform:uppercase; text-shadow:0px 0px 1px #fff; letter-spacing:1px; overflow:hidden; }
The top menu that appears when we view a full image will have the following style:
.top_menu{ height:30px; line-height:30px; position:absolute; top:-30px; left:0; width:100%; overflow:hidden; background:#010101; border-bottom:1px solid #000; z-index:100; -moz-box-shadow:0px 0px 4px #010101; -webkit-box-shadow:0px 0px 4px #010101; box-shadow:0px 0px 4px #010101; }
(If you know that your text will only occupy one line in a specific element, then you can set that element’s line-height to its height in order to center the containing text vertically.)
We set the top to -30 pixels in order to hide the element.
The back link will have the following style:
.top_menu .back{ position:absolute; top:0px; left:10px; height:30px; line-height:30px; cursor:pointer; color:#aaa; }
We will add a little arrow icon for the back link that actually has the same background image like the navigation element. We use double of the width though, so that we can repeat the image twice:
.top_menu .back span{ width:14px; height:30px; display:block; float:left; background:#000 url(../images/prev.png) repeat-x center left; margin-right:5px; opacity:0.5; } .top_menu .back:hover{ color:#fff; } .top_menu .back:hover span{ opacity:0.9; }
The description will appear centered:
.top_menu span.description{ font-style:italic; position:absolute; width:100%; text-align:center; top:0px; left:0px; height:30px; line-height:30px; }
And the info will float right:
.top_menu .info{ float:right; margin-right:10px; }
Let’s style the main header now. We will position it absolutely since we want it to animate from the top and we will give it a yellow background color and some nice box shadow:
.header{ height:80px; position:absolute; top:30px; left:0px; width:100%; overflow:hidden; z-index:90; background-color:#ffd800; -moz-box-shadow:0px 0px 10px #010101; -webkit-box-shadow:0px 0px 10px #010101; box-shadow:0px 0px 10px #010101; } h1{ font-size:60px; padding-left:20px; color:#010101; line-height:80px; text-shadow:1px 1px 1px #000; } h1 span{ font-size:16px; float:right; margin-right:20px; }
Before we style the thumbnails wrapper, let’s first take a look at all the other elements’ style.
The full image will be positioned absolutely, but we will set its final position in the JavaScript:
.preview img{ position:absolute; left:0; top:0; -moz-box-shadow:1px 1px 5px #111; -webkit-box-shadow:1px 1px 5px #111; box-shadow:21px 1px 5px #111; -webkit-box-reflect: below 5px -webkit-gradient( linear, left top, left bottom, from(transparent), color-stop(0.8, transparent), to(rgb(255, 216, 0)) ); }
We will add some nice reflection for webkit browsers and some decent box shadow.
The footer will have almost the same style like the top menu, except the positioning and some other details, like the border:
.footer{ z-index:100; height:30px; line-height:30px; text-align:center; font-size:10px; background:#010101; border-top:1px solid #000; position:absolute; bottom:0px; left:0px; width:100%; -moz-box-shadow:0px 0px 4px #010101; -webkit-box-shadow:0px 0px 4px #010101; box-shadow:0px 0px 4px #010101; } .footer a{ color:#999; text-decoration:none; margin:40px; }
The loading element will be placed in the middle of the page and we will make it round by setting the border radius to half of its width/height:
.loader{ display:none; width:200px; height:200px; background: #000 url(../images/ajax-loader.gif) no-repeat center center; position:fixed; top:50%; left:50%; margin:-100px 0px 0px -100px; opacity: 0.7; z-index:9999; -moz-border-radius:100px; -webkit-border-radius:100px; border-radius:100px; }
The navigation elements will have the following common style:
a.next_image, a.prev_image{ width:50px; height:50px; position:fixed; top:50%; margin-top:-25px; cursor:pointer; opacity:0.7; z-index:999999; -moz-box-shadow:0px 0px 3px #000; -webkit-box-shadow:0px 0px 3px #000; box-shadow:0px 0px 3px #000; -moz-border-radius:25px; -webkit-border-radius:25px; border-radius:25px; } a.next_image:hover, a.prev_image:hover { opacity:0.9; }
And the separate styles will be
a.next_image{ background:#000 url(../images/next.png) no-repeat center center; right:-50px; } a.prev_image{ background:#000 url(../images/prev.png) no-repeat center center; left:-50px; }
Initially, they will both be hidden, that’s why we will set their left/right positioning to the negative value of their widths.
Now, we will style the thumbnails wrapper:
.thumbnails_wrapper{ position:absolute; top:-255px; left:0px; width:100%; -moz-box-shadow:0px 3px 5px #000; -webkit-box-shadow:0px 3px 5px #000; box-shadow:0px 3px 5px #000; }
The bubble image will be positioned in the center of the page and have a width and height of 0. We will animate it then in the JavaScript:
.bubble img{ position:fixed; top:50%; left:50%; width:0px; height:0px; }
Now, we will adapt the style of Manos’ thumbnail scroller:
.tshf_container{ height:85px; position:relative; width:100%; background:#ffd800; } .tshf_container .thumbScroller{ position:relative; width:100%; overflow:hidden; } .tshf_container .thumbScroller, .tshf_container .thumbScroller .container, .tshf_container .thumbScroller .content{ height:85px; } .tshf_container .thumbScroller .container{ position:relative; left:0; } .tshf_container .thumbScroller .content{ float:left; } .tshf_container .thumbScroller .content div{ height:100%; position:relative; } .tshf_container .thumbScroller img{ border:none; } .tshf_container .thumbScroller .content div a{ display:block; height:85px; width:85px; } .tshf_container .thumbScroller .content div a img{ width:85px; } .tshf_container .thumbScroller .content div a:hover{ border-color:#fff; }
We will use the extra span to add our bubble overlay:
.tshf_container .thumbScroller .content span{ cursor:pointer; position:absolute; width:85px; height:85px; top:0px; left:0px; background:transparent url(../images/thumb_overlay.png) no-repeat top left; } .tshf_container .thumbScroller .content div:hover span{ background:transparent url(../images/thumb_overlay_hover.png) no-repeat top left; }
And that’s all the style. Now, let’s add the magic!
The JavaScript
First, we will include the following scripts:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script> <script type="text/javascript" src="js/jquery.easing.1.3.js"></script> <script type="text/javascript" src="js/jquery.thumbnailScroller.js"></script>
We will start by caching some important elements and defining some indexes:
var $thumbnails_wrapper = $('#thumbnails_wrapper'), $thumbs = $thumbnails_wrapper.find('.tshf_container').find('.content'), $top_menu = $('#top_menu'), $header = $('#header'), $bubble = $('#bubble'), $loader = $('#loader'), $preview = $('#preview'), $thumb_images = $thumbnails_wrapper.find('img'), total_thumbs = $thumb_images.length, $next_img = $('#next_image'), $prev_img = $('#prev_image'), $back = $('#back'), $description = $('#description'), //current album and current photo //(indexes of the tshf_container and content elements) currentAlbum = -1, currentPhoto = -1;
Then, we will show the loading element (until all thumbnails are loaded) and call the function that opens the albums:
$loader.show(); //shows the main menu and thumbs menu openPhotoAlbums();
And this is how that function looks like:
function openPhotoAlbums(){ //preload all the thumb images var cnt_loaded = 0; $thumb_images.each(function(){ var $thumb = $(this); var image_src = $thumb.attr('src'); $('<img/>').load(function(){ ++cnt_loaded; if(cnt_loaded == total_thumbs){ $loader.hide(); createThumbnailScroller(); //show the main menu and thumbs menu $header.stop() .animate({'top':'30px'},700,'easeOutBack'); $thumbnails_wrapper.stop() .animate({'top':'110px'},700,'easeOutBack'); } }).attr('src',image_src); }); }
The function “createThumbnailScroller()” will make the thumbnails be scrollable after Manos’ script, but we will get to that later.
Next, we will define what happens when we click on a thumbnail.
$thumbs.bind('click',function(e){ //show loading image $loader.show(); var $thumb = $(this), //source of the corresponding large image img_src = $thumb.find('img.thumb') .attr('src') .replace('/thumbs',''); //track the current album / photo currentPhoto= $thumb.index(), currentAlbum= $thumb.closest('.tshf_container') .index(); //displays the current album and current photo updateInfo(currentAlbum,currentPhoto); //preload the large image $('<img/>').load(function(){ var $this = $(this); //record the size that the large image //should have when it is shown saveFinalPositions($this); //margin_circle is the diameter for the //bubble image var w_w = $(window).width(), w_h = $(window).height(), margin_circle = w_w + w_w/3; if(w_h>w_w) margin_circle = w_h + w_h/3; //the image will be positioned on the center, //with width and height of 0px $this.css({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' }); $preview.append($this); //hide the header $header.stop().animate({'top':'-90px'},400, function(){ $loader.hide(); //show the top menu with the back button, //and current album/picture info $top_menu.stop() .animate({'top':'0px'},400,'easeOutBack'); //animate the bubble image $bubble.stop().animate({ 'width' : margin_circle + 'px', 'height' : margin_circle + 'px', 'marginTop' : -margin_circle/2+'px', 'marginLeft': -margin_circle/2+'px' },700,function(){ //solve resize problem $('BODY').css('background','#FFD800'); }); //after 200ms animate the large image //and show the navigation buttons setTimeout(function(){ var final_w = $this.data('width'), final_h = $this.data('height'); $this.stop().animate({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' },700,showNav); //show the description $description.html($thumb.find('img.thumb').attr('alt')); },200); }); //hide the thumbs $thumbnails_wrapper.stop() .animate({ 'top' : w_h+'px' },400,function(){ //solve resize problem $(this).hide(); }); }).attr('src',img_src); });
When we click on the “next” element of the navigation, we want the following to happen:
$next_img.bind('click',function(){ //increment the currentPhoto ++currentPhoto; //current album: var $album = $thumbnails_wrapper.find('.tshf_container') .eq(currentAlbum), //the next element / thumb to show $next = $album.find('.content').eq(currentPhoto), $current = $preview.find('img'); if($next.length == 0 || $current.is(':animated')){ --currentPhoto; return false; } else{ $loader.show(); updateInfo(currentAlbum,currentPhoto); //preload the large image var img_src = $next.find('img.thumb') .attr('src') .replace('/thumbs',''), w_w = $(window).width(), w_h = $(window).height(); $('<img/>').load(function(){ var $this = $(this); //record the size that the large image //should have when it is shown saveFinalPositions($this); $loader.hide(); $current.stop() .animate({'marginLeft':'-'+($current.width()+20)+'px'},500,function(){ //the current image gets removed $(this).remove(); }); //the new image will be positioned on the center, //with width and height of 0px $this.css({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' }); $preview.prepend($this); var final_w = $this.data('width'), final_h = $this.data('height'); $this.stop().animate({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' },700); //show the description $description.html($next.find('img.thumb').attr('alt')); }).attr('src',img_src); } });
And now we define what happens when we click to view the previous image:
$prev_img.bind('click',function(){ --currentPhoto; //current album: var $album = $thumbnails_wrapper.find('.tshf_container') .eq(currentAlbum), $prev = $album.find('.content').eq(currentPhoto), $current = $preview.find('img'); if($prev.length == 0 || $current.is(':animated') || currentPhoto < 0){ ++currentPhoto; return false; } else{ $loader.show(); updateInfo(currentAlbum,currentPhoto); //preload the large image var img_src = $prev.find('img.thumb') .attr('src') .replace('/thumbs',''), w_w = $(window).width(), w_h = $(window).height(); $('<img/>').load(function(){ var $this = $(this); //record the size that the large image //should have when it is shown saveFinalPositions($this); $loader.hide(); $current.stop() .animate({'marginLeft':(w_w+20)+'px'},500,function(){ //the current image gets removed $(this).remove(); }); //the new image will be positioned on the center, //with width and height of 0px $this.css({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' }); $preview.append($this); var final_w = $this.data('width'), final_h = $this.data('height'); $this.stop().animate({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' },700); //show the description $description.html($prev.find('img.thumb').attr('alt')); }).attr('src',img_src); } });
When we resize the window, we need to recalculate the position and size of the image:
$(window).resize(function(){ var $current = $preview.find('img'), w_w = $(window).width(), w_h = $(window).height(); if($current.length > 0){ saveFinalPositions($current); var final_w = $current.data('width'), final_h = $current.data('height'); $current.css({ 'width' : final_w + 'px', 'height' : final_h + 'px', 'marginTop' : w_h/2 - final_h/2 + 'px', 'marginLeft': w_w/2 - final_w/2 + 'px' }); } });
When we click on the back link, we want to close the preview of the image:
$back.bind('click',closePreview)
The functions for showing and hiding the navigation:
//shows the navigation buttons function showNav(){ $next_img.stop().animate({ 'right' : '10px' },300); $prev_img.stop().animate({ 'left' : '10px' },300); } //hides the navigation buttons function hideNav(){ $next_img.stop().animate({ 'right' : '-50px' },300); $prev_img.stop().animate({ 'left' : '-50px' },300); }
The following function will update the album/image info:
//updates the current album and current photo info function updateInfo(album,photo){ $top_menu.find('.album_info') .html('Album ' + (album+1)) .end() .find('.image_info') .html(' / Shot ' + (photo+1)) }
The next function calculates the final width and height of the full image that will be shown based on the window size:
function saveFinalPositions($image){ var theImage = new Image(); theImage.src = $image.attr("src"); var imgwidth = theImage.width; var imgheight = theImage.height; //140 is 2*60 of next/previous buttons plus 20 of extra margin var containerwidth = $(window).width() - 140; //150 is 30 of header + 30 of footer + extra 90 var containerheight = $(window).height() - 150; if(imgwidth > containerwidth){ var newwidth = containerwidth; var ratio = imgwidth / containerwidth; var newheight = imgheight / ratio; if(newheight > containerheight){ var newnewheight = containerheight; var newratio = newheight/containerheight; var newnewwidth =newwidth/newratio; theImage.width = newnewwidth; theImage.height= newnewheight; } else{ theImage.width = newwidth; theImage.height= newheight; } } else if(imgheight > containerheight){ var newheight = containerheight; var ratio = imgheight / containerheight; var newwidth = imgwidth / ratio; if(newwidth > containerwidth){ var newnewwidth = containerwidth; var newratio = newwidth/containerwidth; var newnewheight =newheight/newratio; theImage.height = newnewheight; theImage.width= newnewwidth; } else{ theImage.width = newwidth; theImage.height= newheight; } } $image.data({'width':theImage.width,'height':theImage.height}); }
When we hit the back link we want the current image to zoom out again with the big yellow bubble. Then we will show the thumbnails again:
function closePreview(){ var $current = $preview.find('img'), w_w = $(window).width(), w_h = $(window).height(), margin_circle = w_w + w_w/3; if(w_h>w_w) margin_circle = w_h + w_h/3; if($current.is(':animated')) return false; //hide the navigation hideNav(); //hide the topmenu $top_menu.stop() .animate({'top':'-30px'},400,'easeOutBack'); //hide the image $current.stop().animate({ 'width' : '0px', 'height' : '0px', 'marginTop' : w_h/2 +'px', 'marginLeft': w_w/2 +'px' },700,function(){ $(this).remove(); }); //animate the bubble image //first set the positions correctly - //it could have changed on a window resize setTimeout(function(){ $bubble.css({ 'width' : margin_circle + 'px', 'height' : margin_circle + 'px', 'margin-top' : -margin_circle/2+'px', 'margin-left': -margin_circle/2+'px' }); $('BODY').css('background','url("bg.jpg") repeat scroll left top #222222'); $bubble.animate({ 'width' : '0px', 'height' : '0px', 'marginTop' : '0px', 'marginLeft': '0px' },500); },200); setTimeout(function(){ $header.stop() .animate({'top':'30px'},700,'easeOutBack'); $thumbnails_wrapper.stop() .show() .animate({'top':'110px'},700,'easeOutBack'); },600); }
And finally, we define the function that will make the thumbnail albums scrollable by applying Manos’ thumbnail scroller:
function createThumbnailScroller(){ /* ThumbnailScroller function parameters: 1) id of the container (div id) 2) thumbnail scroller type. Values: "horizontal", "vertical" 3) first and last thumbnail margin (for better cursor interaction) 4) scroll easing amount (0 for no easing) 5) scroll easing type 6) thumbnails default opacity 7) thumbnails mouseover fade speed (in milliseconds) */ ThumbnailScroller("tshf_container1","horizontal",10,800,"easeOutCirc",0.5,300); ThumbnailScroller("tshf_container2","horizontal",10,800,"easeOutCirc",0.5,300); ThumbnailScroller("tshf_container3","horizontal",10,800,"easeOutCirc",0.5,300); }
And that’s it! We hope you liked the tutorial and found it useful!
Awesome as usual Mary Lou 🙂
Thank you, Manos. Thanks to your awesome thumbnail scroller our imagination just goes wild 🙂 Cheers, ML
Hi Mary Lou, hi Malihu..wonderfull as allways..so brilliant!
Amazing, it works great ! Thnx !
Wild!!!!!
Mary Lou, this is my first comment on your site, and I just have to say I LOVE your tutorials! I check in my Google Reader, or come to your site every day just to check if theres something new. Your skills are AMAZING…
Thank you.
Awesome, just awesome, muy buen trabajo
nice plugin
You always put great effort to make excellent tuts like this one. Brilliant gallery effect. Thanks
luv that !
again, again and again the amazing creativity …
and as usual the artistic photo’s
woOooo… more surprised every day, thanks for such excellent tutorial.
Realmente impresionante 😀
Excellent coding as usual, I’m going to have to find a project to use this on =)
very nice
Very well done!
It’s amazing!
Yhank you! 🙂
I don`t know why, but it made me smile 🙂
Cheers.
really your developer team is really great . so, nice and wonderfull and pretty jquery tuts…
so best of luck for another one…
so bye my favorite developer…
Hi!
Thanks from France, I check your website everyday, and I’m always like “wow” when I see new tutorial…
Thanks for your sharing !
Great Tutorial! i never have seen a bad tutorial here, all are awesome, thank you so much!
This is a pretty cool gallery. Thanks for sharing.
This tuto is awesome. But it is possible to have square intead of round? thanks
May i can put this plug in into my theme ?
That´s cool
how make this script for auto slide, look like slideshow.
thanks.
Missing autoplay but good script
amazing! thanks
Is there any possibilities to avoid the scollable thumb in the begin and just to have the bubble zoom effect for a thumb in any page?
(I’m French^^)
Your works speak for itself. Thank you for sharing your gifts!
Good job!
hi. can you let me know, why after download only 1 album works. I create 3 albums but doesn’t work. i enable the //ThumbnailScroller(“tshf_container2″,”horizontal”,10,800,”easeOutCirc”,0.5,300);
still not working. plz. can help me?
I’ve used your script at my new website here: http://designlabcph.com … Thank you for an excellent tutorial! 🙂
Absolutely brilliant!
I have a question as well…
|Is there a way for me to contain this all within a sized div instead of full screen for the expanded bubble?
Thank you muchly in advance
Ammit, I also try add new album and not function, because… there is missing album into albums folder.
Just copy and paste album1 in album2, album3 and then function.
Of course, uncomment ThumbnailScroller(“tshf_container2?,”horizontal”,10,800,”easeOutCirc”,0.5,300); and ThumbnailScroller(“tshf_container3?,”horizontal”,10,800,”easeOutCirc”,0.5,300);
hi , this work is great , but can tell me how to change speed motion to slower moving. great thanks
hi , my problem is when I throw a lot of a large number of pictures (50 shots), this gallery going to crazy.
🙂 , thanks for help
I was wondering if there is a way to put a link on the large images. I like being able to display the thumbnails and open them, but once they are open, to be able to click either on the image itself or on a link associated with the image to go to another page.
great work. but here is one question:
i am designing my page in Turkish which has a couple of special characters.
so, i need to add this characters to ChunkFive.
any ideas?
Excellent work, Thanks for sharing…
Hi all,
When I use the script with localhost, if there’re more than 1 album, it doesn’t work (just showing the loading forever). I created 2 folders for album2, album3 and uncommented the HTML part but it still doesn’t work. Please help 🙁
@Mol the same for me!
@Mol, I had the exact same problem, then noticed that thumb scroller 2 and 3 contain 28 thumbs in the html while album 1 contains just 24… so if you copied the album1 folder as album 2 and 3, the page still doesn’t find images from 25 to 28 and hangs on the loader
thanks alot, it worked for me like a charm, was looking pretty long this!
Is it possible to add content under the gallery? I have some problem with a content div to place after …it disappears under the footer div…is it normal? is there something to do for adding normal content after the gallery?
Thank you!
p.s.: i’m sorry for my english!