How to Create a Background Text Fade-In Effect on Your Website

Written by on

While we were building the Minneapolis Yoga Conference website, we had a neat idea. We wanted text to start off blurred in the background, slowly become visible while you scroll down the page, and finally become readable when you reached the bottom. We thought it looked similar to other parallax effects out there, but it didn't quite fit the definition.

A background text fade-in effect looks like this.

As you scroll down the page, the background text becomes more visible. Once you reach the bottom, you can finally read through the content.

As you scroll down the page, the background text becomes more visible. Once you reach the bottom, you can finally read through the content.

The text behind the photos starts as an absolute positioned element behind the foreground. Once you scroll to the images, the text becomes fixed. When you've finally scrolled to the end of the images, the text falls into the normal flow of the page, a static position.

Here's how you can do this.

1. Start with this template

We want to separate the foreground and background layers. Constructing them as separate div elements helps us do that. We also declare which background layer will be attached to the foreground.

<div class="background-container">
  <div class="foreground-layer" data-background-layer="background">
    <div>
      <img src="http://via.placeholder.com/350x350" width="350" height="350">
      <h5>Image 1</h5>
    </div>
    <div>
      <img src="http://via.placeholder.com/350x350" width="350" height="350">
      <h5>Image 2</h5>
    </div>
    <div>
      <img src="http://via.placeholder.com/350x350" width="350" height="350">
      <h5>Image 3</h5>
    </div>
    <div>
      <img src="http://via.placeholder.com/350x350" width="350" height="350">
      <h5>Image 4</h5>
    </div>
    <div>
      <img src="http://via.placeholder.com/350x350" width="350" height="350">
      <h5>Image 5</h5>
    </div>
  </div>
  <div class="background-layer" id="background">
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur dictum id nulla quis gravida. Donec et velit sapien. Quisque augue eros, porttitor vel finibus et, consequat ac ante. Morbi eleifend diam vitae purus mattis interdum. Aliquam vitae orci ante. Maecenas non odio urna. Nullam lobortis turpis eget sem accumsan, ac laoreet turpis ullamcorper. Donec quis quam erat. Nam vulputate metus a nisi placerat, a ullamcorper nisi semper. Nulla facilisi. Ut molestie tempus egestas. Nunc lacinia libero sit amet eleifend pellentesque. Etiam sit amet lorem quam. Suspendisse potenti.
    </p>

    <p>
      Fusce nunc nisl, ullamcorper vel congue vel, aliquet ut purus. Praesent laoreet ipsum porta sem dictum, at malesuada tortor ullamcorper. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce vel dui at nulla gravida gravida sit amet quis dui. Cras nec leo metus. Phasellus dignissim, nunc id interdum rutrum, enim turpis pharetra dolor, vel vehicula justo nulla vel quam. Vivamus dapibus dolor id nunc dapibus, id aliquet eros euismod.
    </p>

    <p>
      Sed ac tincidunt tortor, sagittis hendrerit massa. Sed volutpat, dui eu ornare mattis, urna enim tincidunt tellus, eu hendrerit lectus ipsum vitae libero. Suspendisse potenti. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas rutrum, ex ut ultricies ornare, mauris lorem ornare libero, vitae malesuada tortor arcu quis purus. Sed felis odio, facilisis ac egestas in, malesuada nec lacus. Quisque metus erat, aliquam et sollicitudin et, consectetur nec est. Nullam eget nisl quis lectus tempor faucibus. Vestibulum auctor purus id orci dapibus, vitae ullamcorper erat dapibus. Maecenas egestas vitae nisi quis sollicitudin. Cras odio purus, fermentum et hendrerit ac, ultricies a dui. Pellentesque dictum massa faucibus, rutrum eros vitae, facilisis tellus. Morbi vulputate, metus et accumsan interdum, sem eros ultrices dolor, non tristique lacus libero sit amet massa. Donec mollis sapien augue, at ornare libero dictum non. Curabitur in ante venenatis, egestas ante id, sagittis dui.
    </p>
  </div>
</div>

<div>
  <img src="http://via.placeholder.com/350x350" width="350" height="350">
  <h5>Filler Image</h5>
</div>
<div>
  <img src="http://via.placeholder.com/350x350" width="350" height="350">
  <h5>Filler Image</h5>
</div>
<div>
  <img src="http://via.placeholder.com/350x350" width="350" height="350">
  <h5>Filler Image</h5>
</div>

2. Put the background layer behind the foreground layer

The starter template doesn't have anything special to it. The background layer begins on the page where the foreground layer ends. The page flows normally. We need the background layer to appear behind the foreground layer.

.background-container {
  position: relative;
}

.background-layer {
  position: absolute;
  top: 0;
  left: 0;
}

We do this by using absolute positioning on the background layer. The background layer will be absolute positioned relative to the background container. If you have a bunch of content above the background container section, doing this makes sure the background text starts in the right position.

3. Blur the background text

Without doing something with the background text, the foreground will be hard to read. We chose to blur the background text and make it semi-transparent.

.background-container {
  position: relative;
}

.background-layer {
  position: absolute;
  top: 0;
  left: 0;
  filter: blur(3px);
  opacity: 0.1;
}

Your eyes can see something there, but it's not distracting you from the content in the foreground. Be careful with this part. You don't want to let this effect cause problems for people using your website. If the foreground is hard to read, something is wrong.

This is what it looks like on the Minneapolis Yoga Conference website. Although it's blurred and barely visible, you can see the text behind the images.

This is what it looks like on the Minneapolis Yoga Conference website. Although it's blurred and barely visible, you can see the text behind the images.

4. Use JavaScript to listen to scroll events

At this point, we want to setup some JavaScript to listen to scroll events. In our case, we still use jQuery so we continued to use it here. If you don't use jQuery, you could just as easily use window.addEventListener and listen for the scroll event.

Now, the end goal is this:

  • When you scroll down the page, the background text decreases its blur effect and increases its opacity.

  • When you scroll up the page, the background text increases its blur effect and decreases its opacity.

Before we actually do that, we need to do some calculations. We need to know the following:

  • How far down the page have we scrolled?

  • When does the foreground element begin? When does it end?

  • How far have we scrolled within the foreground element?

Like we mentioned in the introduction to this post, we want the background to start as an absolute positioned element. Once we are scrolling inside the foreground, the background should be fixed. Finally, when we scroll past the foreground, the background should flow normally within the page so we can start reading the text.

$(window).on("scroll",
  function(event) {
    // How far have we scrolled down the page?
    var scrollDepth = $(this).scrollTop()
    var $foreground = $("[data-background-layer]")
    var $background = $( '#' + $foreground.data("background-layer") )
    // We need to calculate the height of the foreground layer.
    // This will allow us to transition the background layer
    // from blurred and transparent to in-focus and opaque as we
    // near the bottom of the foreground.
    var foregroundHeight = $foreground.height()
    // The background layer starts as an absolute positioned element,
    // sitting below the foreground layer.
    // When we start scrolling, we'll need to change the background layer
    // to a fixed position.
    //
    // When should we change the background layer to a fixed position?
    var startPosition = $foreground.offset().top
    // When we are done scrolling through the foreground, we need
    // to change the background layer to a static position. This will
    // allow the background to flow with the page as normal, sitting
    // directly below the foreground layer.
    //
    // When should we change the background layer to a static position?
    var endPosition = startPosition + foregroundHeight
    // This is how far we've scrolled relative to the foreground layer.
    var currentPosition = scrollDepth - startPosition
    // We want to use our currentPosition to slowly decrease the blur
    // value and increase the opacity value.
    var initialFilterValue = 3
    var filterValue = initialFilterValue - currentPosition / foregroundHeight * 3
    var initialOpacityValue = 0.1
    var opacityValue = initialOpacityValue + currentPosition / foregroundHeight * 0.9
})

5. Update the position, blur, and opacity values based on scroll depth

We use the values we calculated in step four to update the position of the background text element. When we are scrolling within the foreground, the background should have a fixed position. Once we reach the end of the foreground, we change the background to a static position. This allows the background to "fall into" the normal flow of the page.

Using the calculations above, all you need to do is add this to the end of your scroll event handler.

We handle the position changes of the background element. Also, we use the blur and opacity values we calculated to update these updates as you scroll up or down.

if (scrollDepth >= endPosition) {
  // We've reached the end of the foreground. The background should now
  // flow as normal below the foreground.
  $background.css({ position: "static", filter: "none", opacity: "1" })
} else if (scrollDepth >= startPosition) {
  // We are now scrolling within the foreground. We use the values
  // we calculated previously.
  $background.css({ position: "fixed", filter: "blur("+filterValue+"px)", opacity: opacityValue })
} else {
  // We are above the foreground somewhere. We reset the background
  // to its initial values.
  $background.css({ position: "absolute", filter: "blur("+initialFilterValue+"px)", opacity: initialOpacityValue })
}

6. Make a couple small updates to make things smooth

At this point, things may be a little jumpy and may not work exactly as we described. You may notice the background element doesn't smoothly transition once you scroll past the foreground.

To fix this, you can give a margin-bottom to the foreground element. This margin will be equal to the height of the background element. We do this so the background element has room on the page to flow into once we change the position to static.

if (scrollDepth >= endPosition) {
  $foreground.css({ "margin-bottom": "" })
} else {
  $foreground.css({ "margin-bottom": $background.height() })
}

Finally, you'll likely want to make a few updates to your stylesheet. The final styles should look something like this.

.background-container {
  position: relative;
}

.foreground-layer {
  position: relative;
  z-index: 2;
}

.background-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 1;
  filter: blur(3px);
  opacity: 0.1;
}

Basically, we want to define our intentions here. The background layer should be in a layer below the foreground. Giving the background a z-index of 1 and the foreground a z-index of 2 accomplishes this.

Wrapping Up

In the end, I think we'll use this effect sparingly. It certainly has its place. We don't want to distract people from what's important, like signing up for a mailing list or buying a product. However, this background text fade-in effect was something we were happy with.

Our goal was for people to scroll through the entire list of presenters and read what's below. Hiding the content below the presenters seemed like a good way to do that. As the content comes into view, people will be more likely to continue scrolling down the page.

Do you like this effect? Is it too much? Let us know in the comments.