I have a react component that contains a forms and it is formatted as follows:
<Box
display="flex"
justifyContent="center"
alignItems="center"
style={{ minHeight: "100vh", backgroundColor: "gray", opacity: "0.8" }}
> ...
</Box>
This componenent, called Form is then passed in App.js as follows:
import React from "react";
import Form from "./components/Form";
const sectionStyle = {
height: "100vh",
backgroundImage:
"url('www.blablabla.com/img.jpg') ",
backgroundRepeat: "no-repeat",
backgroundSize: "cover"
};
const App = () => {
return (
<div style={sectionStyle}>
<Form />
</div>
);
};
export default App;
However, the results I get is this one:
I added the opacity to better show that my Box component is 'stretched' all over the window, while I would like it to just wrap its content, so that if some opacity is applied, it will only appear I side the Box, and the background image will be normal.
How can I achieve this?
material-ui Box's default component is a div. see material-ui Box
A div's default behavior is to stretch horizontally across the available space. That is why your Box is stretching horizontally. Where is the default size of a div element defined or calculated?
The minHeight: "100vh" style you are applying to the Box is telling it to stretch across the available vertical space. That is why your Box is stretching vertically.
see Fun with Viewport Units
Perhaps using the Grid component as a wrapper will give you what you are looking for
<Grid container className={props.classes.sectionStyle}
direction="column"
justify="space-evenly"
alignItems="center"
>
<Grid item>
<Form />
</Grid>
</Grid>
This would change your code to be:
import React from "react";
import {Grid} from '#material-ui/core';
import Form from "./components/Form";
const sectionStyle = {
height: "100vh",
backgroundImage:
"url('www.blablabla.com/img.jpg') ",
backgroundRepeat: "no-repeat",
backgroundSize: "cover"
};
const App = () => {
return (
<Grid style={sectionStyle}
container
direction="column"
justify="space-evenly"
alignItems="center"
>
<Grid item>
<Form />
</Grid>
</Grid>
);
};
export default App;
I would suggest you to use pseudo elem like:after and :before
Here is an example.
.background-filter::after {
content: "";
display: block;
position: absolute;
width: 100%;
height: 100%;
opacity: .8;
background: red;
}
.background-filter {
position: relative;
}
.background {
background-image: url('https://upload.wikimedia.org/wikipedia/en/6/62/Kermit_the_Frog.jpg');
width: 200px;
height: 200px;
}
.background span{
position: absolute;
z-index: 1;
}
<div class="background background-filter"><span>Hello World I am text with background blur</span></div>
Do what ever you want to apply to ::after wont effect the form above
Related
I have grid from material UI:
Item element
const Item = styled(Paper)(({theme}) => ({
...theme.typography.body2,
padding: theme.spacing(2),
textAlign: 'center',
color: "black",
}));
Structure
<div className="wrapper">
<Typography variant="h3" component="h3">
List of friends
</Typography>
<div className="friends">
<Grid container
direction="row"
rowSpacing={1}
spacing={{xs: 2, md: 3}} columns={{xs: 4, sm: 8, md: 12}}
alignItems="center"
justifyContent="center"
>
{
friends.map((friend, i) => {
return <Grid item xs={4} sm={6} md={6} mt={5}>
<Item className="item"><span>{i}</span>{friend.name}</Item>
</Grid>
})
}
</Grid>
</div>
</div>
With css:
.wrapper{
width: 100%;
position: relative;
align-items: center;
display: flex;
flex-direction: column;
background:#eaeaea
}
.friends{
position: relative;
width: 75%;
}
It looks like this:
However, i would like the number of friend, to be on the left, and highlighted like:
However, how to stile the <span> element to do this? The when i style span to be
span{
position: absolute;
left: 0
width:25%;
height: 100%
}
Then the span is somewhere else, as the material ui uses lot of styling that makes this hell.
when i change it to:
{
countries.map((friend, i) => {
return <Grid item xs={4} sm={6} md={6} mt={5} >
<span> i </span>
<Item className="item">{friend.name}</Item>
</Grid>
})
}
I would need to make adjustments to the Grid elements, adding position relative and such, but im not sure how this would work with responsivity.
Is there simple way to do this?
Or is there any other component i can use instead of Item(Paper) element?
Thanks for help!
You can use display: grid on the Paper element, like so:
<Paper
sx={{
display: 'grid',
grid: 'auto / 25% 75%',
height: 50,
'& > div': {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
},
}}
>
<Box>1</Box>
<Box>Name</Box>
</Paper>
Alternatively, you can do it with flex: 1 and flex: 3, but I think the grid method is easier to set up, since all the logic is in one line.
I'm facing issue where normal HTML img tag works just fine inside my Masonry List, but when I'm using Next.js Image Component with layout fill, it doesn't render anything.
My Styles:
const ImageList = styled('ul', {
columnCount: 3,
columnGap: 10,
display: 'block',
listStyleType: 'none',
overflowY: 'auto',
padding: 0,
margin: 0
})
const ImageListItem = styled('li', {
position: 'relative',
display: 'inline-block',
lineHeight: 0,
height: 'auto',
marginBottom: 10
})
HTML Skeleton:
<ImageList>
{detailImage.map((image, idx) => {
return (
<ImageListItem key={`_${idx}`}>
<Image
src={image.src}
alt={image.alt}
blurDataURL={image.blurDataURL}
placeholder={'blur'}
layout={'fill'}
objectFit={'cover'}
/>
{/* <img
src={image.src}
style={{
width: '100%',
height: '100%',
objectFit: 'cover'
}}
/> */}
</ImageListItem>
)
})}
</ImageList>
EDIT
Because I'm getting all images from CMS and have width/height I used the padding-top trick to create box and then I use next/image with object-fit: cover.
Code Example:
<ImageListItem key={`_${idx}`}>
<Box
css={{
display: 'inline-flex',
pt: `${100 / (image.width! / image.height!)}%`
}}
>
<Box css={{ position: 'absolute', inset: 0, m: 0 }} as={'figure'}>
<Image
src={image.src}
alt={image.alt}
blurDataURL={image.blurDataURL}
placeholder={'blur'}
layout={'fill'}
objectFit={'cover'}
/>
</Box>
</Box>
</ImageListItem>
When you use layout='fill' it's necesary a parent container for each image and this container needs to have position: relative;. Maybe it doesn't show anything because its parent elements don't have the width property.
This is the description in the documentation:
When fill, the image will stretch both width and height to the
dimensions of the parent element, provided the parent element is
relative. This is usually paired with the objectFit property. Ensure
the parent element has position: relative in their stylesheet.
I'm trying to get rid of the elevation shadow of the navbar over the sidebar.
I'm using Material-UI's AppBar for my NavBar component.
export default function NavBar() {
return (
<div>
<AppBar position="fixed" elevation={4}>
<Toolbar variant="regular">
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
</Toolbar>
</AppBar>
</div>
);
}
I am using a custom sidebar component,
.sidebar {
left: 0;
top: 64px;
height: 100vh;
width: 70px;
background-color: #3f50b5;
position: fixed;
}
.sidebar::before{
display: none;
}
I don't want to lose the elevation/shadow of the entire NavBar, just the section on the left where it's over the Sidebar.
Adding this because I spent a lot of timing finding a simple answer to removing the elevation.
The simplest way to remove the shadow is by adding elevation prop to the AppBar.
<AppBar position="fixed" elevation={0}>
you could add a ::after pseudo element to your navbar to do the job. This element would have the width of your sidebar, and would be have a top property accordingly to your navbar.
Given the AppBar itself has some different breakpoints you would need to change top accordingly:
const useStyles = makeStyles((theme) => ({
root: {
"&::after": {
position: "absolute",
content: '""',
width: "70px",
height: "8px",
top: "48px",
backgroundColor: theme.palette.primary.main,
[theme.breakpoints.down("xs")]: {
top: "56px"
},
"#media (orientation: landscape)": {
top: "48px"
},
[theme.breakpoints.up("sm")]: {
top: "64px"
}
}
}
}));
export default function NavBar() {
const classes = useStyles();
return (
<div>
<AppBar classes={{ root: classes.root }} position="fixed" elevation={4}>
<Toolbar variant="regular">
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
</Toolbar>
</AppBar>
</div>
);
}
I created a sandbox with only the navbar, and a darker shadow to enhance contrast:
I am creating a chat window where I have my users on the left and my messages on the right.
The thing is I want both columns to grow to the end of the viewport or till the footer but there is no way to make it works. Here is my component.
import Grid from "#material-ui/core/Grid";
const Prueba = () => {
return (
<div style={{ display: "flex" }}>
<Grid container spacing={1} style={{ flexGrow: 2 }}>
<Grid
item
xs={12}
sm={12}
md={4}
lg={3}
style={{ background: "black" }}
></Grid>
<Grid
item
xs={12}
sm={12}
md={8}
lg={9}
style={{ background: "blue" }}
></Grid>
</Grid>
<div
style={{
position: "fixed",
bottom: 0,
height: 100,
width: "100%",
backgroundColor: "red",
}}
></div>
</div>
);
};
export default Prueba;
The container is inside a flex element and the Grid Container has flexGrow property 1. What is not working here?
Here is how it renders now. It's like my Grid container has no height and actually I want it to grow all down to the footer.
You can do this in material-ui with css grid
https://codesandbox.io/s/naughty-yonath-wqr1p?file=/src/App.js
import { styled } from "#material-ui/core";
const Grid = styled("div")({
display: "grid",
gridTemplateColumns: "1fr 3fr",
height: "100vh"
});
const Footer = styled("div")({
position: "fixed",
bottom: 0,
height: 100,
width: "100%",
backgroundColor: "tomato"
});
export default function App() {
return (
<div className="App">
<Grid>
<div style={{ background: "khaki" }}>Left</div>
<div style={{ background: "lightsalmon" }}>Right</div>
</Grid>
<Footer />
</div>
);
}
I can't find an answer for this, even though there are many flex themed questions.
I created a simple React app (npx create-react-app).
I then deleted App.css and set the contents of index.css to:
html, body, #root {
height: 100%;
margin: 0;
}
Next, in App.js I'm trying to have a full screen element using flex:
import React from 'react';
function App() {
return (
<div style={{ backgroundColor: 'blue', display: "flex", flex: 1 }}>
<div style={{ display: "flex", flexDirection: "column", flex: 1 }} />
</div>
);
}
But it just won't work. Why is the flex element not stretching?
The flex-grow works when there are other elements in the flex. It makes the element to grow x times in comparison to others.
wrt the solution you have implemented: inner div doesn't require display: flex and direction too. It will be inherited from the parent div.
To make the div take the full height. add height: 100vh to the parent div.
Let me know if this will solve the problem.
Thank you.
To achieve height of window you need to mention height: 100vh for parent tag like
class- .parent{height: 100vh}
object style - style={{height: '100vh'}}
import React from 'react'
function App() {
return (
<div style={{ backgroundColor: 'blue', display: "flex", height:'100vh' }}>
<div style={{ display: "flex", flexDirection: "column", flex: 1 }} >Hello world</div>
</div>
);
}