Creating a CSS animation that smoothly slides across the screen and unveils a hidden text/div once the animation is complete

I have been attempting to replicate the captivating CSS animations seen on a particular website:

My goal is to imitate how the site:

  • initially reveals a full-screen black div sliding away to the right

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

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

You may wonder why I haven't simply inspected the page, analyzed the classes applied to the divs and text, and reviewed the CSS in the network tab. Unfortunately, the CSS appears convoluted. According to my friend, it is pre-processed by SASS, whatever that entails. Consequently, I find deciphering the code to be quite challenging.

I've scoured various StackOverflow pages (like this one) and numerous Google search results. While I learned about utilizing keyframes, I have yet to grasp how to recreate the effect found on Stanographer.com. My friend, who happens to own the website, shared an example with me, but integrating it into individual divs remains elusive. He mentioned something about z-index usage, but I fail to see its application.

I am aware that triggering a class change via JavaScript is necessary to initiate the page with a full black screen sliding out. Thus far, I have implemented:

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>

However, this currently causes the "blackness" div to vanish instantly upon page load rather than sliding out as intended. It is evident that my understanding of CSS animations is lacking.

If you wish to explore further unsuccessful attempts, read on. Otherwise, feel free to skip this section which solely showcases my failed endeavors.

I managed to create a CSS animation that horizontally expands 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>

Furthermore, I succeeded in making text "slide in" from the left, although it initiates at 100% width instead of 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>

Unfortunately, none of these methods mimic the desired effect of the website I aim to replicate.

Answer ā„–1

Unique Explanation

To achieve the desired effect, there are several methods you can explore. Instead of animating the width, which may lead to unexpected results in the initial frames, consider utilizing the clip-path property for masking. This technique allows you to selectively display portions of a div while hiding others. By incorporating either the ::before or ::after pseudo-elements, we can create the animation as follows:

  • Create and position the pseudo-element above the animatable element with absolute positioning.
  • Set the background of the pseudo-element to black.
  • Apply a clipping path using clip-path so that both the animatable element and the pseudo-element are hidden initially. The clipping direction should be from right to left.
  • Use CSS animations and keyframes to gradually reveal the masked div by reversing the original clipping direction (from left to right).
  • Once the element is fully unmasked, the pseudo-element will overlay the visible text.
  • After a short delay, mask only the pseudo-element in the reverse direction (left to right) using clip-path to create a slow reveal effect on the text.

This method successfully achieves the desired animation. For further reference, it's advisable to familiarize yourself with clip-path and practice good understanding of CSS positioning techniques. Additionally, consider using tools like CSS clip-path generators for efficiency in creating complex shapes. Remember to manage z-index values effectively to control the stacking order of elements.


Original Solution

Below is a functional solution following the described approach. Feel free to test it out:

* {
  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>


While CSS alone can accomplish the basic animation requirement, delving into JavaScript-based solutions and libraries offers additional possibilities. When managing multiple animations and transitions, leveraging tools like anime.js can streamline the process. Moreover, achieving scroll-triggered animations similar to the example site typically entails utilizing JS functionalities like browser-supported APIs such as IntersectionObserver. Stay curious and explore various options before settling on a specific animation framework.

Answer ā„–2

Check out these amazing CSS3 animations that can be activated by adding the .active class to the .entrance-animation element.

To make it work, you'll need an observer to detect when the element comes into view and then apply the .active class.

I hope this solution is helpful for your project!

setTimeout(() =>
{
  let animate = document.querySelectorAll('.entrance-animation');
  
  animate.forEach(item => item.classList.add('active'));
}
,1000);
.entrance-animation
{
  position: relative;
  color: blueviolet;
  white-space: nowrap;
  font-size: 24px;
  width: 0;
  overflow: hidden;
  transition: width 0.5s ease;
}
.entrance-animation::before
{
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 100%;
  background-color: black;
  z-index: 10;
  transition: width 0.5s ease;
  transition-delay: 0.5s;
}
.entrance-animation.active
{
  width: 100%;
}
.entrance-animation.active::before
{
  width: 0%;
}
<p class="entrance-animation">
  Hello
</p>
<p class = "entrance-animation">
  Here we are
</p>

Answer ā„–3

To achieve a sliding effect on an element, you can implement CSS3 transitions or animations.

If you are unsure about browser support, you can check it at http://caniuse.com/.

Here are two simple examples to demonstrate how it can be done:

Using CSS Transition (on hover)

Demo One

Relevant Code

.wrapper:hover #slide {
    transition: 1s;
    left: 0;
}

In this example, the position of an element transitions from left: -100px; to 0; over a duration of 1 second. Alternatively, you can also use transform: translate(); for moving elements.

Utilizing CSS Animation

Demo Two

#slide {
    position: absolute;
    left: -100px;
    width: 100px;
    height: 100px;
    background: blue;
    -webkit-animation: slide 0.5s forwards;
    -webkit-animation-delay: 2s;
    animation: slide 0.5s forwards;
    animation-delay: 2s;
}

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

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

This example is similar to Demo One but in this case, the animation begins after a 2-second delay. Moreover, by setting animation-fill-mode to forwards, the end state of the animation is maintained, thereby keeping the div visible once the animation concludes.

As demonstrated, these two examples illustrate different ways to achieve the sliding effect using CSS.

EDIT: For more in-depth information on CSS Animations and Transitions, refer to the following resources:

Animations

https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations

Transitions

https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions

I trust this explanation has been beneficial.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

CSS3 columns causing <li>s to be cropped

I'm attempting to implement css3 columns with a list (<li>), but I'm running into some issues getting it to function properly. I have wrapped the <ul> in a div like this: .ul-container { -moz-column-width: 310px; -moz-column-gap ...

Combining multiple PNG images onto a base image in PHP

I need assistance in merging 24 images with single dashes highlighted into a base circle image using PHP GD, JS or CSS. All images are in PNG format. Your help would be greatly appreciated. ...

What are the steps needed to establish a distinct data scope in AngularJS along with the application of filters?

Iā€™m currently practicing my skills in AngularJS and I have been experimenting with creating reusable components. At this stage, I have successfully created a component using the directive method. However, I now have some doubts that I need clarification ...

Display the current time and continuously update it in real-time on the DOM using React

Incorporating a live clock feature into my app is important to me. I want the time to update automatically, without requiring the user to manually refresh the page. My goal is to have a clock display the time, for example 11:59, and then transition to 12: ...

When using @testing-library/react (rtl), the 'waitFor' function achieves success even without the need for the 'await' keyword

waitFor() is causing my test to fail while waitFor() (without await) makes it pass. The official documentation states: Async methods return a Promise, so you must always use await or .then(done) when calling them. (https://testing-library.com/docs/guide ...

After refreshing in FireFox, the "disabled" attribute of the button fails to function

On my webpage, there are 2 buttons - one enabled by default and the other disabled. When I click on an enabled button, their states switch - the enabled button becomes disabled and vice versa. This functionality works perfectly in Chrome, Edge, and IE11, b ...

Guide to using Ajax to load a partial in Ruby on Rails

Whenever a search is triggered, I have a partial that needs to be loaded. This partial can take a significant amount of time to load, so I would prefer it to be loaded via Ajax after the page has fully loaded to avoid potential timeouts. Currently, my app ...

The Challenge with jQuery Nano Scroll

I recently added the jQuery Nano Scroll plugin to my HTML page. However, I am facing an issue where the scrollpane is not visible. When I inspect the div using Chrome, the scrollpane appears. Any suggestions on how to resolve this? Here's a snippet ...

What is the best way to exclude a particular character from a text element utilizing jquery?

Looking to extract the numerical value from a div containing: <div class="balance"...>$500.48</div> The goal is to retrieve 500.48 as a number, not a string. One approach is to use alert($(".balance").text()) to verify that the content is ret ...

What is the best way to add a right-hand side navigation bar without blocking the scrollbar from view?

Take a look at this webpage: I am designing a website that includes a header, a footer, and a central container with left and right navigation bars surrounding a content area. However, I want the scrollbar for the content to appear on the right side of th ...

"Ensure that all necessary fonts and assets are included in the development of your Vue component

At the moment, I am utilizing vue-cli-service build --target lib --name myLib [entry] to compile Vue into a component library for integration into other projects. Nevertheless, it only produces four files which are: dist/myLib.umd.min.js dist/myLib.umd. ...

Including a hyperlink in VUE Bootstrap for seamless user navigation

Why does this always drive me crazy? I'm determined to include an external link () and an image(enter image description here) on my portfolio page within the title of the project. main.js { id: 18, url: 'single-portfolio. ...

How can we create a two-dimensional image with random dimensions using Math.random?

I am struggling to create a variety of flowers with different sizes from an Array. The issue I'm facing is that every time I click to add a new flower, it changes the size of all existing flowers as well. What I would like is for each added flower to ...

Enhance the functionality of jqGrid by customizing key bindings for arrow and tab keys

In order to enhance my jqGrid functionality, I am seeking to implement the ability for users to press different keys for specific actions. For example, pressing Enter should save data (which is currently working fine), while pressing the left arrow key sho ...

Get the content from a webpage, find and calculate the total count of div elements with a specific class, and display that number

Greetings everyone, I've run into a bit of a roadblock. My goal is to create a basic script that can count the number of servers currently running on this map by scraping the webpage, calculating the divs with the class ".row ark_srv1", and then displ ...

The self-made <Tab/> element is not functioning properly with the ".Mui-selected" class

I have customized a <Tab/> element and I want to change its selected color using Sandbox demo code export const Tab = styled(MuiTab)({ "&.Mui-selected": { color: "red" } }); However, I've noticed that: 1. Apply ...

In Chrome, there is a single pixel missing below the <dl> element

While my website's basic list looks great on Firefox and IE, there seems to be one missing pixel line in Chrome. Check out this JsFiddle link shared by Jared in the comments for reference. If you're not seeing the missing line, try adjusting th ...

Recording Node pathways that begin with the hash symbol #

How can I configure my Node/Express routing to intercept a route like /#/about and send it to /about Is there a way for node to handle routes that start with "/#"? It appears to only cut off at the hash mark. ...

How to use jQuery to extract a particular text from an anchor tag

If I want to choose a specific anchor text and make changes to it, I can do so by targeting anchors with a certain href attribute. For example, on a page with multiple unordered lists, each containing different links: <ul> <li><a href="v ...

What is the best way to merge values in an array based on their keys?

Here is a sample of the data I have: data = [ [ {"name":"cpumhz","data":[[1433856538,0],[1433856598,0]]}, {"name":"mem","data":[[1433856538,13660],[1433856598,13660]]} ], [ {"name":"cpumhz","data":[[1433856538,0],[1433856598,0]]}, {" ...