Mario / Blog 愛

Animating Rectangle Edges

In this site's homepage I made animated borders that surround Japanese characters when each section is scrolled. I'll be explaining how I structured these elements with hover state.

This is the skeleton of the component:

<div class="character-box">
  <h1 class="character">耐久</h1>
  <span class="border  border--top"></span>
  <span class="border  border--right"></span>
  <span class="border  border--bottom"></span>
  <span class="border  border--left"></span>
</div>

Now to the styles. Because the borders will need to move around the parent container .character-box needs to have a position of relative. For the .character I gave the next styling, but feel free to change it:

.character-box { 
  position: relative; 
}

.character {
  display: inline-block;
  margin: 0;
  padding: 48px;
  color: #fff;
  font-size: 4rem;
  cursor: pointer;
}

On to the borders. Every one of them with an absolute position so they behave relative to .character-box container (this is why we set its position to relative). Finally a white background-color, and a transition property to create a smooth effect. I grabbed the cubic-bezier function from easings.net:

.border {
  position: absolute;
  background-color: #fff;
  transition: all 800ms cubic-bezier(0.86, 0, 0.07, 1);  
}

Next we'll define the initial state of each border. Think of it as each vertice of the container that will expand to its next one:

.border--top,
.border--bottom {
  width: 0;
  height: 2px;
}

.border--right,
.border--left {
  width: 2px;
  height: 0;
}

.border--top {
  top: 0;
  left: 0;
}

.border--right {
  top: 0;
  right: 0;
}

.border--bottom {
  bottom: 0;
  right: 0;
}

.border--left {
  bottom: 0;
  left: 0;
}

At last for the transition to happen, the cursor needs to hover in .character-box. Only then the width or height of each border will grow accordingly:

.character-box:hover .border--top,
.character-box:hover .border--bottom { width: 100%; }

.character-box:hover .border--right,
.character-box:hover .border--left { height: 100%; }