CSS Transition on open and close Menu in React - javascript

I have MenuBody component which is showed if state of isOpen is true. I want to add transition when menu is opening and also when is closing. Animation for opening is working but on closing it doesn't work.
This is my code
const [isOpen, setIsOpen] = useState(false);
<button onClick={()=>setIsOpen(!isOpen)}>open menu</button>
{isOpen ? <MenuBody /> : null}
....
const MenuBody = () => {
return (
<div className={styles.menuBody}>
//some content here to display when it's opened
</div>
)}
CSS
#-webkit-keyframes menuBody {
0% { opacity: 0; }
100% { opacity: 1; }
}
#-moz-keyframes menuBody {
0% { opacity: 0; }
100% { opacity: 1; }
}
#-o-keyframes menuBody {
0% { opacity: 0; }
100% { opacity: 1; }
}
#keyframes menuBody {
0% { opacity: 0; }
100% { opacity: 1; }
}
.menuBody {
....
-webkit-animation: menuBody 0.5s ease-in-out;
-moz-animation: menuBody 0.5s ease-in-out;
-o-animation: menuBody 0.5s ease-in-out;
animation: menuBody 0.5s ease-in-out;
}
I would appreciate any kind of help
Thanks

I think that the problem might be in the way how you wrote MenuBody or in isOpen since you didn't provide any code regarding closing I am gonna assume, that maybe it's missing. So I would recommend adding some button into the MenuBody which will be able to change the state of isOpen.
EDIT #1
I would recommend adding and removing a class that says if Modal is open or closed. I would recommend using this method described here: https://erikmartinjordan.com/react-on-disappear-animation

Related

React Transition Group - Does appear prop work with CSSTransition?

I want to run the animation on onLoad.
For this I used the appear prop as described in the docs and set in to true.
But no animation takes place. Does the appear prop not work with the CSSTransition component?
const [showStep, setShowStep] = useState(true);
...
<CSSTransition
in={showStep}
timeout={300}
classNames="fadein"
appear={true}
>
<p>Test</p>
</CSSTransition>
.fadein-enter {
opacity: 0.6;
transform: translateX(10%);
}
.fadein-enter-active {
opacity: 1;
transform: translateX(0);
transition: opacity 300ms, transform 200ms;
}
.fadein-exit {
opacity: 1;
}
.fadein-exit-active {
opacity: 0;
transform: scale(0.9);
transition: opacity 300ms, transform 300ms;
}

Create one CSS animation from 3 separate

I am beginner to animation in CSS and I have exported from desing file CSS animation code for animation like this.
#keyframes first {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes second {
from {
opacity: 1;
}
to {
opacity: 1;
}
}
#keyframes third{
from {
opacity: 1;
}
to {
opacity: 0;
}
}
animation: ${first} 307ms ease-in-out 0ms normal,${second} 2193ms linear 307ms normal,
${third} 503ms ease-in-out 2500ms normal;
However I wonder if it is possible to make it in one animation? If I want to have the same times like in generated version. If so, in what way?

How can I achieve this sequential fade-in effect?

I came across this page https://pepecph.com/ and thought the fade in effect of the pictures were really cool.
I tried to imitate that effect with styled-component to pass each picture's index as a way to separate them when they are all fading in.
-webkit-animation: ${props =>
`fadein ${props.index}s`}; /* Safari, Chrome and Opera > 12.1 */
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
Here is the demo: https://codesandbox.io/s/focused-clarke-eduf1
However it is not quite doing what that page seems to be doing, no matter how I adjust the time of fade-in. On the original page(https://pepecph.com/), every picture is showing up fast and delayed differently for some time. And I inspect the image element of the original page, it has this line of css
transition: top 70ms cubic-bezier(0.25,0.46,0.45,0.94),left 70ms cubic-bezier(0.25,0.46,0.45,0.94),transform 70ms cubic-bezier(0.25,0.46,0.45,0.94),height 150ms cubic-bezier(0.25,0.46,0.45,0.94) 70ms,-webkit-transform 70ms cubic-bezier(0.25,0.46,0.45,0.94)
I am not good at css so I don't know if this has something to do with that visual effect.
I edited your code a little bit, let me explain what I've done:
First we need to start with zero opacity images till those are loaded, we can also add a delay transition based on the index of the image.
<Image
pose={pose}
{...props}
style={{
opacity: this.state.opacity,
transition: "opacity 2s cubic-bezier(0.25,0.46,0.45,0.94)",
transitionDelay: `${props.index * 0.5}s`
}}
/>
We also need to add a setter function to change the opacity state via refs:
toggleOpacity = o => {
this.setState({ opacity: o });
};
The tricky part was to track the images refs, this is how it looks, we also removed all keyframes since those are no longer necessary:
const Gallery = () => {
const [isSelected, setIsSelected] = useState(null);
const refs = {};
let images = [];
for (let i = 0; i < 10; i++) {
refs[i] = useRef(null);
let height = Math.floor(Math.random() * 400 + 400);
let width = Math.floor(Math.random() * 400 + 400);
images.push(
<PicContainer index={i} key={i} selected={isSelected}>
<ZoomImg
src={`https://source.unsplash.com/random/${height}x${width}`}
onLoad={() => {
// Calling ref function
refs[i].current.toggleOpacity(1);
}}
// Setting ref
ref={refs[i]}
index={i}
setIsSelected={setIsSelected}
/>
</PicContainer>
);
}
return (
<Mansory gap={"15em"} minWidth={600}>
{images.map(image => image)}
</Mansory>
);
};
Here is the full example.
Here's an example. The HTML requires a div to be wrapped around the whole of the body content if you want it to fade in all at once. Look for this:
<div class="wrapper fade-in">
There's a lot of stuff you can do with CSS, I've been using it for years and I still learn something new every once in a while.
All the animation commands will appear in your CSS like so:
#keyframes fadeIn
to {
opacity: 1; }
Then your divs are going to have a class that calls the animation (#keyframes):
.fade-in {
animation: fadeIn 1.0s ease forwards;
[other div properties can be included here]
}
The HTML will look like this:
<div class="fade-in">
[content]
</div>
Finally, you'll need to make sure you include the vendor codes to make it compatible with all browsers [which adds a fair amount of code, which is why jQuery can be a better option for this stuff]:
#keyframes fadeIn{
0% {
opacity:0;
}
100% {
opacity:1;
}
}
#-moz-keyframes fadeIn {
0% {
opacity:0;
}
100% {
opacity:1;
}
}
#-webkit-keyframes fadeIn {
0% {
opacity:0;
}
100% {
opacity:1;
}
}
#-o-keyframes fadeIn {
0% {
opacity:0;
}
100% {
opacity:1;
}
}
#-ms-keyframes fadeIn {
0% {
opacity:0;
}
100% {
opacity:1;
}
}
The vendor codes will have to be duplicated again in your div class in the CSS:
.fade-in {
animation: fadeIn ease 5s;
-webkit-animation: fadeIn ease 5s;
-moz-animation: fadeIn ease 5s;
-o-animation: fadeIn ease 5s;
-ms-animation: fadeIn ease 5s;
}

React CSSTransition does not apply classes correctly

I'm working on a carousel application and I have to use the React Transition Group to animate it. For some reason I can't seem to get the classes to apply correctly.
It's a mix of proprietary and open-source code, so if this example isn't enough I'm glad to expand my examples.
React render() calls this:
{this.props.slides.map((slide, index) => (
<CSSTransition
key={this.index}
in={this.appearHome}
appear={true}
timeout={600}
classNames="carouselTransition"
>
<CarouselSlide
key={index}
index={index}
activeIndex={this.state.activeIndex}
slide={slide}
/>
</CSSTransition>
))}
And then the css looks like this:
/* appear on page load */
.carouselTransition-appear {
opacity: 0;
z-index: 1;
}
.carouselTransition-appear.carouselTransition-appear-active {
opacity: 1;
transition: opacity 600ms linear;
}
.carouselTransition-enter {
opacity: 0;
z-index: 1;
}
.carouselTransition-enter.CarouselTransition-enter-active {
opacity: 1;
transition: opacity 300ms linear;
}
.carouselTransition-exit {
opacity: 1;
}
.carouselTransition-exit.carouselTransition-exit-active {
opacity: 0;
transition: opacity 300ms linear;
}
.carouselTransition-exit-done {
opacity: 0;
}
The appear css applies but as I cycle the carousel I can see the enter and exit classes falling off of the divs, never to return. My suspicion is that I'm doing something wrong with the key={index} which I've read is an antipattern, but I'm not sure how to fix it.
Again, if more code is needed, say the word!
It's a tricky thing to work with, as I've heard from pretty much everywhere I turned to for help. They need to work on the documentation and build out some better examples! In any case, the CSS simply had the right things in the wrong places. Specifically, what I was trying to do in the done state needed to be done in the active state, and the stuff I was trying to do in the active state needs to be done in the enter state.
.carouselTransition-appear {
opacity: 1;
}
.carouselTransition-appear.carouselTransition-appear-active {
}
.carouselTransition-enter {
transform: translateX(110%);
}
.carouselTransition-enter.carouselTransition-enter-active {
transition: transform 600ms ease-in-out;
transform: translateX(0);
}
.carouselTransition-enter.carouselTransition-enter-done {
}
.carouselTransition-exit {
transform: translateX(0);
}
.carouselTransition-exit.carouselTransition-exit-active {
transition: transform 600ms ease-in-out;
transform: translateX(-100%);
}
.carouselTransition-exit-done {
left: -10000px;
opacity: 0;
height: 0px;
}

Unset element visibility, change innerHTML, and transisition back

I have an element on my HTML page that I want to give dynamic content, and I want inserted HTML to transition from 0% to 100% opacity.
HTML
<div id="content"></div>
CSS
#content {
opacity: 1;
transition: opacity .5s ease-out;
-moz-transition: opacity .5s ease-out;
-webkit-transition: opacity .5s ease-out;
}
#content.hide {
opacity: 0;
}
JavaScript
function setContent(html) {
var content = document.getElementById("content");
//Set hide class
content.className += " hide";
//Set HTML
content.innerHTML = html;
//Unset hide class
content.className = content.className.replace(/(?:^|\s)hide(?!\S)/g, '');
}
Note that setContent() sets and then unsets the hide class. However, it seems that the browser (Chrome at least) does not invalidate content element until after it return from the function, so the element does not get the chance to transistion. How can I make sure that the animation plays?
EDIT: To be clear, setContent() is called after the DOM is loaded. Imagine an app that clears and repopulates the screen when some action occurs.
Can you be more clear as what the context of this is?
Also where are you calling the function? Is the place where you are calling the function inside a DOM ready function?
In jQuery it would be something like this:
$(document).ready(function(){
//call the function inside here.
});
What about using animations?
#content {
padding-left: 32px;
padding-right: 32px;
animation: fadein 0.5s;
-moz-animation: fadein 0.5s;
-webkit-animation: fadein 0.5s;
}
#keyframes fadein {
from {
opacity:0;
}
to {
opacity:1;
}
}
#-moz-keyframes fadein {
from {
opacity:0;
}
to {
opacity:1;
}
}
#-webkit-keyframes fadein {
from {
opacity:0;
}
to {
opacity:1;
}
}

Categories