Box
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
Flex Example
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>
);
}
Disable Flex Wrap
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>
);
}
Additional Flex Options
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
- applywidth: 100%
disablePadding
- do not apply the default paddingstacked
- setflex-direction: column
reversed
- setflex-direction: row-reverse
orflex-direction: column-reverse
whenstacked
is enabled
See 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>
</>
);
}
Grid Example
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>
);
}
Custom Grid Name
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
Customizing Gap, Padding, and Min Item Size
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
.
Auto-fill Grid Columns
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 space
Try 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>
</>
);
}
Custom Grid Columns
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>
);
}
Grid Column Media Queries
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-media
Each 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>;
}
Grid Auto Rows
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.
Additional Grid Options
The following grid options can be configured by props:
align
-"start" | "center" | "end" | "stretch"
fullWidth
- applywidth: 100%
disablePadding
- do not apply the default padding
See 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>
</>
);
}
Material Grid Example
The material design grid system is defined as:
- 4 columns on mobile
- 8 columns on tablet
- 12 columns on desktop
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>
);
}
Material Grid Customization
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:
Box Class Name Function
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>
);
}
Box Styles Utility Function
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>
);
}