I have the following react component
import React from "react"
import styled from "styled-components"
import { moveInLeft } from '../../styles/Animations'
const StyledHeadingOne = styled.h1`
font-size: 6rem;
text-transform: uppercase;
color: #fff;
font-weight: 300;
letter-spacing: 0.5rem;
animation: ${moveInLeft} 1s ease-in-out .3s both;
`
export default function HeadingOne({ children }) {
return <StyledHeadingOne>{children}</StyledHeadingOne>
}
I add my animation moveInLeft which I import from my file:
import { keyframes} from "styled-components"
export const moveInLeft = keyframes`
#keyframes moveInLeft {
0% {
opacity: 0;
transform: translateX(-10rem);
}
100% {
opacity: 1;
transform: translate(0);
}
}
`
But for some reason the animation does not apply. Can anyone figure out why?
I believe you need to remove the #keyframes from your animation as you are already using the styled components keyframe helper.
const moveInLeft = keyframes`
0% {
opacity: 0;
transform: translateX(-10rem);
}
100% {
opacity: 1;
transform: translate(0);
}
`
https://codepen.io/A-G/pen/mdVoxPo
Related
I am trying to create an animation to a div with fixed position. basically I want that when 5 seconds pass a class is added to this div and an animation is made, but for some reason, it is not happening.
What am I doing wrong?
import { useRef, useEffect } from "react";
export default function Modal() {
const modal = useRef(null);
useEffect(() => {
setTimeout(() => {
modal.current.classList.add("modalShow");
}, 5000);
}, []);
return <div id="modal" ref={modal} className="modalContainer "></div>;
}
.modalContainer {
position: fixed;
height: 100%;
width: 100%;
background: red;
animation: all 5s ease-out;
transform: translateY(100%);
}
.modalShow {
transform: translateY(0%);
}
.modalHide {
transform: translateY(100%);
}
this is my live code:
Live Code
thanks!
You are not using #keyframes.
Change:
animation: all 5s ease-out;
to:
transition: all 5s ease-out;
It is necessary that when the button is pressed, there is an animation of the appearance and hiding of the text. I wrote the following code, but when the page renders, the text hide animation is triggered.
Can I turn off the animation that fires when the page is rendered? Sample code below.
import React, { useState } from "react";
import "./styles.css";
export default function App() {
let [vision, setVision] = useState(true);
let hangler = () => {
setVision(!vision);
};
return (
<div className="App">
<h1 className={vision ? "Text hidden" : "Text shown"}>Hello World</h1>
<button onClick={hangler}>click</button>
</div>
);
}
Css:
.App {
font-family: sans-serif;
text-align: center;
}
.Text {
color: blue;
}
.hidden {
animation: fadeOut ease 1.5s;
animation-fill-mode: forwards;
}
.shown {
animation: fadeIn ease 1.5s;
animation-fill-mode: forwards;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
visibility: hidden;
}
}
This code is at this link
Your classes are inverted, it should be vision ? "Text shown" : "Text hidden".
This will still animate the header to fade in. If it's ok then you are done.
However, if you don't want the initial animation. You can set animation-duration: 0s; to short-circuit it and remove the property after the load but this is not elegant.
For something that simple I would use transitions instead.
.hidden {
opacity: 0;
visibility: hidden;
transition: opacity 1.5s, visibility 1.5s;
}
.shown {
opacity: 1;
visibility: visible;
transition: opacity 1.5s, visibility 1.5s;
}
I am passing a open prop to styled component to create animations for the hamburger icon.
This is the code
const StyledBurger = styled.button`
display: flex;
flex-direction: column;
justify-content: center;
border: 0;
background-color: ${colors.cobaltBlue};
border-radius: 2.7px;
cursor: pointer;
div {
width: 27px;
height: 3px;
margin: 1.5px;
transition: all 0.2s linear;
border-radius: 1.4px;
background-color: ${colors.white};
:first-child {
${({ open }) => open && firstOpenAnimation};
}
:nth-child(2) {
opacity: ${({ open }) => (open ? '0' : '1')};
}
:nth-child(3) {
${({ open }) => open && seconOpenAnimation}
}
}
`;
const firstOpenKeyframe = keyframes`
50% {
transform: translateY(6px) rotate(0);
}
100% {
transform: translateY(6px) rotate(45deg);
}
`;
const secondOpenKeyframe = keyframes`
50% {
transform: translateY(-6px) rotate(0);
}
100% {
transform: translateY(-6px) rotate(-45deg);
}
`;
const firstCloseKeyFrame = keyframes`
50% {
transform:translateY(0) rotate(-45deg);
}
100% {
transform:translateY(-6px) rotate(-45deg) ;
}
`;
const firstOpenAnimation = css`
animation: 0.3s linear ${firstOpenKeyframe} forwards;
`;
const seconOpenAnimation = css`
animation: 0.3s linear ${secondOpenKeyframe} forwards;
`;
const firstCloseAnimation = css`
animation: 0.3s linear ${firstCloseKeyFrame} forwards;
`;
export default StyledBurger;
Basically what I want is if the menu is not open to reverse the animation that was created after the first click.
I tried doing a conditional render of animation keyframe based on the prop open but what happens is when the page loads it immediately creates the animation of not is opened because it satisfies false.
What can I do to fix this and create the opposite animation when unClicked
Make few corrections and it should all work properly.
use state to toggle open and send it as prop to your styled component
use ternary for animation (not just &&) ${({ open }) => (open ? firstOpenAnimation : firstCloseAnimation)}.
implement missing close second animation
working copy of your code is here
Working code snippet
const StyledBurger = styled.button`
display: flex;
flex-direction: column;
justify-content: center;
border: 0;
background-color: red;
border-radius: 2.7px;
cursor: pointer;
height: 30px;
div {
width: 27px;
height: 3px;
margin: 1.5px;
transition: all 0.2s linear;
border-radius: 1.4px;
background-color: white;
:first-child {
${({ open }) =>
open !== null && (open ? firstOpenAnimation : firstCloseAnimation)}
}
:nth-child(2) {
opacity: ${({ open }) => (open ? "0" : "1")};
}
:nth-child(3) {
${({ open }) =>
open !== null && (open ? seconOpenAnimation : secondCloseAnimation)}
}
}
`;
const firstOpenKeyframe = keyframes`
50% {
transform: translateY(6px) rotate(0);
}
100% {
transform: translateY(6px) rotate(45deg);
}
`;
const secondOpenKeyframe = keyframes`
50% {
transform: translateY(-6px) rotate(0);
}
100% {
transform: translateY(-6px) rotate(-45deg);
}
`;
const firstCloseKeyFrame = keyframes`
50% {
transform:translateY(0) rotate(-45deg);
}
100% {
transform:translateY(0) rotate(0) ;
}
`;
const secondCloseKeyFrame = keyframes`
50% {
transform:translateY(0) rotate(-45deg);
}
100% {
transform:translateY(0) rotate(0) ;
}
`;
const firstOpenAnimation = css`
animation: 0.3s linear ${firstOpenKeyframe} forwards;
`;
const seconOpenAnimation = css`
animation: 0.3s linear ${secondOpenKeyframe} forwards;
`;
const secondCloseAnimation = css`
animation: 0.3s linear ${secondCloseKeyFrame} forwards;
`;
const firstCloseAnimation = css`
animation: 0.3s linear ${firstCloseKeyFrame} forwards;
`;
export default function App() {
const [open, setOpen] = useState(null);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<StyledBurger onClick={() => setOpen(prev => !prev)} open={open}>
<div />
<div />
<div />
</StyledBurger>
</div>
);
}
I'm trying to recreate the slider on Gatsby's website but using the styled components library instead of the emotion library they used. The issue is the animation doesn't do anything and the list of strings I pass into the component get concatenated together.
Gatsbyjs.org
Code for their slider component
My slider.js:
import React from "react"
import styled, { keyframes } from "styled-components"
const topToBottom = keyframes`
0%: {
opacity: 0;
}
6%: {
opacity: 0;
transform: translateY(-30px);
}
10%: {
opacity: 1;
transform: translateY(0px);
}
25%: {
opacity: 1;
transform: translateY(0px);
}
29%: {
opacity: 0;
transform: translateY(30px);
}
80%: {
opacity: 0;
}
100%: {
opacity: 0;
}
`;
const SliderDiv = styled.div`
display: inline;
& span: {
animation: ${topToBottom} 10s linear infinite 0s;
opacity: 0;
position: absolute;
:nth-child(2) {
animation-delay: 2.5s;
}
:nth-child(3) {
animation-delay: 5s;
}
:nth-child(4) {
animation-delay: 7.5s;
}
}
`;
const Slider = ({ items, color }) => (
<SliderDiv>
{items.map(item => (
<span key={item} css={{ color }}>
{item}
</span>
))}
</SliderDiv>
)
export default Slider
Result:
Your code works as expected if you remove the : from the css code inside the Styled Component:
span {
// not
span : {
and
0% {
// not
0% : {
I've tested the code in a Codesandbox
import React from "react";
import styled, { keyframes } from "styled-components";
const topToBottom = keyframes`
0% {
opacity: 0;
}
6% {
opacity: 0;
transform: translateY(-30px);
}
10% {
opacity: 1;
transform: translateY(0px);
}
25% {
opacity: 1;
transform: translateY(0px);
}
29% {
opacity: 0;
transform: translateY(30px);
}
80% {
opacity: 0;
}
100% {
opacity: 0;
}
`;
const SliderDiv = styled.div`
display: inline;
& span {
animation: ${topToBottom} 10s linear infinite 0s;
opacity: 0;
position: absolute;
:nth-child(2) {
animation-delay: 2.5s;
}
:nth-child(3) {
animation-delay: 5s;
}
:nth-child(4) {
animation-delay: 7.5s;
}
}
`;
const Slider = ({ items, color }) => (
<SliderDiv>
{items.map(item => (
<span key={item} css={{ color }}>
{item}
</span>
))}
</SliderDiv>
);
export default Slider;
I know I looked for this errors a couple of times :)
To make it more clear, in styled-components you write css, not css-in-js
Hope it helps!
I'm trying to draw an SVG logo using Keyframes. It works fine stand alone when I open the SVG file by itself in the browser, but it doesn't work when I try to use it in my React project.
For mu react project, I am using image-webpack-loader to load SVG images and I have made the following alterations to webpack config file:
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
hash: 'sha512',
digest: 'hex',
name: '[hash].[ext]',
}
},
{
loader:'image-webpack-loader',
options:{
bypassOnDebug:true,
},
}
],
}
Here's my React JS file code:
import React from 'react';
import '../stylesheets/Atom.css'
import Atom from '../Assets/images/atom.svg';
const AtomSpinner = props => {
return (
<div className='atomWrapper'>
<img className='atom' src={Atom}/>
</div>
);
};
export default AtomSpinner;
This is the CSS that I am using for this React Component as well as the SVG file. Even if I am putting all styles for the SVG and React in the same stylesheet, the SVG animation works fine when I use it in the browser. Here's the stylesheet:
.atomWrapper{
text-align: center;
}
.atom{
position:absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
max-height:256px ;
max-width: 256px;
}
svg {
max-width: 256px;
max-height: 256px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
path {
fill-opacity:0;
stroke: #000;
stroke-width: 3;
stroke-dasharray: 351.0306396484375em;
stroke-dashoffset:351em ;
-webkit-animation-name: draw;
-webkit-animation-duration: 10s;
-webkit-animation-fill-mode: forwards;
-webkit-animation-iteration-count: 2;
-webkit-animation-timing-function: ease;
}
circle {
fill-opacity:0;
stroke: #000;
stroke-width: 3;
stroke-dasharray: 304em;
stroke-dashoffset:303.5em ;
-webkit-animation-name: draw;
-webkit-animation-duration: 3s;
-webkit-animation-fill-mode: forwards;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
}
#-webkit-keyframes draw {
to {
stroke-dashoffset: 0.8;
}
to{
fill-opacity: 1;
}
}
#keyframes draw {
to {
stroke-dashoffset: 0.8;
}
to{
fill-opacity: 1;
}
}
Here's a jsFiddle with the SVG and styles in it:
https://jsfiddle.net/nxxu1Lob/1/