Search code examples
csscss-transitionscss-transforms

Smooth CSS Transform Scale on rectangle, keeping an even border


I have an absolutely positioned div that I want to have slowly increase in size (5s transition) on hover, to become a "border" for a relative-positioned div on top of it:

<div class="rectangle">
    <div class="background"></div>
    <div class="content">blah</div>
</div>

Styles (vendor prefixes removed for readability):

.rectangle {
    position: relative;
}

.background {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

.content {
    height: 800px;
    width: 200px;
}

Transitioning the overall .background size results in choppy animation but an even border:

.rectangle:hover .background {
    width: calc(100% + 40px);
    height: calc(100% + 40px);
    top: -20px;
    left: -20px;
    right: -20px;
    bottom: -20px;
    transition: 5s linear all;
}

Transitioning a border is choppy animation, but (obviously) an even border

.rectangle:hover .content {
    border: 20px solid red;
    transition: 5s linear all;
}

Transitioning a transform-scale is smooth, but results in a larger top and bottom "border" because it is a rectangle:

.rectangle:hover .background {
    transition: 5s transform;
    transform: scale(1.1);
}

Any way to either get transform-scale to keep even dimensions, or any other way to create this effect?


Solution

  • You can try using box shadow as a border to achieve smooth transitions.

    .rectangle {
        position: relative;
        width: 300px;
        height: 300px;
        top: 100px;
        left: 30%;
    }
    
    .background {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
    }
    
    .background::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      box-shadow: 0 0 0 0px #000;
      transition: 5s linear box-shadow;
    }
    
    .content {
        height: 300px;
        width: 200px;
    }
    
    .rectangle:hover .background::before {
        box-shadow: 0 0 0 20px #000;
        transition: 5s linear box-shadow;
    }
    <div class="rectangle">
        <div class="background"></div>
        <div class="content">blah</div>
    </div>