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.

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:

	<svg width="200" height="200">
		<line x1="0" y1="0" x2="600" y2="0" />

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

	<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"/>

For each line, we’ll need to set a different translation value on hover:

div:hover svg {
  -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="" 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"/>
	<span>Broccoli, Asparagus, Curry</span>

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,
.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 {
	-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.

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

πŸ‘Ύ Hey! Looking for the latest in frontend? Twice a week, we'll deliver the freshest frontend news, website inspo, cool code demos, videos and UI animations right to your inbox.

Zero fluff, all quality, to make your Mondays and Thursdays more creative!

Feedback 43

Comments are closed.
  1. I love the work you do Mary.
    It is really well explained and the animation/design is always perfectly polished.

    Keep it going πŸ™‚

  2. Beatiful ,as always!! Doesn’t work in IE10, while the effect works on Philipe Brenner website. Really inspirational stuff, thanks!!

  3. Hey Mary

    I enjoyed the animation.
    You are truly an inspiration for me.

    Thank you for sharing your knowledge with us.

  4. 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?

  5. The biggest problem is that these rectangles can not be easily changed size while resizing window.

  6. Very cool. Such a simple method that could be used to produce some great effects. Thanks for sharing.

  7. When I put the a link Element into the box, why it can’t be clicked?

  8. Can i use this and other effects and animations explained here, in DotNetNuke?
    If it’s possible, how?


  9. not working in internet explorer.. but keep up the good’s simply fantastic

  10. I am big fan of yours. Amazing your tutorials such as animated opening eye.

  11. 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 ?

  12. 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?

  13. 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!