We’ve been experimenting lately with SVG path animations, creating transitions for our image slider and hero slider. Today’s tutorial shows you how to animate at once multiple SVG paths to create a stylish background effect for a modal window.

Inspiration: UI8 Nav on Dribbble

Creating the structure

The HTML structure is composed by 2 main elements: a <section> , used to wrap the action button ( #modal-trigger ), and a div.cd-modal , the modal window, containing the modal content ( .cd-modal-content ) and the div.cd-svg-bg , used to create the background covering effect.

<main class="cd-main-content"> <section class="center"> <h1>SVG Modal Window</h1> <a href="#0" class="cd-btn" id="modal-trigger" data-type="cd-modal-trigger">Fire Modal Window</a> </section> </main> <!-- .cd-main-content --> <div class="cd-modal" data-modal="modal-trigger"> <div class="cd-svg-bg" data-step1="M-59.9,540.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L864.8-41c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L-59.5,540.6 C-59.6,540.7-59.8,540.7-59.9,540.5z" data-step2="M33.8,690l-188.2-300.3c-0.1-0.1,0-0.3,0.1-0.3l925.4-579.8c0.1-0.1,0.3,0,0.3,0.1L959.6,110c0.1,0.1,0,0.3-0.1,0.3 L34.1,690.1C34,690.2,33.9,690.1,33.8,690z" data-step3="M-465.1,287.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L459.5-294c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C-464.9,287.7-465,287.7-465.1,287.5z" data-step4="M-329.3,504.3l-272.5-435c-0.1-0.1,0-0.3,0.1-0.3l925.4-579.8c0.1-0.1,0.3,0,0.3,0.1l272.5,435c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C-329,504.5-329.2,504.5-329.3,504.3z" data-step5="M341.1,797.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L1265.8,216c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L341.5,797.6 C341.4,797.7,341.2,797.7,341.1,797.5z" data-step6="M476.4,1013.4L205,580.3c-0.1-0.1,0-0.3,0.1-0.3L1130.5,0.2c0.1-0.1,0.3,0,0.3,0.1l271.4,433.1c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C476.6,1013.6,476.5,1013.5,476.4,1013.4z"> <svg height="100%" width="100%" preserveAspectRatio="none" viewBox="0 0 800 500"> <title>SVG Modal background</title> <path id="cd-changing-path-1" d="M-59.9,540.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L864.8-41c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L-59.5,540.6 C-59.6,540.7-59.8,540.7-59.9,540.5z"/> <path id="cd-changing-path-2" d="M-465.1,287.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L459.5-294c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C-464.9,287.7-465,287.7-465.1,287.5z"/> <path id="cd-changing-path-3" d="M341.1,797.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L1265.8,216c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L341.5,797.6 C341.4,797.7,341.2,797.7,341.1,797.5z"/> </svg> </div> <div class="cd-modal-content"> <!-- modal content here --> </div> <!-- cd-modal-content --> <a href="#0" class="modal-close">Close</a> </div> <!-- cd-modal --> <div class="cd-cover-layer"></div> <!-- .cd-cover-layer -->

An additional div.cd-cover-layer has been used to cover the main content when the modal window is fired (it is positioned between the modal window and the main content of the page).

Adding style

The .cd-modal window has, initially, visibility: hidden, height: 100% and width: 100% and is in fixed position.

When user clicks the a#modal-trigger , the visibility of the modal window is changed to visible (using the .modal-is-visible class).

.cd-modal { position: fixed; z-index: 2; top: 0; left: 0; height: 100%; width: 100%; visibility: hidden; transition: visibility 0s 0.6s; } .cd-modal.modal-is-visible { visibility: visible; transition: visibility 0s 0s; }

To create the modal background covering effect, we animate the 'd' attribute of the <path> elements inside the div.cd-svg-bg > svg (more in the Events handling section).

Our first approach to creating the "masked" text effect consisted in using the SVG foreignObject to include the modal content into the SVG element. This way we could use the path elements as a reference to cut the text outside the animated background. However, we had several issues, mostly related to browsers compatibility.

That's why we decided to use this simple trick instead: when the modal window is fired, a layer ( .cd-cover-layer ) becomes visible, right below the modal background, and, immediately after, the text becomes visible as well. The .cd-cover-layer and the text have the same color, this way only the text over the blue paths is visible during the animation.

More in details: when a user clicks the a#modal-trigger , the .modal-is-visible class is added to the .cd-cover-layer and the .cd-modal . This class changes the .cd-cover-layer opacity from 0 to 1 and its visibility from hidden to visible, so that the .cd-cover-layer entirely covers the page main content.

.cd-cover-layer { position: fixed; z-index: 1; top: 0; left: 0; height: 100%; width: 100%; background-color: #f2f2f2; visibility: hidden; opacity: 0; transition: opacity 0.3s 0.3s, visibility 0s 0.6s; } .cd-cover-layer.modal-is-visible { opacity: 1; visibility: visible; transition: opacity 0.3s 0s, visibility 0s 0s; }

As soon as the .cd-cover-layer opacity transition is over, the opacity of the .cd-modal-content is set to 1:

.cd-modal-content { color: #f2f2f2; opacity: 0; transform: translateY(50px); transition: opacity 0.3s 0s, transform 0.3s 0s; } .modal-is-visible .cd-modal-content { opacity: 1; transform: translateY(0); transition: opacity 0.3s 0.3s, transform 0.3s 0.3s; }

Since the color of the .cd-modal-content is the same of the .cd-cover-layer background color, the only visible content will be the one over the blue svg background (which is still animating), while the one over the .cd-cover-layer won't be visible.

Events handling

To animate the modal background, we animated the 'd' attribute of the 3 <path> elements inside the svg.

First, we defined the two steps of our animation, using the same process described in the Animated SVG Hero Slider article (Events handling section).

Once defined the paths, we added to the .cd-svg-bg a data-stepn attribute (one for each step) equal to the 'd' attribute of the defined path (to easily retrieve it with JavaScript).

We then used the animate() method provided by Snap.svg to animate the path element.