Handling the overall layout of a page.
The first level navigation is left aligned near a logo, and the secondary menu is right aligned.
64px
, the second level navigation 48px
.80px
, the second level navigation 56px
.48+8n
.200+8n
.Style of a navigation should conform to its level.
Emphasis by colorblock
When background color is a deep color, you can use this pattern for the parent level navigation item of the current page.
The highlight match stick
When background color is a light color, you can use this pattern for the current page navigation item; we recommend using it for the last item of the navigation path.
Highlighted font
From the visualization aspect, a highlighted font is stronger than colorblock; this pattern is often used for the parent level of the current item.
Enlarge the size of the font
12px
, 14px
is a standard font size of navigation's, 14px
is used for the first and the second level of the navigation. You can choose an appropriate font size regarding the level of your navigation.
Layout
: The layout wrapper, in which Header
Sider
Content
Footer
or Layout
itself can be nested, and can be placed in any parent container.Header
: The top layout with the default style, in which any element can be nested, and must be placed in Layout
.Sider
: The sidebar with default style and basic functions, in which any element can be nested, and must be placed in Layout
.Content
: The content layout with the default style, in which any element can be nested, and must be placed in Layout
.Footer
: The bottom layout with the default style, in which any element can be nested, and must be placed in Layout
.Based on
flex layout
, please pay attention to the compatibility.
import React from 'react';
import { Layout, Space } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
const headerStyle: React.CSSProperties = {
textAlign: 'center',
color: '#fff',
height: 64,
paddingInline: 50,
lineHeight: '64px',
backgroundColor: '#7dbcea',
};
const contentStyle: React.CSSProperties = {
textAlign: 'center',
minHeight: 120,
lineHeight: '120px',
color: '#fff',
backgroundColor: '#108ee9',
};
const siderStyle: React.CSSProperties = {
textAlign: 'center',
lineHeight: '120px',
color: '#fff',
backgroundColor: '#3ba0e9',
};
const footerStyle: React.CSSProperties = {
textAlign: 'center',
color: '#fff',
backgroundColor: '#7dbcea',
};
const App: React.FC = () => (
<Space direction="vertical" style={{ width: '100%' }} size={[0, 48]}>
<Layout>
<Header style={headerStyle}>Header</Header>
<Content style={contentStyle}>Content</Content>
<Footer style={footerStyle}>Footer</Footer>
</Layout>
<Layout>
<Header style={headerStyle}>Header</Header>
<Layout>
<Sider style={siderStyle}>Sider</Sider>
<Content style={contentStyle}>Content</Content>
</Layout>
<Footer style={footerStyle}>Footer</Footer>
</Layout>
<Layout>
<Header style={headerStyle}>Header</Header>
<Layout>
<Content style={contentStyle}>Content</Content>
<Sider style={siderStyle}>Sider</Sider>
</Layout>
<Footer style={footerStyle}>Footer</Footer>
</Layout>
<Layout>
<Sider style={siderStyle}>Sider</Sider>
<Layout>
<Header style={headerStyle}>Header</Header>
<Content style={contentStyle}>Content</Content>
<Footer style={footerStyle}>Footer</Footer>
</Layout>
</Layout>
</Space>
);
export default App;
import React from 'react';
import { Breadcrumb, Layout, Menu, theme } from 'antd';
const { Header, Content, Footer } = Layout;
const App: React.FC = () => {
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout className="layout">
<Header>
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
items={new Array(15).fill(null).map((_, index) => {
const key = index + 1;
return {
key,
label: `nav ${key}`,
};
})}
/>
</Header>
<Content style={{ padding: '0 50px' }}>
<Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<div className="site-layout-content" style={{ background: colorBgContainer }}>
Content
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2023 Created by Ant UED</Footer>
</Layout>
);
};
export default App;
.site-layout-content {
min-height: 280px;
padding: 24px;
}
#components-layout-demo-top .logo {
float: left;
width: 120px;
height: 31px;
margin: 16px 24px 16px 0;
background: rgba(255, 255, 255, 0.3);
}
.ant-row-rtl #components-layout-demo-top .logo {
float: right;
margin: 16px 0 16px 24px;
}
import React from 'react';
import { LaptopOutlined, NotificationOutlined, UserOutlined } from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Breadcrumb, Layout, Menu, theme } from 'antd';
const { Header, Content, Sider } = Layout;
const items1: MenuProps['items'] = ['1', '2', '3'].map((key) => ({
key,
label: `nav ${key}`,
}));
const items2: MenuProps['items'] = [UserOutlined, LaptopOutlined, NotificationOutlined].map(
(icon, index) => {
const key = String(index + 1);
return {
key: `sub${key}`,
icon: React.createElement(icon),
label: `subnav ${key}`,
children: new Array(4).fill(null).map((_, j) => {
const subKey = index * 4 + j + 1;
return {
key: subKey,
label: `option${subKey}`,
};
}),
};
},
);
const App: React.FC = () => {
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout>
<Header className="header">
<div className="logo" />
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']} items={items1} />
</Header>
<Layout>
<Sider width={200} style={{ background: colorBgContainer }}>
<Menu
mode="inline"
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
style={{ height: '100%', borderRight: 0 }}
items={items2}
/>
</Sider>
<Layout style={{ padding: '0 24px 24px' }}>
<Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<Content
style={{
padding: 24,
margin: 0,
minHeight: 280,
background: colorBgContainer,
}}
>
Content
</Content>
</Layout>
</Layout>
</Layout>
);
};
export default App;
#components-layout-demo-top-side-2 .logo {
float: left;
width: 120px;
height: 31px;
margin: 16px 24px 16px 0;
background: rgba(255, 255, 255, 0.3);
}
.ant-row-rtl #components-layout-demo-top-side-2 .logo {
float: right;
margin: 16px 0 16px 24px;
}
import React from 'react';
import { LaptopOutlined, NotificationOutlined, UserOutlined } from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Breadcrumb, Layout, Menu, theme } from 'antd';
const { Header, Content, Footer, Sider } = Layout;
const items1: MenuProps['items'] = ['1', '2', '3'].map((key) => ({
key,
label: `nav ${key}`,
}));
const items2: MenuProps['items'] = [UserOutlined, LaptopOutlined, NotificationOutlined].map(
(icon, index) => {
const key = String(index + 1);
return {
key: `sub${key}`,
icon: React.createElement(icon),
label: `subnav ${key}`,
children: new Array(4).fill(null).map((_, j) => {
const subKey = index * 4 + j + 1;
return {
key: subKey,
label: `option${subKey}`,
};
}),
};
},
);
const App: React.FC = () => {
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout>
<Header className="header">
<div className="logo" />
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']} items={items1} />
</Header>
<Content style={{ padding: '0 50px' }}>
<Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<Layout style={{ padding: '24px 0', background: colorBgContainer }}>
<Sider style={{ background: colorBgContainer }} width={200}>
<Menu
mode="inline"
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
style={{ height: '100%' }}
items={items2}
/>
</Sider>
<Content style={{ padding: '0 24px', minHeight: 280 }}>Content</Content>
</Layout>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2023 Created by Ant UED</Footer>
</Layout>
);
};
export default App;
#components-layout-demo-top-side .logo {
float: left;
width: 120px;
height: 31px;
margin: 16px 24px 16px 0;
background: rgba(255, 255, 255, 0.3);
}
.ant-row-rtl #components-layout-demo-top-side .logo {
float: right;
margin: 16px 0 16px 24px;
}
import React, { useState } from 'react';
import {
DesktopOutlined,
FileOutlined,
PieChartOutlined,
TeamOutlined,
UserOutlined,
} from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Breadcrumb, Layout, Menu, theme } from 'antd';
const { Header, Content, Footer, Sider } = Layout;
type MenuItem = Required<MenuProps>['items'][number];
function getItem(
label: React.ReactNode,
key: React.Key,
icon?: React.ReactNode,
children?: MenuItem[],
): MenuItem {
return {
key,
icon,
children,
label,
} as MenuItem;
}
const items: MenuItem[] = [
getItem('Option 1', '1', <PieChartOutlined />),
getItem('Option 2', '2', <DesktopOutlined />),
getItem('User', 'sub1', <UserOutlined />, [
getItem('Tom', '3'),
getItem('Bill', '4'),
getItem('Alex', '5'),
]),
getItem('Team', 'sub2', <TeamOutlined />, [getItem('Team 1', '6'), getItem('Team 2', '8')]),
getItem('Files', '9', <FileOutlined />),
];
const App: React.FC = () => {
const [collapsed, setCollapsed] = useState(false);
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout style={{ minHeight: '100vh' }}>
<Sider collapsible collapsed={collapsed} onCollapse={(value) => setCollapsed(value)}>
<div style={{ height: 32, margin: 16, background: 'rgba(255, 255, 255, 0.2)' }} />
<Menu theme="dark" defaultSelectedKeys={['1']} mode="inline" items={items} />
</Sider>
<Layout className="site-layout">
<Header style={{ padding: 0, background: colorBgContainer }} />
<Content style={{ margin: '0 16px' }}>
<Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>User</Breadcrumb.Item>
<Breadcrumb.Item>Bill</Breadcrumb.Item>
</Breadcrumb>
<div style={{ padding: 24, minHeight: 360, background: colorBgContainer }}>
Bill is a cat.
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2023 Created by Ant UED</Footer>
</Layout>
</Layout>
);
};
export default App;
import React, { useState } from 'react';
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
UploadOutlined,
UserOutlined,
VideoCameraOutlined,
} from '@ant-design/icons';
import { Layout, Menu, theme } from 'antd';
const { Header, Sider, Content } = Layout;
const App: React.FC = () => {
const [collapsed, setCollapsed] = useState(false);
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout>
<Sider trigger={null} collapsible collapsed={collapsed}>
<div className="logo" />
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['1']}
items={[
{
key: '1',
icon: <UserOutlined />,
label: 'nav 1',
},
{
key: '2',
icon: <VideoCameraOutlined />,
label: 'nav 2',
},
{
key: '3',
icon: <UploadOutlined />,
label: 'nav 3',
},
]}
/>
</Sider>
<Layout className="site-layout">
<Header style={{ padding: 0, background: colorBgContainer }}>
{React.createElement(collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, {
className: 'trigger',
onClick: () => setCollapsed(!collapsed),
})}
</Header>
<Content
style={{
margin: '24px 16px',
padding: 24,
minHeight: 280,
background: colorBgContainer,
}}
>
Content
</Content>
</Layout>
</Layout>
);
};
export default App;
#components-layout-demo-custom-trigger .trigger {
padding: 0 24px;
font-size: 18px;
line-height: 64px;
cursor: pointer;
transition: color 0.3s;
}
#components-layout-demo-custom-trigger .trigger:hover {
color: #1890ff;
}
#components-layout-demo-custom-trigger .logo {
height: 32px;
margin: 16px;
background: rgba(255, 255, 255, 0.3);
}
import React from 'react';
import { UploadOutlined, UserOutlined, VideoCameraOutlined } from '@ant-design/icons';
import { Layout, Menu, theme } from 'antd';
const { Header, Content, Footer, Sider } = Layout;
const App: React.FC = () => {
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout>
<Sider
breakpoint="lg"
collapsedWidth="0"
onBreakpoint={(broken) => {
console.log(broken);
}}
onCollapse={(collapsed, type) => {
console.log(collapsed, type);
}}
>
<div className="logo" />
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['4']}
items={[UserOutlined, VideoCameraOutlined, UploadOutlined, UserOutlined].map(
(icon, index) => ({
key: String(index + 1),
icon: React.createElement(icon),
label: `nav ${index + 1}`,
}),
)}
/>
</Sider>
<Layout>
<Header style={{ padding: 0, background: colorBgContainer }} />
<Content style={{ margin: '24px 16px 0' }}>
<div style={{ padding: 24, minHeight: 360, background: colorBgContainer }}>content</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2023 Created by Ant UED</Footer>
</Layout>
</Layout>
);
};
export default App;
#components-layout-demo-responsive .logo {
height: 32px;
margin: 16px;
background: rgba(255, 255, 255, 0.2);
}
import React from 'react';
import { Breadcrumb, Layout, Menu, theme } from 'antd';
const { Header, Content, Footer } = Layout;
const App: React.FC = () => {
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout>
<Header style={{ position: 'sticky', top: 0, zIndex: 1, width: '100%' }}>
<div
style={{
float: 'left',
width: 120,
height: 31,
margin: '16px 24px 16px 0',
background: 'rgba(255, 255, 255, 0.2)',
}}
/>
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
items={new Array(3).fill(null).map((_, index) => ({
key: String(index + 1),
label: `nav ${index + 1}`,
}))}
/>
</Header>
<Content className="site-layout" style={{ padding: '0 50px' }}>
<Breadcrumb style={{ margin: '16px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<div style={{ padding: 24, minHeight: 380, background: colorBgContainer }}>Content</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2023 Created by Ant UED</Footer>
</Layout>
);
};
export default App;
import React from 'react';
import {
AppstoreOutlined,
BarChartOutlined,
CloudOutlined,
ShopOutlined,
TeamOutlined,
UploadOutlined,
UserOutlined,
VideoCameraOutlined,
} from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Layout, Menu, theme } from 'antd';
const { Header, Content, Footer, Sider } = Layout;
const items: MenuProps['items'] = [
UserOutlined,
VideoCameraOutlined,
UploadOutlined,
BarChartOutlined,
CloudOutlined,
AppstoreOutlined,
TeamOutlined,
ShopOutlined,
].map((icon, index) => ({
key: String(index + 1),
icon: React.createElement(icon),
label: `nav ${index + 1}`,
}));
const App: React.FC = () => {
const {
token: { colorBgContainer },
} = theme.useToken();
return (
<Layout hasSider>
<Sider
style={{
overflow: 'auto',
height: '100vh',
position: 'fixed',
left: 0,
top: 0,
bottom: 0,
}}
>
<div style={{ height: 32, margin: 16, background: 'rgba(255, 255, 255, 0.2)' }} />
<Menu theme="dark" mode="inline" defaultSelectedKeys={['4']} items={items} />
</Sider>
<Layout className="site-layout" style={{ marginLeft: 200 }}>
<Header style={{ padding: 0, background: colorBgContainer }} />
<Content style={{ margin: '24px 16px 0', overflow: 'initial' }}>
<div style={{ padding: 24, textAlign: 'center', background: colorBgContainer }}>
<p>long content</p>
{
// indicates very long content
Array.from({ length: 100 }, (_, index) => (
<React.Fragment key={index}>
{index % 20 === 0 && index ? 'more' : '...'}
<br />
</React.Fragment>
))
}
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2023 Created by Ant UED</Footer>
</Layout>
</Layout>
);
};
export default App;
<Layout><Header>header</Header><Layout><Sider>left sidebar</Sider><Content>main content</Content><Sider>right sidebar</Sider></Layout><Footer>footer</Footer></Layout>
The wrapper.
Property | Description | Type | Default |
---|---|---|---|
className | Container className | string | - |
hasSider | Whether contain Sider in children, don't have to assign it normally. Useful in ssr avoid style flickering | boolean | - |
style | To customize the styles | CSSProperties | - |
The sidebar.
Property | Description | Type | Default |
---|---|---|---|
breakpoint | Breakpoints of the responsive layout | xs | sm | md | lg | xl | xxl | - |
className | Container className | string | - |
collapsed | To set the current status | boolean | - |
collapsedWidth | Width of the collapsed sidebar, by setting to 0 a special trigger will appear | number | 80 |
collapsible | Whether can be collapsed | boolean | false |
defaultCollapsed | To set the initial status | boolean | false |
reverseArrow | Reverse direction of arrow, for a sider that expands from the right | boolean | false |
style | To customize the styles | CSSProperties | - |
theme | Color theme of the sidebar | light | dark | dark |
trigger | Specify the customized trigger, set to null to hide the trigger | ReactNode | - |
width | Width of the sidebar | number | string | 200 |
zeroWidthTriggerStyle | To customize the styles of the special trigger that appears when collapsedWidth is 0 | object | - |
onBreakpoint | The callback function, executed when breakpoints changed | (broken) => {} | - |
onCollapse | The callback function, executed by clicking the trigger or activating the responsive layout | (collapsed, type) => {} | - |
{xs: '480px',sm: '576px',md: '768px',lg: '992px',xl: '1200px',xxl: '1600px',}