You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Ant Design响应式Sider避免内容重排

只用Ant Design组件实现侧边栏推开内容的效果

当然可以!完全不需要依赖Ant Design Mobile的Drawer组件,只用Ant Design PC端的组件就能实现你想要的侧边栏展开时推开内容、避免内部元素重排的效果。官网的移动端侧边栏效果,其实就是用了PC版的Drawer组件或者改造了Sider的样式来实现的,下面给你两种可行方案:

你的当前问题根源

你现在的代码里,SiderContent处于同一流式布局中,当Sider展开/折叠时,它会改变自身宽度,进而挤压Content的可用空间,这就导致了Content内部元素的重排。而你想要的效果是Sider从左侧滑入,视觉上把Content整体向右推开,这需要让Sider脱离文档流,或者通过控制Content的位置来实现。

期望效果:侧边栏从左侧滑入,主内容区域整体向右平移,内部元素保持原有布局不重排
我的折叠状态Sider:侧边栏完全收起,主内容区域占满可用宽度
我的展开状态Sider:侧边栏展开后挤压主内容区域宽度,导致内部元素重排

方案一:使用Ant Design的Drawer组件(推荐,贴近官网效果)

Drawer组件本身就支持从侧边滑入的交互,我们可以配合Content的过渡动画,实现“被推开”的视觉效果,同时避免内部元素重排:

import 'antd/dist/antd.css';
import { Layout, Menu, Icon, Drawer, Button } from 'antd';
import { useState } from 'react';

const { Header, Content } = Layout;

const App = () => {
  // 控制Drawer的显示状态
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);

  return (
    <Layout style={{ minHeight: '100vh' }}>
      {/* 移动端的菜单触发按钮,仅在小屏幕显示 */}
      <Header style={{ padding: 0, display: 'flex', alignItems: 'center' }}>
        <Button 
          type="text" 
          icon="menu" 
          onClick={() => setIsDrawerOpen(true)}
          style={{ color: '#fff', fontSize: '18px' }}
        />
      </Header>

      {/* 主内容区域,添加过渡动画实现平滑推开效果 */}
      <Content 
        style={{ 
          margin: '10px', 
          padding: '15px',
          transition: 'margin-left 0.3s ease-in-out',
          // 根据Drawer状态调整左侧边距
          marginLeft: isDrawerOpen ? '200px' : '0'
        }}
      >
        <ListOfData />
      </Content>

      {/* 侧边栏Drawer */}
      <Drawer
        title="导航菜单"
        placement="left"
        closable={false}
        onClose={() => setIsDrawerOpen(false)}
        visible={isDrawerOpen}
        width={200}
        mask={false} // 不需要遮罩层,让内容和Drawer同时显示
        bodyStyle={{ padding: 0 }}
      >
        <Menu theme="dark" mode="inline" selectedKeys={['1']}>
          <Menu.Item key="1">
            <Icon type="user" />
            <span className="nav-text">nav 1</span>
          </Menu.Item>
          <Menu.Item key="2">
            <Icon type="video-camera" />
            <span className="nav-text">nav 2</span>
          </Menu.Item>
        </Menu>
      </Drawer>
    </Layout>
  );
};

export default App;

方案二:改造现有Sider组件的样式

如果你想继续使用Sider组件,可以通过修改它的定位属性,让它脱离文档流,再配合Content的过渡动画来实现效果:

import 'antd/dist/antd.css';
import { Layout, Menu, Icon } from 'antd';
import { useState } from 'react';

const { Sider, Content } = Layout;

const App = () => {
  const [isCollapsed, setIsCollapsed] = useState(true);

  return (
    <Layout style={{ minHeight: '100vh' }}>
      <Sider
        breakpoint="sm"
        collapsedWidth="0"
        collapsed={isCollapsed}
        onCollapse={(newState) => setIsCollapsed(newState)}
        style={{
          position: 'fixed', // 让Sider脱离文档流,不占用布局空间
          left: 0,
          top: 0,
          height: '100vh',
          zIndex: 1000,
          transition: 'width 0.3s ease-in-out'
        }}
      >
        <Menu theme="dark" mode="inline" selectedKeys={['1']}>
          <Menu.Item key="1">
            <Icon type="user" />
            <span className="nav-text">nav 1</span>
          </Menu.Item>
          <Menu.Item key="2">
            <Icon type="video-camera" />
            <span className="nav-text">nav 2</span>
          </Menu.Item>
        </Menu>
      </Sider>

      <Layout>
        <Content
          style={{
            margin: '10px',
            padding: '15px',
            transition: 'margin-left 0.3s ease-in-out',
            // 根据Sider的折叠状态调整左侧边距
            marginLeft: isCollapsed ? '0' : '200px'
          }}
        >
          <ListOfData />
        </Content>
      </Layout>
    </Layout>
  );
};

export default App;

核心实现要点

  • 脱离文档流:通过position: fixed让Sider/Drawer不占用文档流空间,避免挤压Content的布局。
  • 过渡动画:给Content添加transition: margin-left 0.3s ease-in-out,实现平滑的推开/收回效果。
  • 状态同步:通过状态变量控制侧边栏的显示/隐藏,同时同步修改Content的margin-left值,确保两者交互一致。

这样就能实现你想要的效果:侧边栏展开时,Content整体向右平移,内部元素保持原有布局,不会发生重排。

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

火山引擎 最新活动