<button>Add border</button>
<div></div>
:root {
  --border-colour: black;  
  --border-thickness: 5px;
  --padding: 8px;
  --border-transition-time: 0ms;
}

@media screen and (prefers-reduced-motion: no-preference) { 
  :root {
    --border-transition-time: 250ms;
  }
}

div {
  position: relative;
  width: 200px;
  height: 100px;
  top: 50px;
  left: 50px;
  background-color: pink;
  padding: var(--padding);
}

div::before,
div::after {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  z-index: -1;
}

div::before {
  top: calc(var(--padding) * -1 - var(--border-thickness));
  left: calc(var(--padding) * -1);
  border-top: 0px solid var(--border-colour);
  border-right: 0px solid var(--border-colour);
  transition: width var(--border-transition-time) linear, height var(--border-transition-time) linear var(--border-transition-time);
}

div::after {
  right: calc(var(--padding) * -1);
  bottom: calc(var(--padding) * -1 - var(--border-thickness));
  border-bottom: 0px solid var(--border-colour);
  border-left: 0px solid var(--border-colour);
  transition: border-width 0s linear calc(var(--border-transition-time) * 2), width var(--border-transition-time) linear calc(var(--border-transition-time) * 2), height var(--border-transition-time) linear calc(var(--border-transition-time) * 3);
}

div.border::before,
div.border::after {
  width: calc(100% + var(--padding) * 2);
  height: calc(100% + var(--padding) * 2 + var(--border-thickness));
  border-width: var(--border-thickness);
}
const button = document.querySelector('button');
const div = document.querySelector('div');

button.addEventListener('click', function() {
  div.classList.add('border');
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.