Material UI网格与独立滚动列

18

我希望使用 React 中的 Material UI 制作多个滚动列。在使用 flex 在 bootstrap 中实现过一种方法,但无法转换到 Material UI 中。我已经组合了一个示例来实现它,但这种方式很糟糕,需要知道你要滚动内容的上方的大小(在此示例中为 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;
}
在此演示中,我将所有高度设置为100%(html,body,#root),然后创建了两个类 grid-container ,其高度为100%- AppBar 高度,以及grid-column,其高度为100%并且具有自动的overflow-y。
在Bootstrap中,我将分别应用这些类于rowcolumn元素。
.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 可以处理高度,所以它并不重要。

具体来说,我想避免使用 height: calc(100% - 64px),因为这需要我事先知道元素的高度。在某些页面中,我想在滚动区域上方放置一些具有动态高度内容的内容。


你想通过JSS应用CSS吗? - Sakhi Mansoor
@SakhiMansoor 我知道如何将其翻译为JSS,这不是问题。我正在寻找一种更动态的完成方式。我将有一些页面不仅在顶部有AppBar,并且我宁愿不计算元素的高度(特别是如果它可以变化)。这就是我喜欢使用flexbox的原因。 - AKrush95
我还不确定你的实际关注点是什么。对于我的误解,我感到很抱歉。您的代码即使只使用“100%高度”替换calc也可以正常工作。 - Sakhi Mansoor
抱歉我表达不够清晰。当您删除calc,只使用100%时,底部会出现一些额外的滚动条。您将被卡在向下滚动到列底部的位置,然后会剩下64px,然后您可以再次滚动并隐藏AppBar https://codesandbox.io/s/kow9ww5kj5。 - AKrush95
4个回答

23

2020 更新

顺便说一句,我刚刚成功地将这两个样式属性添加到一个 Box 组件中,以实现可滚动的 <div> 列:

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

2
也适用于Grid - yoges nsamy
Davis谢谢你! @yogesnsamy 除非你将它垂直居中 xD - Uros Randelovic

13

在我努力模仿bootstrap做法的决心下(https://jsfiddle.net/aq9Laaew/226591/),我实际上也把它成功地用在了Material UI上。由于我在这个特定案例(React / Material UI可滚动列)中没有找到任何示例,希望这能对其他人有所帮助。

这里是示例: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;
}

我所缺失的是在根元素上设置 flex。一旦我们这样做了,那么我们就可以利用 flex-sectionflex-col-scrollflex-no-shrink(后者用于防止滚动区域上方的元素被压缩)


1
感谢您分享您的解决方案。它对我很有帮助。对于material-ui 1.5.1,我需要在flex-section类中添加flex-wrap: nowrap。此外,我还需要删除flex-direction: column - kokeksibir
1
谢谢你。不过我有一个问题...如果h1标签中的文本稍微长一点,似乎就会出错。你能帮忙吗? - asgerhallas
这非常有帮助!非常感谢。 - Philippe

2

您只需要使您的导航条固定即可。它将保持不变到顶部。之后,为您将拥有所有内容的 grid容器 添加填充。您甚至可以给出百分比填充来确保响应性。

这是工作的codesandbox:Fixed Navbar

如果问题仍然存在,请告诉我。


1
谢谢您的回复。这是我想要实现的完美例子。然而,我不认为将栏固定与静态会有所帮助。现在它是静态的,你必须给每个视图添加填充来消除重叠。接下来,您在初始网格上方添加了一些文本。那很好。那也是我想要做到的。但是,正如您所看到的,现在主视图以及两列都有另一个滚动条。这可以通过向.grid-container添加height: calc(100% - 36px);来补偿新行的额外空间。 - AKrush95
然而,这让我回到了最初的问题,即我不想计算/确定可滚动内容上方的内容高度;如果我能像使用flexbox那样动态地做到这一点,那就太好了。我将组合一个例子来演示它在bootstrap中是如何工作的。也许那会有所帮助。 - AKrush95
我其实认为,在我努力创建 Bootstrap 版本的过程中,我已经找到了答案(请参见此处:https://jsfiddle.net/aq9Laaew/226591/)。 - AKrush95

1

我发现使用Material UI的网格布局非常困难,因为正如另一个答案的评论所指出的那样,在没有 "flex-wrap: nowrap" 的情况下似乎无法实现,而添加 "flex-wrap: nowrap" 会破坏Material UI的网格布局系统。

然而,我发现如果我使用Material UI的盒子(Boxes)而不是网格(Grids),我可以相当容易地复制Josh Sherman的 带有固定标题和独立滚动列的布局

在index.html中:

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

#root 当然是由 create-react-app 创建的。

而在 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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接