Start an animation after page loads on react - javascript

I am trying to make an element animate after the page loads on react, how do I do that please.
I'm new to react so I don't really know how to target the class and animation, but here is the
HTML and CSS
<div className="dangle" >
</div>
.dangle {
animation: swing ease-out 5s forwards;
float: left;
background-color: red;
}
link to codepen sample
Please I need the solution in react please

First, use "useState" to decide whether to apply animation. ( changing the state of the page )
Second, use "useEffect" to make the desired action run after the page loads. If you pass an empty array as the second parameter, the callback is executed only once after the page is loaded.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
</head>
<style>
body {background-color: powderblue; display:grid; place-items: center;}
#keyframes swing {
0% { transform: rotate(30deg); }
100% { transform: rotate(-30deg); }
}
.dangle {
animation: swing ease-out 5s forwards;
float: left;
background-color: red;
}
</style>
<body>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {animate: false};
}
componentDidMount(){
this.setState({animate: true})
}
render() {
return <div className={this.state.animate ? "dangle" : ""}>Hello</div>;
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
</script>
</body>
</html>

You can add a load event:
window.addEventListener('load', (event) => {
for (let dangle of document.querySelectorAll(".dangle")) dangle.classList.add("loaded");
});
and enhance the CSS to be executed, make sure the CSS is to be executed only when it's loaded:
.dangle.loaded {
animation: swing ease-out 5s forwards;
background-color: red;
height: 10rem;
width: 10rem;
}
and let's fix the HTML as well:
<div class="dangle" >
foo
</div>

Related

Safari: CSS animation doesn't start second time when transitioning from display: none to display: block

I have this simple animation triggered when transitioning from display: none to display: block.
It works perfect on Chrome but on Safari it is triggered only for first time, when I hide element and then show it again second time, it is not working.
.child1 {
display: none;
}
.child2 {
display: block;
}
.visibility .child1 {
display: block;
}
.visibility .child2 {
display: none;
}
#keyframes myAnimation {
0% { transform: scale(0.5); }
}
.animated {
animation: myAnimation 0.4s ease-out;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="testdiv" class="visibility">
<div class="child1">Hello</div>
<div class="child2 animated">Bye</div>
</div>
<script>
const elem = document.getElementById("testdiv");
elem.addEventListener("click", () => {
if (!elem.classList.length) {
elem.classList.add("visibility");
} else {
elem.classList.remove("visibility")
}
})
</script>
</body>
</html>
Here's the trick: give the animation a very small delay, let's say 0.0001s and there you go.
.animated {
animation: myAnimation 0.4s ease-out 0.0001s;
}
As you're using CSS animation with display - a non-animatable property, different browsers will treat this in different ways and somehow unpredictable.
The reason it works when we put a small delay is that before the text slide from right to left, the text should not appear on the screen, hence, display: none. However, as I said, display is not animatable, so the text would appear immediately leading to no transition visible, what we do is to give it some time to disappear.
Anyway, this is still a trick, when you switch to another tab on Safari then get back, the animation will not run. It's better not to use display for animation.

Smooth transition to make element appear

When I click on the button, I would like the arrow to appear by sliding out smoothly. I'm currently doing this by adding the 'show' class if the arrow should be shown. I've tried display: none; -> display: inline-block I've tried width:0 -> width: 100%.
This code makes the arrow appear/disappear onclick, but without a smooth transition.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
span {
-webkit-transition: all .5s;
-moz-transition: all .5s;
transition: all .5s;
width: 0;
overflow: hidden;
max-width: 0;
display:none;
}
.show {
width: 100%;
display: inline;
}
</style>
<script>
function toggleArrow(elemId) {
let elem = document.getElementById(elemId);
if (elem.classList.contains('show')) {
elem.classList.remove('show');
} else {
elem.classList.add('show');
}
}
</script>
</head>
<body>
<div> Here's the button:
<button onClick="toggleArrow('title-arrow')">my button<span id="title-arrow" > ↑</span></button>
</div>
</body>
</html>
Did it works right?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
button{
position:relative;
padding-right:20px;
overflow: hidden
}
span {
-webkit-transition: all .5s;
-moz-transition: all .5s;
transition: all .5s;
overflow: hidden;
top:50px;
position: absolute;
right:5px;
}
.show {
top:0;
}
</style>
<script>
function toggleArrow(elemId) {
let elem = document.getElementById(elemId);
if (elem.classList.contains('show')) {
elem.classList.remove('show');
} else {
elem.classList.add('show');
}
}
</script>
</head>
<body>
<div> Here's the button:
<button onClick="toggleArrow('title-arrow')">my button<span id="title-arrow" > ↑</span></button>
</div>
</body>
</html>
If you want to make it appear, you can use
button.addEventListener("click", function() {
element.style.opacity = 1;
});
#element {
opacity: 0;
transition: 1s;
}
then when you click the button, the arrow element fades in in one second.

Can i use web components in AMP pages

I am trying to use web components in AMP page with amp-script but it's not working.
I am trying to add following code in index.html
<amp-script width="200" height="50" script="app-render">
<div id="app">loading...</div>
</amp-script>
<script id="app-render" type="text/plain" target="amp-script">
const app = document.getElementById('app');
app.innerHTML = <amp-news-container id="amp-news-container"></amp-news-container>;
</script>
But not working.
I also tried to add custom component into page but that creates error as custom component not allowed.
Is there any way i can use web components in AMP pages? no content or example found to user web components in AMP.
Adding whole index page -
<!DOCTYPE html>
<html ⚡️ lang="en" dir="ltl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<title>AMP Web Components</title>
<link rel="canonical" href="https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup/">
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "NewsArticle",
"headline": "Open-source framework for publishing content",
"datePublished": "2015-10-07T12:02:41Z",
"image": [
"logo.jpg"
]
}
</script>
<style amp-boilerplate>
body {
-webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
animation: -amp-start 8s steps(1, end) 0s 1 normal both
}
#-webkit-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-moz-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-ms-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-o-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
</style><noscript>
<style amp-boilerplate>
body {
-webkit-animation: none;
-moz-animation: none;
-ms-animation: none;
animation: none
}
</style>
</noscript>
<meta name="amp-script-src" content="sha384-N4a96F4jCQXTuaWhxfKGHDf9ZQmsqohVQd4GoJxNFVi1PznNK-wtSZXZuJTCettD" />
<script custom-element="amp-script" src="https://cdn.ampproject.org/v0/amp-script-0.1.js" async=""></script>
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght#500;700&display=swap" rel="stylesheet">
</head>
<body class="news">
<amp-script width="200" height="50" script="app-render">
<div id="app">loading...</div>
</amp-script>
<script id="app-render" type="text/plain" target="amp-script">
const app = document.getElementById('app');
app.innerHTML = <amp-news-container id="amp-news-container"></amp-news-container>;
</script>
</body>
</html>
Here is my - amp-news-container.js
const ampNewsContainer = document.createElement('ampNewsContainer');
ampNewsContainer.innerHTML = `
<style>
</style>
<div class="amp-news-container">
<amp-news-header class="amp-news-header"></amp-news-header>
</div>
`;
class AmpNewsContainer extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(ampNewsContainer.cloneNode(true));
}
}
window.customElements.define('amp-news-container', AmpNewsContainer);
and
const ampNewsHeader = document.createElement('ampNewsHeader');
ampNewsHeader.innerHTML = `
<style>
</style>
<div class="amp-news-header">
<h1>Page header</h1>
</div>
`;
class AmpNewsHeader extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(ampNewsHeader.cloneNode(true));
}
}
window.customElements.define('amp-news-container', AmpNewsHeader);
But i am facing error while i am trying add/bind amp-news-container to body or div tag.
I can't use custom component directly in body as follow, it's giving AMP validation error as custom component not allowed.
The way i use web component in normal projects, add custom container component in index.html and import other sub models into same index page but no similar way found to use them in AMP.
Example of trying custom component in body -
<body class="afc-champions-league-news">
<div id="amp-news-container">
<amp-news-container id="amp-news-container"></amp-news-container>
</div>
<amp-script type="module" src="js/modules/news/components/amp-news-header.js" width="300" height="100">
</amp-script>
<amp-script type="module" src="js/modules/news/components/amp-news-container.js" width="300" height="100">
</amp-script> -->
</body>
no Clue if is there any way i can have these two integrated together.

How do i make the image appear at the same time as the next and to be on the rightt

The loading screen is loading to high up it needs to be under the menu section of the page to make it look more realistic, and how do I make the image appear at the same time as the text cause the image after the loading always comes up first
HTML
<!DOCTYPE HTML>
<HTML lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/CSS" href="dropdownmenu.css">
<link rel="stylesheet" type="text/CSS" href="rainbowheading.css">
<link rel="stylesheet" type="text/CSS" href="loadingcss.css">
<script src="loading.js"></script>
<title> North Macedonia </title>
<div class="container">
<h1 class="rainbow"> The pearl of the Balkans: Macedonia </h1>
<div class="navbar">
Home
Macedonian Dispora
Cities
<div class="dropdown">
<button class="dropbtn">History
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content">
Ancient History
Ottoman Period
Yugoslav Period
Modern History
</div>
</div>
</div>
</head>
<body onload="myFunction()" style="margin:0;">
<div id="loader"></div>
<div style="display:none;" id="myDiv" class="animate-bottom">
<h2>Welcome to my website about Macedonia</h2>
<p>x</p>
</div>
<div style="display:none;" id="MyDi" class="animate-bottom">
<img src="./images/ohridindex.jpg" class="center">
</body>
CSS (For loading) This is the main CSS document
/* Center the loader */
#loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
#-webkit-keyframes animatebottom {
from { bottom:-100px; opacity:0 }
to { bottom:0px; opacity:1 }
}
#keyframes animatebottom {
from{ bottom:-100px; opacity:0 }
to{ bottom:0; opacity:1 }
}
#myDiv {
display: none;
text-align: center;
}
#myDi {
display: Float;
text-align: center;
}
Javascript:
var myVar;
function myFunction() {
myVar = setTimeout(showPage, 3000);
}
function showPage() {
document.getElementById("loader").style.display = "none";
document.getElementById("myDiv").style.display = "block";
document.getElementById("myDi").style.display = "block";
}
There are a number of approaches you can take. The current code says explicitly: "put #loader 200px below the top of the document" because of the top and position css properties. You could increase the top number to move it further down.
If you wanted to guarantee the loader is below the menu bar, even if the menu bar changes size, you could put it inside a relatively positioned div and remove the top property, which will make it display above the other content, but positioned relatively to the wrapper element (read more about positioning).
<!-- the navbar goes here -->
<div id="loader-wrapper">
<div id="loader" />
<div>
#loader-wrapper {
position: relative;
}
Another note about your code - make sure all your visible content is wrapped in your <body>. Right now your navbar is inside the <head>, which isn't valid.
#loader {
position: absolute;
left: 50%;
top: 200px;
transform: translate(-50%, 0);
}
Loader icon is loading in center of screen.
I see the HTML code. But The div in header should be placed in body tag.

Triggering CSS animation with JavaScript

I have this html
<!DOCTYPE html>
<html>
<head>
<title></title>
<link href="StyleSheet.css" rel="stylesheet" />
<link href="animation.css" rel="stylesheet" />
<meta charset="utf-8" />
</head>
<body>
<div class="box box-anim-start box-anim-end"></div>
<script src="jquery-2.1.4.min.js"></script>
<script src="JavaScript.js"></script>
</body>
</html>
As you can see there are two stylesheets linked to this page.
StyleSheet code
.box {
height: 100px;
width: 100px;
background-color: red;
}
animation code
.box-anim-start {
}
.box-anim-end {
transition-property: transform;
transition-duration: 2s;
transition-delay: 5s;
}
And here's the JavaScript code
var box = $(".box").eq(0);
var sheet = document.styleSheets[1];
var rules = sheet.cssRules || sheet.rules;
var rule0 = rules[0];
rule0.style.transform = "translateX(100px)";
var rule1 = rules[1];
rule1.style.transform = "translateX(0px)";
What I wanted was an animation upon opening this page. And, since the delay is mentioned in css, i thought that would work. But it didn't. Could you explain why?
It's makes a lot more sense to define your CSS animation in your CSS using keyframes, you can then call it in by adding a class to your box once the page has loaded.
So initially remove the .box-anim-start class
<div class="box"></div>
Then define the animation using keyframes:
#keyframes slide {
0%{
transform: translate(0, 0)
}
100% {
transform: translate(100px, 0)
}
}
Then call the animation within .box-anim-start
.box-anim-start {
animation: slide ease-in 2s;
animation-delay: 2s;
}
.box{
transition: 2s ease-in;
}
And finally add the class once the page has loaded using jQuery
$(document).ready(function){
$('.box').addClass('.box-anim-start');
});
The best way is to use the stylesheet.
In Chrome, for instance, your line:
var rules = sheet.cssRules || sheet.rules;
is wrong because rules is null. This happens because you need to change the index to
var sheet = document.styleSheets[0]; // instead of 1 in my case
But consider to put a delay between the two transition.
Instead, if you want simply use the js with your styles you can do:
$(function () {
$('div.box').css('transform', 'translateX(100px)').delay(3000).queue(function (next) {
$(this).css('transform', 'translateX(0px)');
next();
});
});
.box {
height: 100px;
width: 100px;
background-color: red;
}
.box-anim-start {
}
.box-anim-end {
transition-property: transform;
transition-duration: 1s;
transition-delay: 2s;
}
<script src="http://code.jquery.com/jquery-1.11.3.js"></script>
<div class="box box-anim-start box-anim-end"></div>

Categories