Guide To Fade-In Effect On Scroll Into View

Did you notice this fade-in??

Many of the UI we see today, whether it’s on TV, slideshow presentations, mobile apps and many other kinds of visuals, all incorporate some form of transition to keep the user engaged. A few days ago I was designing a mock e-commerce website for a local business and spent quite some time stuck on how to implement this fade-in effect. While there are a lot of ways to incorporate fade-in effects and there are many webpages showing you how to do so, I’ve found that there are no articles which matched the exact effect I was looking for, and thus I’m putting it here for the sake of documentation and knowledge sharing.

Read on to learn more about how to incorporate fade-in of elements the moment it is partly visible in the viewport.

Why Incorporate Transition Effects??

Before we go into the actual implementation details, readers may be inclined to understand why fade-in and other transition effects are important in keeping users engaged. The following are some of my observations.

As a form of guidance

Have you ever sat in a meeting with slideshow presentations and the presenter changes into the next slide with so much information scattered around that you have no idea where to look?? It happens very often for me and if the presenter does not use a laser pointer device it would require much more of my attention to simultaneously listen to the presenter and follow the material.

Figure 1-1 : A crude example of fade-in effect to guide the reader through a workflow.

Incorporating some transition effects throughout the UI serves to prevent the user from being distracted by other content and keeps them focused on the current topic.

More natural feel

Flipping pages of a book, swiping right on a smartphone app, scrolling down a webpage… all of these smooth movements ease and prepare the user for new content. Everything in the perceivable real world takes time to execute – nothing switches from 0 to 1 in an instant. While incorporating transition effects DO have impact on performance (Windows’s UI is a prime example… disabling Windows animations reduces CPU load and enables a faster UI), sacrificing some performance or resources to engage the visitor is a small price worth paying.

Better than static

The official Google Pixel 4 product page is a prime, one-of-a-kind example (although possibly overkill for most) of different effects to wow the user. I would never have imagined such a webpage could exist, and the amount of effort that went into developing this page must have been substantial. In the context of adding transitions to a webpage or other form of UI, I strongly believe in a form of the Pareto Principle, where twenty percent of your effort equates to eighty percent of the result. In other words, there is no need to spent so much energy to make your webpage look extravagant like Google Pixel’s or Apple IPhone’s product page, but small transition elements definitely do breathe life into your UI.

Implementing Fade-In On Scroll Into Viewport


Let’s start with the CSS:

Figure 2-1 : CSS settings for a class and it’s subclass. Elements with classname “fade-in” will appear hidden by default, with the “is-visible” subclass triggering the animation.

The following code initiates settings for a class and subclass to perform the fade-in effect:

.fade-in {
  opacity: 0;
  transform: translateY(20vh);
  visibility: hidden;
  transition: opacity 0.6s ease-out, transform 1.2s ease-out;
  will-change: opacity, visibility;
} {
  opacity: 1;
  transform: none;
  visibility: visible;

The combination of 0 opacity and hidden visibility causes all elements with class “fade-in” to appear invisible by default. The transform: translateY(20vh) provides the upwards movement associated with an element fading into view. Those who don’t want the upwards movement can remove the transform parts in the class. Lastly, the transition line sets the parameters for how fast the fade-in should occur – feel free to adjust and experiment accordingly.

Next, the “is-visible” subclass provides the mechanism for the dynamic fade-in effect. In essence, when conditions for the animation are met the “is-visible” classname is appended to element with the “fade-in” class which will then cause the animation to begin. Adding “is-visible” to an element withOUT the “fade-in” class will do nothing. The appending of the subclass is done via JQuery, thus every event compatible with JQuery can be used to trigger the appending of “is-visible” (scrolling, button click, element change, etc).


The next part deals with the JQuery. Here’s the code:

$(window).scroll(function() {
    $('.fade-in').each(function() {
        var top_of_element = $(this).offset().top;
        var bottom_of_element = $(this).offset().top + $(this).outerHeight();
        var bottom_of_screen = $(window).scrollTop() + $(window).innerHeight();
        var top_of_screen = $(window).scrollTop();

        if ((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element) && !$(this).hasClass('is-visible')) {

At the top is where the “event” is designated. In this situation we are detecting all scrolling of the page, but it can be modified to another event such as button click or detecting changes in some other element. Next, the $(‘.fade-in’).each(function() { checks for all elements with the “fade-in” class and runs the code afterwards accordingly. This is especially important to control fade-in effects for individual elements, because without this code all elements will fade-in if a single one is partially visible in the viewport.

The rest of the code is based off of a wonderful StackOverflow answer in which the element position and viewport dimensions are scanned and then compared to see if the element exists in the viewport. A !$(this).hasClass(‘is-visible’) is added as an additional condition to prevent the element from fading in twice.

This jQuery code can be added anywhere in the code, but do make sure that the jQuery library has already been imported and that the code itself has finished loading before the user can scroll. In a faster, optimized website this shouldn’t be such an issue, but otherwise it is suggested to place the code at the end of the “head” element.


The HTML part is easy – just add the “fade-in” class to all elements you wish to animate. For example, the following shows the class for the top paragraph of this webpage which has the fade-in animation:

Figure 2-2 : HTML demonstrating the class “fade-in”.

Note that the JQuery code triggers for EACH element with the fade-in class, thus performance may be significantly impacted for a huge amount of elements. Consider grouping elements under a single parent element and setting the class for that top-level element to simulate fade-in effect for multiple elements at the same time.

Note to WordPress Users

Careful of the jQuery code!

For WordPress users, note that “$” is substituted for “jQuery” because WordPress runs jQuery in safe mode and therefore uses a different syntax to avoid conflict with other potential libraries which also use “$”. Refer to the below code block for an updated version for WordPress users:

jQuery(window).scroll(function() {
    jQuery('.fade-in').each(function() {
        var top_of_element = jQuery(this).offset().top;
        var bottom_of_element = jQuery(this).offset().top + jQuery(this).outerHeight();
        var bottom_of_screen = jQuery(window).scrollTop() + jQuery(window).innerHeight();
        var top_of_screen = jQuery(window).scrollTop();

        if ((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element) && !jQuery(this).hasClass('is-visible')) {

Make Settings via the WordPress UI

For the CSS portion of the code, all WordPress themes have a UI setting for “Additional CSS”. If you don’t feel like fiddling with the theme code, setting it via the UI is absolutely painless:

Figure 3-1 : The “Additional CSS” section of WordPress theme customization

Next is the jQuery code. While there is the option to paste the code via the Theme code editor, there is a separate WordPress add-on called Header and Footer Scripts which allows you to set header and footer code via the admin console (Settings -> Header and Footer Scripts):

Figure 3-2 : jQuery code in the footer section. It is also OK to paste the code in the header section as well.

Lastly, for the HTML itself, the new “Block” interface of WordPress posts has an advanced section for Additional CSS classes. Just throw the “fade-in” class to that setting as shown below:

Figure 3-3 : Advanced settings showing Additional CSS classes field. This UI can be found in WordPress post’s right side column “Block Settings”.