如何在 flexbox 布局上获得溢出滚动条

How to get overflow scrollbar on flexbox layout

我正在使用 React MUI 构建网络聊天。对于布局,我想使用 Flexbox,因为聊天输入设置为自动增长,我希望消息提要容器能够自动调整高度。

但是,我很难让溢出滚动条与 flex 布局一起使用。

  1. 当我将消息长度设置为 20 时,消息提要溢出到容器上方,即使我有 overflowY: "auto"
  2. 也无法获得滚动条

  1. 当我将联系人长度设置为 20 时,它会将内容下推,即使我将根容器设置为 height: '100vh'

我已经阅读了“How can I combine flexbox and vertical scroll in a full-height app?', and 'Scrolling a flexbox with overflowing content', and 'How to make a scrollable container with dynamic height using Flexbox”的答案。使用技巧,例如在父级 div 上设置 overflow: 'hidden',或将 minHeight: 0 设置到列表和提要容器。我仍然无法让它工作。我正在努力获得正确的滚动行为并且不知道我在哪里失踪。请帮忙!

这是代码沙盒:https://codesandbox.io/s/mui-webchat-lsn3tm?file=/demo.js

// ----------------------------------------------------------
const contactLenghth = 10;
const messageLength = 20;
// ----------------------------------------------------------

export default function Chat() {
  return (
    <main
      style={{
        height: "100vh",
        display: "flex",
        flexDirection: "column"
      }}
    >
      <AppBar position="sticky">
        <Toolbar>
          <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
            LOGO
          </Typography>
          <Button color="inherit">Login</Button>
        </Toolbar>
      </AppBar>

      <Grid container direction="row" alignItems="stretch" sx={{ flexGrow: 1 }}>
        <Grid
          item
          md={3}
          sx={{
            display: { xs: "none", sm: "flex" },
            flexDirection: "column",
            overflowY: "auto",
            borderRight: "1px solid lightgrey"
          }}
        >
          <Toolbar>
            <Typography variant="h6"> Contacts </Typography>
          </Toolbar>
          <Divider />
          <List>
            {[...Array(contactLenghth)].map((n, i) => (
              <ListItemButton key={i}>
                <ListItem disablePadding>
                  <ListItemAvatar>
                    <Avatar />
                  </ListItemAvatar>
                  <ListItemText primary={`Contact ${i + 1}`} />
                </ListItem>
              </ListItemButton>
            ))}
          </List>
        </Grid>
        <Grid
          item
          xs={12}
          md={9}
          sx={{ display: "flex", flexDirection: "column" }}
        >
          <Toolbar>
            <Avatar sx={{ mr: 2 }} />
            <ListItemText primary="John Doe" />
          </Toolbar>
          <Divider />

          <Stack
            direction="column"
            spacing={1}
            p={2}
            justifyContent="flex-end"
            sx={{ flexGrow: 1, overflowY: "auto", height: 0 }}
          >
            {[...Array(messageLength)].map((n, i) => (
              <Stack
                key={i}
                direction="row-reverse"
                spacing={2}
                justifyContent="end"
              >
                <Box
                  sx={{
                    px: 2,
                    py: 1,
                    maxWidth: "60%",
                    borderRadius: 20,
                    bgcolor: "secondary.main",
                    color: "#fff"
                  }}
                >
                  <Typography>Test message {i + 1}</Typography>
                </Box>
              </Stack>
            ))}
          </Stack>

          <Stack direction="row" p={2} alignItems="flex-end">
            <TextField
              placeholder="Message"
              fullWidth
              multiline
              maxRows={5}
              sx={{
                flexGrow: 1,
                borderRadius: 7,
                "& fieldset": { borderRadius: 7 }
              }}
            />
            <Box p={1}>
              <IconButton>
                <SendIcon />
              </IconButton>
            </Box>
          </Stack>
        </Grid>
      </Grid>
    </main>
  );
}

问题出在 属性 justifyContent="flex-end" 你的堆栈上。

<Stack
            direction="column"
            spacing={1}
            p={2}
            justifyContent="flex-end"
            sx={{ flexGrow: 1, overflowY: "auto", height: 0 }}
          >

解决方案

您可以将 属性 替换为 direction="column-reverse"。因为,这是一个聊天应用程序。您可以使用 unshift 将消息附加到开始。

备用解决方案:

你可以保持方向为direction="column"。有一个 JS 函数,它会定期检查 div 并将内容滚动到底部

function scrollToBottom(){
    var element = document.getElementById("yourDiv");
    element.scrollTop = element.scrollHeight;
}
//checking every 1sec

window.setInterval(scrollToBottom, 1000)