A simple instafeed.js user feed example with a modal gallery and 'load more' button to load in additional posts using jQuery and GSAP (Greensock).
A Pen by Selcuk Cura on CodePen.
| <div class="instafeed-gallery"> | |
| <div class="header"> | |
| <ul class="meta"> | |
| <li> | |
| <span class="count post-count"></span> | |
| <span class="title">posts</span> | |
| </li> | |
| <li> | |
| <span class="count follower-count"></span> | |
| <span class="title">followers</span> | |
| </li> | |
| <li> | |
| <span class="count following-count"></span> | |
| <span class="title">following</span> | |
| </li> | |
| </ul> | |
| </div> | |
| <div id="instafeed-gallery-feed" class="row no-gutter"> | |
| <!-- instagram feed loads here --> | |
| </div> | |
| </div> | |
| <button id="btn-instafeed-load" class="btn">Load more</button> | |
| <div class="post-modal-container"> | |
| <!-- <div class="arrow-left">left</div> | |
| <div class="arrow-right">right</div> --> | |
| </div> | |
| <div class="post-modal-backdrop"></div> |
A simple instafeed.js user feed example with a modal gallery and 'load more' button to load in additional posts using jQuery and GSAP (Greensock).
A Pen by Selcuk Cura on CodePen.
| // ----- Notes ----- | |
| // A maximum of 20 posts can be loaded due to the app being in sandbox mode on instagram | |
| // How to get an access token: | |
| // http://jelled.com/instagram/access-token | |
| // API Endpoints: | |
| // https://www.instagram.com/developer/endpoints/ | |
| // Model guide example: | |
| // https://www.instagram.com/selcukcura/media/ | |
| // {{model.user.username}}, {{likes}} likes | |
| // user data example using userId and accessToken: | |
| // https://api.instagram.com/v1/users/4622774/?access_token=4622774.7cbaeb5.ec8c5041b92b44ada03e4a4a9153bc54 | |
| $( window ).on('load', function() { | |
| var feedHTML = | |
| // header | |
| '<div class="header-container">'+ | |
| '<img src="{{model.user.profile_picture}}" class="avatar">'+ | |
| '<div class="user-container">'+ | |
| '<p class="name">{{model.user.full_name}}</p>'+ | |
| '<p class="username"><a href="http://instagram.com/{{model.user.username}}" target="_blank">@{{model.user.username}}</a></p>'+ | |
| '</div>'+ | |
| '</div>'+ | |
| // posts | |
| '<div class="img-featured-container col-xs-4">'+ | |
| '<div class="img-backdrop"></div>'+ | |
| '<div class="description-container">'+ | |
| '<span class="likes"><i class="icon ion-heart"></i> {{likes}}</span>'+ | |
| '<span class="comments"><i class="icon ion-chatbubble"></i> {{comments}}</span>'+ | |
| '</div>'+ | |
| '<img src="{{image}}" class="img-responsive">'+ | |
| '</div>'+ | |
| // modal | |
| '<div class="post-modal">'+ | |
| '<div class="btn-close">'+ | |
| '<div class="close-icon">×</div>'+ | |
| '</div>'+ | |
| '<img src="{{image}}">'+ | |
| // video | |
| // '<video controls autoplay>' + | |
| // '<source src="{{model.videos.standard_resolution.url}}" type="video/mp4">' + | |
| // 'Your browser does not support the video tag.' + | |
| // '</video>' + | |
| '<div class="post-modal-body">'+ | |
| '<div class="post-modal-meta-container">'+ | |
| '<p class="likes"><i class="icon ion-heart"></i> {{likes}}</p>'+ | |
| '<p class="comments"><i class="icon ion-chatbubble"></i> {{comments}}</p>'+ | |
| '</div>'+ | |
| '<div class="post-modal-caption-container">'+ | |
| '<p class="caption">{{caption}}</p>'+ | |
| '</div>'+ | |
| '</div>'+ | |
| '</div>' | |
| var galleryFeed = new Instafeed({ | |
| target: "instafeed-gallery-feed", | |
| get: "user", | |
| userId: 4622774, | |
| accessToken: "4622774.7cbaeb5.ec8c5041b92b44ada03e4a4a9153bc54", | |
| resolution: "standard_resolution", | |
| useHttp: "true", | |
| limit: 6, | |
| template: feedHTML, | |
| before: function(){ | |
| // get user data | |
| var url = 'https://api.instagram.com/v1/users/' + this.options.userId + '/?access_token=' + this.options.accessToken; | |
| $.ajax({ | |
| method: 'GET', | |
| url: url, | |
| dataType: 'jsonp', | |
| jsonp: 'callback', | |
| success: function (response) { | |
| // currently being replaced on each 'load more' button click | |
| $('.post-count').html(response.data.counts.media); | |
| $('.follower-count').html(response.data.counts.follows); | |
| $('.following-count').html(response.data.counts.followed_by); | |
| } | |
| }); | |
| }, | |
| after: function() { | |
| console.log('after'); | |
| var $headerContainer = $('.header-container'), | |
| $imagePost = $('.img-featured-container'), | |
| totalImages = $imagePost.length, | |
| $postModalContainer = $('.post-modal-container'), | |
| $postModal = $('.post-modal'), | |
| $postModalBackdrop = $('.post-modal-backdrop'), | |
| counter = 0; | |
| console.log('totalImages', totalImages) | |
| // remove all $headerContainer except one from template function and move to header | |
| for (i=1; i < totalImages; i++) { | |
| console.log('remove', i) | |
| $headerContainer.eq(i).remove(); | |
| $('.header').prepend($headerContainer.eq(0)); | |
| $postModalContainer.prepend($postModal); | |
| } | |
| $imagePost.on('click', function() { | |
| var postIndex = $(this).index(); | |
| console.log('clicked post', postIndex); | |
| $postModal.eq(postIndex).addClass('show'); | |
| $postModalBackdrop.addClass('show'); | |
| }); | |
| $('.btn-close').on('click', function() { | |
| var postIndex = $(this).index(); | |
| console.log('modal closed', postIndex) | |
| $(this).parent().removeClass('show'); | |
| $postModalBackdrop.removeClass('show'); | |
| }); | |
| $postModalBackdrop.on('click', function() { | |
| $postModal.removeClass('show'); | |
| $postModalBackdrop.removeClass('show'); | |
| }); | |
| $(document.documentElement).keydown(function(event) { | |
| if (event.keyCode == 37) { // left arrow key | |
| prevModal(); | |
| } | |
| if (event.keyCode == 39) { // right arrow key | |
| nextModal(); | |
| } | |
| if (event.keyCode == 27) { // escape key | |
| if ($postModal.hasClass('show')) { | |
| $postModal.removeClass('show'); | |
| $postModalBackdrop.removeClass('show'); | |
| } | |
| } | |
| }); | |
| TweenMax.staggerTo($imagePost, 0.5, {autoAlpha:1}, 0.02); | |
| // disable button if no more results to load | |
| if (!this.hasNext()) { | |
| console.log('no more posts to load') | |
| TweenMax.to($btnInstafeedLoad, 0.5, {opacity:0.5, onComplete: function(){ | |
| $btnInstafeedLoad.attr('disabled', 'disabled'); | |
| }}, 0) | |
| } | |
| } | |
| }); | |
| galleryFeed.run(firstLoad()); | |
| var $btnInstafeedLoad = $("#btn-instafeed-load"); | |
| $btnInstafeedLoad.on('click', function() { | |
| console.log('btn clicked - load posts') | |
| galleryFeed.next(); | |
| }); | |
| function firstLoad() { | |
| console.log('first load'); | |
| var tl = new TimelineMax(); | |
| tl.to('body', 0.3, {autoAlpha:1}, 1); | |
| tl.to('.instafeed-gallery', 0.3, {autoAlpha:1}, 0.2); | |
| tl.staggerFrom('span', 0.5, {autoAlpha:0, y:10}, 0.05); | |
| tl.from('.btn', 0.5, {autoAlpha:0, y:20, ease:Power2.easeOut}, 1.5); | |
| } | |
| // modal | |
| function prevModal() { | |
| console.log('prev modal') | |
| } | |
| function nextModal() { | |
| var postIndex = $('post-modal.show').index(); | |
| counter = postIndex; | |
| counter++ | |
| console.log('next modal: current index', counter) | |
| } | |
| }); |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/instafeed.js/1.4.1/instafeed.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script> |
| // vars | |
| $postPadding: 0px; | |
| $minWidth: 280px; | |
| $maxWidth: 420px; | |
| // general | |
| @import url('https://fonts.googleapis.com/css?family=Lato:100,100i,300,300i,400,400i,700,700i,900,900i'); | |
| body { | |
| background: #f9f9f9; | |
| font-family: 'Lato', "Helvetica", Arial, sans-serif; | |
| line-height: 1.2; | |
| opacity: 0; | |
| } | |
| // helper | |
| .hide { | |
| display: none !important; | |
| opacity: 0 !important; | |
| } | |
| .show { | |
| display: block !important; | |
| opacity: 1 !important; | |
| } | |
| /* remove bootstrap gutter*/ | |
| .row.no-gutter { | |
| margin-left: 0; | |
| margin-right: 0; | |
| } | |
| .row.no-gutter [class*='col-']:not(:first-child), | |
| .row.no-gutter [class*='col-']:not(:last-child) { | |
| padding-right: 0; | |
| padding-left: 0; | |
| } | |
| // the good stuff | |
| .instafeed-gallery { | |
| background: #fff; | |
| min-width: $minWidth; | |
| max-width: $maxWidth; | |
| width: 100%; | |
| margin: 0 auto; | |
| box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15); | |
| border-radius: 2px; | |
| transition: all 0.2 ease; | |
| opacity: 0; | |
| } | |
| .header { | |
| p { | |
| margin: 0; | |
| } | |
| a { | |
| color: inherit; | |
| &:hover { | |
| color: #aaa; | |
| text-decoration: none; | |
| } | |
| } | |
| .header-container { | |
| text-align: center; | |
| padding: 30px 30px 0; | |
| .avatar { | |
| width: 100%; | |
| max-width: 120px; | |
| border-radius: 100%; | |
| margin: 0 auto; | |
| display: block; | |
| } | |
| .user-container { | |
| margin-top: 20px; | |
| } | |
| .name { | |
| font-size: 20px; | |
| font-weight: 600; | |
| } | |
| .username { | |
| color: #bbb; | |
| font-size: 16px; | |
| } | |
| } | |
| .meta { | |
| width: 100%; | |
| margin: 0; | |
| padding: 30px; | |
| display: table; | |
| li { | |
| text-align: center; | |
| width: 33%; | |
| display: table-cell; | |
| } | |
| span { | |
| display: block; | |
| } | |
| .count { | |
| font-size: 20px; | |
| font-weight: 600; | |
| } | |
| .title { | |
| color: #bbb; | |
| font-size: 16px; | |
| } | |
| } | |
| } | |
| .post-modal-container { | |
| .post-modal { | |
| background: #fff; | |
| min-width: $minWidth; | |
| max-width: $maxWidth; | |
| margin: auto; | |
| top: 0; | |
| right: 0; | |
| left: 0; | |
| z-index: 9999; | |
| position: fixed; | |
| display: none; | |
| opacity: 0; | |
| } | |
| .btn-close { | |
| color: #fff; | |
| background: rgba(0, 0, 0, 0.5); | |
| width: 40px; | |
| height: 40px; | |
| top: 0; | |
| right: 0; | |
| position: absolute; | |
| cursor: pointer; | |
| &:hover { | |
| background: rgba(0, 0, 0, 0.7); | |
| } | |
| } | |
| .close-icon { | |
| font-size: 22px; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| position: absolute; | |
| } | |
| img { | |
| width: 100%; | |
| } | |
| .post-modal-body { | |
| padding: 15px; | |
| } | |
| .post-modal-meta-container { | |
| margin-bottom: 10px; | |
| p { | |
| color: #bbb; | |
| display: inline-block; | |
| margin-right: 10px; | |
| } | |
| .icon { | |
| margin-right: 2px; | |
| } | |
| } | |
| .post-modal-caption-container { | |
| } | |
| } | |
| .post-modal-backdrop { | |
| background: rgba(0,0,0,0.7); | |
| top: 0; | |
| right: 0; | |
| bottom: 0; | |
| left: 0; | |
| position: fixed; | |
| z-index: 999; | |
| display: none; | |
| cursor: pointer; | |
| } | |
| // post | |
| .img-featured-container { | |
| overflow: hidden; | |
| position: relative; | |
| padding: $postPadding; | |
| opacity: 0; | |
| cursor: pointer; | |
| } | |
| .img-featured-container img { | |
| width: 100%; | |
| } | |
| .img-featured-container .img-backdrop { | |
| background: linear-gradient(135deg, rgba(38, 163, 255, 0.85), rgba(83, 201, 179, 0.85)); | |
| margin: 0; | |
| padding: $postPadding; | |
| width: 100%; | |
| height: 100%; | |
| position: absolute; | |
| z-index: 1; | |
| opacity: 0; | |
| transition: all 0.3s ease; | |
| } | |
| .img-featured-container:hover > .img-backdrop { | |
| opacity: 1; | |
| } | |
| // center text horizontally and vertically on image hover | |
| .img-featured-container .description-container { | |
| color: #fff; | |
| font-size: 16px; | |
| line-height: 1.2; | |
| text-align: center; | |
| line-height: 20px; | |
| width: 100%; | |
| padding: 10px; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| position: absolute; | |
| transform-style: preserve-3d; | |
| transition: all .2s ease; | |
| z-index: 2; | |
| opacity: 0; | |
| } | |
| .img-featured-container .description-container .fa-instagram { | |
| font-size: 40px; | |
| } | |
| .img-featured-container .description-container p { | |
| font-weight: 300; | |
| margin-bottom: 0; | |
| } | |
| .img-featured-container:hover .description-container { | |
| opacity: 1; | |
| } | |
| .img-featured-container .description-container .likes, | |
| .img-featured-container .description-container .comments { | |
| margin: 0 5px; | |
| } | |
| // load more button | |
| #btn-instafeed-load { | |
| color: #fff; | |
| background: #26a3ff; | |
| font-size: 16px; | |
| margin: 20px auto; | |
| padding: 8px 40px; | |
| display: block; | |
| border: none; | |
| } | |
| // media queries | |
| @media screen and (min-width:$maxWidth) { | |
| .post-modal-container { | |
| .post-modal { | |
| margin: 20px auto; | |
| } | |
| } | |
| } | |
| @media screen and (min-width:768px) { | |
| .instafeed-gallery { | |
| margin: 50px auto 30px; | |
| } | |
| } |
| <link href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" /> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> |