Overview
Layout: Layout containers. You can nest Header Sider Content Footer or Layout itself inside.
Header: Head component, can only be used inside Layout.
Sider: Sidebar, can only be used inside Layout.
Content: Content component, can only be used inside Layout.
Footer: Footer component, can only be used inside Layout.
Notice
1、Layout components are implemented with Flex layout. Browser compatibility may need to be considered.
2、The Layout component will only help you implement the layout, but will not include styles such as background color, text color, width and height. You can pass in style according to your actual needs or write a separate css implementation given a specific class name
Demos
How to import
< script lang = "ts" >
import { Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider } from '@fibrae/semi-ui-svelte' ;
</ script >
The subcomponents are LayoutHeader, LayoutSider, LayoutContent and LayoutFooter, which stand for Layout.Header, Layout.Sider, Layout.Content and Layout.Footer below, and are imported by name.
Three-section Layout
Code Copy code < script lang = "ts" >
import { Layout, LayoutContent, LayoutFooter, LayoutHeader } from '@fibrae/semi-ui-svelte' ;
const commonStyle = 'height: 64px; line-height: 64px; background: var(--semi-color-fill-0)' ;
</ script >
< Layout class = "components-layout-demo" >
< LayoutHeader style ={commonStyle}>Header</ LayoutHeader >
< LayoutContent style = "height: 300px; line-height: 300px" >Content</ LayoutContent >
< LayoutFooter style ={commonStyle}>Footer</ LayoutFooter >
</ Layout >
Code Copy code < script lang = "ts" >
import { Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider } from '@fibrae/semi-ui-svelte' ;
const commonStyle = 'height: 64px; line-height: 64px; background: var(--semi-color-fill-0)' ;
</ script >
< Layout class = "components-layout-demo" >
< LayoutHeader style ={commonStyle}>Header</ LayoutHeader >
< Layout >
< LayoutSider style = "width: 120px; background: var(--semi-color-fill-2)" >Sider</ LayoutSider >
< LayoutContent style = "height: 300px; line-height: 300px" >Content</ LayoutContent >
</ Layout >
< LayoutFooter style ={commonStyle}>Footer</ LayoutFooter >
</ Layout >
Code Copy code < script lang = "ts" >
import { Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider } from '@fibrae/semi-ui-svelte' ;
const commonStyle = 'height: 64px; line-height: 64px; background: var(--semi-color-fill-0)' ;
</ script >
< Layout class = "components-layout-demo" >
< LayoutHeader style ={commonStyle}>Header</ LayoutHeader >
< Layout >
< LayoutContent style = "height: 300px; line-height: 300px" >Content</ LayoutContent >
< LayoutSider style = "width: 120px; background: var(--semi-color-fill-2)" >Sider</ LayoutSider >
</ Layout >
< LayoutFooter style ={commonStyle}>Footer</ LayoutFooter >
</ Layout >
Code Copy code < script lang = "ts" >
import { Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider } from '@fibrae/semi-ui-svelte' ;
const commonStyle = 'height: 64px; line-height: 64px; background: var(--semi-color-fill-0)' ;
</ script >
< Layout class = "components-layout-demo" >
< LayoutSider style = "width: 120px; background: var(--semi-color-fill-2)" >Sider</ LayoutSider >
< Layout >
< LayoutHeader style ={commonStyle}>Header</ LayoutHeader >
< LayoutContent style = "height: 300px; line-height: 300px" >Content</ LayoutContent >
< LayoutFooter style ={commonStyle}>Footer</ LayoutFooter >
</ Layout >
</ Layout >
Responsive Layout
Six response sizes are preset in the sidebar: xs,sm,md,lg,xl,xxl. You can use breakpoint to set breakpoints.
Use onBreakpoint to call callback functions.
Code Copy code < script lang = "ts" >
import { Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider } from '@fibrae/semi-ui-svelte' ;
const commonStyle = 'height: 64px; line-height: 64px; background: var(--semi-color-fill-0)' ;
</ script >
< Layout class = "components-layout-demo" >
< LayoutHeader style ={commonStyle}>Header</ LayoutHeader >
< Layout >
< LayoutSider breakpoint ={[ 'md' ]} onBreakpoint ={( screen , matches ) => console. log (screen, matches)} style = "width: 120px; background: var(--semi-color-fill-2)" >Sider</ LayoutSider >
< LayoutContent style = "height: 300px; line-height: 300px" >Content</ LayoutContent >
</ Layout >
< LayoutFooter style ={commonStyle}>Footer</ LayoutFooter >
</ Layout >
Layout Examples
Top-nav Layout
首页 / 当这个页面标题很长时需要省略 / 上一页 / 详情页 Code Copy code < script lang = "ts" >
import { IconBell, IconBytedanceLogo, IconHelpCircle, IconHome, IconLive, IconSemiLogo, IconSetting } from '@fibrae/semi-icons-svelte' ;
import { Avatar, Breadcrumb, Button, Layout, LayoutContent, LayoutFooter, LayoutHeader, Nav, NavFooter, NavHeader, NavItem, Skeleton, SkeletonParagraph } from '@fibrae/semi-ui-svelte' ;
const routes = [ '首页' , '当这个页面标题很长时需要省略' , '上一页' , '详情页' ];
const actionStyle = 'color: var(--semi-color-text-2); margin-inline-end: 12px' ;
</ script >
{# snippet header ()}
< NavHeader >
< IconSemiLogo style = "font-size: 36px" />
</ NavHeader >
{/ snippet }
{# snippet footer ()}
< NavFooter >
< Button aria-label = "通知" style ={actionStyle} theme = "borderless" >
{# snippet icon ()}
< IconBell size = "large" />
{/ snippet }
</ Button >
< Button aria-label = "帮助" style ={actionStyle} theme = "borderless" >
{# snippet icon ()}
< IconHelpCircle size = "large" />
{/ snippet }
</ Button >
< Avatar color = "orange" size = "small" >YJ</ Avatar >
</ NavFooter >
{/ snippet }
< Layout style = "border: 1px solid var(--semi-color-border)" >
< LayoutHeader style = "background-color: var(--semi-color-bg-1)" >
< div >
< Nav { footer } { header } mode = "horizontal" selectedKeys ={[ 'Home' ]}>
< NavItem itemKey = "Home" text = "首页" >
{# snippet icon ()}
< IconHome size = "large" />
{/ snippet }
</ NavItem >
< NavItem itemKey = "Live" text = "直播" >
{# snippet icon ()}
< IconLive size = "large" />
{/ snippet }
</ NavItem >
< NavItem itemKey = "Setting" text = "设置" >
{# snippet icon ()}
< IconSetting size = "large" />
{/ snippet }
</ NavItem >
</ Nav >
</ div >
</ LayoutHeader >
< LayoutContent style = "padding: 24px; background-color: var(--semi-color-bg-0)" >
< Breadcrumb { routes } style = "margin-bottom: 24px" />
< div style = "border-radius: 10px; border: 1px solid var(--semi-color-border); height: 376px; padding: 32px" >
< Skeleton loading >
{# snippet placeholder ()}
< SkeletonParagraph rows ={ 2 } />
{/ snippet }
< p >Hi, Bytedance dance dance.</ p >
< p >Hi, Bytedance dance dance.</ p >
</ Skeleton >
</ div >
</ LayoutContent >
< LayoutFooter style = "display: flex; justify-content: space-between; padding: 20px; color: var(--semi-color-text-2); background-color: var(--semi-grey-0)" >
< span style = "display: flex; align-items: center" >
< IconBytedanceLogo size = "large" style = "margin-inline-end: 8px" />
< span >Copyright © 2023 ByteDance. All Rights Reserved. </ span >
</ span >
< span >
< span style = "margin-inline-end: 24px" >平台客服</ span >
< span >反馈建议</ span >
</ span >
</ LayoutFooter >
</ Layout >
首页 / 当这个页面标题很长时需要省略 / 上一页 / 详情页 Code Copy code < script lang = "ts" >
import { IconBell, IconBytedanceLogo, IconHelpCircle, IconHistogram, IconHome, IconLive, IconSemiLogo, IconSetting } from '@fibrae/semi-icons-svelte' ;
import { Avatar, Breadcrumb, Button, Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider, Nav, NavFooter, NavHeader, Skeleton, SkeletonParagraph, type NavItems } from '@fibrae/semi-ui-svelte' ;
const items : NavItems = [
{ itemKey: 'Home' , text: '首页' },
{ itemKey: 'Histogram' , text: '基础数据' },
{ itemKey: 'Live' , text: '测试功能' },
{ itemKey: 'Setting' , text: '设置' },
];
const icons = { Home: IconHome, Histogram: IconHistogram, Live: IconLive, Setting: IconSetting };
const routes = [ '首页' , '当这个页面标题很长时需要省略' , '上一页' , '详情页' ];
const actionStyle = 'color: var(--semi-color-text-2); margin-inline-end: 12px' ;
</ script >
{# snippet topHeader ()}
< NavHeader >
< IconSemiLogo style = "height: 36px; font-size: 36px" />
</ NavHeader >
{/ snippet }
{# snippet topFooter ()}
< NavFooter >
< Button aria-label = "通知" style ={actionStyle} theme = "borderless" >
{# snippet icon ()}
< IconBell size = "large" />
{/ snippet }
</ Button >
< Button aria-label = "帮助" style ={actionStyle} theme = "borderless" >
{# snippet icon ()}
< IconHelpCircle size = "large" />
{/ snippet }
</ Button >
< Avatar color = "orange" size = "small" >YJ</ Avatar >
</ NavFooter >
{/ snippet }
< Layout style = "border: 1px solid var(--semi-color-border)" >
< LayoutHeader style = "background-color: var(--semi-color-bg-1)" >
< div >
< Nav aria-label = "顶部导航" footer ={topFooter} header ={topHeader} mode = "horizontal" selectedKeys ={[ 'Home' ]}>
<!-- Nav renders its children straight into the list, so other content needs its own li -->
< li style = "display: contents" >
< span style = "color: var(--semi-color-text-2)" >
< span style = "margin-inline-end: 24px; color: var(--semi-color-text-0); font-weight: 600" >模版推荐</ span >
< span style = "margin-inline-end: 24px" >所有模版</ span >
< span >我的模版</ span >
</ span >
</ li >
</ Nav >
</ div >
</ LayoutHeader >
< Layout >
< LayoutSider style = "background-color: var(--semi-color-bg-1)" >
< Nav aria-label = "侧边导航" footer ={{ collapseButton: true }} { items } selectedKeys ={[ 'Home' ]} style = "max-width: 220px; height: 100%" >
{# snippet icon ({ item })}
{@ const Icon = icons[item.itemKey as keyof typeof icons]}
< Icon size = "large" />
{/ snippet }
</ Nav >
</ LayoutSider >
< LayoutContent style = "padding: 24px; background-color: var(--semi-color-bg-0)" >
< Breadcrumb { routes } style = "margin-bottom: 24px" />
< div style = "border-radius: 10px; border: 1px solid var(--semi-color-border); height: 376px; padding: 32px" >
< Skeleton loading >
{# snippet placeholder ()}
< SkeletonParagraph rows ={ 2 } />
{/ snippet }
< p >Hi, Bytedance dance dance.</ p >
< p >Hi, Bytedance dance dance.</ p >
</ Skeleton >
</ div >
</ LayoutContent >
</ Layout >
< LayoutFooter style = "display: flex; justify-content: space-between; padding: 20px; color: var(--semi-color-text-2); background-color: var(--semi-grey-0)" >
< span style = "display: flex; align-items: center" >
< IconBytedanceLogo size = "large" style = "margin-inline-end: 8px" />
< span >Copyright © 2023 ByteDance. All Rights Reserved. </ span >
</ span >
< span >
< span style = "margin-inline-end: 24px" >平台客服</ span >
< span >反馈建议</ span >
</ span >
</ LayoutFooter >
</ Layout >
首页 / 当这个页面标题很长时需要省略 / 上一页 / 详情页 Code Copy code < script lang = "ts" >
import { IconBell, IconBytedanceLogo, IconHelpCircle, IconHistogram, IconHome, IconLive, IconSemiLogo, IconSetting } from '@fibrae/semi-icons-svelte' ;
import { Avatar, Breadcrumb, Button, Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider, Nav, NavFooter, NavHeader, Skeleton, SkeletonParagraph, type NavItems } from '@fibrae/semi-ui-svelte' ;
const items : NavItems = [
{ itemKey: 'Home' , text: '首页' },
{ itemKey: 'Histogram' , text: '基础数据' },
{ itemKey: 'Live' , text: '测试功能' },
{ itemKey: 'Setting' , text: '设置' },
];
const icons = { Home: IconHome, Histogram: IconHistogram, Live: IconLive, Setting: IconSetting };
const routes = [ '首页' , '当这个页面标题很长时需要省略' , '上一页' , '详情页' ];
const actionStyle = 'color: var(--semi-color-text-2); margin-inline-end: 12px' ;
</ script >
{# snippet sideHeader ()}
< NavHeader text = "Semi Design" >
{# snippet logo ()}
< IconSemiLogo style = "font-size: 36px" />
{/ snippet }
</ NavHeader >
{/ snippet }
{# snippet topFooter ()}
< NavFooter >
< Button aria-label = "通知" style ={actionStyle} theme = "borderless" >
{# snippet icon ()}
< IconBell size = "large" />
{/ snippet }
</ Button >
< Button aria-label = "帮助" style ={actionStyle} theme = "borderless" >
{# snippet icon ()}
< IconHelpCircle size = "large" />
{/ snippet }
</ Button >
< Avatar color = "orange" size = "small" >YJ</ Avatar >
</ NavFooter >
{/ snippet }
< Layout style = "border: 1px solid var(--semi-color-border)" >
< LayoutSider style = "background-color: var(--semi-color-bg-1)" >
< Nav aria-label = "侧边导航" footer ={{ collapseButton: true }} header ={sideHeader} { items } selectedKeys ={[ 'Home' ]} style = "max-width: 220px; height: 100%" >
{# snippet icon ({ item })}
{@ const Icon = icons[item.itemKey as keyof typeof icons]}
< Icon size = "large" />
{/ snippet }
</ Nav >
</ LayoutSider >
< Layout >
< LayoutHeader style = "background-color: var(--semi-color-bg-1)" >
< Nav aria-label = "顶部导航" footer ={topFooter} mode = "horizontal" />
</ LayoutHeader >
< LayoutContent style = "padding: 24px; background-color: var(--semi-color-bg-0)" >
< Breadcrumb { routes } style = "margin-bottom: 24px" />
< div style = "border-radius: 10px; border: 1px solid var(--semi-color-border); height: 376px; padding: 32px" >
< Skeleton loading >
{# snippet placeholder ()}
< SkeletonParagraph rows ={ 2 } />
{/ snippet }
< p >Hi, Bytedance dance dance.</ p >
< p >Hi, Bytedance dance dance.</ p >
</ Skeleton >
</ div >
</ LayoutContent >
< LayoutFooter style = "display: flex; justify-content: space-between; padding: 20px; color: var(--semi-color-text-2); background-color: var(--semi-grey-0)" >
< span style = "display: flex; align-items: center" >
< IconBytedanceLogo size = "large" style = "margin-inline-end: 8px" />
< span >Copyright © 2019 ByteDance. All Rights Reserved. </ span >
</ span >
< span >
< span style = "margin-inline-end: 24px" >平台客服</ span >
< span >反馈建议</ span >
</ span >
</ LayoutFooter >
</ Layout >
</ Layout >
API Reference
Layout
Props
Property Description Type Default children Content of the Layout: LayoutHeader, LayoutSider, LayoutContent, LayoutFooter or a nested Layout. Snippet- hasSider Indicates that a Sider is inside. A Sider among the direct children is detected automatically; a deeper one registers after mount, so pass true during server rendering to avoid style flashing. Passing false cannot remove the has-sider class that a Sider adds. boolean- prefixCls Class name prefix. string"semi-layout"tagName Tag name of the root element. keyof HTMLElementTagNameMap"section"
class, style and native attributes (including role and aria-*) land on the root element.
The three share one API. Their default tags are header, footer and main.
Props
Property Description Type Default children Content of the header. Snippet- prefixCls Class name prefix. string"semi-layout"tagName Tag name of the root element. keyof HTMLElementTagNameMap"header"type For internal use; decides the class name suffix. string"header"
Props
Property Description Type Default children Content of the footer. Snippet- prefixCls Class name prefix. string"semi-layout"tagName Tag name of the root element. keyof HTMLElementTagNameMap"footer"type For internal use; decides the class name suffix. string"footer"
Layout.Content
Props
Property Description Type Default children Content of the main area. Snippet- prefixCls Class name prefix. string"semi-layout"tagName Tag name of the root element. keyof HTMLElementTagNameMap"main"type For internal use; decides the class name suffix. string"content"
class, style and native attributes (including role and aria-*) land on each root element.
Layout.Sider
Props
Property Description Type Default breakpoint Breakpoints that trigger the responsive layout: xs, sm, md, lg, xl or xxl. Read once at mount. TypeArray<keyof ResponsiveMap> - children Content of the sider. Snippet- onBreakpoint Called once at mount for each screen listed in breakpoint with the current viewport state, then whenever it starts or stops matching, with the screen name and whether it matches. Type(screen: keyof ResponsiveMap, match: boolean) => void - prefixCls Class name prefix. string"semi-layout"
class, style and native attributes and events (including role, aria-* and onclick) land on the root aside element.
responsive map
{
xs: '(max-width: 575px)',
sm: '(min-width: 576px)',
md: '(min-width: 768px)',
lg: '(min-width: 992px)',
xl: '(min-width: 1200px)',
xxl: '(min-width: 1600px)',
}
Accessibility
ARIA
Sider renders an aside; pass aria-label to describe what this Sider is for.
Header and Footer render header and footer by default. Inside the section of a Layout they are not banner or contentinfo landmarks; pass role="banner" or role="contentinfo" when they are the header or footer of the whole page.
Content renders main by default, and a page should have only one main; when nesting, use tagName to switch to another tag.
Header, Content and Footer accept role and aria-label to describe the corresponding element.