Creating a Border Animation Effect with SVG and CSS

The website of Carl Philipe Brenner has some very creative and subtle animations and today we want to explore how to recreate a border animation effect using CSS transitions on SVG lines.

BorderAnimationSVG

View demo Download source

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:

bordereffect_01

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:

bordereffect_02

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:

bordereffect03

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 :)

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.

View demo Download source

Previous:
Next:

Tagged with:

Mary Lou (Manoela Ilic) is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

View all contributions by

Website: http://tympanus.net/

Related Articles

Feedback 34

  1. 8

    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 ?

Follow this discussion

Leave a Comment

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>