Skip to main content

Container

A centred Column with a maximum width. Below that width it fills its parent, so a phone sees no change. On a tablet or a browser window the content stops at the width you name and sits in the middle.

Use it as the one child of a ScrollView, with the screen padding on it. Every screen then shares one content column, and no screen writes its own maxWidth.

Usage​

import { Container, Typography } from '@rootnative/components'
import { mdiResolver } from '@rootnative/components/mdi'
import { ThemeProvider } from '@rootnative/core'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { ScrollView } from 'react-native'

export default function App() {
return (
<SafeAreaProvider>
<ThemeProvider iconResolver={mdiResolver}>
<ScrollView>
<Container p="lg" gap="md">
<Typography variant="headlineSmall">Settings</Typography>
<Typography variant="bodyMedium">
This column is at most 600dp wide and sits in the middle of a
wide window. On a phone it fills the screen.
</Typography>
</Container>
</ScrollView>
</ThemeProvider>
</SafeAreaProvider>
)
}

Widths​

The width prop names a breakpoint band. The Container grows to the lower bound of that band and no further. The limit includes the padding.

widthMaximum widthUse for
medium (default)600dpReading content, forms, a settings list
expanded840dpA list with a detail pane, a wide form
large1200dpA dashboard, a card grid
extraLarge1600dpA full-width canvas with margins
<ScrollView>
<Container width="large" p="lg">
<Grid columns={{ compact: 1, medium: 2, expanded: 4 }} gap="md">
{cards}
</Grid>
</Container>
</ScrollView>

The values are the same as the breakpoints export of @rootnative/core, so a Grid inside a Container changes its column count at the same widths the Container stops growing.

Padding goes on the Container​

Put the screen padding on the Container, not on the ScrollView. The limit then applies to the padded box, and the content column lines up from screen to screen.

// Both screens show their text at the same x on a wide window.
<ScrollView>
<Container p="lg" gap="xl">
<Typography variant="headlineSmall">First screen</Typography>
</Container>
</ScrollView>

<ScrollView>
<Container p="lg" gap="xl">
<Typography variant="headlineSmall">Second screen</Typography>
</Container>
</ScrollView>

A style prop wins over the width rule, so style={{ maxWidth: 400 }} narrows one screen without a new band.

Props​

PropTypeDefaultRequiredDescription
widthenummediumNoThe widest the Container grows, padding included. Below that width it fills its parent.
invertedbooleanfalseNoReverses the layout direction (`column-reverse`).
pSpacingValue-NoPadding on all sides
pxSpacingValue-NoHorizontal padding (paddingStart + paddingEnd)
pySpacingValue-NoVertical padding (paddingTop + paddingBottom)
ptSpacingValue-NoPadding top
pbSpacingValue-NoPadding bottom
psSpacingValue-NoPadding start (left in LTR, right in RTL)
peSpacingValue-NoPadding end (right in LTR, left in RTL)
mSpacingValue-NoMargin on all sides
mxSpacingValue-NoHorizontal margin (marginStart + marginEnd)
mySpacingValue-NoVertical margin (marginTop + marginBottom)
mtSpacingValue-NoMargin top
mbSpacingValue-NoMargin bottom
msSpacingValue-NoMargin start
meSpacingValue-NoMargin end
gapSpacingValue-NoGap between children
rowGapSpacingValue-NoRow gap between children
columnGapSpacingValue-NoColumn gap between children
flexnumber-NoFlex value
alignenum-NoAlign items along the cross axis
justifyenum-NoJustify content along the main axis
bgstring-NoBackground color
hrefAttrs{ target?: string; rel?: string; download?: string | boolean; }-NoWeb only. The `target`, `rel` and `download` of the `<a>` that a view with an `href` renders, for example under Expo Router's `<Link asChild>`. `target: '_blank'` opens the link in a new tab. Native ignores it.
onKeyDown(event: { nativeEvent: { key?: string; }; }) => void-No-