< Back

How to Build a TED-style Video Scroll Control using HTML5, CSS3, jQuery and YouTube

Recently, a client asked about a slick interaction they saw on TED’s website. Instead of trying to describe the functionality, check out the following screen grab:

TED example

As you can see, when the video is running and you scroll down away from the player, it attaches itself to the top of the window and continues playing. TED accomplished this without replication of the YouTube embed code using CSS and a sprinkling of JS.

So, how do we get this done on our own website

It starts with HTML

<div class="player">
    <div class="player-container">
        <iframe src="https://www.youtube.com/watch?v=Zce-QT7MGSE?autoplay=0&showinfo=0&controls=0"></iframe>
    </div>
</div>

The .player div will continuously hold the original size and position of the video, while the .player-container will morph and shift depending on where the scroll position of the browser is. Drop your YouTube embed code in and it’s time to style this thing.

CSS

We’ll break the CSS down into a couple of sections.

.player {
    width: 100%;
}
.player .player-container {
    width: 100%;
    height: 100%;
}
.player .player-container iframe {
    width: 100%;
    height: 100%;
    border: 0;
}

This first section sets the assumption that the video will completely fill its parent container.

@media(min-width:992px) {
    /* PIP support */
    .player.player-pip-on .player-container {
        background: #FFF;
        color: #111;
        display: block;
        height: 72px;
        width: 100%;
        z-index: 10;
        position: fixed;
        top: 0;
        left: 0;
    }
    .player.player-pip-on .player-container iframe {
        width: 128px;
        height: 100%;
        border: 0;
        margin-left: 50px;
    }
}

The above styling builds the active state of the control. As the user scrolls down beyond the bounds of the statically placed video, the .player-pip-on class tells the .player-container to break out of the .player layout and fix itself to the top of the window.

@media screen and (max-width: 768px) {
    .player {
        height: 235px;
    }
}
@media screen and (min-width: 769px) and (max-width: 991px) {
    .player {
        height: 405px;
    }
}
@media screen and (min-width: 992px) and (max-width: 1199px) {
    player {
        height: 529px;
    }
}
@media screen and (min-width: 1201px) {
    .player {
        height: 641px;
    }
}

Finally, when the .player-container breaks out of the layout of its parent, we still need the .player to assume it’s original height so that the scroll bar doesn’t suddenly shrink. I did this manually using media queries, but I’m sure there’s a more elegant solution.

The Javascript

var toggleVideoScroll = function() {
    // determine video Y pos break point
    var offset = $(?.player').offset();
    var videoBreakYPos = offset.top + $(?.player').height();

    // if scroll pos is below video
    if($(window).scrollTop() > videoBreakYPos) { //jQuery(?#background-video').height() - 50) {
      if(!$(?.player').hasClass(?player-pip-on')) {
        $(?.player').addClass(?player-pip-on');
      }
    }
    else {
      $(?.player').removeClass(?player-pip-on');
    }
}

The function above finds the bottom of the .player and checks if the user has scrolled beyond that point. If so, it adds the .player-pip-class (and if not, makes sure to remove it). Remember from the CSS section, that this class is responsible for styling the fixed video bar.

// handle window scroll event
  $(window).on(?scroll', function(e) {
    toggleVideoScroll();
  });

The last piece we need is a event handler for the browser’s scroll events. Simply wire it up with jQuery and we’re good to go.

Connect with us

Thank You!

We really appreciate your interest in what we do.

We'll get back to you as soon as we can.