Fullscreen gallery

Share on Facebook
Share on Twitter
There are tons of various javascript galleries out there. Some have complex functionality and suit well large slideshows, others are minimalistic for simple browsing. Although one can usually find a good fit, sometimes the same issue arises - a need for a slight adjustment would require plethora of time to implement. Thus, to start from scratch is oftentimes the best solution
Share on Facebook
Share on Twitter

Recently when we were working on a new website for a construction company, we'd come up with an interesting gallery design. The idea was to have a gallery that would responsivelly fill the available height and width. You can checkout the final (slighltly adjusted) implementation here. Contemplating, it comes down to three areas:

  • Design
  • Image slider
  • Fade Out/In animation

Layout with flexbox

If flexbox sounds unknown or somewhat confusing, I recommend reading this guide that helped me understand it quickly. To get our three column responsive structure working, let's start with the HTML.


<div class="gallery">

    <div class="gallery__aside">
        <div class="gallery__column">
            <div class="gallery__item" style="background: url('https://static.pexels.com/photos/34950/pexels-photo.jpg');"></div>
        </div>
    </div>

    <div class="gallery__aside gallery__aside--right">
        <div class="gallery__column">
            <div class="gallery__item" style="background: url('https://static.pexels.com/photos/39811/pexels-photo-39811.jpeg');"></div>
        </div>
    </div>

    <div class="gallery__column">
        <div class="gallery__item" style="background: url('https://static.pexels.com/photos/33109/fall-autumn-red-season.jpg');"></div>
        <div class="gallery__item" style="background: url('https://static.pexels.com/photos/39811/pexels-photo-39811.jpeg');"></div>
        <div class="gallery__item" style="background: url('https://static.pexels.com/photos/230629/pexels-photo-230629.jpeg');"></div>
        <div class="gallery__item" style="background: url('https://static.pexels.com/photos/34950/pexels-photo.jpg');"></div>
    </div>

</div>

The whole content is stored within a gallery container which spreads across the full width and height of the screen. The two lateral tiles have a hard-coded background image to for the time being. However, they'll be filled with javascript later on. Lastly, tha main column stores all the images in the gallery. You can copy as it is and use photos from pexels or replace them with your own.

That's all the HTML needed for the start. Now to the styling part.


.gallery {
    height: 100vh;
    width: 100vw;
    display: flex;
    background-color: black;
}

.gallery__aside {
    display: flex;
    /* Fill the available space, but no more than 10% of the screen width */
    flex: 1;
    max-width: 10%;
}

/* Move the second tile to the right */
.gallery__aside--right {
    order: 3;
}

/* Make each column flexible (especially vertically) */
.gallery__column {
    flex: 1;
}

.gallery__item {
    /* Fill the available space (that is 100vh) */
    height: 100%;
    background-size: cover;
}

As I have mentioned above, the gallery container spreads across the whole screen. The children elements, thanks to flexbox, may spread freely across the available space. The direct children are gallery__column and gallery__aside. Therefore, these three elements would share the available height and width equally. However, we wish the lateral tiles to be rather small, so we set a limit of maximum width to 10%. Lastly, to be able to have gallery__aside blocks next to each other in HTML and divided in a browser, we set the order of flexbox items and move the right tile to the right side.

At this point, all the images are displayed at the same time. That is because we haven't started with the slider yet. We'll do it in a minute. First though, let's make the lateral boxes saturated on hover.


.gallery__aside {
    display: flex;
    /* Fill the available space, but no more than 10% of screen width */
    flex: 1;
    max-width: 10%;

    /* Styling and transition of lateral boxes */
    filter: brightness(.6) saturate(.15);
    transition: filter 0.2s ease-out;
}

.gallery__aside:hover {
    filter: brightness(1) saturate(.6);
    cursor: pointer;
}

Using the CSS filter and transition properties, this nice-looking effect is easily achieved.

1 Design

Image slider

There is plethora of javascript gallery libraries. In this example, I'm going to use Pedro Duarte's minimalist gallery called Wallop.js that handles this job well. Although I said at the beginning it's sometimes good to start completely from scratch, this library handles nothing more than browsing through the images. No styles needed to inherit, easily customizable animations. Time efficient in this case. Once you download the slider and include it in your page, we will have to add couple of classes to the HTML.


<div class="Wallop gallery">
    <!-- Left Preview Tile  -->
    <div class="Wallop-buttonPrevious gallery__aside">
        <div class="gallery__column" id="leftPreview">
            <div class="gallery__item" style="background: url('https://static.pexels.com/photos/34950/pexels-photo.jpg');"></div>
        </div>
    </div>
    <!-- Right Preview Tile  -->
    <div class="Wallop-buttonNext gallery__aside gallery__aside--right">
        <div class="gallery__column">
            <div class="gallery__item" style="background: url('https://static.pexels.com/photos/39811/pexels-photo-39811.jpeg');"></div>
        </div>
    </div>

    <!-- Image Box  -->
    <!-- Include all images here  -->
    <!-- More on the image slider - http://pedroduarte.me/wallop/ -->
    <div class="gallery__column Wallop-list" id="galleryBox">
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/33109/fall-autumn-red-season.jpg'); background-size: cover;"></div>
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/39811/pexels-photo-39811.jpeg'); background-size: cover;"></div>
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/230629/pexels-photo-230629.jpeg'); background-size: cover;"></div>
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/34950/pexels-photo.jpg'); background-size: cover;"></div>
    </div>
</div>

Firstly, add Wallop class the gallery container. Then, set the lateral columns to be buttons that allow users to move between images using Wallop-buttonPrevious and Wallop-buttonNext classes. Then define Wallop-list container where our the gallery images will be stored. Each image must have Wallop-item class to work properly. You could configure to use different class names, but I prefer keeping the default naming.

Lastly, we need to initiliaze the wallop slider through javascript.


// Initialize wallop.js image slider
var wallopEl = document.querySelector('.Wallop');
var slider = new Wallop(wallopEl);

That is all. The image slider is up and running and it is already possible to browse through images.

2 Image slider

Transition and animation

Alright so the slider works, but the lateral boxes don't change which kinda ruins the whole idea. Before we fix that, we'll include one more libray. It's called Green Sock Animation Platform (GSAP) which according to their website is the standard for JavaScript HTML5 animation. I upvote that as on many occassions it has better performance results than css animations. The basic (yet vastly powerful) version is free and fairly easy to learn and start using right away.

Back to our work. To be able to change the lateral images, we'll add id="leftPreview", to the left column and id="rightPreview" to the right one. Lastly, add id="galleryBox" to the middle box. At this point, delete background images from the lateral columns. The final HTML has the following structure.


<div class="Wallop gallery" id="gallery">
    <!-- Left Preview Tile  -->
    <div class="Wallop-buttonPrevious gallery__aside">
        <div class="gallery__column">
            <div class="gallery__item" id="leftPreview"></div>
        </div>
    </div>
    <!-- Right Preview Tile  -->
    <div class="Wallop-buttonNext gallery__aside gallery__aside--right">
        <div class="gallery__column">
            <div class="gallery__item" id="rightPreview"></div>
        </div>
    </div>

    <!-- Image Box  -->
    <!-- Include all images here  -->
    <!-- More on the image slider - http://pedroduarte.me/wallop/ -->
    <div class="gallery__column Wallop-list" id="galleryBox">
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/33109/fall-autumn-red-season.jpg'); background-size: cover;"></div>
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/39811/pexels-photo-39811.jpeg'); background-size: cover;"></div>
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/230629/pexels-photo-230629.jpeg'); background-size: cover;"></div>
        <div class="gallery__item Wallop-item" style="background: url('https://static.pexels.com/photos/34950/pexels-photo.jpg'); background-size: cover;"></div>
    </div>
</div>

Let's turn the focus fully on javascript. We've already defined a Wallop slider. Now, declare variables that will contain each of the columns. Additionally, we'll add a Wallop change listener. This is a wallop's feature that triggers onSliderChange anytime picture in the galleryBox is changed.


// Initialize wallop.js image slider
var wallopEl = document.querySelector('.Wallop');
var slider = new Wallop(wallopEl);

// Find preview tiles and main image box
var leftPreview = document.getElementById("leftPreview");
var rightPreview = document.getElementById("rightPreview");
var gallery = document.getElementById("galleryBox");

// Listen for image change on preview tiles click
slider.on('change', onSliderChange);

Once the lateral tile is clicked, there are several things that need to occur.

  • Determine which picture is going to be displayed in the main column.
  • Prepare the previous and following picture for the preview.
  • Change the side picture using fade out/in effect.
    
var allImagesArray = slider.allItemsArray;
var lastImageIndex = slider.allItemsArray.length - 1;

function onSliderChange(event) {
    // Determine index of next and previous picture
    var previousImageIndex = slider.currentItemIndex - 1 < 0 ? lastImageIndex : slider.currentItemIndex - 1;
    var nextImageIndex = slider.currentItemIndex + 1 > lastImageIndex ? 0 : slider.currentItemIndex + 1;

    // Get the background image property declared within html
    var previousImage = allImagesArray[previousImageIndex].getAttribute("style");
    var nextImage = allImagesArray[nextImageIndex].getAttribute("style");

    // Pass the background image of next and previous image to animate function
    fadeOutIn(leftPreview, previousImage); fadeOutIn(rightPreview, nextImage);
}
    

The first point, changing the main picture, is handled by Wallop so we don't need to worry about that.

For the second point, we need to determine which picture is next and which is previous. Using ternary operators and current index, we select the next a previous picture. All is left to do is to change background-image properties properly. We pass the background-image attribute to the fadeOutIn function to animate the transition. The first attribute contains the element whose background should be changed.

    
function fadeOutIn(element, background) {
    // Prepare GSAP TimeLine variable
    var timeline = new TimelineLite();

    // First, fade out the current picture
    timeline.to(element, 0.2, {
        opacity: 0.2,
        display: "none",
        // Once the fade out is complete, change background image of both tile boxes
        onComplete: function () {
             element.setAttribute("style", background);
        }
    });

    // Then fade in again
    timeline.to(element, 0.1, {
        opacity: 1,
        display: "block"
    });
}
    

This function tackles the third point. Using GSAP, we declare a new timeline (regular tweens would work just as well). Firstly, the lateral box will fade out over 0.2 seconds. After that, the background-image of the lateral box will change. Once that is finished, the box will fade in back to view. That's it.

3 Fade out/in animation

Final code

4 All together

Note on IE11 and below

This design is dependent on the css filter property to a great degree, which unfortunatelly doesn't work in IE11 and below. Here is a fallback solution, which doesn't look as nice, but gets the job done.

    
.gallery__aside::after {
    content: "";
    position: absolute;
    left: 0;
    background-color: rgba(0, 0, 0, 0.6);
    width: 100%;
    height: 100%;

}

@supports (filter: brightness(.2) saturate(.15)) {
    .gallery__aside::after {
        content: none;
    }
}
    

Add a black box over the gallery__aside divs with opacity of 0.6. So the preview tiles are dark at least, when the filter is not supported. However, if the filter property is supported (and @supports feature is supported too), than remove the after content and use filter instead.

5 :/

< back