I want to smoothly resize a DIV with onClick event. But transition doesn't work. onClick just changes the style without animation.
App.js
import React, { useState } from 'react'
import './App.scss';
function App() {
const [clicked, setClicked] = useState(-1)
return (
<div
className={clicked === -1 ? "app" : "app__clicked"}
onClick={() => setClicked(0)}>
div clicked {clicked}
</div>
);
}
export default App;
App.scss
.app {
background-color: red;
transition: width 3s;
&__clicked {
background-color: blue;
width: 100px;
}
}
I think I'm doing something wrong with SCSS.
As can be seen here, your SASS rules will result in two different css classes which you toggle between when assigning a className prop to your div.
The second class is app__clicked and it has no transition property which is why the transition doesn't work. It also doesn't work because, as indicated in the comments, you don't have an initial width on the div, so there is nothing to transition between. By moving the transition property to the app_clicked class and setting width to 100% in the initial state, you will have a working example.
As an advice when doing transitions manually, use a base class which has the transition property set and then toggle the other state by means of other classes (or inline with style) to make sure that the element always has the transition property set. Like this:
<div className={ `app ${clicked === -1 ? "before" : "after"}`}>
div clicked {clicked}
</div>
or
<div className={ "app" } style={{"width": clicked === -1 ? "100%" : "100px"}}>
div clicked {clicked}
</div>
Finally, you might wanna have a look at react-transition-group where transitions with React components is shown. However, you might think that this brings nothing new to the table and that it is too verbose. But it's good to know about and it might have its use cases.
Here is a sandbox with all of the above examples and an example with the CSSTransition component from react-transition-group: Sandbox
Related
I have a component in react on which touchmove event should be disabled. I have tried the following but it does not work.
parentRef.current.addEventListener("touchMove", e => e.preventDefault(), false)
You can simply use the touch-action property in your CSS file to remove the scroll event from your html body or an element. Add the below code in your code.
touch-action: none;
-ms-touch-action: none;
You can check if this device has innerWidth below certain pixels then set overflow:hidden and height & width to 100vh & 100vw respectively to the parentRef in useEffect
To prevent scrolling using CSS on React rendered components, we can set the overflow CSS property to hidden with JavaScript.
For instance, we write:
import React, { useEffect } from "react";
export default function App() {
useEffect(() => {
document.body.style.overflow = "hidden";
}, []);
return <div>hello world</div>;
}
to set the overflow CSS of the body element to hidden when the component mounts with:
document.body.style.overflow = "hidden";
The useEffect callback only runs when the component mounts since we passed in an empty array as the 2nd argument of useEffect.
I´m havin issues with blocking the whole height of the screen. I made this navbar and want it to look like it´s "floating" on the page, by adding some margin around ist, so it´s not touching the border of the screen.
Using the height: 100% prop won´t work, bc I the margin won´t get attached at the bottom of the screen -> First it goes all the way down the screen, so that I have to scroll down a bit until the margin gets added + the following content does not appear to the right, but underneath the sidebar -> watch the image.
So I basically want this thing to be in a vertical div element for example, so that the next element will be next to the right of the navbar (right now the text "TEST" still is underneath the navbar).
I´m also using TailwindCSS, those are my classes attached to the wrapping div of the navbar:
import SidebarHeader from './sidebarHeader';
import SidebarMenu from './SidebarMenu';
const Sidebar = () => {
return (
<div
style={{ height: '100vh' }}
className=" m-5 rounded-2xl bg-primary w-80 border-l-4 border-primary transition duration-500 pl-5 py-5">
<SidebarHeader />
<SidebarMenu />
</div>
);
};
export default Sidebar;
App code:
import { BrowserRouter } from 'react-router-dom';
import './assets/tailwind.css';
import Sidebar from './page-components/sidebar';
import Header from './page-components/header';
function App() {
return (
<BrowserRouter>
<Sidebar />
<Header />
</BrowserRouter>
);
}
export default App;
// Header code
//const Header = () => {
// return <div>TEST</div>;
//};
//
//export default Header;
I could do a grid layout I guess, but I don´t know if that´s the smartest solution. There must be a way to have smth like a vertical block element or not?
Glad for any help I can get- cheers!
You can use css calc like height: calc(100vh - XXpx) and then you can add margins to it - sum of bottom and top margins must be equal to XXpx you defined earlier.
Or just wrap the sidebar in a parent component with some padding { height: 100vh; padding: XXpx}; display: flex;, with display flex. Child should have a flex-grow property set to 1.
To put something next to the sidebar, both elements should have display: inline-block; vertical-aligh: top in that case the second solution would not work unless you wrapp the sidebar parent + aside content in a wrapper div with display: flex property.
I have a button component that makes use of a theme provided by a context:
Button.js
() => {
const theme = useContext(themeContext); // { primaryColor: "blue" }
return <button className="MyButton" styles={{ backgroundColor: theme.primaryColor }}>Hello</button>
}
Button.styles.scss
.MyButton {
background-color: purple
transition: background-color 0.1s
&:hover {
background-color: green
}
}
Since the background color is now being set by React, the transition effect no longer works. Is there a way to get this to work without, for example, rewriting everything in JSS (given that all the app's styling is done in scss).
Did you verify that the React theme isn't setting transition and hover rules? If it is, then the only way to override those is to set the styles inline. Perhaps add onto the theme object (or a clone of it) before assigning in the styles attr, or somehow overlay the theme nearer to its source.
In my React based application I'm trying to perform a simple css3 width transition like:
.foo {
transition: width 1s ease-in-out;
}
what I want to do is set a style inside an element in the react component which is "width: xx%" and the animate it from 0% to xx%. Since the element when rendered already has this property the animation is not working. I've looked into the "ReactCSSTransitionGroup" but did not come closer to a solution. I started messing around with setTimeOut to set the style attribute after the component was rendered but it felt really messy and "hackish". Could someone point me in the right direction?
If you are trying to animate the component after it has been rendered (from 0 to n%) you can do it by calling setState in componentDidMount. As browsers are not rerendering stuff that has changed in the same animation frame but merge changes and render the end result, you'll need to wrap it in requestAnimationFrame
I explained it throughly in this blog post.
Code will look like this:
export default class AnimateMe extends Component {
state = {
width: 0
};
componentDidMount() {
requestAnimationFrame(() => {
this.setState({ width: "75%" });
});
}
render() {
return (
<div style={{ width: this.state.width }}>
Animate my width
</div>
);
}
}
I made a working example:
https://codesandbox.io/s/7z1j794oy1
Hope that helps!
EDIT Simplify the question
http://jsfiddle.net/bf830qoq/
Why the transition in that minimalist example does not work? (It mimics the real case in my code)
Former post
I would like to apply a transition on a custom component in VueJs 2, depending on v-if condition.
I tried to put the transition inner the component loading :
Parent component
<loading v-if="shared.loading"></loading>
Loading.vue
<template>
<transition name="slide-fade">
<div class="loading-container">
<div class="container-no-text">
<div class="title-no">Loading</div>
</div>
</div>
</transition>
</template>
<script>
import Store from '../store.js'
export default{
data () {
return {
shared: Store.state,
}
},
}
</script>
<style>
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active for <2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
</style>
It simply does not work, the login disappears without any animation.
I tried to mimic the situation with JSFiddle :
Outer transition : http://jsfiddle.net/0v0wyLv0/ WORKING
Inner transition : http://jsfiddle.net/jpcays2b/ NOT WORKING
Here are the questions:
Why the second JSFiddle does not work (the inner one)?
Why on my code the "outer" does not work?
How can I make the loading component disappear smoothly?
Example which is working
https://jsfiddle.net/er3tjyh0/
Thank you
As par the implementation of transition in vue.js, transition wrapper component allows you to add entering/leaving transitions for any element or component in the following contexts:
Conditional rendering (using v-if)
Conditional display (using v-show)
Dynamic components
Component root nodes
From the docs:
When an element wrapped in a transition component is inserted or removed, this is what happens:
Vue will automatically sniff whether the target element has CSS transitions or animations applied. If it does, CSS transition classes will be added/removed at appropriate timings.
If the transition component provided JavaScript hooks, these hooks will be called at appropriate timings.
If no CSS transitions/animations are detected and no JavaScript hooks are provided, the DOM operations for insertion and/or removal will be executed immediately on next frame (Note: this is a browser animation frame, different from Vue’s concept of nextTick).
That's why transition will only work, when it is wrapping the v-if and not when it is inside, thats how it is implemented.