12

I am starting to use React/Material-UI, and also new to CSS etc... I have a simple page layout with an APPBar. Unfortunately this AppBar overlaps the elements which are meant to go below it.

I have found this answer: AppBar Material UI questions

But this feels completely wrong. What if my AppBar has a variable height, depending on the icons, display modes etc...?

I have tried to create a vertical grid, to wrap the elements in different items, made the top container a flex one and play with flex settings, nothing seems to work, the app bar always sits on top of the text.

The code is very simple:

import React from 'react';
import { AppBar, Typography, Box } from '@material-ui/core';

function App() {
    return (
        <div>
            <AppBar>
                <Typography variant='h3'>
                    AppBar
                </Typography>
            </AppBar>
            <Box>
                <Typography variant='h1' style={{ border: '1px solid black' }}>
                    Hello
                </Typography>
            </Box>
        </div>
    )
}

export default App;

The "Hello" text chunk is only half visible:

enter image description here

Rob
  • 14,746
  • 28
  • 47
  • 65
Will59
  • 1,430
  • 1
  • 16
  • 37

7 Answers7

10

This is happening because the MaterialUI App Bar defaults to position="fixed". This separates it from the standard DOM's layout to allow content to scroll beneath it, but as a result no space is made for it on the page.

You can get around this by wrapping all content below it in a div and specifying enough margin, or by changing the position property of <AppBar> so it's no longer "fixed". In your example, you could also just apply the styles to <Box> if that's the only content below the <AppBar>.

e.g.

import React from 'react';
import { AppBar, Typography, Box } from '@material-ui/core';

function App() {
    return (
        <div>
            <AppBar>
                <Typography variant='h3'>
                    AppBar
                </Typography>
            </AppBar>
            <div style={{marginTop: 80}}>
                <Box>
                    <Typography variant='h1' style={{ border: '1px solid black' }}>
                        Hello
                    </Typography>
                </Box>
            </div>
        </div>
    )
}

export default App;
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
Kavin2468
  • 208
  • 2
  • 10
  • 2
    The code illustrated above is not what I was looking for, as any fixed size div will not work with a variable size app bar (as stated in the question). However simply changing the AppBar position did the trick. So accepting this solution. – Will59 Nov 15 '19 at 17:06
5

MaterialUI provides a theme mixin for the AppBar that can help. Not sure if you're using the recomended JSS setup, but you can do something like this:

import withStyles from '@material-ui/core/styles/withStyles';
const styles = theme => ({
  appBarSpacer: theme.mixins.toolbar
});

const style = withStyles(styles)

function MyScreen ({ classes }) {
  <AppBar></AppBar>
    <div className={classes.appBarSpacer}></div>
  <Box></Box>
}

export default style(MyScreen)

The mixin will give that div the same height as your AppBar, pushing down the other content.

jhummel
  • 1,724
  • 14
  • 20
  • 2
    Thanks for the answer. Isn't the appBarSpacer's height going to be fixed to 64px though? I tried this option, placing items in the AppBar which modify its height, and the appBarSpacer doesn't seem to adjust? – Will59 Nov 06 '19 at 22:41
  • @Will59 I just tried this, and the height adjusts depending on the app bar's height. The app bar height will responsively change heights depending on your window width & app bar props/config. **Edit:** I think I misunderstood your comment. It sounds like your app bar height is custom, which this approach would not account for. – Matt Huggins Sep 19 '20 at 16:43
5

According to Material-ui, there are 3 solutions to this problem.

https://material-ui.com/components/app-bar/#fixed-placement

  1. You can use position="sticky" instead of fixed. ⚠️ sticky is not supported by IE 11.
  2. You can render a second component
  3. You can use theme.mixins.toolbar CSS

I personally enjoy using the 2nd solution like this.

  return (
    <>
      <AppBar position="fixed">
        <Toolbar>{/* content */}</Toolbar>
      </AppBar>
      <Toolbar />
    </>
  );
m-nis
  • 51
  • 1
  • 1
2

<AppBar position='static'>

use this it will do it and content won't hide under Appear

1

I think having a good app setup is opinianted, but I would recommend the following

import React from "react";
import ReactDOM from "react-dom";
import {
  AppBar,
  Typography,
  Box,
  CssBaseline,
  makeStyles,
  Container,
  Grid,
  Toolbar
} from "@material-ui/core";

const useStyles = makeStyles(theme => ({
  content: {
    flexGrow: 1,
    height: "100vh",
    overflow: "auto"
  },
  appBarSpacer: theme.mixins.toolbar,
  title: {
    flexGrow: 1
  },
  container: {
    paddingTop: theme.spacing(4),
    paddingBottom: theme.spacing(4)
  }
}));

function App() {
  const classes = useStyles();
  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar position="absolute">
        <Toolbar className={classes.toolbar}>
          <Typography
            component="h1"
            variant="h6"
            color="inherit"
            noWrap
            className={classes.title}
          >
            AppBar
          </Typography>
        </Toolbar>
      </AppBar>
      <main className={classes.content}>
        <div className={classes.appBarSpacer} />
        <Container maxWidth="lg" className={classes.container}>
          <Grid container spacing={3}>
            <Grid item xs={12}>
              <Box>
                <Typography variant="h1" style={{ border: "1px solid black" }}>
                  Hello
                </Typography>
              </Box>
            </Grid>
          </Grid>
        </Container>
      </main>
    </div>
  );
}

How the result should look

Julian Kleine
  • 1,539
  • 6
  • 14
  • 1
    Thanks for the answer. Isn't the appBarSpacer's height going to be fixed to 64px though? I tried this option, placing items in the AppBar which modify its height, and the appBarSpacer doesn't seem to adjust? – Will59 Nov 07 '19 at 07:33
  • Why would you modify the height of the appBar? – Julian Kleine Nov 07 '19 at 13:22
  • 1
    You'd modify the height if you wanted to add a logo (that can't be shrunk past a certain size) to the appbar, change the text size, or any number of other things... – lowcrawler Dec 09 '20 at 04:43
0

try this!

const useStyles = makeStyles((theme) => ({
root: {
    flexGrow: 1,
    [theme.breakpoints.down('sm')]: {
        marginBottom: 56,
    },
    [theme.breakpoints.up('sm')]: {
        marginBottom: 64,
    },
},
menuButton: {
    marginRight: theme.spacing(1),
},
title: {
    flexGrow: 1,
}, }))

You can add the above to your code like this

const Navbar = () => {
const classes = useStyles()
return (
    <div className={classes.root}>
        <AppBar position='fixed' color='primary'>
            <Toolbar>
                <IconButton
                    edge='start'
                    className={classes.menuButton}
                    color='inherit'
                    aria-label='menu'>
                    <MenuIcon />
                </IconButton>
                <Typography variant='h6' className={classes.title}>
                    News
                </Typography>
                <Button color='inherit'>Login</Button>
            </Toolbar>
        </AppBar>
    </div>
)}

For more documentation visit material-ui breakpoint customization

0

Shortest trick can be giving position as sticky to Appbar. For reference, you can see the below attached image!

enter image description here

  • It would be best to paste in the code snippet directly rather than linking an image. Additionally, be sure to use helpful link text. – Thenlie Jul 18 '23 at 02:19