Would you like to show off a remodeling job with before and after pictures? Or perhaps a stylized photo before and after? Whatever the need, it’s an easy little effect to create with a SVG and a clipPath.
The SVG setup
Nothing too complicated here. A 1000 x 1000 SVG, 2 images and a clipPath. I’m also adding a few elements in a group that we’ll use as a dragger for the effect.
The images
We make sure the bottom image is loaded first. It has no grouping and no clipPath applied to it. The image we’ll be revealing with the dragger and clipPath is placed into a group and the group is clipped. Both images are moved to an x,y of 100,100 rather than filling the whole SVG.
<image xlink:href="https://assets.codepen.io/314556/beforeAfterPost01.jpg" x="100" y="100" width="800" height="800" /> <g clip-path="url(#theClipPath)"> <image xlink:href="https://assets.codepen.io/314556/beforeAfterPost02.jpg" x="100" y="100" width="800" height="800" /> </g>
The clipPath
The clipPath holding the rectangle has a width and height of 800. (The same as our images). The rectangle in the clipPath needs to be set on the left edge of the image. How then, do we determine the x attribute position?
We know the width is 800. We know the x position of the image is 100. We subtract the width from the x position and get a value of -700. That’s where we need to set the clipPath rectangle. (The y position is the same as the images: 100.) The rectangle fill color makes no difference in a clipPath. If you need a refresher, check out my post about masks and clipPaths.
<defs> <clippath id="theClipPath"> <rect id="clipper" x="-700" y="100" width="800" height="800" fill="red" /> </clippath> </defs>
The animation code
I’m using the Draggable plugin from GreenSock to create an interactive group that we’ll use to pull the clipPath rectangle. I’m also adding the inertia plugin so you can throw the draggable element back and forth.
The code is straightforward. The group is set to drag along the x axis, bounds are 0 (starting point) and 800 (width of the images and rectangle). When we drag or throw the draggable element, the moveMask() function is called.
Draggable.create("#dragger", { type: "x", bounds: { minX: 0, maxX: 800 }, inertia: true, edgeResistance: 1, onDrag: moveMask, onThrowUpdate: moveMask });
Moving the clipPath rectangle
The magic happens in the moveMask() function. Each time we move the draggable group, GSAP sets the position of the mask accordingly. Notice it gets set to the x position of the dragger -700. Why? Remember when we set the position of the rectangle at the beginning? It was set to -700. When the dragger is at x:0, the clipping rectangle is at -700. When the dragger is at x:800 (its max limit), the clipping rectangle is set to x:100 (800 -700).
The clipPath rectangle is traveling 800 units (-100 → 700) to cover the entire image.
function moveMask() { gsap.set("#clipper", { attr: { x: this.x - 700 } }); }
The final result
Putting all that into action, you get a cool little before and after reveal. Trying dragging it back and forth and then, throw it back and forth. Pretty cool, right? That’s the inertia plugin from GreenSock in action.
See the Pen Before & after clipPath dragger by Craig Roblewsky (@PointC) on CodePen.
Adding a feature
Maybe you want to partially reveal the underlying image so your users get the idea. You can animate the draggable element to any position before the user starts working with it.
In the following demo, I’ve added a little timeline with a 2 second delay that will do just that. Once the animation plays, a function is called to create the draggable element. Note: all the other features are the same as the first demo above.
gsap .timeline({ onComplete: createDragger, delay: 2, defaults:{duration: 1, ease:"power2.inOut"} }) .to("#dragger", 1, { x: 400 }) .to( "#clipper", 1, { attr: { x: -300 } }, 0 );
I’m delaying the creation of the draggable element so the user can’t grab it until the animation is complete. Try clicking the rerun button (lower right) of the following demo. See how the dragger animates to the middle position? You can add a delay as I have here or you could hook it to the new ScrollTrigger plugin from GreenSock.
See the Pen Before & after clipPath dragger w/auto intro by Craig Roblewsky (@PointC) on CodePen.
Note: in the above demo I used a second copy of the dog image that I changed to black and white. In a similar case, you could use a second copy of the original image with a filter.
Final thoughts
You can also use a mask rather than a clipPath for the reveal. That offers the added ability to use gradients so the reveal could have a nice feathered edge. There are many possibilities for your before and after SVG slider. I’ll save that technique for a more advanced tutorial. I hope you picked up a few nuggets of knowledge. Until next time, keep those pixels movin’.