From our sponsor: Chromatic - Visual testing for Storybook, Playwright & Cypress. Catch UI bugs before your users do.
Today we’d like to explore a very subtle, but interesting border animation effect that can be seen on the creative website of Carl Philipe Brenner. When you hover over one of the white portfolio items in the grid, you will see a subtle animation happening: the grid item becomes transparent and the border lines of each side animate clockwise, creating a really nice effect. In this case, the effect is done by animating the widths or heights of several spans with some JS. We’ll try a different approach that uses SVG and CSS transitions. Please note that this technique is highly experimental.
Let’s take a look at the basic concept first, and then we’ll work towards the final effect.
Please note that we’ll be using CSS transitions on SVGs which might not be supported in all browsers.
When looking at the effect, it might not be immediately clear what’s going on, but when you look closely at only one border, let’s say, the top border, then you’ll notice that first, the white line’s width is decreasing from right to left and a new line moves in from the right with a bit of a delay, or gap. When adding all the other sides, it appears as if the top line moves around the corner down to the left side, the left side moves to the down side, and so on.
You can surely create this effect without SVG, even without extra elements, just using pseudo-elements. But here we want to explore what we can do with SVG and how we can control it via CSS rather than using JavaScript.
Now, thinking about how to create this effect using SVG, we could animate the stroke-dashoffset of a rectangle’s stroke or draw the lines directly. We wanted to try a solution without using JS and after some fiddling, we figured that transitioning the stroke-dashoffset and the stroke-dasharray values in CSS can get quite buggy. So, we decided to try a different solution using lines and animating their translation. (We can imagine other approaches to this specific effect, but we liked the idea of moving lines because it is quite easy to understand and to do in CSS, and it also gives us some more opportunities for different animations as you can see in the demo.)
The special thing about the lines that we’ll be using is that they will serve as three states of our animation. They will actually be three times as long as the size of the box they are contained by. In the middle, the line will have a gap the size of the box side. We will achieve this by setting the stroke-dashoffset value to the side length of the box. Now, the trick lies in transitioning the position of the line:
The SVG will have the size of the box, so we won’t see the overflowing part beyond the dashed line.
Before we continue with the next three lines, let’s code this first step up.
We’ll have a div
with a SVG that has our line:
<div> <svg width="200" height="200"> <line x1="0" y1="0" x2="600" y2="0" /> </svg> </div>
The division has a width and height of 200px, just like the SVG drawing, and we’re setting the SVG to position absolute. The line has a stroke width of 10 and most importantly, a stroke-dasharray value of 200:
div { width: 200px; height: 200px; position: relative; overflow: hidden; background: #ddd; } svg { position: absolute; top: 0; left: 0; } svg line { stroke-width: 10; stroke: #000; fill: none; stroke-dasharray: 200; -webkit-transition: -webkit-transform .6s ease-out; transition: transform .6s ease-out; } div:hover svg line { -webkit-transform: translateX(-400px); transform: translateX(-400px); }
The line also has a transition and when we hover over the division, we want the line to move two thirds of its own length to the left, so we translate it -400px on the x-axis. You can take a look and play around with this first step in this JSBin example. Since we cannot use percentages for the translation values here, we need to set the translation in pixels.
The next step is to add the other lines. In order to understand how we need to position and animate them, let’s have a look at this GIF:
We want to animate each line in a way that when the first part of a line moves out of the box, the last part of the joining perpendicular line moves in. This will create the illusion that the lines move around the corners.
Let’s take a look at our coordinate system to define the line points correctly:
The points for the left line are (0,200) and (0,-400), for the bottom one (200,200) and (-400,200), and for the right one (200,0) and (200,600):
<div> <svg width="200" height="200"> <line class="top" x1="0" y1="0" x2="600" y2="0"/> <line class="left" x1="0" y1="200" x2="0" y2="-400"/> <line class="bottom" x1="200" y1="200" x2="-400" y2="200"/> <line class="right" x1="200" y1="0" x2="200" y2="600"/> </svg> </div>
For each line, we’ll need to set a different translation value on hover:
div:hover svg line.top { -webkit-transform: translateX(-400px); transform: translateX(-400px); } div:hover svg line.bottom { -webkit-transform: translateX(400px); transform: translateX(400px); } div:hover svg line.left { -webkit-transform: translateY(400px); transform: translateY(400px); } div:hover svg line.right { -webkit-transform: translateY(-400px); transform: translateY(-400px); }
Check out the code in action.
Now we got the main idea right, this is the effect we are after. Let’s make this look pretty π
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
Our box will be of a different size now (300 x 460) and we’ll also add some other text elements to the item:
<div class="box"> <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"> <line class="top" x1="0" y1="0" x2="900" y2="0"/> <line class="left" x1="0" y1="460" x2="0" y2="-920"/> <line class="bottom" x1="300" y1="460" x2="-600" y2="460"/> <line class="right" x1="300" y1="0" x2="300" y2="1380"/> </svg> <h3>D</h3> <span>2012</span> <span>Broccoli, Asparagus, Curry</span> </div>
To recreate the effect as seen on Carl Philipe Brenner’s website, we’ll add some color transition to the box itself and add a little gap between the SVG border and the item using a box shadow:
.box { width: 300px; height: 460px; position: relative; background: rgba(255,255,255,1); display: inline-block; margin: 0 10px; cursor: pointer; color: #2c3e50; box-shadow: inset 0 0 0 3px #2c3e50; -webkit-transition: background 0.4s 0.5s; transition: background 0.4s 0.5s; } .box:hover { background: rgba(255,255,255,0); -webkit-transition-delay: 0s; transition-delay: 0s; }
Let’s also style the text elements:
.box h3 { font-family: "Ruthie", cursive; font-size: 180px; line-height: 370px; margin: 0; font-weight: 400; width: 100%; } .box span { display: block; font-weight: 400; text-transform: uppercase; letter-spacing: 1px; font-size: 13px; padding: 5px; } .box h3, .box span { -webkit-transition: color 0.4s 0.5s; transition: color 0.4s 0.5s; } .box:hover h3, .box:hover span { color: #fff; -webkit-transition-delay: 0s; transition-delay: 0s; }
The SVG and line will be styled as before:
.box svg { position: absolute; top: 0; left: 0; } .box svg line { stroke-width: 3; stroke: #ecf0f1; fill: none; -webkit-transition: all .8s ease-in-out; transition: all .8s ease-in-out; }
We want a little delay for the line transition otherwise we don’t see it because of the background color transition of the box:
.box:hover svg line { -webkit-transition-delay: 0.1s; transition-delay: 0.1s; }
Before we have defined the stroke-dasharray with only one value but now we want the “filled” parts and the gap to be of a different size so that the effect becomes exactly what we want:
.box svg line.top, .box svg line.bottom { stroke-dasharray: 330 240; } .box svg line.left, .box svg line.right { stroke-dasharray: 490 400; }
If you play with these values, you’ll be able to see how the lines appear differently.
And finally, we’ll set the respective values for the translations on hover. Since the width of our item is 300px, the horizontal lines will need to transition two thirds of the total width which is 900px. The same holds for the vertical lines:
.box:hover svg line.top { -webkit-transform: translateX(-600px); transform: translateX(-600px); } .box:hover svg line.bottom { -webkit-transform: translateX(600px); transform: translateX(600px); } .box:hover svg line.left { -webkit-transform: translateY(920px); transform: translateY(920px); } .box:hover svg line.right { -webkit-transform: translateY(-920px); transform: translateY(-920px); }
And that’s it! I hope you like this little effect and find it inspiring. Check out the alternatives to see what other possibilities there are with this technique.
Another Masterpiece from you.. Awesome!!!!!
I love the work you do Mary.
It is really well explained and the animation/design is always perfectly polished.
Keep it going π
Beatiful ,as always!! Doesn’t work in IE10, while the effect works on Philipe Brenner website. Really inspirational stuff, thanks!!
Sorry, didn’t read that the original effect is JS based.
Yes !!! Thanks a lot Mary Lou π
In find this in the same way but with TweenLite here : http://codepen.io/Zeaklous/pen/kyaFB
Thanks for sharing!
I see carl philip brenner website inspiration π
Hey Mary
I enjoyed the animation.
You are truly an inspiration for me.
Thank you for sharing your knowledge with us.
Awesome, and I finally understand how to use SVG in a simply way! π PS: Is there a complete resource with all sv attribute/properties available?
Great article! The approach I created a couple weeks ago, found at http://codepen.io/Zeaklous/pen/kyaFB , uses two lines instead of four, thus reducing the markup. The downside is that it is a little harder to manipulate than this approach
As Vincent mentioned, the transitions in my approach are javascript based so that the transitions work across more platforms as well
Very nice solution, Zach! Thanks for sharing it π ML
Sir, thanks, now I can put background in the boxes.
Awesome, thank you so much!
So Cool! Thank you for sharing!
There is useful script for this stuff http://velocityzen.github.io/strokes/
You’re the best… thanks!
Awesome Tutorial.
Here is my simple version – http://jsfiddle.net/manish2535/6CDLu/1/
Using Gradient Backgrounds.
Thanks for sharing!
Awesome Tutorial. thanks for post nice tutorial.
Great job as always π
I did a version in pure CSS using box-shadow
http://codepen.io/fixcl/full/lemjw
The biggest problem is that these rectangles can not be easily changed size while resizing window.
Very cool. Such a simple method that could be used to produce some great effects. Thanks for sharing.
When I put the a link Element into the box, why it canβt be clicked?
Can i use this and other effects and animations explained here, in DotNetNuke?
If it’s possible, how?
Thanks
Very clever!!
not working in internet explorer.. but keep up the good work..it’s simply fantastic
Saying “Not working in internet explorer” is like saying “The sky is blue”
me likeeeee,became big fan of urs …:)
Brilliant, thank you!
Amazing Tutorial, But it doesnt work on firefox for me π
Fantastic π
Love it.
I am big fan of yours. Amazing your tutorials such as animated opening eye.
Creating a Border Animation Effect with SVG and CSS
Very Good Effect Mary,
But why its not working in IE browser and Safari browser please let me know can I run this animation in both browser ?
How can I use it with png images? Please, help!
Regards, Ferenc
That’s a great tutorial , Thank you
But it doesnt work on firefox for me π
Great Tutorial, but how would you go about doing an animation like this for a fluid design, containers that have a variation of heights and widths?
I was looking exactly for this kind of effects and I really like your color choices. However, I tried it on IE 11 and it did not work but then I saw this example in Stackoverflow
http://stackoverflow.com/questions/28693659/how-to-make-a-smooth-dashed-border-rotation-animation-like-marching-ants
or the demo
DEMO
I just thought if anyone else is working of an effect like this you might want to read and study how it worked.
And now I need to read both. Haha.
very nice π
It’s Simply Superb, I Need This, Very Helpful to Me
Thank you for sharing!
Thanks so much for taking the time to post such a great tutorial on this border effect! I recently saw this border effect being used on a website and really wanted to recreate it, but I was having trouble finding a good resource. Much appreciated, <3 *internet double high-fives* for the great work!