I have a div with adding a class by condition
<div
className={`${
showLinks ? "links-container show-container" : "links-container"
}`}
>
And some styles
.links-container {
height: 0;
overflow: hidden;
transition: all 0.3s linear;
}
.show-container {
height: 10rem;
}
So when the component is render/rerender, a smooth div extension animation is triggered thanks to my transition style. How it works? Is this css or react rules?
Related
I trying animate a component when rendering and unmount it in React, but unsuccessfully.
Component to animate
One of the ways I've tried was create a state (fade) with the class of animation property, when rendering, the class is fadeIn and on will unmount the class is fadeOut
const handlePokemonDetails = async () => {
if (pokemonDetails === true){
setFade(styles.fadeOut)
await timeout(500)
}
else{
setFade(styles.fadeIn)
}
setPokemonDetails(!pokemonDetails)
}
...
<div className={pokemonDetails ? styles.pokemonDetails + " " + fade : ""}></div>
SASS code:
.pokemonDetails
position: absolute
top: 0
z-index: 3
display: flex
width: 35vmin
height: 39.5vmin
flex-direction: column
background-color: rgba(210, 210, 210, 0.85)
border-radius: 10px
#keyframes fade
0%
height: 0vmin
100%
height: 39.5vmin
.fadeIn
animation: fade 0.5s normal
.fadeOut
animation: fade 0.5s reverse
But, when I change state to other class, the component don't apply this new class animation style. Does anyone know how I can fix this or another way to do it?
Good question. I just finished writing hook for React that helps with that
look at https://github.com/perymimon/React-Anime-Manager
Just publish ver2-alpha so the documentation is still lake.
import {useAnimeManager,ADDED,REMOVED} from "#perymimon/react-anime-manager"
const phase2class = {
[ADDED]: "fadeIn",
[REMOVED]: "fadeOut",
}
function Pokemons({pokemones}){
const pokemonesStates = useAnimeManager(pokemones);
return (
<pokemones>
{ pokemonesStates.map(state =>(
<div className={phase2class[state.phase] } onAnimationEnd={state.done}/>
)
)}
</pokemones>
)
}
This is the exact use case for react-transition-group.
Wrap your component inside <CSSTransition>
function App() {
const [inProp, setInProp] = useState(false);
return (
<div>
<CSSTransition in={inProp} timeout={200} classNames="my-node">
<div>
{"I'll receive my-node-* classes"}
</div>
</CSSTransition>
<button type="button" onClick={() => setInProp(true)}>
Click to Enter
</button>
</div>
);
}
Then add CSS to your classes. If you set className of CSSTransition to my-node, you will have 4 classes to style:
.my-node-enter {
opacity: 0;
}
.my-node-enter-active {
opacity: 1;
transition: opacity 200ms;
}
.my-node-exit {
opacity: 1;
}
.my-node-exit-active {
opacity: 0;
transition: opacity 200ms;
}
I have this scss code in my vue app. I'm trying to make a smooth transition from left for a menu when the isVisible property is set to true but I'm not able to apply the transition I've defined and the menu will instantly appear.
I've done a reserach here on SO and I've found some interesting questions but all of them are using jQuery and css animation so they are not really useful.
I'm not a CSS master, any suggestion about?
HTML
<div class="col-12 settings p-3 position-fixed" :class="{ 'show': isVisible }" ref="settings" v-if="isVisible">
<h4>Settings</h4>
</div>
CSS
.settings {
top: 0;
width: 50%;
height: 100vh;
background-color: white;
transform: translateX(-100%);
transition: transform 0.5s ease;
&.show {
transform: translateX(0);
transition: transform 0.5s ease;
}
}
This is done with <transition>
Here an example:
<transition name="slide">
<div class="col-12 settings p-3 position-fixed" class="settings" v-if="isVisible">
<h4>Settings</h4>
</div>
</transition>
CSS class
.slide-enter-active, .slide-leave-active {
transition: transform .5s;
}
.slide-enter, .slide-leave-to {
transform: translateX(-200px);
}
.settings {
top: 0;
width: 50%;
height: 100vh;
background-color: white;
}
Its really not that hard
Take a look: https://v2.vuejs.org/v2/guide/transitions.html
I believe the issue is that, because you are using v-if, the element is only being rendered when the condition isVisible === True. This means that it is being rendered with the conditional 'show' class already applied, therefore no transition.
You could use the v-show directive instead of v-if, this makes the element hidden but rendered until the condition is true. (more info here).
<div
class="col-12 settings p-3 position-fixed"
:class="{ 'show': isVisible }"
ref="settings"
v-show="isVisible">
<h4>Settings</h4>
</div>
If you want to do more with transitions, I suggest looking up vue-transitions - documentation here - this allows you to assign css to the element during its rendering states, i.e. what styles apply as it enters and when it leaves.
See the other answer here for an example of how to do this with vue transition.
I have a div that i want to use a background color with a transition and that transition should be applied when the background color is leaving as well.
I'm maintaining a state to decide when to use the background color and when to remove the background color. I want this background color to enter and leave smoothly. How can i do this in css? right now the background color just comes and goes without any transition effects.
My code
<div className='current_code_div'>
<div style={{backgroundColor: setInviteCodeStatus === 'success' ? '#b4c067':'transparent'}}>
</div>
</div>
CSS
.current_code_div {
width: auto;
display: table;
overflow: hidden;
-webkit-transition: background-color 1s;
-moz-transition: background-color 1s;
-ms-transition: background-color 1s;
background-color: transparent;
position: relative;
border-radius: 4px;
}
You can just do it by css, please add below css to the div which you want to change background color on mouse enter.
transition:0.5s all;
transition-timing-function:cubic-bezier(.66,.22,.73,1.43);
try this:
<div className='current_code_div'>
<div style={{backgroundColor: setInviteCodeStatus === 'success' ? '#b4c067':'transparent', transition: 'background-color 0.5s ease'}}>
</div>
</div>
I'm trying to get my sidebar to slide in by toggling the state of my Sidebar (going from open: false to open: true) on component load. I'm doing this is an attempt to get a slide-in effect once the user loads the page.
Unfortunately, the way I'm currently doing this, it appears as though the state is changed and the component re-rendered essentially immediately, preventing the slide-in effect from happening. Here's my code:
export default class Sidebar extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
}
componentDidMount() {
this.setState({open: !this.state.open})
}
handleToggle = () => this.setState({open: !this.state.open});
render() {
return (
<div>
<Drawer width={'25%'} open={this.state.open}>
<AppBar title="Wealth Management" onLeftIconButtonClick={this.handleToggle}/>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
</div>
);
}
}
How do you get this to work? Am I updating on the wrong lifecycle method?
It is called CSS transition.
You could have a look at this medium post or check the MDN documentation.
We use a sidebar that slide open or closed based on user settings, the trick is to set a negative margin on the base css-class "sidebar" in this case.
Then add/remove the toggle class (on render or button event). That is all that is required to get a smoth animation on load
css-classes:
.sidebar {
z-index: 1000;
position: fixed;
left: 200px;
top: 0px;
bottom: 0px;
width: 250px;
margin-left: -250px;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.sidebarToggled {
width: 65px;
}
Is there a way to animate display:none to display:block using CSS so that the hidden div slides down instead of abruptly appearing, or should I go about this a different way?
$(document).ready(function() {
$('#box').click(function() {
$(this).find(".hidden").toggleClass('open');
});
});
#box {
height:auto;
background:#000;
color:#fff;
cursor:pointer;
}
.hidden {
height:200px;
display:none;
}
.hidden.open {
display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="box">
Initial Content
<div class="hidden">
This is hidden content
</div>
</div>
And a JSFiddle
Yes, there is a way:
http://jsfiddle.net/6C42Q/12/
By using CSS3 transitions, and manipulate height, rather than display property:
.hidden {
height: 0px;
-webkit-transition: height 0.5s linear;
-moz-transition: height 0.5s linear;
-ms-transition: height 0.5s linear;
-o-transition: height 0.5s linear;
transition: height 0.5s linear;
}
.hidden.open {
height: 200px;
-webkit-transition: height 0.5s linear;
-moz-transition: height 0.5s linear;
-ms-transition: height 0.5s linear;
-o-transition: height 0.5s linear;
transition: height 0.5s linear;
}
More here: Slide down div on click Pure CSS?
Since you're already using jQuery, the simplest thing is just to use slideDown(). http://api.jquery.com/slidedown/
There's also slideToggle().
Then you don't need to manually do all the browser-specific transition css.
I like the idea of CSS transitions, but it's still very jumpy. Sometimes the max-height has to be set to a very high number because of dynamic content which renders the transition useless as it's very jumpy. So, I went back to jQuery, but it had its own faults. inline elements are jumpy.
I found this to work for me:
$(this).find('.p').stop().css('display','block').hide().slideDown();
The stop stops all previous transitions.
The css makes sure it's treated as a block element even if it's not.
The hide hides that element, but jquery will remember it as a block element.
and finally the slideDown shows the element by sliding it down.
What about
$("#yourdiv").animate({height: 'toggle'});
Toggle will switch your div on/off, and the animate should make it appear from below. In this scenario, you don't need the specific CSS to "hide" it.
We can use visibility: hidden to visibility: visible instead of display: none to display: block property.
See this example:
function toggleSlide () {
const div = document.querySelector('div')
if (div.classList.contains('open')) {
div.classList.remove('open')
} else {
div.classList.add('open')
}
}
div {
visibility: hidden;
transition: visibility .5s, max-height .5s;
max-height: 0;
overflow: hidden;
/* additional style */
background: grey;
color: white;
padding: 0px 12px;
margin-bottom: 8px;
}
div.open {
visibility: visible;
/* Set max-height to something bigger than the box could ever be */
max-height: 100px;
}
<div>
<p>First paragraph</p>
<p>Second paragraph</p>
</div>
<button
onclick="toggleSlide()"
>
toggle slide
</button>
I did this workaround for the navigation header in my React site.
This is the regular visible css class
.article-header {
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
}
This is the class that is attached to the div (when scrolled in my case)
.hidden {
top: -50px !important;
transition: top 0.5s ease-in-out;
}
You can use also
$('#youDiv').slideDown('fast');
or you can tell that the active div goes up then the called one goes down
$('.yourclick').click(function(e) {
var gett = $(this).(ID);
$('.youractiveDiv').slideUp('fast', function(){
$('.'+gett).slideDown(300);
});
});
Something like that.