The Box component can be used for simple flex and grid layouts that have
spacing between each item. This should be the go-to component for creating
layouts or spacing items on the page.
Most of these examples are only available on desktop due to limited demo preview
The Box defaults to using display: flex, align-items: center,
justify-content: center, padding: 1rem, and gap: 1rem.
The padding and gap can be configured globally by changing the
core.$box-gap and core.$box-padding Sass variables.
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { type ReactElement } from "react";
export default function FlexExample(): ReactElement {
return (
<Box>
{Array.from({ length: 20 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
);
}
Enable the disableWrap prop to prevent line wrapping and instead attempt to
shrink each item to fit on a single line.
Here is some long text that should be truncated
import { Box } from "@react-md/core/box/Box";
import { Typography } from "@react-md/core/typography/Typography";
import FavoriteIcon from "@react-md/material-icons/FavoriteIcon";
import { type ReactElement } from "react";
export default function DisableFlexWrap(): ReactElement {
return (
<Box style={{ width: "12rem" }} disableWrap>
<FavoriteIcon />
<Typography textOverflow="ellipsis">
Here is some long text that should be truncated
</Typography>
</Box>
);
}
The following flex options can be configured by props:
align - "start" | "center" | "end" | "stretch"justify - "start" | "center" | "end" | "stretch" | "space-around" | "space-between" | "space-evenly"fullWidth - apply width: 100%disablePadding - do not apply the default paddingstacked - set flex-direction: columnreversed - set flex-direction: row-reverse or flex-direction: column-reverse when stacked is enabledSee the example below to see how these props can be used.
No Default Padding
Stacked, Align Stretch, Full Width
Align Start
Reversed, Justify Space Between
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { Divider } from "@react-md/core/divider/Divider";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement } from "react";
export default function AdditionalFlexOptions(): ReactElement {
return (
<>
<Typography>No Default Padding</Typography>
<Box disablePadding>
{Array.from({ length: 8 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
<Typography>Stacked, Align Stretch, Full Width</Typography>
<Box stacked align="stretch" fullWidth>
{Array.from({ length: 4 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
<Divider />
<Typography>Align Start</Typography>
<Box align="start">
<Card>
<CardContent>First</CardContent>
</Card>
<Card>
<CardContent>Second</CardContent>
<CardContent>Some additional content.</CardContent>
</Card>
</Box>
<Divider />
<Typography>Reversed, Justify Space Between</Typography>
<Box align="start" reversed justify="space-between">
<Card>
<CardContent>First</CardContent>
</Card>
<Card>
<CardContent>Second</CardContent>
<CardContent>Some additional content.</CardContent>
</Card>
</Box>
</>
);
}
Enable the grid prop to render equal width dynamic columns that will be at
least 8rem wide.
The min width can be configured globally by changing the core.$box-item-min-size Sass variable.
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { type ReactElement } from "react";
export default function GridExample(): ReactElement {
return (
<Box grid>
{Array.from({ length: 20 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
);
}
As the app grows it might be useful to define different grid variants that
provide different min item size, gap, and/or padding. The variants can be
configured by setting the core.$box-grids variable when @forward-ing or
@use-ing @react-md/core. Each mapped name will be available as a gridName
on the Box component.
Variant 1
Variant 2
Variant 3
The gap, padding, and min item size for part of the DOM using the
core.box-set-var mixin or a custom class name on the Box component.
The gap and padding are also available for the flex version
of the Box.
The grid defaults to using auto-fit but can be configured to auto-fill
by setting gridColumns="fill". To help explain the difference between the two:
auto-fit - fill the entire width with columns and stretch columns to fill
the remaining spaceauto-fill - fill the entire width with columns and add empty columns to
fill the remaining spaceTry changing the ITEMS value below to see the difference.
auto-fit (default)
auto-fill
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement } from "react";
// Change this value to see the difference between fit and fill
const ITEMS = 3;
export default function AutoFillGridColumnsExample(): ReactElement {
return (
<>
<Typography>auto-fit (default)</Typography>
<Box grid gridColumns="fit">
{Array.from({ length: ITEMS }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
<Typography>auto-fill</Typography>
<Box grid gridColumns="fill">
{Array.from({ length: ITEMS }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
</>
);
}
If a specific number of columns should be enforced, set the gridColumns prop
to that number.
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { type ReactElement } from "react";
export default function CustomGridColumnsExample(): ReactElement {
return (
<Box grid gridColumns={4}>
{Array.from({ length: 16 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
);
}
The gridColumns prop also supports setting different column behavior based on the
defined media queries:
phone - core.phone-mediatablet - core.tablet-mediadesktop - core.desktop-medialargeDesktop - core.large-desktop-mediaEach of the breakpoints can be "fit", "fill", or a number of columns.
Using desktop: "fit"
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { useAppSize } from "@react-md/core/media-queries/AppSizeProvider";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement } from "react";
export default function GridColumnMediaQueries(): ReactElement {
return (
<>
<AppSize />
<Box
grid
gridColumns={{
phone: 1,
tablet: "fill",
desktop: "fit",
largeDesktop: 6,
}}
>
{Array.from({ length: 7 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
</>
);
}
function AppSize(): ReactElement {
const appSize = useAppSize();
let current: string;
if (appSize.isPhone) {
current = "phone: 1";
} else if (appSize.isTablet) {
current = 'tablet: "fill"';
} else if (appSize.isLargeDesktop) {
current = "largeDesktop: 6";
} else {
current = 'desktop: "fit"';
}
return <Typography>Using {current}</Typography>;
}
To create rows with an equal height, enable the gridAutoRows restrict
the height through CSS. This is most useful when handling unknown sized items
(like file uploads).
Check out the useFileUpload for another example using auto rows.
The following grid options can be configured by props:
align - "start" | "center" | "end" | "stretch"fullWidth - apply width: 100%disablePadding - do not apply the default paddingSee the example below to see how these props can be used.
No Default Padding
Align Stretch, Full Width
Align Start
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { Divider } from "@react-md/core/divider/Divider";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement } from "react";
export default function AdditionalGridOptions(): ReactElement {
return (
<>
<Typography>No Default Padding</Typography>
<Box grid disablePadding>
{Array.from({ length: 8 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
<Typography>Align Stretch, Full Width</Typography>
<Box grid align="stretch" fullWidth>
{Array.from({ length: 4 }, (_, i) => (
<Card key={i}>
<CardContent>{`Item ${i + 1}`}</CardContent>
</Card>
))}
</Box>
<Divider />
<Typography>Align Start</Typography>
<Box align="start" grid>
<Card>
<CardContent>First</CardContent>
</Card>
<Card>
<CardContent>Second</CardContent>
<CardContent>Some additional content.</CardContent>
</Card>
</Box>
</>
);
}
The material design grid system is defined as:
The material grid is no longer supported out of the box (ha) anymore but can be
re-created using the gridColumns prop and setting the grid-column CSS
property on cells to span multiple columns.
import { Box } from "@react-md/core/box/Box";
import { type BoxGridBreakpointColumns } from "@react-md/core/box/styles";
import { Card } from "@react-md/core/card/Card";
import { cssUtils } from "@react-md/core/cssUtils";
import { type CSSProperties, type ReactElement } from "react";
const GRID_COLUMNS: BoxGridBreakpointColumns = {
phone: 4,
tablet: 8,
desktop: 12,
};
export default function MaterialGridExample(): ReactElement {
return (
<>
<Box grid gridColumns={GRID_COLUMNS} align="stretch">
{Array.from({ length: 12 }, (_, i) => (
<Cell key={i} index={i} />
))}
</Box>
<Box grid gridColumns={GRID_COLUMNS} align="stretch">
{Array.from({ length: 6 }, (_, i) => (
<Cell key={i} index={i} style={{ gridColumn: "span 2" }} />
))}
</Box>
<Box grid gridColumns={GRID_COLUMNS} align="stretch">
{Array.from({ length: 8 }, (_, i) => (
<Cell key={i} index={i} style={{ gridColumn: "span 3" }} />
))}
</Box>
</>
);
}
interface CellProps {
style?: CSSProperties;
index: number;
}
function Cell({ index, style }: CellProps): ReactElement {
return (
<Card
align="center"
justify="center"
style={{ minHeight: "4rem", ...style }}
className={cssUtils({ textAlign: "center" })}
>
{`Cell ${index + 1}`}
</Card>
);
}
If the material grid system is actually still useful, it is recommended to create a few utility classes to help position grid items.
This is not natively supported by react-md since I've never needed
to create layouts that could not be solved with the non-material design grid
system.
Here's an example:
The box styles can also be applied using the box class name function. It
supports all the box styling options and can be applied to any element that
supports display: flex or display: grid.
Setting the gridColumns to a number with the box class name
function does not enforce the provided number of columns like the Box
component. It will only update the --rmd-box-item-min-size to 0.
Use the boxStyles utility if the number of columns must be enforced.
import { box } from "@react-md/core/box/styles";
import { Fieldset } from "@react-md/core/form/Fieldset";
import { Form } from "@react-md/core/form/Form";
import { Legend } from "@react-md/core/form/Legend";
import { TextField } from "@react-md/core/form/TextField";
import { type ReactElement } from "react";
export default function BoxClassNameFunctionExample(): ReactElement {
return (
<Form>
<Fieldset className={box({ grid: true, gridColumns: 3 })}>
<Legend style={{ marginBottom: "1em" }}>Name</Legend>
<TextField label="First Name" autoCompleteValue="given-name" required />
<TextField label="Middle Name" autoCompleteValue="additional-name" />
<TextField label="Last Name" autoCompleteValue="family-name" required />
</Fieldset>
</Form>
);
}
If the number of columns or item size need to be controlled, use the
boxStyles utility function instead. It returns a style object with CSS
variables and the corresponding class names.
import { boxStyles } from "@react-md/core/box/styles";
import { Fieldset } from "@react-md/core/form/Fieldset";
import { Form } from "@react-md/core/form/Form";
import { Legend } from "@react-md/core/form/Legend";
import { TextField } from "@react-md/core/form/TextField";
import { type ReactElement } from "react";
export default function BoxStylesUtilityFunctionExample(): ReactElement {
return (
<Form>
<Fieldset
{...boxStyles({
grid: true,
gridColumns: { phone: 1, desktop: 3 },
gridItemSize: { tablet: "12rem" },
})}
>
<Legend style={{ marginBottom: "1em" }}>Name</Legend>
<TextField label="First Name" autoCompleteValue="given-name" required />
<TextField label="Middle Name" autoCompleteValue="additional-name" />
<TextField label="Last Name" autoCompleteValue="family-name" required />
</Fieldset>
</Form>
);
}