Skip to content

Галерея-сетка Google

В этом концепте создана адаптивная галерея-сетка, вдохновленная галереей Google в Руководстве по началу работы с Chromebook. Мы используем Masonry для создания сетки и 3D-преобразований для навигации по элементам. Для небольших экранов у нас есть медиа-запросы, которые регулируют макет сетки и вид галереи. Кроме того сделаем возможным управление галереей с клавиатуры: «стрелки» для навигации по галерее, “Esc” для её закрытия.

Напомню, что 3D Трансформации работают не во всех браузерах.

HTML

<div id="grid-gallery" class="grid-gallery">
    <section class="grid-wrap">
        <ul class="grid">
            <li class="grid-sizer"></li><!-- for Masonry column width -->
            <li>
                <figure>
                    <img src="img/thumb/1.png" alt="img01">
                    <figcaption><h3>Letterpress asymmetrical</h3><p>Chillwave hoodie ea gentrify aute sriracha consequat.</p></figcaption>
                </figure>
            </li>
            <li>
                <figure>
                    <img src="img/thumb/2.png" alt="img02">
                    <figcaption><h3>Vice velit chia</h3><p>Laborum tattooed iPhone, Schlitz irure nulla Tonx retro 90's chia cardigan quis asymmetrical paleo. </p></figcaption>
                </figure>
            </li>
            <li>
                <figure>
                    <img src="img/thumb/3.png" alt="img03">
                    <figcaption><h3>Brunch semiotics</h3><p>Ex disrupt cray yr, butcher pour-over magna umami kitsch before they sold out commodo.</p></figcaption>
                </figure>
            </li>
            <li>
                <figure>
                    <img src="img/thumb/4.png" alt="img04">
                    <figcaption><h3>Chillwave nihil occupy</h3><p>In post-ironic gluten-free deserunt, PBR&B non pork belly cupidatat polaroid. </p></figcaption>
                </figure>
            </li>
            <li>
                <figure>
                    <img src="img/thumb/5.png" alt="img05">
                    <figcaption><h3>Kale chips lomo biodiesel</h3><p>Pariatur food truck street art consequat sustainable, et kogi beard qui paleo. </p></figcaption>
                </figure>
            </li>
            <li>
                <figure>
                    <img src="img/thumb/6.png" alt="img06">
                    <figcaption><h3>Exercitation occaecat</h3><p>Street chillwave hoodie ea gentrify.</p></figcaption>
                </figure>
            </li>
        </ul>
    </section><!-- // grid-wrap -->
    <section class="slideshow">
        <ul>
            <li>
                <figure>
                    <figcaption>
                        <h3>Letterpress asymmetrical</h3>
                        <p>Kale chips lomo biodiesel stumptown Godard Tumblr, mustache sriracha tattooed cray aute slow-carb placeat delectus. Letterpress asymmetrical fanny pack art party est pour-over skateboard anim quis, ullamco craft beer.</p>
                    </figcaption>
                    <img src="img/large/1.png" alt="img01">
                </figure>
            </li>
            <li>
                <figure>
                    <figcaption>
                        <h3>Vice velit chia</h3>
                        <p>Chillwave Echo Park Etsy organic Cosby sweater seitan authentic pour-over. Occupy wolf selvage bespoke tattooed, cred sustainable Odd Future hashtag butcher.</p>
                    </figcaption>
                    <img src="img/large/2.png" alt="img02">
                </figure>
            </li>
            <li>
                <figure>
                    <figcaption>
                        <h3>Brunch semiotics</h3>
                        <p>IPhone PBR polaroid before they sold out meh you probably haven't heard of them leggings tattooed tote bag, butcher paleo next level single-origin coffee photo booth.</p>
                    </figcaption>
                    <img src="img/large/3.png" alt="img03">
                </figure>
            </li>
            <li>
                <figure>
                    <figcaption>
                        <h3>Chillwave nihil occupy</h3>
                        <p>Vice cliche locavore mumblecore vegan wayfarers asymmetrical letterpress hoodie mustache. Shabby chic lomo polaroid, scenester 8-bit Portland Pitchfork VHS tote bag.</p>
                    </figcaption>
                    <img src="img/large/4.png" alt="img04">
                </figure>
            </li>
            <li>
                <figure>
                    <figcaption>
                        <h3>Kale chips lomo biodiesel</h3>
                        <p>Chambray Schlitz pug YOLO, PBR Tumblr semiotics. Flexitarian YOLO ennui Blue Bottle, forage dreamcatcher chillwave put a bird on it craft beer Etsy.</p>
                    </figcaption>
                    <img src="img/large/5.png" alt="img05">
                </figure>
            </li>
            <li>
                <figure>
                    <figcaption>
                        <h3>Exercitation occaecat</h3>
                        <p>Cosby sweater hella lomo Thundercats VHS occupy High Life. Synth pop-up readymade single-origin coffee, fanny pack tousled retro. Fingerstache mlkshk ugh hashtag, church-key ethnic street art pug yr.</p>
                    </figcaption>
                    <img src="img/large/6.png" alt="img06">
                </figure>
            </li>
        </ul>
        <nav>
            <span class="icon nav-prev"></span>
            <span class="icon nav-next"></span>
            <span class="icon nav-close"></span>
        </nav>
        <div class="info-keys icon">Navigate with arrow keys</div>
    </section><!-- // slideshow -->
</div><!-- // grid-gallery -->

<script src="js/imagesloaded.pkgd.min.js"></script>
<script src="js/masonry.pkgd.min.js"></script>
<script src="js/classie.js"></script>
<script src="js/cbpGridGallery.js"></script>
<script>
    new CBPGridGallery( document.getElementById( 'grid-gallery' ) );
</script>

CSS

@font-face {
    font-family: 'fontawesome';
    src:url('../fonts/fontawesome/fontawesome.eot?-e43dk9');
    src:url('../fonts/fontawesome/fontawesome.eot?#iefix-e43dk9') format('embedded-opentype'),
        url('../fonts/fontawesome/fontawesome.woff?-e43dk9') format('woff'),
        url('../fonts/fontawesome/fontawesome.ttf?-e43dk9') format('truetype'),
        url('../fonts/fontawesome/fontawesome.svg?-e43dk9#fontawesome') format('svg');
    font-weight: normal;
    font-style: normal;
} /* Made with http://icomoon.io/app */

/* General style */
.grid-gallery ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.grid-gallery figure {
    margin: 0;
}

.grid-gallery figure img {
    display: block;
    width: 100%;
}

.grid-gallery figcaption h3 {
    margin: 0;
    padding: 0 0 0.5em;
}

.grid-gallery figcaption p {
    margin: 0;
}

/* Grid style */
.grid-wrap {
    max-width: 69em;
    margin: 0 auto;
    padding: 0 1em 1.875em;
}

.grid {
    margin: 0 auto;
}

.grid li {
    width: 25%;
    float: left;
    cursor: pointer;
}

.grid figure {
    padding: 15px;
    -webkit-transition: opacity 0.2s;
    transition: opacity 0.2s;
}

.grid li:hover figure {
    opacity: 0.7;
}

.grid figcaption {
    background: #e4e4e4;
    padding: 25px;
}

/* Slideshow style */
.slideshow {
    position: fixed;
    background: rgba(0,0,0,0.6);
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: 500;
    opacity: 0;
    visibility: hidden;
    overflow: hidden;
    -webkit-perspective: 1000px;
    perspective: 1000px;
    -webkit-transition: opacity 0.5s, visibility 0s 0.5s;
    transition: opacity 0.5s, visibility 0s 0.5s;
}

.slideshow-open .slideshow {
    opacity: 1;
    visibility: visible;
    -webkit-transition: opacity 0.5s;
    transition: opacity 0.5s;
}

.slideshow ul {
    width: 100%;
    height: 100%;
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
    -webkit-transform: translate3d(0,0,150px);
    transform: translate3d(0,0,150px);
    -webkit-transition: -webkit-transform 0.5s;
    transition: transform 0.5s;
}

.slideshow ul.animatable li {
    -webkit-transition: -webkit-transform 0.5s;
    transition: transform 0.5s;
}

.slideshow-open .slideshow ul {
    -webkit-transform: translate3d(0,0,0);
    transform: translate3d(0,0,0);
}

.slideshow li {
    width: 660px;
    height: 560px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -280px 0 0 -330px;
    visibility: hidden;
}

.slideshow li.show {
    visibility: visible;
}

.slideshow li:after {
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background: rgba(255,255,255,0.8);
    -webkit-transition: opacity 0.3s;
    transition: opacity 0.3s;
}

.slideshow li.current:after {
    visibility: hidden;
    opacity: 0;
    -webkit-transition: opacity 0.3s, visibility 0s 0.3s;
    transition: opacity 0.3s, visibility 0s 0.3s;
}

.slideshow figure {
    width: 100%;
    height: 100%;
    background: #fff;
    border: 50px solid #fff;
    overflow: hidden;
}

.slideshow figcaption {
    padding-bottom: 20px;
}

.slideshow figcaption h3 {
    font-weight: 300;
    font-size: 200%;
}

/* Navigation */
.slideshow nav span {
    position: fixed;
    z-index: 1000;
    color: #59656c;
    text-align: center;
    padding: 3%;
    cursor: pointer;
    font-size: 2.2em;
}

.slideshow nav span.nav-prev,
.slideshow nav span.nav-next {
    top: 50%;
    -webkit-transform: translateY(-50%);
    transform: translateY(-50%);
}

.slideshow nav span.nav-next {
    right: 0;
}

.slideshow nav span.nav-close {
    top: 0;
    right: 0;
    padding: 0.5em 1em;
    color: #31373a;
}

.icon:before,
.icon:after {
    font-family: 'fontawesome';
    speak: none;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

span.nav-prev:before {
    content: "\e601";
}

span.nav-next:before  {
    content: "\e600";
}

span.nav-close:before {
    content: "\e602";
}

/* Info on arrow key navigation */
.info-keys {
    position: fixed;
    top: 10px;
    left: 10px;
    width: 60px;
    font-size: 8px;
    padding-top: 20px;
    text-transform: uppercase;
    color: #fff;
    letter-spacing: 1px;
    text-align: center;
}

.info-keys:before,
.info-keys:after {
    position: absolute;
    top: 0;
    width: 16px;
    height: 16px;
    border: 1px solid #fff;
    text-align: center;
    line-height: 14px;
    font-size: 12px;
}

.info-keys:before {
    left: 10px;
    content: "\e603";
}

.info-keys:after {
    right: 10px;
    content: "\e604";
}

/* Example media queries (reduce number of columns and change slideshow layout) */

@media screen and (max-width: 60em) {
    /* responsive columns; see "Element sizing" on http://masonry.desandro.com/options.html */
    .grid li {
        width: 33.3%;
    }

    .slideshow li {
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        margin: 0;
    }

    .slideshow li figure img {
        width: auto;
        margin: 0 auto;
        max-width: 100%;
    }

    .slideshow nav span,
    .slideshow nav span.nav-close {
        font-size: 1.8em;
        padding: 0.3em;
    }

    .info-keys {
        display: none;
    }

}

@media screen and (max-width: 35em) {
    .grid li {
        width: 50%;
    }
}

@media screen and (max-width: 24em) {
    .grid li {
        width: 100%;
    }
}

JavaScript

/**
 * cbpGridGallery.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2014, Codrops
 * http://www.codrops.com
 */
;( function( window ) {
	
	'use strict';

	var docElem = window.document.documentElement,
		transEndEventNames = {
			'WebkitTransition': 'webkitTransitionEnd',
			'MozTransition': 'transitionend',
			'OTransition': 'oTransitionEnd',
			'msTransition': 'MSTransitionEnd',
			'transition': 'transitionend'
		},
		transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
		support = {
			transitions : Modernizr.csstransitions,
			support3d : Modernizr.csstransforms3d
		};

	function setTransform( el, transformStr ) {
		el.style.WebkitTransform = transformStr;
		el.style.msTransform = transformStr;
		el.style.transform = transformStr;
	}

	// from http://responsejs.com/labs/dimensions/
	function getViewportW() {
		var client = docElem['clientWidth'],
			inner = window['innerWidth'];
		
		if( client < inner )
			return inner;
		else
			return client;
	}

	function extend( a, b ) {
		for( var key in b ) { 
			if( b.hasOwnProperty( key ) ) {
				a[key] = b[key];
			}
		}
		return a;
	}

	function CBPGridGallery( el, options ) {
		this.el = el;
		this.options = extend( {}, this.options );
		extend( this.options, options );
		this._init();
	}

	CBPGridGallery.prototype.options = {
	};

	CBPGridGallery.prototype._init = function() {
		// main grid
		this.grid = this.el.querySelector( 'section.grid-wrap > ul.grid' );
		// main grid items
		this.gridItems = [].slice.call( this.grid.querySelectorAll( 'li:not(.grid-sizer)' ) );
		// items total
		this.itemsCount = this.gridItems.length;
		// slideshow grid
		this.slideshow = this.el.querySelector( 'section.slideshow > ul' );
		// slideshow grid items
		this.slideshowItems = [].slice.call( this.slideshow.children );
		// index of current slideshow item
		this.current = -1;
		// slideshow control buttons
		this.ctrlPrev = this.el.querySelector( 'section.slideshow > nav > span.nav-prev' );
		this.ctrlNext = this.el.querySelector( 'section.slideshow > nav > span.nav-next' );
		this.ctrlClose = this.el.querySelector( 'section.slideshow > nav > span.nav-close' );
		// init masonry grid
		this._initMasonry();
		// init events
		this._initEvents();
	};

	CBPGridGallery.prototype._initMasonry = function() {
		var grid = this.grid;
		imagesLoaded( grid, function() {
			new Masonry( grid, {
				itemSelector: 'li',
				columnWidth: grid.querySelector( '.grid-sizer' )
			});
		});
	};

	CBPGridGallery.prototype._initEvents = function() {
		var self = this;

		// open the slideshow when clicking on the main grid items
		this.gridItems.forEach( function( item, idx ) {
			item.addEventListener( 'click', function() {
				self._openSlideshow( idx );
			} );
		} );

		// slideshow controls
		this.ctrlPrev.addEventListener( 'click', function() { self._navigate( 'prev' ); } );
		this.ctrlNext.addEventListener( 'click', function() { self._navigate( 'next' ); } );
		this.ctrlClose.addEventListener( 'click', function() { self._closeSlideshow(); } );

		// window resize
		window.addEventListener( 'resize', function() { self._resizeHandler(); } );

		// keyboard navigation events
		document.addEventListener( 'keydown', function( ev ) {
			if ( self.isSlideshowVisible ) {
				var keyCode = ev.keyCode || ev.which;

				switch (keyCode) {
					case 37:
						self._navigate( 'prev' );
						break;
					case 39:
						self._navigate( 'next' );
						break;
					case 27:
						self._closeSlideshow();
						break;
				}
			}
		} );

		// trick to prevent scrolling when slideshow is visible
		window.addEventListener( 'scroll', function() {
			if ( self.isSlideshowVisible ) {
				window.scrollTo( self.scrollPosition ? self.scrollPosition.x : 0, self.scrollPosition ? self.scrollPosition.y : 0 );
			}
			else {
				self.scrollPosition = { x : window.pageXOffset || docElem.scrollLeft, y : window.pageYOffset || docElem.scrollTop };
			}
		});
	};

	CBPGridGallery.prototype._openSlideshow = function( pos ) {
		this.isSlideshowVisible = true;
		this.current = pos;

		classie.addClass( this.el, 'slideshow-open' );

		/* position slideshow items */

		// set viewport items (current, next and previous)
		this._setViewportItems();
		
		// add class "current" and "show" to currentItem
		classie.addClass( this.currentItem, 'current' );
		classie.addClass( this.currentItem, 'show' );

		// add class show to next and previous items
		// position previous item on the left side and the next item on the right side
		if( this.prevItem ) {
			classie.addClass( this.prevItem, 'show' );
			var translateVal = Number( -1 * ( getViewportW() / 2 + this.prevItem.offsetWidth / 2 ) );
			setTransform( this.prevItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)' );
		}
		if( this.nextItem ) {
			classie.addClass( this.nextItem, 'show' );
			var translateVal = Number( getViewportW() / 2 + this.nextItem.offsetWidth / 2 );
			setTransform( this.nextItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)' );
		}
	};

	CBPGridGallery.prototype._navigate = function( dir ) {
		if( this.isAnimating ) return;
		if( dir === 'next' && this.current === this.itemsCount - 1 ||  dir === 'prev' && this.current === 0  ) {
			this._closeSlideshow();
			return;
		}

		this.isAnimating = true;
		
		// reset viewport items
		this._setViewportItems();

		var self = this,
			itemWidth = this.currentItem.offsetWidth,
			// positions for the centered/current item, both the side items and the incoming ones
			transformLeftStr = support.support3d ? 'translate3d(-' + Number( getViewportW() / 2 + itemWidth / 2 ) + 'px, 0, -150px)' : 'translate(-' + Number( getViewportW() / 2 + itemWidth / 2 ) + 'px)',
			transformRightStr = support.support3d ? 'translate3d(' + Number( getViewportW() / 2 + itemWidth / 2 ) + 'px, 0, -150px)' : 'translate(' + Number( getViewportW() / 2 + itemWidth / 2 ) + 'px)',
			transformCenterStr = '', transformOutStr, transformIncomingStr,
			// incoming item
			incomingItem;

		if( dir === 'next' ) {
			transformOutStr = support.support3d ? 'translate3d( -' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px, 0, -150px )' : 'translate(-' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px)';
			transformIncomingStr = support.support3d ? 'translate3d( ' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px, 0, -150px )' : 'translate(' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px)';
		}
		else {
			transformOutStr = support.support3d ? 'translate3d( ' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px, 0, -150px )' : 'translate(' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px)';
			transformIncomingStr = support.support3d ? 'translate3d( -' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px, 0, -150px )' : 'translate(-' + Number( (getViewportW() * 2) / 2 + itemWidth / 2 ) + 'px)';
		}

		// remove class animatable from the slideshow grid (if it has already)
		classie.removeClass( self.slideshow, 'animatable' );

		if( dir === 'next' && this.current < this.itemsCount - 2 || dir === 'prev' && this.current > 1 ) {
			// we have an incoming item!
			incomingItem = this.slideshowItems[ dir === 'next' ? this.current + 2 : this.current - 2 ];
			setTransform( incomingItem, transformIncomingStr );
			classie.addClass( incomingItem, 'show' );
		}

		var slide = function() {
			// add class animatable to the slideshow grid
			classie.addClass( self.slideshow, 'animatable' );

			// overlays:
			classie.removeClass( self.currentItem, 'current' );
			var nextCurrent = dir === 'next' ? self.nextItem : self.prevItem;
			classie.addClass( nextCurrent, 'current' );

			setTransform( self.currentItem, dir === 'next' ? transformLeftStr : transformRightStr );

			if( self.nextItem ) {
				setTransform( self.nextItem, dir === 'next' ? transformCenterStr : transformOutStr );
			}

			if( self.prevItem ) {
				setTransform( self.prevItem, dir === 'next' ? transformOutStr : transformCenterStr );
			}

			if( incomingItem ) {
				setTransform( incomingItem, dir === 'next' ? transformRightStr : transformLeftStr );
			}

			var onEndTransitionFn = function( ev ) {
				if( support.transitions ) {
					if( ev.propertyName.indexOf( 'transform' ) === -1 ) return false;
					this.removeEventListener( transEndEventName, onEndTransitionFn );
				}

				if( self.prevItem && dir === 'next' ) {
					classie.removeClass( self.prevItem, 'show' );
				}
				else if( self.nextItem && dir === 'prev' ) {
					classie.removeClass( self.nextItem, 'show' );
				}

				if( dir === 'next' ) {
					self.prevItem = self.currentItem;
					self.currentItem = self.nextItem;
					if( incomingItem ) {
						self.nextItem = incomingItem;
					}
				}
				else {
					self.nextItem = self.currentItem;
					self.currentItem = self.prevItem;
					if( incomingItem ) {
						self.prevItem = incomingItem;
					}
				}

				self.current = dir === 'next' ? self.current + 1 : self.current - 1;
				self.isAnimating = false;
			};

			if( support.transitions ) {
				self.currentItem.addEventListener( transEndEventName, onEndTransitionFn );
			}
			else {
				onEndTransitionFn();
			}
		};

		setTimeout( slide, 25 );
	}

	CBPGridGallery.prototype._closeSlideshow = function( pos ) {
		// remove class slideshow-open from the grid gallery elem
		classie.removeClass( this.el, 'slideshow-open' );
		// remove class animatable from the slideshow grid
		classie.removeClass( this.slideshow, 'animatable' );

		var self = this,
			onEndTransitionFn = function( ev ) {
				if( support.transitions ) {
					if( ev.target.tagName.toLowerCase() !== 'ul' ) return;
					this.removeEventListener( transEndEventName, onEndTransitionFn );
				}
				// remove classes show and current from the slideshow items
				classie.removeClass( self.currentItem, 'current' );
				classie.removeClass( self.currentItem, 'show' );
				
				if( self.prevItem ) {
					classie.removeClass( self.prevItem, 'show' );
				}
				if( self.nextItem ) {
					classie.removeClass( self.nextItem, 'show' );
				}

				// also reset any transforms for all the items
				self.slideshowItems.forEach( function( item ) { setTransform( item, '' ); } );

				self.isSlideshowVisible = false;
			};

		if( support.transitions ) {
			this.el.addEventListener( transEndEventName, onEndTransitionFn );
		}
		else {
			onEndTransitionFn();
		}
	};

	CBPGridGallery.prototype._setViewportItems = function() {
		this.currentItem = null;
		this.prevItem = null;
		this.nextItem = null;

		if( this.current > 0 ) {
			this.prevItem = this.slideshowItems[ this.current - 1 ];
		}
		if( this.current < this.itemsCount - 1 ) {
			this.nextItem = this.slideshowItems[ this.current + 1 ];
		}
		this.currentItem = this.slideshowItems[ this.current ];
	}

	// taken from https://github.com/desandro/vanilla-masonry/blob/master/masonry.js by David DeSandro
	// original debounce by John Hann
	// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
	CBPGridGallery.prototype._resizeHandler = function() {
		var self = this;
		function delayed() {
			self._resize();
			self._resizeTimeout = null;
		}
		if ( this._resizeTimeout ) {
			clearTimeout( this._resizeTimeout );
		}
		this._resizeTimeout = setTimeout( delayed, 50 );
	}

	CBPGridGallery.prototype._resize = function() {
		if ( this.isSlideshowVisible ) {
			// update width value
			if( this.prevItem ) {
				var translateVal = Number( -1 * ( getViewportW() / 2 + this.prevItem.offsetWidth / 2 ) );
				setTransform( this.prevItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)' );
			}
			if( this.nextItem ) {
				var translateVal = Number( getViewportW() / 2 + this.nextItem.offsetWidth / 2 );
				setTransform( this.nextItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)' );
			}
		}
	}

	// add to global namespace
	window.CBPGridGallery = CBPGridGallery;

})( window );

Ссылки