Today we'll be exploring how to quickly construct a media gallery using two Formstone components, Carousel and Lightbox. We'll also be using the Grid to handle general layout and positioning.

Getting Started

Our media gallery will display images one at a time above a 'controller' thumbnail strip. The images will open a larger version in the Lightbox on click. Let's begin by defining the Carousels that will contain the images and thumbnails.

<div class="fs-grid">
    <div class="fs-row media_gallery">
        <div class="fs-cell-centered fs-lg-9 fs-xl-8">
            <div class="media_large js-carousel_large">
                ...
            </div>
            <div class="media_small js-carousel_small" data-carousel-controller-for=".js-carousel_large">
                ...
            </div>
        </div>
    </div>
</div>

You'll notice the small Carousel's data-carousel-controller-for attribute contains a selector for the large Carousel. This tells the small Carousel to act as a controller for the large Carousel. As a result, when the large Carousel is advanced the small Carousel will respond by setting an 'active' item. Conversly, clicks to an item in the the small Carousel will advance the large Carousel to the selected item.

The large Carousel will contain the large, linked version of the images, while the small Carousel will contain the thumbnail version at the same index relative to it's parent Carousel. Becuase the active item's index is used to set each carousel position, the order of the two sets of items should match.

<div class="media_large js-carousel_large">
    <a href="//spacehold.it/1600x900/1.jpg">
        <img src="//spacehold.it/800x450/1.jpg" alt="">
    </a>
    <a href="//spacehold.it/1600x900/2.jpg">
        <img src="//spacehold.it/800x450/2.jpg" alt="">
    </a>
    <a href="//spacehold.it/1600x900/3.jpg">
        <img src="//spacehold.it/800x450/3.jpg" alt="">
    </a>
    ...
</div>
<div class="media_small js-carousel_small" data-carousel-controller-for=".js-carousel_large">
    <div class="media_gallery_thumbnail">
        <img src="//spacehold.it/125x125/1.jpg" alt="">
    </div>
    <div class="media_gallery_thumbnail">
        <img src="//spacehold.it/125x125/2.jpg" alt="">
    </div>
    <div class="media_gallery_thumbnail">
        <img src="//spacehold.it/125x125/3.jpg" alt="">
    </div>
    ...
</div>

Next we'll define each of the large item's additional attributes required for the Lightbox, including a class for targeting, a unique gallery identifier (data-lightbox-gallery), and the item's caption text (title):

<a href="//spacehold.it/1600x900/1.jpg" class="js-lightbox" data-lightbox-gallery="media_gallery" title="Caption text">
    <img src="//spacehold.it/800x450/1.jpg" alt="">
</a>

Adding Behaviors

The javascript to bring the gallery to life is pretty simple, and consists of just 3 plugin initialization calls. The large Carousel will default to showing one item at a time, while the small Carousel is set to show a different number of items based on the user's minimum screen width. We're also setting the mobile option on the Lightbox, triggering the full-screen takeover display mode instead of the standard modal.

$(document).ready(function() {

    $(".js-carousel_large").carousel({
        pagination: false,
        autoHeight: true
    });

    $(".js-carousel_small").carousel({
        show: {
            "0px": 4,
            "500px": 6,
            "980px": 8
        },
        controls: false,
        pagination: false
    });

    $(".js-lightbox").lightbox({
        mobile: true
    });

});

Setting Styles

On smaller screens where space is limited, the gallery will display the caption below the image to avoid obstructing the subject. This is where the large Carousel's autoHeight option comes in to play. The large Carousel will automatically adjust it's viewport to match the height of the current item. On larger screens where space is not at a premium, the caption will overlay the bottom of the image. It's also worth noting that we're using unprefixed LESS in this example.

.media_gallery {
    margin-top: 30px;
    margin-bottom: 30px;

    img {
        display: block;
        width: 100%;
    } 
}

.media_large {

    a {
        display: block;
        margin: 0 0 2.5%;
        text-decoration: none;
    }

    &.fs-carousel-enabled {
        margin-bottom: 10px; 

        .fs-carousel-item {
            position: relative;

            margin: 0 10px 0 0;

            &:after {
                width: 100%;

                background: #263238;
                color: #fff;
                content: attr(title);
                display: block;
                padding: 20px;

                @media screen and (min-width: 740px) {
                    position: absolute;
                    bottom: 0;
                    left: 0;

                    background: fade(#263238, 90);
                    color: transparent;
                    transition: 
                        color 0.25s linear 0s,
                        transform 0.25s ease 0s;
                    transform: translateY(100%);
                }
            }   

            &.fs-carousel-visible {

                &:after {
                    color: #fff;
                    transform: translateY(0);
                    transition-delay: 0.35s;
                }
            }
        }
    }
}

.media_small {

    &.fs-carousel-enabled {

        .fs-carousel-item {
            position: relative;

            cursor: pointer;
            margin: 0 10px 0 0;

            &:after {
                height: 100%;
                width: 100%;

                position: absolute;
                top: 0;
                left: 0;

                background: fade(#00bcd4, 50);
                border: 0 solid #00bcd4;
                content: '';
                opacity: 0;
                transition: 
                    border 0.25s linear,
                    opacity 0.25s linear;
            }

            &.fs-carousel-active {

                &:after {
                    border-width: 5px;
                    opacity: 1;
                }
            }
        }
    }
}

Putting it all together, we have our final media gallery.

View Larger

Next Steps

This is a quick example of how you can combine different plugin functionality to create more complex interface and user interactions. Feel free to fully customize the look and feel of the individual plugins using Themes. And don't forget to explore all of the plugin options in the Carousel and Lightbox documentation.


Comments