I have a Material UI <Paper> component that serves as a background and exists in my main React component- it's nested inside a <ThemeProvider>, which is nested a <div>, which is then nested in the <body>. I've applied the viewport: 100vh attribute to make it take the full height of the screen. It does take up the full height, but only prior to rendering another <Paper> component on the right hand side. Then the bottom of the paper no longer extends to the bottom of the screen:
Beginning of App render method:
return (
<ThemeProvider theme={theme}>
<Paper style={{ height: '100vh', boxShadow: 'none' }}>
<Container fluid id='app'>
.......
)
I tried applying the viewport: 100vh attribute to both the <div> that encloses the App component in index.js and the <body> element in index.html. There wasn't any difference. It may be worth mentioning that I'm using react-bootstrap Containers/Rows/Cols for my grid system at the moment (haven't switched that part to Material UI yet), but they're all nested inside the Paper, so I wouldn't expect they would be causing the problem. I also tried removing any css applied to the <Container> but it didn't help.
I'm also using a muiTheme for the <ThemeProvider> (obviously):
export default function createTheme(isDarkModeEnabled) {
return createMuiTheme({
palette: {
type: isDarkModeEnabled ? 'dark' : 'light',
primary: {
main: '#6DD3CE',
dark: '#639FAB'
},
secondary: {
main: '#52CBC5'
}
},
typography: {
fontFamily: [ 'montserratlight', 'Times New Roman' ].join(','),
body2: {
fontFamily: [ 'montserratmedium', 'Times New Roman' ].join(',')
},
h3: {
fontSize: '1.75rem'
},
button: {
fontFamily: [ 'montserratmedium', 'Times New Roman' ].join(',')
}
}
})
}
Update and Solution
I did redo my layout using flexbox instead of react-bootstrap, and ultimately fixed the problem by using min-height: 100vh instead of height: 100vh for my container so it had room to expand.
It appears that your <Container> has a bit of padding that is causing the content to go beyond its height:
This could also be due to your <textarea /> not having an assigned height. This is a particular issue when you are in a medium-sized screen.
If you are already planning to do away with Bootstrap's layout system, consider flex box and styled containers:
import React from "react";
import styled from "styled-components";
export default function App() {
return (
<Container>
<StyledHeader>Hello StackOverflow</StyledHeader>
<StyledCol>
<p>This is column 1.</p>
</StyledCol>
<StyledCol>
<p>This is another column.</p>
</StyledCol>
</Container>
);
}
const Container = styled.div`
height: 700px;
width: 100%;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
`;
const StyledHeader = styled.h1`
height: 30%;
width: 100%;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
`;
const StyledCol = styled.div`
height: 70%;
width: 50%;
& p {
text-align: center;
}
`;
CodeSandbox Example: https://codesandbox.io/s/stack-63802170-flexbox-example-909ol
This will ultimately give you more control over the layout of the page.
Related
I'm using react styled components and react-responsive hooks for media-query. My problem is when trying to pass the variable that contains the matching window size, to the styled component CSS.
After importing the hook, I defined the window sizes and assigned to "big" and "mobile" screen. The following variables returns a boolean if the conditions are meet:
const isMobile = useMediaQuery({ query: '(max-width: 600px)' });
const isBigScreen = useMediaQuery({ query: '(min-width: 600px)' });
The next step is to create the Styled components in the render() component and in the .styles.js file. The three components from the render() are inside a paragraph tag.
My goal is to pass the props to the styling and if the width isMobile, the component inside the tag will hide the overflow text in the ellipse dots (...);
{/* House details */}
<HouseDetailsInfo>
<p>{house.city}</p>
<p>{house.street}</p>
{/* <p>Price: {house.price} £ / {house.typeOfTenancy}</p> */}
<p>
<HousePriceEl isBigScreen isMobile={isMobile}>Price: </HousePriceEl>
<HousePriceNr isBigScreen isMobile={isMobile}>{house.price}£ </HousePriceNr>
<HouseTenancy isBigScreen isMobile={isMobile}>, {house.typeOfTenancy}</HouseTenancy>
</p>
</HouseDetailsInfo>
The following css are created in the component.styles.js file:
export const HouseDetailsInfo = styled.div`
display: flex;
flex-direction: column;
justify-content: space-around;
max-width: inherit;
& > p {
margin: 0;
padding: 5px 10px 5px 5px;
width: ${props => props.isMobile ? "180px" : "inherit"};
background: ${props => props.isBigScreen ? Colors.darkGrey : Colors.orange};
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
`;
I tried also to log the width props in the main element, and is working. But no matter what I do, the styles are not applying in the styles....
I have a loading component that I am importing on many pages in my project in that component I am using a modal, a modal that I have rewritten some of his CSS styles in a CSS file that I imported in the component
the problem that I have is that this CSS change of the modal effects other modals in my project
how can I let this CSS change only related to my component modal without affecting others
my loading component
import React, {Component, PropTypes} from 'react';
import {Modal} from "react-bootstrap";
import ReactLoading from 'react-loading';
import './loading.css'
export default class Loading extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
const {show} = this.props;
return(
<div >
<Modal show={show} className="loadingModal" keyboard={false}>
<Modal.Body className="testtest">
<ReactLoading id="modale" type={"bubbles"} color={"#2f96a1"} height={120} width={120} />
</Modal.Body>
</Modal>
</div>
)
}
}
my loading css:
.modal-backdrop.in {
opacity: 0;
filter: alpha(opacity=00);
}
.modal.in .modal-dialog {
display: flex;
justify-content: center;
margin-top: 9%;
}
#modale{
display: flex;
justifyContent: 'center';
margin: auto;
}
.testtest{
flex: 1;
alignItems: 'center';
justifyContent: 'center'
}
If you're not using CSS modules or such, I think the best way would be to respect the cascade and always assume that the css you import will spill. To do so I would encourage you to use BEM model. With it, it could be rewritten as:
<div>
<Modal show={show} className="loading-modal modal--test" keyboard={false}>
<Modal.Body className="modal--test__body">
<ReactLoading id="modale" class="modal--test__content" type={"bubbles"} color={"#2f96a1"} height={120} width={120} />
</Modal.Body>
</Modal>
</div>
And for css:
.modal--test .modal-backdrop.in {
opacity: 0;
filter: alpha(opacity=00);
}
.modal--test .modal.in .modal-dialog {
display: flex;
justify-content: center;
margin-top: 9%;
}
/* don't use ids for css */
.modal--test__content{
display: flex;
justify-content: 'center';
margin: auto;
}
.modal--test__body{
flex: 1;
alignItems: 'center';
justifyContent: 'center'
}
Naturally, this doesn't follow BEM model exactly as it would require passing classes to the internal elements. Alternatively, for scoping, you can use CSS modules.
You have multiple options:
assign a unique ID for the Modal and change your CSS selectors to target elements with this ID only (recommended)
use the Modal.container property to attach the modal to your Loading component rather than to the document body (discouraged if you do some tricky CSS styling, especially use absolute or fixed positioning of elements - this may mess up the Modal positioning logic)
use the Modal.bsPrefix property to change the class names of the modal elements. Probably OK to do, even though the documentation states that this should be used only if absolutely necessary
You should use CSS-module
According to the official repo CSS Modules are “CSS files in which all class names and animation names are scoped locally by default”.
in this data table i decalre rows and colums only as simple variables so i cant give them style with 'style={{textAlign: center}}' and i tried adding css file but it didnt work on either tr or th when using this material ui table so im not so sure how to do it... this is my code
import * as React from 'react';
import { DataGrid } from '#material-ui/data-grid';
export default function DataTable({data, someColumns}) {
const columns = someColumns
const rows = data;
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid rows={rows} columns={columns} pageSize={5} checkboxSelection />
</div>
);
}
by default the data in columns is aligned left and not center how can i change it?
EDIT: i've managed to fix it with this css. thanks to fahad
.MuiDataGrid-colCellTitle {
display: block;
text-align:center;
width: 100%;
}
.MuiDataGrid-cell {
display: block;
position: relative;
text-align: center;
}
which will center both rows and columns.
For anyone else who comes across this, check out the implementation of ColDef here.
The way to do this 'correctly' would be like this:
const [columns, setColumns] = useState([
{
field: 'status',
width: 130,
// these properties can only be 'left' | 'center' | 'right'
// note that these only set text-align property.
headerName: 'Status',
headerAlign: 'center',
align: 'center',
renderCell: (params) => {
return (
<Chip label={params.value} />
)
}
},
]);
If you're rendering anything other than text (like in the example above) it won't center your content. The cells are display: flex and align-items: center but to center horizontally you need to add a justify-content for centered cells:
.MuiDataGrid-cellCenter {
justify-content: center;
}
You can do the same for MuiDataGrid-cellLeft or MuiDataGrid-cellRight if needed.
This worked for me.
In your style.css you can target th and tr by
this property .MuiDataGrid-colCellTitle. So to align it in center use this
Style.css
.MuiDataGrid-colCellTitle {
display: block;
text-align:center;
width: 100%;
}
After importing things
import { DataGrid } from '#material-ui/data-grid';
Declare your rows and columns data inside the function.
export default function DataGridDemo() {
const columns = [
Data in columns
];
const rows = [
Data in rows
];
//Apply your styles
return (
<div
style={{
height: 400,
width: "100%",
backgroundColor: "red",
textAlign: "center"
}}
>
<DataGrid rows={rows} columns={columns} pageSize={5} checkboxSelection />
</div>
);
}
Code Sandbox link : https://codesandbox.io/s/thirsty-leaf-izuhd?file=/src/App.js
I'm using Material-UI library on ReactJS, but I'm having some issues with flexbox.
I want to set my Item Container in the center of my div, stretching it to take all the height available and set Bottom and Top margin.
I'm trying with alignItems="stretch" but it doesn't work (Original version code).
I can certainly set the height of the Grid Item and Paper to 100%, but I don't see this as an elegant way to make the element fill all the vertical space (Second version code).
More, if I set Grid Item height and Paper height to 100%, and set top margin and bottom margin to both element, Paper ignores the bottom margin completely.
More again, the width and height goes over the screen size (see second image belowe), why this happens?
Original version:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Paper from '#material-ui/core/Paper';
import Grid from '#material-ui/core/Grid';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
height: "100%"
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
},
}));
export default function CenteredGrid() {
const classes = useStyles();
return (
<div className={classes.root}>
<Grid container style={{height: "100%", backgroundColor:"green"}} justify= "center" alignItems="stretch"spacing={3}>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
</Grid>
</div>
);
}
Second version:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Paper from '#material-ui/core/Paper';
import Grid from '#material-ui/core/Grid';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
height: "100%"
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
height: "100%",
color: theme.palette.text.secondary,
},
}));
export default function CenteredGrid() {
const classes = useStyles();
return (
<div className={classes.root}>
<Grid container style={{height: "100%", backgroundColor:"green"}} justify= "center" alignItems="stretch" spacing={3}>
<Grid item xs={12} style={{backgroundColor: "red", marginTop:10, marginBottom:10}}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
</Grid>
</div>
);
}
This is my index.css, where I set all the component to height="100%".
body {
height: 100%;
width: 100%;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
html {
height: 100%;
width: 100%;
}
div#root {
height: 100%; /* remove this line to see div.app is no more 100% height */
width: 100%;
background-color: indigo;
}
div.app {
height: 100%;
width: 100%;
background-color: cornsilk;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
My expected result is a Grid Item with a Paper element inside it, that is centered inside the Grid container, stretched height to fill all the vertical space but some prefixed bottom and top margin.
My Original Code Result:
My Second version Code Result:
Plus:
I've used React Native and I feel like flexbox on mobile phone is more "straightforward". Do you have some resources and tutorial to understand very well how I can handle UI in Reactjs with code examples?
Check this codesandbox code I have fixed the code for you. If you want to remove the red border as well, just set padding:0 for the item-container.
Also, another suggestion, don't mix the styles. You are using inline styling as well as creating styles using makeStyle. Use only one, so you have a single source to change whenever you need to make any changes.
I've made a sticky footer higher-level component that wraps other components inside itself:
Footer.js
//this is a higher-order component that wraps other components placing them in footer
var style = {
backgroundColor: "#F8F8F8",
borderTop: "1px solid #E7E7E7",
textAlign: "center",
padding: "20px",
position: "fixed",
left: "0",
bottom: "0",
height: "60px",
width: "100%",
};
const Footer = React.createClass({
render: function() {
return (
<div style={style}>
{this.props.children}
</div>
);
}
});
export default Footer;
Usage:
<Footer><Button>test</Button></Footer>
But it is hiding the contents of the page:
This looks like a common problem, so I searched a bit and found this issue, where is FlexBox is recommended for the sticky footer. But at this demo the footer is at the very bottom of the page, while I need the footer to be always displayed on the page and the content being scrolled inside the above area (like in SO chat). In addition to that, there is an advice to change all the other components with custom stylesheet rules. Is it possible to achieve what I need using styling only the footer component so the code will remain modular?
Here's an idea (sandbox example link).
Include a phantom div in your footer component that represents the footer's position that other dom elements will respect (i.e. affecting page flow by not being position: 'fixed';).
var style = {
backgroundColor: "#F8F8F8",
borderTop: "1px solid #E7E7E7",
textAlign: "center",
padding: "20px",
position: "fixed",
left: "0",
bottom: "0",
height: "60px",
width: "100%",
}
var phantom = {
display: 'block',
padding: '20px',
height: '60px',
width: '100%',
}
function Footer({ children }) {
return (
<div>
<div style={phantom} />
<div style={style}>
{ children }
</div>
</div>
)
}
export default Footer
Much easier idea (following the trend), i imported both bootstrap and reactstrap, used the bootstrap fixed bottom class and workaround with that like this.
class AppFooter extends Component{
render() {
return(
<div className="fixed-bottom">
<Navbar color="dark" dark>
<Container>
<NavbarBrand>Footer</NavbarBrand>
</Container>
</Navbar>
</div>
)
}
There is a much simpler way. I am creating a portfolio site with React, and some of my pages are not very long, so in some devices, like kindle fire hd for example, the footer would not stick to the bottom. And of course to set this up in the traditional fashion with would not work, because the would be wrapped in there. And we don't want that. So this is what I did:
In App.js:
import React, { Component } from 'react';
import {Header} from './components/Header';
import {Main} from './components/Main';
import {Footer} from './components/Footer';
class App extends Component {
render() {
return (
<div className="App Site">
<div className="Site-content">
<div className="App-header">
<Header />
</div>
<div className="main">
<Main />
</div>
</div>
<Footer />
</div>
);
}
}
export default App;
And then in _sticky-footer.css (I use POSTCSS):
:root {
--space: 1.5em 0;
--space: 2em 0;
}
.Site {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.Site-content {
flex: 1 0 auto;
padding: var(--space) var(--space) 0;
width: 100%;
}
.Site-content:after {
content: '\00a0';
display: block;
margin-top: var(--space);
height: 0;
visibility: hidden;
}
The original solution for this was created by Philip Walton: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/
You can fix this by adding margin-bottom: 60px; to the body of your website. With the 60px being the height of your footer.
.footer{
width: 100%;
position: fixed;
bottom: 0;
}
This should do the trick! Cheers! (:
.App will be the main component you load to your Root.
Assume that the footer is the last child of .App in the document flow
.App {
height: 100vh;
display: flex;
flex-direction: column;
}
footer {
margin-top: auto;
}
I found that if you wrap your 'footer' component in a standard html
<footer>
tag, it pretty much sorts out all of the positioning for you
I wanted to share this solution that worked. I cribbed this from https://react.semantic-ui.com/modules/sticky. Scroll to the bottom of this page and inspect the text 'This is the bottom' to see where I stole it. Its a site built on react so it should work for your situation.
Here it is:
{
padding-top: 50vh;
}
Conceptually, this solution is creating negative space like jacoballenwood's phantom div to push the footer down to the bottom and stick it there. Just add it to your css style class for the footer and adjust the value to taste.
Very late answer, but someone can find this useful. You can, instead of phantom style, set Toolbar. I have build some standard layout for the components, where {children} is component from the parent component - App.js. This is example:
import React from "react";
import { Route } from "react-router-dom";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import CssBaseline from "#material-ui/core/CssBaseline";
import Toolbar from "#material-ui/core/Toolbar";
import Header from "../components/header";
import Footer from "../components/footer";
import SideBar from "../components/sidebar";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
},
content: {
flexGrow: 5,
padding: theme.spacing(3),
},
}));
const StandardLayout = ({ children }) => {
const classes = useStyles();
return (
<div className={classes.root}>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Route path="/" component={Header} />
</AppBar>
<SideBar />
<main className={classes.content}>
<Toolbar />
<br />
{children}
<Toolbar/>
</main>
<AppBar className={classes.appBar}>
<Route path="/" component={Footer} />
</AppBar>
</div>
);
};
export default StandardLayout;
Its rule for me
<footer style={{position:"fixed",bottom:"0"}}>
Try this html code:
/public/index.html
<html lang="en" class="h-100">
<body class="h-100">
<div id="root" class="d-flex flex-column h-100"></div>
...
/src/App.js
<main role='main' className='flex-shrink-0'>
You can follow this template:
react-bootstrap-sticky-footer/public/index.html
react-bootstrap-sticky-footer/src/App.js