Position an element with relative x but absolute y coordinate - css

I have this layout:
So I have three Material UI Columns in a row, which have different widths I don't know in advance. Now I want to place Button ("Create Item") at the bottom of the screen (absolute), but horizontally centered to the middle (i.e. the main) Column. The content of this middle column can be short, or even more than fits on a screen, and is scrollable in that case.
The problem: The Button positioning does not work.
Placing the Button with a fixed position doesn't center it horizontally at the middle column but the screen.
Placing it at the bottom of the middle column's content with a relative position and textAlign: 'center' messes with the button vertical position (it can even get pushed out of the screen if the middle column's content is too long).
Placing it at the top of the middle column with textAlign: 'center', transform: 'translateY(85vh)' looks only nice until you start scrolling down and you see the Button moving up.
How can I achive this "floating" behavior just regarding the vertical position?
Edit - here's a minimal example:
<Grid container>
<Grid xs={2}>
<Box style={{ textAlign: 'center' }}>
<div>Left Column for Navigation</div>
<div>Nav 1</div>
<div>Nav 2</div>
</Box>
</Grid>
<Grid xs={6}>
<Grid
style={{
zIndex: 9001,
position: 'relative',
textAlign: 'center',
maxHeight: 0,
transform: 'translateY(85vh)',
}}
>
<Button>Create Item</Button>
</Grid>
<Box style={{ textAlign: 'center' }}>
<Grid>Main Column</Grid>
<Grid>Many Items,</Grid>
<Grid>it might even</Grid>
<Grid>require scrolling</Grid>
</Box>
</Grid>
<Grid style={{ textAlign: 'center' }} xs={4}>
<div>Right Column For Context-Related Stuff</div>
<Grid>Context Entry 1</Grid>
<Grid>Context Entry 2</Grid>
<Grid>Context Entry 3</Grid>
</Grid>
</Grid>
In this example, the Button "Create Item" would get scrolled away if there where more items in the main column, but I want it floating at a fixed y-position at the screen.

Related

How to make a grid column the same height as the element above it and pushed left

I'm using material UI and I have a grid sitting on top of a Paper element. The first column in the grid is a text input field that I'd to be the same height as the paper and I'd like it pushed left so that it shares the left border with the paper element but I'm not sure how to achieve this affect, I've tried setting 0 margins, changing the position, and messing with the height and width to no affect.
Code pen: https://codesandbox.io/s/laughing-ardinghelli-7cutft?file=/src/App.js
code
import * as React from "react";
import { styled } from "#mui/material/styles";
import Grid from "#mui/material/Grid";
import Paper from "#mui/material/Paper";
import { TextField } from "#mui/material";
export default function ComplexGrid() {
return (
<Paper
sx={{
p: 2,
margin: "auto",
maxWidth: 500,
flexGrow: 1,
backgroundColor: "#1A2027"
}}
>
<Grid container spacing={2}>
<Grid item xs={4} sx={{ alignSelf: "flex-start" }}>
<TextField
id="outlined-basic"
label=""
variant="outlined"
sx={{
backgroundColor: "white",
padding: "0",
flex: 0
}}
/>
</Grid>
<Grid sx={{ alignSelf: "flex-end", color: "white" }} item xs={6}>
<span>test v. test</span>
</Grid>
</Grid>
</Paper>
);
}
edit: I found that if I disable padding-left for all the classes MuiGrid-root.Muigrid-item in inspect element it will push it to the left, but I only want to disable the padding for this first grid item. Overriding it with sx={{paddingLeft: 0}} doesn't seem to do anything
edit2: setting sx={{paddingLeft: "0 !important", paddingTop: "0 !important"}} has gotten the position I wanted, now I just want it to stretch to the size of the paper
The padding: 2 on my paper was the issue, removing this gave me a text input field the same size as my paper

MUI Grid spacing causes grid to have padding left

I am trying to create a grid with a bunch of elements but there seems to be a problem when I add spacing to the elements. Here's a picture with spacing={0} on the Grid container:
Grid container with no spacing
Here's the result when adding spacing :
Grid container with spacing = 3
I am trying to keep the grid the same width as the buttons above (see picture). I tried different solutions but it does not seem to work on my side. Here is my code :
return (
<Grid
sx={{
width: "100vw",
overflowX: "hidden",
padding: { xs: "20px", md: "50px" },
margin: 0,
background: "hsl(0, 0%, 98%)",
}}
container
>
<Grid
sx={{ width: "100%", marginBottom: "30px" }}
item
display="flex"
flexWrap={"wrap"}
justifyContent={"space-between"}
gap={"25px"}
>
<SearchInput />
<FilterMenu />
</Grid>
<Grid container spacing={3} xs={12}>
{countries?.map((country, idx) => (
<Grid item xs={3}>
<CountryCard key={idx} country={country} />
</Grid>
))}
</Grid>
</Grid>
The easiest and correct way in my opinion based on your images, would be to separate your Grid containers. One Grid containing the Search and Filter inputs and another to contain your flags. In this way you can keep a better control of your spacing and use let css customisations in the Grid items. Have a look in this codesandbox where i have left a few comments and let me know it it helps.

centering a div in a grid item

I've been trying to horizontally center a div on the screen of an Iphone. The div is a bit narrower than the phone screen. I have been googling and searching this site and trying every combination of display, flex, margin, width, justify*, align*, placeself, etc. etc. in the container as well as item style and nothing has worked. Here is the code, with all my attempts removed from the style since none of it worked and I assume may interfere with correct solution. No matter what I try, the div just stays on the left side of the screen.
{left} and {right} are divs, with width: 400px
<Mobile>
<Grid container style={{ }} >
<Grid item xs={12} style={{ }}>{left}{right}</Grid>
</Grid>
</Mobile>
const Mobile = ({ children }) => useMediaQuery({ maxWidth: 799 }) && children
Here is what finally worked for me after lots of trial and error.
<Mobile>
<Grid container style={{ justifyItems: 'center', alignItems: 'center', display: 'inline-grid', width: '100%' }} >
<Grid item xs={12} style={{ width: '400px' }}>{left}{right}</Grid>
</Grid>
</Mobile>
To clarify, my question was probably inaccurate. What I needed to do was center the grid item in the grid container.

Making titles of cards have same height

So I have the following situation:
From a certain point on the darkblue color of the boxes just doesn't align anymore. These two boxes are currently being rendered in a flex container. What would be a solution for this problem? I want the upper container to always be aligned with the one next to it. It is also possible that it will be more than 2 components next to each other.
Flex container (material ui Grid component uses Flex)
<Box>
<Grid container>
{resultField.fields?.map((blockField, index) => {
return (
<Grid item xs={12} md={6}>
<DarkValueBox label={blockField.label} value={blockField.value} />
</Grid>
);
})}
</Grid>
DarkValueBox
export const DarkValueBox = ({ label, value, index }) => {
const classes = useStyles();
return (
<Box sx={{ borderRadius: 5 }}>
<Box
sx={{
backgroundColor: "#0A7BB1",
color: "#fff",
px: 2,
py: 3,
borderRight: "1px solid #fff",
}}
>
<Typography fontWeight={600} variant="subtitle1">
{label}
</Typography>
</Box>
<Box sx={{ px: 2, py: 2, border: "1px solid lightgrey" }}>
<Typography variant="subtitle1">
{value}
</Typography>
</Box>
</Box>
);
};
Here's a codesandbox where I recreated the problem:
https://codesandbox.io/s/add-material-ui-forked-ge42z?file=/src/index.js
An approach would be - if you do not want to cut the labels for showing the user as much information as possible - to ensure the blue box is always taking the height of the highest container in the row.
You can do this with adding a wrapper class to the container DarkValueBox with following specification:
wrapper: {
height: "100%",
display: "flex",
flexDirection: "column"
}
Then, tell your box class to take 100%:
box: {
backgroundColor: "darkblue",
border: "1px solid grey",
color: "white",
wordBreak: "break-word", // btw: its `break-word`, not `word-break`
height: "100%"
},
That is it, find it working in a forked sandbox:
https://codesandbox.io/s/add-material-ui-forked-24zg7?file=/src/index.js
Ok, so I was going through your Sandbox and instead of writing the code I decided to point you in the right direction.
You have declared a Grid with material UI which is a type of container similar to FlexBox.
You have not declared a size or width for the box or the containers inside.
Once you set the grid size and wrap direction for the outer 'main' container you will be able to set the sizes for the containers inside, your label boxes.
This will align them.
For the text, there is a 'textOverflow' property which will stop any additional text wrapping over the component and instead replace it with '...'
Material UI Grid - https://mui.com/components/grid/
Textoverflow - CSS: text-overflow: ellipsis with reactJS and IE

Why won't must flexDirection: 'column' push space between?

I have:
<Grid item xs={12} md={6} className={classes.heroGrid}>
<Typography variant='h3' >
Some stuff
</Typography>
<div style={{ display: 'flex' }}>
here
</div>
</Grid>
And heroGrid is:
heroGrid: {
flexDirection: 'column',
justifyContent: 'space-between',
alignContent: 'space-between',
alignItems: 'space-between'
}
But it doesn't push my content to be apart.
The height of the top level <Grid> component is probably being calculated to be exactly the height of the elements it contains.
So, it's pushing all the extra space between the two elements—it just so happens there's 0px of extra space!
You could test this temporarily by setting a fixed height to the <Grid> element with something like:
<Grid item xs={12} md={6} className={classes.heroGrid} style={{height: 500}}>
If you're elements are then pushed apart as desired, you then need to figure out how you want to actually set the height of the Grid element. If it should fill the parent, you could make the height 100%. If it should be a fixed height, you could set it to the specific fixed height.

Resources