0

Trying to get this neat CSS transform effect to trigger on load rather than on hover. I've tried to get the "transform: translate3d(0, 0, 0);" bit to run in a BODY onload, but with no success so far. Perhaps that's because the syntax of the CSS code is a little more advanced than what I'm used to.

Either a pure CSS or JavaScript based solution would be very welcome.

<html>
<head>
<!-- original code by codepen user Thomas Vaeth -->

<style>

body {
  margin: 0;
  padding: 0;
}

* {
  box-sizing: border-box;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  width: 100%;
  background-color: #424242;
}

a {
  font-size: 1.5em;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
}

.btn {
  position: relative;
  display: inline-block;
  padding: 0.5em 2em;
  cursor: pointer;
  overflow: hidden;
}
.btn:before, .btn:after {
  content: "";
  position: absolute;
  left: 0;
  height: 4px;
  width: 100%;
  background-color: #131313;
}
.btn:before {
  top: 0;
}
.btn:after {
  bottom: 0;
}
.btn:hover > * > *:before, .btn:hover > * > *:after {
  transform: translate3d(0, 0, 0);
}
.btn:hover > * > * > *:before, .btn:hover > * > * > *:after {
  transform: translate3d(0, 0, 0);
}
.btn > *:before, .btn > *:after {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: 4px;
  background-color: #131313;
}
.btn > *:before {
  left: 0;
}
.btn > *:after {
  right: 0;
}
.btn > * > *:before, .btn > * > *:after {
  content: "";
  position: absolute;
  left: 0;
  z-index: 9;
  height: 4px;
  width: 100%;
  background-color: #168dff;
}
.btn > * > *:before {
  top: 0;
  transform: translate3d(-105%, 0, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.btn > * > *:after {
  bottom: 0;
  transform: translate3d(105%, 0, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.btn > * > * > *:before, .btn > * > * > *:after {
  content: "";
  position: absolute;
  top: 0;
  z-index: 9;
  height: 100%;
  width: 4px;
  background-color: #168dff;
}
.btn > * > * > *:before {
  left: 0;
  transform: translate3d(0, 105%, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.btn > * > * > *:after {
  right: 0;
  transform: translate3d(0, -105%, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

</style>

</head>
<body>

<a class="btn">
  <span>
    <span>
      <span>&nbsp;</span>
    </span>
  </span>
</a>

</body>
</html>
John Blatz
  • 77
  • 7
  • That's some nifty CSS. A bit beyond me, too, but I've no doubt there's a way to achieve what you're after – Craig Mar 22 '21 at 22:03

1 Answers1

2
  1. Replace this:
.btn:hover > * > *:before,
.btn:hover > * > *:after {
  transform: translate3d(0, 0, 0);
}
.btn:hover > * > * > *:before,
.btn:hover > * > * > *:after {
  transform: translate3d(0, 0, 0);
}

With this:

.btn.animate > * > *:before,
.btn.animate > * > *:after {
  transform: translate3d(0, 0, 0);
}
.btn.animate > * > * > *:before,
.btn.animate > * > * > *:after {
  transform: translate3d(0, 0, 0);
}
  1. Add this to javascript:
const btn = document.querySelector(".btn");

window.addEventListener("load", function () {
  btn.classList.add("animate");
});



const btn = document.querySelector(".btn");

window.addEventListener("load", function() {
  btn.classList.add("animate");
});
body {
  margin: 0;
  padding: 0;
}

* {
  box-sizing: border-box;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  width: 100%;
  background-color: #424242;
}

a {
  font-size: 1.5em;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
}

.btn {
  position: relative;
  display: inline-block;
  padding: 0.5em 2em;
  cursor: pointer;
  overflow: hidden;
}

.btn:before,
.btn:after {
  content: "";
  position: absolute;
  left: 0;
  height: 4px;
  width: 100%;
  background-color: #131313;
}

.btn:before {
  top: 0;
}

.btn:after {
  bottom: 0;
}

.btn.animate>*>*:before,
.btn.animate>*>*:after {
  transform: translate3d(0, 0, 0);
}

.btn.animate>*>*>*:before,
.btn.animate>*>*>*:after {
  transform: translate3d(0, 0, 0);
}

.btn>*:before,
.btn>*:after {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: 4px;
  background-color: #131313;
}

.btn>*:before {
  left: 0;
}

.btn>*:after {
  right: 0;
}

.btn>*>*:before,
.btn>*>*:after {
  content: "";
  position: absolute;
  left: 0;
  z-index: 9;
  height: 4px;
  width: 100%;
  background-color: #168dff;
}

.btn>*>*:before {
  top: 0;
  transform: translate3d(-105%, 0, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.btn>*>*:after {
  bottom: 0;
  transform: translate3d(105%, 0, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.btn>*>*>*:before,
.btn>*>*>*:after {
  content: "";
  position: absolute;
  top: 0;
  z-index: 9;
  height: 100%;
  width: 4px;
  background-color: #168dff;
}

.btn>*>*>*:before {
  left: 0;
  transform: translate3d(0, 105%, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.btn>*>*>*:after {
  right: 0;
  transform: translate3d(0, -105%, 0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
<a class="btn">
  <span>
        <span>
          <span>&nbsp;</span>
  </span>
  </span>
</a>
Manas Khandelwal
  • 3,790
  • 2
  • 11
  • 24
  • Very nice solution, and it works flawlessly on Chrome, but not on IE11 unfortunately, while the original code does. Sorry, I should have specified that I would need to retain IE11 compatibility if possible. – John Blatz Mar 22 '21 at 22:20
  • 1
    Note that not not long ago I have to do like `setTimeout(()=>{ btn.classList.add('animate'); }, 0)` in Firefox, to get transformations to work, even when using a `load` Event. Looks like they've fixed that now, but could be a concern on some Browsers. That being said, don't worry about IE anymore. You won't be able to do a bunch of stuff if you want to comply with IE. It's been depreciated for a while. – StackSlave Mar 22 '21 at 22:20
  • @StackSlave Check this: https://stackoverflow.com/a/588048/11171286 – Manas Khandelwal Mar 22 '21 at 22:22
  • @ManasKhandelwal, I'm not saying don't use a `load` Event. I always use a `load` Event. It's just that without the timeout it used to be a problem in Firefox. – StackSlave Mar 22 '21 at 22:25
  • @StackSlave I did not mention that... I agree with you, I was telling the reason why it was acting differently in firefox... "*By default, it is fired when the entire page loads, including its content (images, CSS, scripts, etc.). In some browsers it now takes over the role of `document.onload` and fires when the DOM is ready as well.* – Manas Khandelwal Mar 22 '21 at 22:28
  • It is my mistake I should have mentioned it properly ! – Manas Khandelwal Mar 22 '21 at 22:29