Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a CSS animation that "slides in", revealing a text/div after it finishes sliding?

I am trying to mimic the CSS animations from a website here: https://stanographer.com/

I want to copy the way the site:

  • starts by showing a full screen black div sliding away to the right

  • "loads" the black background (div tags) behind text (as in "Hi, I'm Stanley Sakai"), expanding left to right and

    • "loads" the text over the black background div, expanding left to right.

Now you might ask, "Why not just inspect the page, look at the classes on the divs and text, then inspect the CSS sheet in the network tab?" And I've tried that. The CSS looks weird. My friend said it is pre-processed by SASS, whatever that means. Anyway, I cannot decipher the code.

I've been to a few different StackOverflow pages (here's one) & over a dozen different pages on Google. I learned about using keyframes but I haven't figured out how to recreate the effect on Stanographer.com. My friend, who owns the website, also provided this example, but I don't get how to apply it to individual divs. He said something about using the z-index but I just don't see it.

I know that to make the page start with a full black screen & then slide out, I have to trigger a class change using JavaScript. I have:

let blackStuff = document.getElementById("blackness");

window.addEventListener("load", () => {
    console.log("loaded");
    blackStuff.setAttribute("class", "black-box-out");
  },
  false
);
.black-box {
  position: fixed;
  float: left;
  top: 0;
  width: 100%;
  height: 100%;
  bottom: 0;
  background-color: #000;
  z-index: 999999;
  -webkit-animation: powerslide 0.5s forwards;
  -webkit-animation-delay: 2s;
  animation: powerslide 0.5s forwards;
  animation-delay: 2s;
}

@-webkit-keyframes powerslide {
  100% {
    left: 0;
  }
}

@keyframes powerslide {
  100% {
    left: 0;
  }
}

.black-box-out {
  margin-left: 100%;
  animation: slide 0.5s forwards;
  -webkit-transition: slide 0.5s forwards;
  transition: slide 0.5s forwards;
}
<div id="blackness" class="black-box"></div>

But this just makes the "blackness" div disappear instantly on page load. I want it to slide out. Clearly, I don't get how to use CSS animations.

If you are interested in seeing more of what doesn't work, read on. Otherwise, you can skip this section: it only shows my failed trials.

I've learned how to make a CSS animation expand horizontally from 0:

.wrapper {
  position: relative;
  overflow: hidden;
  width: 500px;
  height: 50px;
  border: 1px solid black;
}

.slide-custom {
  width: 500px;
  height: 50px;
  background: cyan;
  position: relative;
  -webkit-animation: slideIn 2s forwards;
  animation: slideIn 2s forwards;
}


/* moz and webkit keyframes excluded for space */

@keyframes slideIn {
  0% {
    transform: scaleX(0);
  }
  100% {
    transform: scaleX(1);
  }
}
<div class="wrapper slide-custom">
  <h1 class="slide-custom">
    <span>MEET ROLY POLY.</span>
    <!-- expands horizontally from 0 width to 100% width -->
  </h1>
</div>

And I've learned to make text "slide in" from the left, though it starts at 100% width when I want it to start at 0% width:

/* CSS */

.test-slide {
  animation-duration: 3s;
  animation-name: testSlide;
}

@keyframes testSlide {
  from {
    margin-left: 0%;
    width: 50%;
  }
  to {
    margin-left: 100%;
    width: 100%;
  }
}
<div class="test-slide">
  <h1><span>ABOUT.</span></h1>
  <!-- will slide in from the left -->
</div>

There's more -- unfortunately none of it mimics the website I'm trying to copy.

like image 345
Roly Poly Avatar asked Mar 27 '20 23:03

Roly Poly


People also ask

How do you make a floating animation in CSS?

You can change your animation as you like by using this property. First start with the @keyframes rule followed by name of the animation (In this case, it is “floating”). Inside the @keyframes, you can see 3 percentage values have been declared. It is followed by a code snippet containing properties and their values.

Can you animate a div in CSS?

Let's look at an example. Say the animated element is a div, its animation name is “slide-right,” and its animation cycle is four seconds. To control how the div renders at a given time during the animation sequence, you can add a @keyframes at-rule with two or more keyframe selectors.

How do you add an animation text in CSS?

CSS Code: Step 1: Do some basic style like background-color, text-color, margins, padding etc. Step 2: Now, use before select/or to set the content of span to an initial word. Step 3: Use animation property to set the total time for the animation.


1 Answers

Explanation

There are multiple ways to achieve what you want actually. I did not opt to animate width. The first few frames of the animation will be not as expected.

So instead, we can use clip-path. What clip-path basically does is masking. You can "crop" a div such that only a part of it is visible. We will utilise clip-path and ::before or ::after pseudo-element (either is fine) to create this animation. What we need to do:

  • Create the pseudo-element and position it such that it covers (is on top) the whole animatable element (position: absolute)
  • Set the pseudo-element's background to black
  • Using clip-path, mask the animatable element to display no parts of the element (this will also cause the pseudo-element to not be displayed as it is part of the element). The direction of the clipping is important. The direction here is from the right side to the left side.
  • Using animation and @keyframes, unmask the previously masked div. This will reveal it slowly from the left side to the right side (because initially, we masked it from the right to left; upon unmasking, the reverse direction happens)
  • Upon unmasking the element, the pseudo-element will be on top of the text we want to display
  • After a short while later, mask the pseudo-element (not the whole element) from the right direction to the left direction, again using clip-path so that the text seems revealed slowly

It works! However, I recommend reading about clip-path. Also, one really handy clip-path CSS generator I really like to use is this (if you want to clip from the right to left, you should drag the points from the right to left). I also highly recommend reading about CSS positioning (a staple in good CSS animations). You needn't be using z-index: 9999; you generally want to keep track of the z-index you use.


Solution

Here's a working solution using the described method. Try running it.

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: Helvetica;
}

body,
html {
  width: 100%;
  height: 100%;
}

#wrapper {
  background: #555555;
  width: 100%;
  height: 100%;
  color: white;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

#wrapper * {
  margin: 5px;
}

.heading {
  font-size: 3em;
  padding: 10px 5px;
}

.caption {
  font-size: 1em;
  padding: 5px;
  font-family: Courier;
}

.animatable {
  position: relative;
  clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%);
  animation: .75s cubic-bezier(1,-0.01,.12,.8) 1s 1 reveal forwards;
}

.animatable::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #20262b;
  padding: inherit;
  animation: .75s cubic-bezier(1,-0.01,.12,.8) 1.75s 1 hideBlack forwards;
}

@keyframes reveal {
  from { clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%); }
  to { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
}

@keyframes hideBlack {
  from { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
  to { clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%); }
}
<div id="wrapper">
  <div class="heading animatable">Hi, I am Richard!</div>
  <div class="caption animatable">I am a person.</div>
</div>

Although the simple animation you wanted can be created using merely CSS, I still suggest you read about how to make animations using JavaScript and the various libraries it has in making animations. This is because once there are many animations and transitions going on, it becomes hard to keep track of animations (especially when you want animations to start after another animation ends). A good library is anime.js (do explore more options before settling on one). Furthermore, notice how the animations only appear upon scrolling down in the website you provided? That's doable only with JS (one such method is using IntersectionObserver API provided by most browsers).

like image 187
Richard Avatar answered Nov 14 '22 21:11

Richard