Mobile App Showcase on MaterializeCSS


A responsive example with iPhone images that snap into place as you scroll each section.

This code nugget uses the new MaterializeCSS framework inspired by Material Design. You could use this as a mobile app landing page, app tour, or mobile screenshot showcase. For this example, we use AngularJS 1.3 to get user data and profile images from the RandomUser.me API, but you can replace this with your own static images and data as desired.

The interesting bit: Sections that snap into place upon scroll so that the user experiences smooth transitions between each section. This also prevents the sections from being partially or "half-way" scrolled. It is responsive in that the textual content is hidden on smaller screen widths so that only the iPhone image frame is visible.

The structure: The white iPhone is a transparent image background that is placed in an overlayed "placeholder" container. This .outer container is position:fixed over the sections that are repeated down the page. As you will notice, the iPhone is actually a background in the .ph-overlay div.

.outer {
    position: fixed;
    z-index: 8;
    width: 100%;
    height: 100%;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
}
.ph-overlay {
    position: relative;
    height: 660px;
    width: 330px;
    z-index: 9;
    overflow: hidden;
    background-image: url('https://faces.fiverr.com/images/iphone-with-cutout.svg');
    background-repeat:no-repeat;
    margin:0 auto;
    top: 50%;
    margin-top: -330px;
}

And the overlay container markup looks like this..

<div class="row outer">  
       <div class="col s12 m7 full hide-on-small-only">
           &nbsp;
       </div>
       <div class="col s12 m5 full center-align">
           <div class="ph-overlay"></div>
      </div>
</div>  

Scroll snap sections: jQuery is used to determine the current scroll position (lastScrollTop), and when to either scroll down to next section, or back up to the previous section.

var lastScrollTop = 0;  
$(window).scroll(function() {

    var curr = $('.highlight:not(".wait")');

    if (curr.length===0) {
        // auto scroll to first section...
        setTimeout(function(){
            var first = $("section:first");
            if (isScrolledIntoView(first)) {
               $("section").removeClass("highlight");
               $("body").animate({ scrollTop: first.offset().top }, 200, function(){
                    first.addClass("highlight");
               });
            }
        },500);
        lastScrollTop = st;
        return;
    }

    // get the sections that precede (prev) and follow (next) the curr section...
    var next = curr.next();
    var prev = curr.prev();

    // determine whether to snap up or down...
    var st = $(this).scrollTop();
    if (st > lastScrollTop){
       // downscroll...
    }
    else {
       // upscroll...
    }
    lastScrollTop = st;
    return;
});

This simple function enables use to see if the next or prev section has started to become visible in the viewport..

function isScrolledIntoView(elem)  
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + ($(window).height());
    var elemTop = elem.offset().top;
    var elemBottom = elemTop + elem.height();

    return (elemTop <= docViewBottom) && (elemTop > docViewTop);
}

When you dive down into the full code you'll see that jQuery animate is used to smoothly scroll the appropriate section into place. We temporarily add the .wait class during this transition so that the $(window).scroll event (constantly fired as the user scrolls) ignores any in-progress section transition. For this reason, the $('.highlight:not(".wait")') selector is used when determining the current section.


The HTML, JS and CSS code

The Demo!

Download on Codeply

So that's it for this snippet. Let me know how it works for you, and any improvements you'd recommend.