使用Next.js Layout时页面内容显示在Mantine侧边栏下方的问题
侧边栏与页面内容布局问题(Mantine + Next.js)
我使用mantine.dev为应用创建侧边栏组件,通过Next.js Layout确保它在所有页面显示。链接功能正常,但页面实际内容显示在侧边栏下方而非侧边,效果如图:
应用测试页面截图
Navbar组件代码
export function NavbarSimple() { const { classes, cx } = useStyles(); const [active, setActive] = useState('Dashboard'); const items = data.map((item, index) => ( <Link href={item.link} passHref style={{textDecoration: 'none'}}> <NavLink style={{ textDecoration: 'none' }} key={item.label} // @ts-ignore active={index === active} label={item.label} icon={<item.icon size={16} stroke={1.5} />} // @ts-ignore onClick={() => setActive(index)} /> </Link> )); return ( <Navbar height='100vh' width={{ sm: '28vh' }} p="md" zIndex={0}> <Navbar.Section grow> <Group className={classes.header} position="apart"> <Code sx={{ fontWeight: 700 }}>0.1</Code> </Group> {items} </Navbar.Section> {/* Bottom section Here \/ */} <Navbar.Section className={classes.footer}> <a href="#" className={classes.item} onClick={(event) => event.preventDefault()}> <IconSwitchHorizontal className={classes.linkIcon} stroke={1.5} /> <span>Change account</span> </a> <a href="#" className={classes.item} onClick={(event) => event.preventDefault()}> <IconLogout className={classes.linkIcon} stroke={1.5} /> <span>Logout</span> </a> </Navbar.Section> </Navbar> ); }
Layout代码
import { NavbarSimple } from "./Navbar/Navbar"; export default function Layout({ children }) { return ( <> <NavbarSimple /> <main>{children}</main> </> ) }
我曾尝试使用Mantine的AppShell组件放置Navbar,但不确定如何实现页面切换,且使用时会导致整页重渲染,因此改用Next.js Layout,但仍未解决布局问题。
解决方法
方式1:用Flexbox改造现有Layout
问题根源是Fragment包裹的元素默认是块级垂直排列,给外层容器添加flex布局即可让侧边栏和主内容横向排列:
export default function Layout({ children }) { return ( <div style={{ display: "flex", minHeight: "100vh" }}> <NavbarSimple /> <main style={{ flex: 1, padding: "md" }}>{children}</main> </div> ); }
display: flex让子元素横向排列flex: 1让主内容占满剩余空间minHeight: 100vh确保布局撑满视口高度
方式2:正确使用Mantine AppShell(解决重渲染问题)
之前用AppShell导致整页重渲染,是因为状态管理和页面切换的写法有误,正确用法如下:
- 改造AppShell布局:
import { AppShell } from "@mantine/core"; import { NavbarSimple } from "./Navbar/Navbar"; export default function AppShellLayout({ children }) { return ( <AppShell navbar={<NavbarSimple />} navbarWidth={{ sm: 220, md: 280 }} padding="md" > <AppShell.Main>{children}</AppShell.Main> </AppShell> ); }
- 优化Navbar的active状态判断(用Next.js路由替代手动state):
import { usePathname } from "next/navigation"; // 导入路由钩子 export function NavbarSimple() { const { classes, cx } = useStyles(); const pathname = usePathname(); // 获取当前路由路径 const items = data.map((item) => ( <Link href={item.link} passHref style={{textDecoration: 'none'}}> <NavLink style={{ textDecoration: 'none' }} key={item.label} active={pathname === item.link} // 用当前路径判断激活状态 label={item.label} icon={<item.icon size={16} stroke={1.5} />} /> </Link> )); // 其余代码保持不变... }
这样页面切换时只会更新AppShell.Main里的内容,不会触发整页重渲染,同时active状态判断更准确。
内容的提问来源于stack exchange,提问作者pratheek78
相关产品推荐
相关产品推荐

