Creating A Border Animation Effect With SVG and CSS

11:02 AM Deepak 0 Comments


Let’s take a look at the basic concept first, and then we’ll work towards the final effect.

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.

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

0 comments: