President of WebFX. Bill has over 25 years of experience in the Internet marketing industry specializing in SEO, UX, information architecture, marketing automation and more. William's background in scientific computing and education from Shippensburg and MIT provided the foundation for MarketingCloudFX and other key research and development projects at WebFX.

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>

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:

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.