Menu

Animated SVG Pipes Effect

We recently launched Happy Apps. In considering the design of the Happy Apps website, we aimed to have something uniquely eye-catching, fun and whimsical — we’re supposed to be "happy" after all — but also serious enough that our users feel confident trusting us with their uptime monitoring.

One design element of the Happy Apps site that has received many compliments (and questions) so far is what we call "The Pipes."

The Pipes is a full-page animation effect that we built using SVG, CSS and JavaScript.

The SVG pipes is visually engaging enough that many people have wanted to know how it works. It’s pretty simple, and I figured I’d share an overview of how it works.

I’ve isolated and recreated parts of the SVG animation on CodePen for your convenience.

The HTML

We have 3 pipes that are colored blue, yellow and purple. These pipes are SVG paths that we created in Illustrator. When isolated from the page, the SVG paths look like this:

There’s a div element (which has a class of visual-container) that contains the svg element for that particular section of the web page. The div element has a fixed height and width.

The markup looks like this:

<div class="visual-container">
  <svg viewBox="0 0 563 800" class="stroke-lines paralax on">
    <!-- Pipe #1 (blue) -->
    <path fill="none" stroke="#56AFD0" stroke-width="10" stroke-linejoin="bevel" stroke-miterlimit="10" d="M572,0
c0,0-0.2,7.3,0.2,13.1C572.9,26.8,580.5,50,622,50c59,0,124,0,124,0s50.5-4,50.5,53s0,94,0,94s-7.5,45.5-41.5,45.5s-55,0-55,0
s-36.5-3.5-36.5,37s0,195,0,195S661.3,519,702,519c38,0,36.5,54,36.5,54v54.5c0,0,2.8,45-44.5,45c-43,0-46.5,0-46.5,0
S610.7,668,611,730c0.4,66.4,0.9,70,0.9,70" />
    <!-- Pipe #2 (yellow) -->
    <path fill="none" stroke="#F5EC87" stroke-width="10" stroke-miterlimit="10" d="M527.5,0l0,42c0,0-3,41.5,42,41.5s112.5,0,112.5,0
s65-3.5,65,58.5s0,57,0,57v13.5c0,0-3.3,32.2,45.5,32c53.5-0.2,232,0,232,0s55.5-8,55.5,46s0,171,0,171s7.3,56.2-45.5,56
c-46-0.1-296,0-296,0s-57.8-7.5-56.5,53c1.4,65,0,102,0,102s4,51-54.5,51s-51,76.5-51,76.5" />
    <!-- Pipe #3 (purple) -->
    <path fill="none" stroke="#B685C5" stroke-width="10" stroke-miterlimit="10" d="M550,0v90c0,0-3.3,41.4,52.5,41
c51-0.4,143.8,0,143.8,0s53.2-5,53.2,41s-6,68,39,68s183.5,0,183.5,0s55-4.3,55,50c0,56,0,175,0,175s0,43-61,43c-54,0-265,0-265,0
s-47.7-4.7-47,52.5c0.7,61,0,105,0,105s7.3,45-66,45c-77.5,0-45.5,0-45.5,0s-42.5-6-42.5,40.5s0,49,0,49" />
  </svg>
</div>

SVG Pipes

The SVG

The svg element is the centerpiece of the whole thing, so let’s talk a little bit about it. It’s pretty straightforward.

The svg element is inline, in the sense that it’s right inside the document instead of being served as an external resource (.svg file). The svg element consists of several path elements which represent the three pipes (as stated earlier).

One important part of the svg element to note is the viewBox attribute.

<svg viewBox="0 0 563 800" class="stroke-lines paralax on">

The viewBox attribute basically sets a "stage" for the SVG. The viewBox of the SVG will be drawn relative to the parent element of the SVG. This parent element, in our case, is the visual-container div. The viewBox attribute takes four numbers: min-x,  min-y width and height.

viewBox="[min-x] [min-y] [width] [height]"

The first two numbers, min-x and min-y, is the origin of the viewBox with respect to the parent element of the SVG. In our case, our viewBox starts at (0, 0). That means the viewBox origin is at the left-top corner of the the visual-container div. From the left-top corner, a rectangle with a width of 563px and height of 800px is drawn. That rectangle is our "stage". It will contain the SVG elements.

Why does the viewBox attribute matter? The "S" in SVG stands for "scalable". The viewBox attribute allows us to tell the browser how to scale our SVGs. When we explicitly declare a viewBox attribute, we reduce the risk that our graphic is distorted when it’s not used in the exact dimensions it was created for.

The CSS

The CSS of the page was composed with Sass:

div.visual-container {
  width: 503px;
  height: 800px;
  position: relative;
}

svg.paralax {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  height: 805px;
  width: 503px;
  margin: 0 auto;
  z-index: 0;
  overflow: visible;
  path, polyline {
    fill: none;
    stroke-dasharray: 3000px;
    stroke-dashoffset: 3000px;
    transition: 1.5s stroke-dashoffset ease-in;
  }
  &.on {
    path, polyline {
    stroke-dashoffset: 0;
    }
  }
}

// For Internet Explorer
html[data-useragent*='Trident'] {
  svg.paralax {
    path, polyline {
      stroke-dashoffset: 0;
      transition:none;
    }
  }
}

Here’s the compiled CSS:

div.visual-container {
  width: 503px;
  height: 800px;
  position: relative;
}

svg.paralax {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  height: 805px;
  width: 503px;
  margin: 0 auto;
  z-index: 0;
  overflow: visible;
}

svg.paralax path,
svg.paralax polyline {
  fill: none;
  stroke-dasharray: 3000px;
  stroke-dashoffset: 3000px;
  transition: 1.5s stroke-dashoffset ease-in;
}

svg.paralax.on path,
svg.paralax.on polyline {
  stroke-dashoffset: 0;
}

html[data-useragent*='Trident'] svg.paralax path,
html[data-useragent*='Trident'] svg.paralax polyline {
  stroke-dashoffset: 0;
  transition: none;
}

The key CSS properties I used for the animated SVG pipe effect are stroke-dasharray and stroke-dashoffset. The transition property was used to create the effect that the pipes are being rendered on-the-fly as the user is scrolling the page.

svg.paralax path, svg.paralax polyline {
  fill: none;
  stroke-dasharray: 3000px;
  stroke-dashoffset: 3000px;
  transition: 1.5s stroke-dashoffset ease-in;
 }

svg.paralax.on path, svg.paralax.on polyline {
  stroke-dashoffset: 0;
}

stroke-dasharray is a cool property that allows us to create a dashed pattern in your stroke. This is the key trick of the effect. We use the stroke-dasharray property in conjunction with stroke-dashoffset to make it appear as though the pipes are being drawn as the user is scrolling down the page.

stroke-dashoffset tells the browser where to start painting  the dash array on the path. For example — just for simplicity’s sake — let’s pretend 0px is the start of the path and 100px is the end. Setting the stroke-dashoffset property to 50px will tell the browser to start the stroke-dasharray at 50px into the path.

You can see the offset in the following example is forcing the stroke pattern to paint only part of the full path. So in our case this creates a path that looks something like this:

Stroke Offset

The path is actually fully drawn already, but the stroke does not span the entire path because of our CSS. That’s how the magic happens.

If we then use the CSS transition property on stroke-dashoffset, we can make it look as though the pipes are being drawn on-the-fly:

transition: 1.5s stroke-dashoffset ease-in;

The JavaScript

Now for timing the animation. We wanted to make it feel like the pipes were beckoning you to keep scrolling down the page as you entered page section. So to do this, we have some JavaScript listeners bound to the document’s scroll event so that when the user reaches a particular section, we trigger the CSS transition.

document.addEventListener('scroll',function (event) {
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  if (scrollTop > 456) {
    document.querySelector('section.dashboard svg.paralax').classList.add('on');
    document.querySelector('section.dashboard svg.paralax.small').classList.add('on');
  }
})

At the point where the user has scrolled about two-thirds of the way down the the SVG pipes they’re on, we kick off the animation for the next set of pipes simply by adding a class attribute called paralax that changes the stroke offset on the paths.

Caveat

There’s one drawback to the stroke-dashoffset property. Internet Explorer — surprise, surprise — can’t transition the stroke-dashoffset property.

So in the case where the viewer is on Internet Explorer, they will still see the SVG pipes, but they unfortunately won’t get to experience the animation. This will also be the case for users that have disabled JavaScript. The SVG animation, then, is a form of progressive enhancement for feature-capable browsers.

Conclusion

All in all, it takes very little code to implement this sort of full-page SVG animation effect.

When used with CSS and JavaScript, it’s easy to see that the svg element truly has the potential to bring our web pages to life in a scalable and methodical way.

Related Content

Andy Warner is a Principal Engineer at Happy Apps, an uptime monitoring service. He’s based in Denver, Colorado. Connect with Andy on GitHub.

This was published on Jul 29, 2015

4 Comments

I scrolled quickly through the site. But only after reading your author summary below the post I found out that Happy Apps is an uptime monitoring service. The pipes are catchy and I appreciate the fact that you share the techniques with us, but the way it’s applied it really distracts from the content instead of supporting your story.

Great post! Just to add on:

I recently used this technique in a project and I found it’s possible to make stroke-dashoffset work in IE by using requestAnimationFrame. See http://tympanus.net/Development/SVGDrawingAnimation/ for an example (I’ve tested it in IE9 to 11).

Just playing around with svg animation for a side project and decided to use and modify the code here with my own svg’s. But it doesn’t work, the code is identical to what is written here but i get a “Cannot read property ‘classList’ of null” why is this?

    Jacob Gube Nov 12 2015

    The HTML markup is not complete. That’s why you’re getting that error. The .classList property is null because this bit:

    .querySelector('section.dashboard svg.paralax')

    won’t exist in the DOM if you are just using the HTML in the post.

    This post is more about sharing a concept/technique of animating your SVGs based on the scroll event. It isn’t a straight up, copy-and-paste solution. I think we should’ve made that clear in the article, because I’m aware that we cater to a wide variety of readers. Many readers are just interested in a ready-made, functional plug-and-play website component. I will have to keep that in mind, moving forward.

This comment section is closed. Please contact us if you have important new information about this post.

Partners