Fragments Portfolio Uncategorized

Having Fun Refurbish My Portfolio Page – IntersectionObserver

When I was building my own portfolio page, I thought I was smart and creative — creating a simple webpage using plain javascript.

However, I changed my mind on a beautiful Sunday afternoon. A guy sitting next to me was playing his phone and murmuring:

It’s 2019 and this website is not even responsive?

He was not complaining about my portfolio, but it was a truce. I should make it responsive.

So I spent an afternoon watching tutorials on Linkedin Learning, and learned Bootstrap and Vue.js, and made my website responsive.

Then I had a new idea — Can I play the video when the user scrolls and sees the thumbnail of a project?

My first thought is to find some libraries to do this job. I tried 3 libraries, but all of them are not perfect.

isInViewportGithub is a JQuery plugin. It could get the job done but it lacks a clear example and tutorial.

vue-observe-visibilityGithub works. However, it doesn’t support customized tolerance. It triggers immediately when the div enters the viewport, but I want my video to play when the div is at the upper area of a user’s screen.

Then I found this, IntersectionObserverMDN.

Admittedly, I still prefer native javascript over frameworks and libraries. Then I dug further and integrated this into my portfolio page.

It’s very easy to use. However, I’ve encountered a few errors.
Here is a few tips when using the IntersectionObserver:

  • IntersectionObserver.observe(targetElement); targetElement means literally a single html element. It doesn’t work with JQuery objects nor HTMLCollection object.

  • When it’s triggered, it will pass an array called entries to the callback function, in which you can find everything you need. the one you will need is entries[index].isIntersecting.

  • threshold is what the name indicates, how much portion of the HTML element in the viewport could trigger it. If you want it to trigger only when the whole div is in the view, set it to 0.99

var elementsInView = [];
var observer = new IntersectionObserver((entries) => {
    // console.log(entries);
    let currentFirstEl = elementsInView[0];
    entries.forEach(entry => {
        if (entry.isIntersecting) {
        } else {
            let spliceInd = $.inArray(, elementsInView);
            if (spliceInd >= 0) {
                elementsInView.splice(spliceInd, 1);
    if (elementsInView[0] != undefined && elementsInView[0] != currentFirstEl) {
        //currentFirstEl is undefined when first initiated.
        try {
            playVideo(currentFirstEl, false)
        } catch (error) {
        playVideo(elementsInView[0], true);
}, {
    threshold: 0.9

function playVideo(project, bl) {
    switch (bl) {
        case true:
            $(project).find(".darkOverlay").fadeTo("slow", 0.2);
            $(project).find("img").fadeTo("slow", 0);
        case false:
            $(project).find(".darkOverlay").fadeTo("slow", 0.75);
            $(project).find("img").fadeTo("slow", 1);


function startObserve() {
    // only do it if the device is a mobile phone.
    if ( {
        $(".coverContainer").each((index, element) => {

$.getJSON("data/content.json", (res) => {
    console.log(res); = res.projects;
    var app = new Vue(vueApp);

I added the enlarger effect as an extra sprinkle.

My portfolio page: click me to visit, now is mobile device friendly.

I will write more about how I integrate Bootstrap and Vue.js next week.

Leave a Reply

Your email address will not be published. Required fields are marked *