I wanted to make use of the breakpoints in the component from MUI v4 to let items of my Grid-System appear and disappear.
How can I make a smooth CSS transition for b from 0px to to definied breakpoint size 3 for xl? it works for me when I use %, but I can't figure out how to achieve the same with a Grid. It wont have width 0px
eg:
let show = true; //reactUseState
const toggle = (p) => {
return(!p);
}
<Grid container direction="row>
<Grid id="a" item xl={show?12:9}>{children}</Grid>
<Grid id="b" item xl={show?false:3}>{otherchildren}</Grid>
</Grid>
<Button onClick={() => toggle(show)}>Show 1 or 2 items</Grid>
I hope someone knows the trick!
This should work:
<Grid container direction="row">
<Grid className="right" id="b" item lg={show ? 12 : 9}>{'otherchildren'}</Grid>
<Grid className={show? "left left-hide" : "left"} id="a" item lg={3}>{'children'}</Grid>
</Grid>
css
.right {
transition: ease 0.5s;
}
.left {
transition: ease 0.5s;
overflow: hidden;
}
.left-hide {
flex-basis: 0% !important;
}
Related
So I have a component which is basically a custom button, with position: fixed, and I need it to render twice, one next to the other, but how can I achieve this if this component has position: fixed ? Basically, Is rendered twice in the same position.
Here is my code, where FloatingButton is the component with the issue above:
return (
<div className="details">
<Grid container spacing={3}>
<Grid item xs={12} md={12}>
<Header {...headerProps} />
</Grid>
<Grid container className="inner-container" justifyContent="flex-end">
<Grid item>
{floatingButtonProps ? <FloatingButton {...floatingButtonProps} /> : null}
</Grid>
<Grid item>
{floatingButtonProps ? <FloatingButton {...floatingButtonProps} /> : null}
</Grid>
</Grid>
</Grid>
</div>
);
and here is the CSS from the Button component:
min-width: 80px;
max-width: 80px;
height: 80px;
border-radius: 40px;
position: fixed;
bottom: 32px;
right: 32px;
display: inline-flex;
border-color: transparent;
color: #fff;
overflow: hidden;
cursor: pointer;
transition: max-width 0.5s;
position:fixed: An element with position: fixed is positioned relative to the viewport, which means it always stays in the same place even if the page is scrolled. SO technically your code is working just fine.
Now if you want to achieve two "fixed buttons" side by side. One of the ways is:- you should make the container of the button to be position:fixed and render the button without a fixed position
You can also pass the value for right in props to FloatingButton
like,
For first button <FloatingButton right='32px'/> and for second one <FloatingButton right='132px'/>
and in the Button component, you can assign it as CSS property
I have a navbar with position fixed, but in some ios devices it does not show, I googled it and I think it's an issue with the fixed position. So, I changed to absolute, but the navbar goes to the bottom of the page. Does someone know which css proprierty can I pass to centralized it on the top of the page?
I'm already using "top:0"
here's the code:
<Header>
<NewNavbar />
</Header>
header styled component:
export const Header = styled.header`
position: absolute;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
align-items: center;
// padding: 0 20px;
min-height: 52px;
`;
I don't know if this could be another reason of why safari is not showing the navbar component, but the NewNavbar component also has some divs that only is displayed when it's in a mobile size
{mobileSidebar ? (
<Grid xs={6} item className={classes.mobile}>
<Button onClick={toggleDrawerMobile(true)}>
<MenuIcon />
</Button>
</Grid>
) : null}
UPDATE !!!! Thanks everyone! I could solve it by giving to the father div the height 100vh !!!
Im making a container with 3 cards. Each card (brown-ish color in example) has a header with title (sand-buiscuit color) and content (blue one).
What I want to acheive is when the cards are closed (click on header in example), the content (blue) is transitioning to height 0, and so the only visible part is header.
Also when the card is open I want to show the available content but only then, when there is enough available space in container (green).
When 3 cards are open, they have the same height (expand evenly in container), and remaining content (blue) is scrolled.
Is it possible to make?
I prepared a demo codesandbox
I made a small code example using styled-components (just because i like it), you can easily change it to regular react components with css, but this demonstrates the idea.
I created 3 boxes, each box has a default height(40px) and after clicking (which opens it) its height is set to: 100%.
Wrapping all of this boxes with flex container does the trick.
import styled from 'styled-components';
import React, { useState } from 'react';
const MyComponent = () => {
return (
<Container>
<BoxContainer height={100} number={1} />
<BoxContainer height={100} number={2} />
<BoxContainer number={3} />
</Container>
);
};
export default MyComponent;
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-start;
width: 200px;
height: 400px;
overflow: hidden;
border: 1px solid black;
background-color: blue;
`;
const BoxContainer = ({ number, height = '100' }) => {
const [open, setOpen] = useState(false);
return (
<Box style={{ height: open ? '100%' : '40px' }} onClick={() => setOpen(!open)}>
Box: {number}
{open && <p>Content</p>}
</Box>
);
};
const Box = styled.div`
width: 100%;
overflow: scroll;
background-color: #00b8a2;
border: 1px solid red;
`;
sandbox example here: https://codesandbox.io/s/boxes-fill-container-evenly-when-opened-btlvb
I want tp use css to Material-UI component.
in MyCss.css
.trackTitle {
color:white;
}
in myComponent.js
import "./MyCss.css"
<Grid container item xs={1} className="trackTitle">
change color test
</Grid>
It doesn't change the color.
However the below works.
import "./MyCss.css"
<Grid container item xs={1} className="trackTitle">
<span className="trackTitle">
change color test
</span>
</Grid>
If I use basic tag span not Material-ui Grid
The class works.
See another case for component Slider
in MyCss.css
.mySlider {
height:"80px";
}
in myComponent.js
<Slider className="mySlider"
min={0} max={1} step={0.1}/>
not work.
<Slider className="mySlider" style={{height:"80px"}}
min={0} max={1} step={0.1}/>
works.
Now I understood className for component doesn't work.
Howeber, I want to use css to Material-UI component, how can I make it?
What you can do is to find the material-UI components CSS selector in the browser console, then override the css in your css file. Most likely this would work. Here is an example this is the root css for the slider
.MuiSlider-root {
color: #1976d2;
width: 100%;
cursor: pointer;
height: 2px;
display: inline-block;
padding: 13px 0;
/* position: relative; */
box-sizing: content-box;
touch-action: none;
-webkit-tap-highlight-color: transparent;
}
copy-paste it and then set your updates in the css
.MuiSlider-root {
/* update */
}
Material-ui is a css framework, if you want to use className for material-ui component
you have to injectFirst in root. example:
ReactDOM.render(
<StylesProvider injectFirst>
<App/>
</StylesProvider>
document.getElementById('root')
);
after this you will be able to use className anywhere on the app for any material-ui component
I want to reproduce the effect I coded in this vanilla JS example in my React app.
This is my Sass
.item
opacity: 0
transition-property: opacity
transition-timing-function: ease-in
.is-transitioning
opacity: 1
the loop generating the images and their containers:
this.props.images.map((image, index) => <ImageContainer key={`img-${index}`}
image={image}
transitionDuration={Math.trunc(index * Math.random() * 1000) + 200} />
)
and finally the ImageContainer component:
const ImageContainer = (props) => (
<div className="item is-transitioning"
style={{ transitionDuration: `${props.transitionDuration}ms` }}
>
<img src={`${props.image.path}`} />
</div>
);
export default ImageContainer;
Even though the inline class is correctly applied and the css is there, I can't figure out why the effect doesn't show up.
The issue is that the is-transitioning is added from the beginning so your elements are already at opacity:1 and notihng will happen. You need to add the class in order to trigger the opacity change and see the transition.
Another way, in case you cannot add the class is to use animaton. Here is the JS example that you can convert to react:
Array.from(document.querySelectorAll('.item')).map((i, index) => {
i.style.animationDuration = `${(index * Math.trunc(Math.random() * 1000)) + 200}ms`;
});
.container {
display: flex;
}
.item {
display: flex;
justify-content:center;
align-items: center;
width: 1rem;
height: 1rem;
background-color: teal;
padding: 2rem;
margin-right: 1.2rem;
border-radius: 10px;
font-size: 2rem;
color: white;
opacity: 0;
animation:change 2s forwards;
}
#keyframes change{
to {
opacity:1;
}
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
Simply keep the same code you wrote and replace transitionDuration with animationDuration and adjust the CSS.
(As said in another answer to this thread,) The issue is that the CSS (classes) didn't change, so the transition is "not needed", causing no animation.
For React people who wants to use transition over animation or other libraries, here is a "working" fiddle with a dirty hack:
https://jsfiddle.net/s16nd2j5/
The trick is to add the class to <ImageContainer> in componentDidMount() with a setTimeout for 0ms.
setTimeout( _ => this.setState({ transitioning: true }), 0);
This kinda forces the state update to be "postponed" to another render, causing the "CSS class change" to take place.
P.S. it is a hack. The code smells when a setTimeout / setInterval is used like this.
P.P.S. The shuffle() part from OP's fiddle is omitted for simplicity.