You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现两个垂直堆叠的MUI手风琴占父容器50%且内容独立滚动

解决React MUI手风琴垂直堆叠的固定标题与动态高度需求

核心思路

通过flex布局嵌套结合动态样式控制,实现手风琴的以下行为:

  • 单个手风琴展开时占据父容器全部可用空间
  • 两个手风琴都展开时各占父容器50%高度
  • 手风琴内容溢出时仅内容区滚动,标题(AccordionSummary)保持固定

关键实现步骤

  1. 父容器布局:设置display: flex、flex-direction: column和固定高度,为子元素分配空间提供基础
  2. 手风琴容器动态flex控制:根据其他手风琴的展开状态,动态设置当前手风琴容器的flex属性,实现空间分配逻辑
  3. 重写MUI手风琴组件样式:将Accordion改为flex column布局,固定AccordionSummary高度,让AccordionDetails成为可滚动区域

完整代码示例

import { useState } from 'react';
import { Accordion, AccordionSummary, AccordionDetails, Typography, Box } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';

const StackedAccordions = () => {
  const [expanded, setExpanded] = useState({
    accordion1: false,
    accordion2: false,
  });

  const handleChange = (panel) => (event, isExpanded) => {
    setExpanded(prev => ({ ...prev, [panel]: isExpanded }));
  };

  // 根据展开状态计算当前手风琴容器的flex值
  const getFlexValue = (panel) => {
    const { accordion1, accordion2 } = expanded;
    if (panel === 'accordion1') {
      return !accordion2 ? (accordion1 ? '1 1 auto' : '0 0 auto') : (accordion1 ? '1 1 50%' : '0 0 auto');
    } else {
      return !accordion1 ? (accordion2 ? '1 1 auto' : '0 0 auto') : (accordion2 ? '1 1 50%' : '0 0 auto');
    }
  };

  return (
    <Box sx={{ 
      height: '80vh', 
      display: 'flex', 
      flexDirection: 'column', 
      gap: 2, 
      padding: 2, 
      backgroundColor: '#f5f5f5' 
    }}>
      {/* 第一个手风琴容器 */}
      <Box sx={{ 
        flex: getFlexValue('accordion1'), 
        display: 'flex', 
        flexDirection: 'column', 
        minHeight: 0 
      }}>
        <Accordion
          expanded={expanded.accordion1}
          onChange={handleChange('accordion1')}
          sx={{
            display: 'flex',
            flexDirection: 'column',
            height: '100%',
            overflow: 'hidden',
          }}
        >
          <AccordionSummary
            expandIcon={<ExpandMoreIcon />}
            sx={{ flex: '0 1 auto' }}
          >
            <Typography>手风琴标题 1</Typography>
          </AccordionSummary>
          <AccordionDetails
            sx={{
              flex: '1 1 auto',
              overflowY: 'auto',
              minHeight: 0,
              padding: 2,
            }}
          >
            {/* 模拟长内容 */}
            {Array.from({ length: 50 }).map((_, idx) => (
              <Typography key={idx}>内容行 {idx + 1}</Typography>
            ))}
          </AccordionDetails>
        </Accordion>
      </Box>

      {/* 第二个手风琴容器 */}
      <Box sx={{ 
        flex: getFlexValue('accordion2'), 
        display: 'flex', 
        flexDirection: 'column', 
        minHeight: 0 
      }}>
        <Accordion
          expanded={expanded.accordion2}
          onChange={handleChange('accordion2')}
          sx={{
            display: 'flex',
            flexDirection: 'column',
            height: '100%',
            overflow: 'hidden',
          }}
        >
          <AccordionSummary
            expandIcon={<ExpandMoreIcon />}
            sx={{ flex: '0 1 auto' }}
          >
            <Typography>手风琴标题 2</Typography>
          </AccordionSummary>
          <AccordionDetails
            sx={{
              flex: '1 1 auto',
              overflowY: 'auto',
              minHeight: 0,
              padding: 2,
            }}
          >
            {/* 模拟长内容 */}
            {Array.from({ length: 50 }).map((_, idx) => (
              <Typography key={idx}>内容行 {idx + 1}</Typography>
            ))}
          </AccordionDetails>
        </Accordion>
      </Box>
    </Box>
  );
};

export default StackedAccordions;

关键细节解释

  • flex动态分配:getFlexValue函数根据两个手风琴的展开状态,决定当前容器的空间占比——单个展开时占满剩余空间,两个都展开时各占50%
  • 手风琴内部布局:将Accordion设置为flex-direction: column并高度100%,让Summary固定(flex: 0 1 auto),Details占据剩余空间并开启滚动(overflowY: auto)
  • minHeight: 0:解决flex布局中子元素内容溢出时不触发滚动的问题,这是flex布局的常见特性,必须添加才能让overflow生效

内容的提问来源于stack exchange,提问作者paullc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:35:21