Responsive Product Grid Layout with CSS3 and Javscript
File Size: | 679 KB |
---|---|
Views Total: | 3785 |
Last Update: | |
Publish Date: | |
Official Website: | Go to website |
License: | MIT |
In this tutorial we're going to create a clean and responsive grid layout that provides a fashion and user-friendly way to showcase your products on the website. Click the rotate button in the upper-right corner will rotate showing the backside of the product.
How to use it:
1. Markup html structure
<div id="cbp-pgcontainer" class="cbp-pgcontainer"> <ul class="cbp-pggrid"> <li> <div class="cbp-pgcontent"> <span class="cbp-pgrotate">Rotate Item</span> <div class="cbp-pgitem"> <div class="cbp-pgitem-flip"> <img src="images/1_front.png" /> <img src="images/1_back.png" /> </div> </div> <!-- /cbp-pgitem --> <ul class="cbp-pgoptions"> <li class="cbp-pgoptcompare">Compare</li> <li class="cbp-pgoptfav">Favorite</li> <li class="cbp-pgoptsize"> <span data-size="XL">XL</span> <div class="cbp-pgopttooltip"> <span data-size="XL">XL</span> <span data-size="L">L</span> <span data-size="M">M</span> <span data-size="S">S</span> </div> </li> <li class="cbp-pgoptcolor"> <span data-color="c1">Blue</span> <div class="cbp-pgopttooltip"> <span data-color="c1">Blue</span> <span data-color="c2">Pink</span> <span data-color="c3">Orange</span> <span data-color="c4">Green</span> </div> </li> <li class="cbp-pgoptcart"></li> </ul> <!-- cbp-pgoptions --> </div> <!-- cbp-pgcontent --> <div class="cbp-pginfo"> <h3>Save my trees</h3> <span class="cbp-pgprice">$29</span> </div> </li> <li> <div class="cbp-pgcontent"> <span class="cbp-pgrotate">Rotate Item</span> <div class="cbp-pgitem"> <div class="cbp-pgitem-flip"> <img src="images/2_front.png" /> <img src="images/2_back.png" /> </div> </div> <!-- /cbp-pgitem --> <ul class="cbp-pgoptions"> <li class="cbp-pgoptcompare">Compare</li> <li class="cbp-pgoptfav">Favorite</li> <li class="cbp-pgoptsize"> <span data-size="XL">XL</span> <div class="cbp-pgopttooltip"> <span data-size="XL">XL</span> <span data-size="L">L</span> <span data-size="M">M</span> <span data-size="S">S</span> </div> </li> <li class="cbp-pgoptcolor"> <span data-color="c2">Pink</span> <div class="cbp-pgopttooltip"> <span data-color="c1">Blue</span> <span data-color="c2">Pink</span> <span data-color="c3">Orange</span> <span data-color="c4">Green</span> </div> </li> <li class="cbp-pgoptcart"></li> </ul> </div> <div class="cbp-pginfo"> <h3>Nature Lover</h3> <span class="cbp-pgprice">$19</span> </div> </li> <li> <div class="cbp-pgcontent"> <span class="cbp-pgrotate">Rotate Item</span> <div class="cbp-pgitem"> <div class="cbp-pgitem-flip"> <img src="images/3_front.png" /> <img src="images/3_back.png" /> </div> </div> <!-- /cbp-pgitem --> <ul class="cbp-pgoptions"> <li class="cbp-pgoptcompare">Compare</li> <li class="cbp-pgoptfav">Favorite</li> <li class="cbp-pgoptsize"> <span data-size="XL">XL</span> <div class="cbp-pgopttooltip"> <span data-size="XL">XL</span> <span data-size="L">L</span> <span data-size="M">M</span> <span data-size="S">S</span> </div> </li> <li class="cbp-pgoptcolor"> <span data-color="c3">Orange</span> <div class="cbp-pgopttooltip"> <span data-color="c1">Blue</span> <span data-color="c2">Pink</span> <span data-color="c3">Orange</span> <span data-color="c4">Green</span> </div> </li> <li class="cbp-pgoptcart"></li> </ul> </div> <div class="cbp-pginfo"> <h3>Forrest Walk</h3> <span class="cbp-pgprice">$39</span> </div> </li> <li> <div class="cbp-pgcontent"> <span class="cbp-pgrotate">Rotate Item</span> <div class="cbp-pgitem"> <div class="cbp-pgitem-flip"> <img src="images/4_front.png" /> <img src="images/4_back.png" /> </div> </div> <!-- /cbp-pgitem --> <ul class="cbp-pgoptions"> <li class="cbp-pgoptcompare">Compare</li> <li class="cbp-pgoptfav">Favorite</li> <li class="cbp-pgoptsize"> <span data-size="XL">XL</span> <div class="cbp-pgopttooltip"> <span data-size="XL">XL</span> <span data-size="L">L</span> <span data-size="M">M</span> <span data-size="S">S</span> </div> </li> <li class="cbp-pgoptcolor"> <span data-color="c4">Green</span> <div class="cbp-pgopttooltip"> <span data-color="c1">Blue</span> <span data-color="c2">Pink</span> <span data-color="c3">Orange</span> <span data-color="c4">Green</span> </div> </li> <li class="cbp-pgoptcart"></li> </ul> </div> <div class="cbp-pginfo"> <h3>Land of Trees</h3> <span class="cbp-pgprice">$35</span> </div> </li> <li> <div class="cbp-pgcontent"> <span class="cbp-pgrotate">Rotate Item</span> <div class="cbp-pgitem"> <div class="cbp-pgitem-flip"> <img src="images/3_front.png" /> <img src="images/3_back.png" /> </div> </div> <!-- /cbp-pgitem --> <ul class="cbp-pgoptions"> <li class="cbp-pgoptcompare">Compare</li> <li class="cbp-pgoptfav">Favorite</li> <li class="cbp-pgoptsize"> <span data-size="XL">XL</span> <div class="cbp-pgopttooltip"> <span data-size="XL">XL</span> <span data-size="L">L</span> <span data-size="M">M</span> <span data-size="S">S</span> </div> </li> <li class="cbp-pgoptcolor"> <span data-color="c3">Orange</span> <div class="cbp-pgopttooltip"> <span data-color="c1">Blue</span> <span data-color="c2">Pink</span> <span data-color="c3">Orange</span> <span data-color="c4">Green</span> </div> </li> <li class="cbp-pgoptcart"></li> </ul> </div> <div class="cbp-pginfo"> <h3>Tree Shirt</h3> <span class="cbp-pgprice">$29</span> </div> </li> <li> <div class="cbp-pgcontent"> <span class="cbp-pgrotate">Rotate Item</span> <div class="cbp-pgitem"> <div class="cbp-pgitem-flip"> <img src="images/1_front.png" /> <img src="images/1_back.png" /> </div> </div> <!-- /cbp-pgitem --> <ul class="cbp-pgoptions"> <li class="cbp-pgoptcompare">Compare</li> <li class="cbp-pgoptfav">Favorite</li> <li class="cbp-pgoptsize"> <span data-size="XL">XL</span> <div class="cbp-pgopttooltip"> <span data-size="XL">XL</span> <span data-size="L">L</span> <span data-size="M">M</span> <span data-size="S">S</span> </div> </li> <li class="cbp-pgoptcolor"> <span data-color="c1">Blue</span> <div class="cbp-pgopttooltip"> <span data-color="c1">Blue</span> <span data-color="c2">Pink</span> <span data-color="c3">Orange</span> <span data-color="c4">Green</span> </div> </li> <li class="cbp-pgoptcart"></li> </ul> </div> <div class="cbp-pginfo"> <h3>Greenhouse</h3> <span class="cbp-pgprice">$19</span> </div> </li> </ul> <!-- /cbp-pggrid --> </div>
2. The CSS
@font-face { font-family: 'pgicons'; src: url('../fonts/pgicons/pgicons.eot'); src: url('../fonts/pgicons/pgicons.eot?#iefix') format('embedded-opentype'), url('../fonts/pgicons/pgicons.woff') format('woff'), url('../fonts/pgicons/pgicons.ttf') format('truetype'), url('../fonts/pgicons/pgicons.svg#pgicons') format('svg'); font-weight: normal; font-style: normal; } .cbp-pgcontainer { position: relative; width: 100%; padding: 0 30px 100px 30px; } .cbp-pgcontainer ul, .cbp-pgcontainer li { padding: 0; margin: 0; list-style-type: none; } .cbp-pggrid { position: relative; text-align: center; } /* If flexbox is supported we'll use it to lay out the grid */ .flexbox .cbp-pggrid { display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: flex; -webkit-flex-flow: row wrap; -moz-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap; -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; -webkit-justify-content: center; } .cbp-pggrid > li { display: inline-block; vertical-align: top; position: relative; width: 33%; min-width: 340px; max-width: 555px; padding: 20px 2% 50px 2%; text-align: left; } .flexbox .cbp-pggrid > li { display: block; } .cbp-pgcontent { border: 3px solid #47a3da; position: relative; } .cbp-pgrotate { width: 36px; height: 36px; position: absolute; display: block; color: transparent; font-size: 0; z-index: 100; border-bottom: 3px solid #47a3da; border-left: 3px solid #47a3da; right: 0px; top: 0px; cursor: pointer; text-align: center; } .cbp-pgrotate:before { font-size: 18px; line-height: 32px; color: #47a3da; } .no-touch .cbp-pgrotate:hover, .cbp-pgrotate.cbp-pgrotate-active { background: #47a3da; } .no-touch .cbp-pgrotate:hover:before, .cbp-pgrotate.cbp-pgrotate-active:before { color: #fff; } /* The item with the images will have perspective */ .cbp-pgitem { width: 100%; position: relative; padding: 2em; -webkit-perspective: 1400px; -moz-perspective: 1000px; perspective: 1000px; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; backface-visibility: hidden; } /* The flip container */ .cbp-pgitem-flip { -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transition: -webkit-transform .4s ease-out; -moz-transition: -moz-transform .4s ease-out; transition: transform .4s ease-out; } /* If you want to rotate on hover instead of click, you could use something like this: .cbp-pgrotate:hover + .cbp-pgitem .cbp-pgitem-flip */ .cbp-pgitem.cbp-pgitem-showback .cbp-pgitem-flip { -webkit-transform: rotateY(180deg); -moz-transform: rotateY(180deg); transform: rotateY(180deg); } .cbp-pgitem-flip img { display: block; margin: 0 auto; max-width: 100%; max-height: 100%; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; backface-visibility: hidden; } .cbp-pgitem img:first-child { position: relative; } /* The second image will be rotated so that we'd be looking at the back of it */ .cbp-pgitem img:nth-child(2) { position: absolute; top: 50%; left: 50%; -webkit-transform: translateX(-50%) translateY(-50%) rotateY(-180deg); -moz-transform: translateX(-50%) translateY(-50%) rotateY(-180deg); transform: translateX(-50%) translateY(-50%) rotateY(-180deg); } /* Fallback for browsers that don't support 3d transforms */ .no-csstransforms3d .cbp-pgitem img:nth-child(2) { position: relative; top: 0; left: 0; display: none; } .no-csstransforms3d .cbp-pgitem.cbp-pgitem-showback img:first-child { display: none; } .no-csstransforms3d .cbp-pgitem.cbp-pgitem-showback img:nth-child(2) { display: block; } /* The options bar */ .cbp-pgoptions { height: 60px; width: 100%; border-top: 3px solid #47a3da; ; } .cbp-pgoptions > li { width: 20%; height: 100%; float: left; position: relative; display: block; cursor: pointer; color: transparent; font-size: 0; border-left: 3px solid #47a3da; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .cbp-pgoptions > li:first-child { border-left: none; } .no-touch .cbp-pgoptions li { color: #47a3da; } .no-touch .cbp-pgoptions li:hover, .cbp-pgoptions li.cbp-pgoption-active { background: #47a3da; } .cbp-pgoptions li:before, .cbp-pgoptions li > span { font-size: 22px; line-height: 60px; text-indent: 0; text-align: center; color: #47a3da; } .no-touch .cbp-pgoptions li:hover:before, .no-touch .cbp-pgoptions li:hover > span, .cbp-pgoptions li.cbp-pgoption-active > span { color: #fff; } .cbp-pgoptions li.cbp-pgoptsize > span { font-size: 22px; } .cbp-pgoptions li > span { display: block; } .cbp-pgoptions li:before { position: absolute; width: 100%; height: 100%; } /* Icons */ .cbp-pgoptcompare, .cbp-pgoptcart, .cbp-pgoptfav, .cbp-pgrotate { font-family: 'pgicons'; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; -webkit-font-smoothing: antialiased; } .cbp-pgoptcompare:before { content: "\e001"; } .cbp-pgoptfav:before { content: "\e003"; } .cbp-pgoptfav.cbp-pgoptfav-selected:before { content: "\e002"; color: #ee73b8; } .cbp-pgoptfav.cbp-pgoptfav-selected:hover:before { color: #f9c0e0; } .cbp-pgoptcart:before { content: "\e000"; } .cbp-pgrotate:before { content: "\e004"; } /* Tooltips */ .cbp-pgopttooltip { position: absolute; bottom: 180%; margin-bottom: 0px; background: #fff; padding: 25px; width: 100px; left: 50%; margin-left: -50px; border: 3px solid #47a3da; opacity: 0; z-index: 1000; visibility: hidden; pointer-events: none; -webkit-transition: visibility 0s 0.3s, opacity 0.3s, bottom 0.3s; -moz-transition: visibility 0s 0.3s, opacity 0.3s, bottom 0.3s; transition: visibility 0s 0.3s, opacity 0.3s, bottom 0.3s; } .cbp-pgoptions li:hover .cbp-pgopttooltip, .cbp-pgoptions li.cbp-pgoption-active .cbp-pgopttooltip { visibility: visible; opacity: 1; -webkit-transition-delay: 0s; -moz-transition-delay: 0s; transition-delay: 0s; bottom: 100%; pointer-events: auto; } .cbp-pgopttooltip:after, .cbp-pgopttooltip:before { top: 100%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; } .cbp-pgopttooltip:after { border-color: transparent; border-top-color: #fff; border-width: 10px; left: 50%; margin-left: -10px; } .cbp-pgopttooltip:before { border-color: transparent; border-top-color: #47a3da; border-width: 14px; left: 50%; margin-left: -14px; } /* Size tooltip */ .cbp-pgoptsize .cbp-pgopttooltip { margin-left: -50px; } .cbp-pgoptsize .cbp-pgopttooltip span { display: block; text-indent: 0; background: url(../images/tshirt.svg) no-repeat center center; background-size: 100%; margin: 0 auto 4px; text-align: center; font-size: 12px; font-weight: 700; color: #65b3e2; } .cbp-pgoptsize .cbp-pgopttooltip span:hover { color: #0968a1; -webkit-transform: scale(1.1); -moz-transform: scale(1.1); transform: scale(1.1); } .cbp-pgoptsize .cbp-pgopttooltip span[data-size="XL"] { width: 44px; height: 44px; line-height: 44px; } .cbp-pgoptsize .cbp-pgopttooltip span[data-size="L"] { width: 40px; height: 40px; line-height: 40px; } .cbp-pgoptsize .cbp-pgopttooltip span[data-size="M"] { width: 34px; height: 34px; line-height: 34px; } .cbp-pgoptsize .cbp-pgopttooltip span[data-size="S"] { width: 30px; height: 30px; line-height: 30px; } /* Color tooltip */ .cbp-pgoptcolor .cbp-pgopttooltip { padding: 5px; } .cbp-pgoptions li.cbp-pgoptcolor > span, .cbp-pgoptcolor .cbp-pgopttooltip span { display: block; margin: 12px auto 0; text-indent: -900em; } .cbp-pgoptions li.cbp-pgoptcolor > span { width: 36px; height: 36px; border: 3px solid #fff; } .cbp-pgoptcolor .cbp-pgopttooltip span { float: left; margin: 4px; width: 34px; height: 34px; } .no-touch .cbp-pgoptcolor .cbp-pgopttooltip span:hover { -webkit-transform: scale(1.1); -moz-transform: scale(1.1); transform: scale(1.1); } .cbp-pgoptcolor span[data-color="c1"] { background: #72bbe9; } .cbp-pgoptcolor span[data-color="c2"] { background: #e577aa; } .cbp-pgoptcolor span[data-color="c3"] { background: #e5b178; } .cbp-pgoptcolor span[data-color="c4"] { background: #7abe93; } .cbp-pginfo { padding-top: 10px; } .cbp-pginfo:before, .cbp-pginfo:after { content: " "; display: table; } .cbp-pginfo:after { clear: both; } .cbp-pginfo h3, .cbp-pginfo span { float: left; width: 50%; font-size: 1.8em; padding: 10px 5px; margin: 0; } .cbp-pginfo h3 { font-weight: 300; } .cbp-pginfo span { font-weight: 700; text-align: right; } /* Media Queries */ @media screen and (max-width: 68.125em) { .cbp-pggrid > li { width: 48%; } } @media screen and (max-width: 46.125em) { .cbp-pggrid > li { width: 100%; } }
3. The javascript
;( function( window ) { 'use strict'; function cbpShop( el ) { this.el = el; this._init(); } cbpShop.prototype = { _init : function() { var self = this; this.touch = Modernizr.touch; this.products = this.el.querySelectorAll( 'ul.cbp-pggrid > li' ); Array.prototype.slice.call( this.products ).forEach( function( el, i ) { var content = el.querySelector( 'div.cbp-pgcontent' ), item = content.querySelector( 'div.cbp-pgitem' ), rotate = content.querySelector( 'span.cbp-pgrotate' ); if( self.touch ) { rotate.addEventListener( 'touchstart', function() { self._rotateItem( this, item ); } ); var options = content.querySelector( 'ul.cbp-pgoptions' ), size = options.querySelector( 'li.cbp-pgoptsize > span' ), color = options.querySelector( 'li.cbp-pgoptcolor > span' ); size.addEventListener( 'touchstart', function() { self._showItemOptions( this ); } ); color.addEventListener( 'touchstart', function() { self._showItemOptions( this ); } ); } else { rotate.addEventListener( 'click', function() { self._rotateItem( this, item ); } ); } } ); }, _rotateItem : function( trigger, item ) { if( item.getAttribute( 'data-open' ) === 'open' ) { item.setAttribute( 'data-open', '' ); trigger.className = trigger.className.replace(/\b cbp-pgrotate-active\b/,''); item.className = item.className.replace(/\b cbp-pgitem-showback\b/,''); } else { item.setAttribute( 'data-open', 'open' ); trigger.className += ' cbp-pgrotate-active'; item.className += ' cbp-pgitem-showback'; } }, _showItemOptions : function( trigger ) { if( trigger.getAttribute( 'data-open' ) === 'open' ) { trigger.setAttribute( 'data-open', '' ); trigger.parentNode.className = trigger.parentNode.className.replace(/\b cbp-pgoption-active\b/,''); } else { trigger.setAttribute( 'data-open', 'open' ); trigger.parentNode.className += ' cbp-pgoption-active'; } }, /* other functions.. */ } window.cbpShop = cbpShop; } )( window );
This awesome jQuery plugin is developed by codrops. For more Advanced Usages, please check the demo page or visit the official website.