AKrush95
AKrush95

Reputation: 1441

Material UI grid with independent scrolling columns

I'm looking to make multiple scrolling columns using Material UI in React. I had a way of doing it in Bootstrap with Flex, but I can't get it to translate over. I have put together a demo of a hacky way to do it that requires knowing the size of the contents above what you're trying to scroll (in this case, the AppBar)

https://codesandbox.io/s/pmly895mm

html,
body {
  margin: 0;
  height: 100%;
}

#root {
  height: 100%;
}

.grid-container {
  height: calc(100% - 64px);
}

.grid-column {
  height: 100%;
  overflow-y: auto;
}

In this demo, I set all of the heights to 100% (html, body, #root) and then created two classes grid-container with a height of 100% - AppBar height and grid-column with a height of 100% and an overflow-y of auto.

In Bootstrap, I would apply these classes to the row and column elements respectively

.flex-section {
  flex-grow: 1;

  display: flex;
  flex-direction: column;

  min-height: 0;
}

.flex-col-scroll {
  flex-grow: 1;

  overflow: auto;

  min-height: 100%;
}

And it wouldn't matter what was above the elements because Flex took care of the heights.

Specifically, I am looking to avoid having to do height: calc(100% - 64px) as this requires me to know the element heights beforehand. I'm going to have some pages where I'd like to put some content above the scrolling area that will have dynamically tall content.

Upvotes: 19

Views: 44834

Answers (5)

Albert
Albert

Reputation: 131

Set the height of each column to 100% and the hidden and scroll properties to each column as appropriate. Something like this:

<Grid
  container
  sx={{
    height: '100%',
  }}
>
  <Grid
    container
    item
    sx={{ height: '100%', overflowX: 'hidden' }}
  >
    <></>
  </Grid>
  <Grid container item sx={{ height: '100%', overflowX: 'auto' }} xs>
    <></>
  </Grid>
</Grid>

Upvotes: 1

user240515
user240515

Reputation: 3207

I found it really difficult to do this with Material UI's Grids because, as was pointed out in a comment to another one of the answers, it doesn't seem to be achievable without "flex-wrap: nowrap", and adding "flex-wrap: nowrap" breaks Material UI's grid layout system.

I did find, however, that I could reproduce Josh Sherman's Layout with fixed header and independently scrolling columns fairly easily if I used Material UI's Boxes instead of Grids.

In index.html:

<style>
  body,
  html,
  #root {
    height: 100%;
  }
</style>

#root is, of course, created by create-react-app.

And in App.tsx:

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

function App() {
  return (
    <>
      <AppBar>
        <Toolbar />
      </AppBar>
      <Box flexDirection="column" display="flex" height="100%">
        <Toolbar />
        <Box flexGrow={1} display="flex" overflow="hidden">
          <Box overflow="auto">
             <!-- The contents of the left column go here -->
          </Box>
          <Box overflow="auto">
            <!-- The contents of the right column go here -->
          </Box>
        </Box>
      </Box>
    </>
  );
}

export default App;

Upvotes: 1

Davis Jones
Davis Jones

Reputation: 1882

2020 Update

FWIW I was just able to add these two style properties to a Box component to achieve a scrollable <div> column:

<Box style={{maxHeight: '100vh', overflow: 'auto'}}>...</Box>

Upvotes: 24

AKrush95
AKrush95

Reputation: 1441

In my determination to recreate how I used to do it in bootstrap (https://jsfiddle.net/aq9Laaew/226591/) I was actually able to get it working in Material UI as well. And since I wasn't able to find any sort of examples of this online for this specific use case (React / Material UI scrollable columns), hopefully this will help someone else.

Here is the example: https://codesandbox.io/s/z24wl3n58m

html,
body {
  margin: 0;
  height: 100%;
}

#root {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.flex-section {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.flex-col-scroll {
  flex-grow: 1;
  overflow: auto;
  min-height: 100%;
}

.flex-no-shrink {
  flex-shrink: 0;
}

What I was missing was setting the flex on the root. Once we do that, then we can utilize flex-section, flex-col-scroll, and flex-no-shrink (the latter of which is used to prevent elements above the scrolling from being compressed)

Upvotes: 14

Sakhi Mansoor
Sakhi Mansoor

Reputation: 8122

You just need to make your navbar fixed. It will remain intact to the top. After that, add a padding to you grid container which is going to have all your content. You can even give percentage padding to make sure responsiveness.

Here is the working codesandbox: Fixed Navbar

Let me know if the issue still persists.

Upvotes: 2

Related Questions