A flexbox wrapper for Material UI Box and Grid components with handy shorthand props.
If you have never been confused whether to use justify-content
or align-items
, then Flexy is not for you. If you have, then get started with yarn add mui-flexy
or npm install mui-flexy
.
Vanilla CSS requires a lot of mental gymnastics to remember which alignment property to use depending on the axis of your flexbox:
justify-content
aligns along the main axis and align-items
aligns along the cross axis. When you change the axis, you have to re-write your alignments. This gets exponentially more difficult when you introduce responsive breakpoints.
Science and math solved this problem a long time ago with constants like x
and y
to represent 2-dimensional space, where x
is the horizontal axis and y
is the vertical axis.
mui-flexy gives you a way to align things in the same way using x
and y
props instead, calculating all the hard CSS stuff for you so you don't have to.
So instead of:
<FlexBox
justifyContent="center" // is this the main or cross axis?
alignItems="center" // maybe I can use stretch or space-around? 🤷‍♂️
flexDirection="row" // if I change this to column, do I need to change the other two?
width="100vw"
height="100vh"
/>
You can just do:
<FlexBox x="center" y="center" width="100vw" height="100vh" />
// and
<FlexBox column x="left" y="bottom" />
yarn add mui-flexy
# or
npm install mui-flexy
Notes:
- This lib was designed for TypeScript, so please file a bug or PR if you find any issues using it with untyped JS.
- As of v1.2.0, CommonJS is no longer supported. If you need it, please use an older version, or file a bug/PR.
Make sure you've got @mui/material
and its dependencies installed, as well as React:
yarn add @mui/material @emotion/react @emotion/styled react react-dom
# or
npm install @mui/material @emotion/react @emotion/styled react react-dom
If you haven't already, make sure to wrap your app with the MUI ThemeProvider
:
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { CssBaseline } from "@mui/material";
const theme = createTheme({
palette: {
mode: "light", // or "dark"
},
});
const App = () => (
<ThemeProvider theme={theme}>
<CssBaseline />
<YourApp />
</ThemeProvider>
);
Import the FlexBox
or FlexGrid
components from mui-flexy
and use them in your app as you would with MUI's Box
or Grid
components:
import { Typography } from "@mui/material"; // or use a <p> if you don't like fun typography
import { FlexBox, FlexGrid } from "mui-flex";
<FlexBox x="top" y="center">
<Typography>Hello, Bajor</Typography>
</FlexBox>;
As of v1.2.0, you can also use FlexGrid2
for MUI v6, which is a drop-in replacement for @mui/material/Grid2
. Because both v5 and v6 are supported simultaneously in this package, you should use React.lazy()
to import FlexGrid2
:
// @mui/material v6+
const FlexGrid2 = React.lazy(() => import("mui-flexy/FlexGrid2"));
// @mui/material v5
const FlexGrid2 = React.lazy(() => import("mui-flexy/Unstable_FlexGrid2"));
// Then use it in a <Suspense> block:
<Suspense fallback={<div>{/* Loading... */}</div>}>
<FlexGrid2 container x="center" y="center">
<FlexGrid2 item xs={12} sm={6} md={4} lg={3}>
<Typography>Grids are cool</Typography>
</FlexGrid2>
</FlexGrid2>
</Suspense>;
If your transpiler supports top-level await
, you can also use await import("mui-flexy/FlexGrid2")
:
const FlexGrid2 = muiVersion > 5 ? await import("../src/FlexGrid2") : await import("../src/Unstable_FlexGrid2");
Or import createFlexGrid2
/ createUnstableFlexGrid2
from mui-flexy
and export your own FlexGrid2
:
// for @mui/material v6+
import { createFlexGrid2 } from "mui-flexy/FlexGrid2";
const FlexGrid2 = createFlexGrid2();
// for @mui/material v5
import { createUnstable_FlexGrid2 } from "mui-flexy/Unstable_FlexGrid2";
const FlexGrid2 = createUnstable_FlexGrid2();
Check out the live demo for examples of all mui-flexy
's features.
FlexBox can be used as a drop-in replacement for MUI's Box component, with the added benefit of x
and y
props for alignment:
const YouTooCanCenterADiv = () => (
<FlexBox x="center" y="center" width="100vw" height="100vh">
<Typography>2-D coordinate systems are cool</Typography>
</FlexBox>
);
where:
{
x: "center",
y: "center",
row: true // default is row, or you can pass column
}
produces {
justifyContent: "center",
alignItems: "center",
flexDirection: "row"
}
and
{
x: "left",
y: "bottom",
column: true
}
produces {
justifyContent: "flex-end",
alignItems: "flex-start",
flexDirection: "column"
}
It also supports ResponsiveStyleObject arrays/object notation:
{
x: ["left", "center", "right"],
y: ["bottom", "center", "top"],
row: true
}
produces {
justifyContent: ["flex-start", "center", "flex-end"],
alignItems: ["flex-end", "center", "flex-start"],
flexDirection: "row"
}
//
{
x: ["left", "space-between"],
y: ["top", "center"],
flexDirection: ["row", "column"]
}
produces {
justifyContent: ["flex-start", "center"],
alignItems: ["flex-start", "space-between"],
flexDirection: ["row", "column"]
}
//
{
x: {
xs: "left",
sm: "center",
md: "right"
},
y: {
xs: "bottom",
sm: "center",
md: "top"
},
row: true
}
produces {
justifyContent: {
xs: "flex-start",
sm: "center",
md: "flex-end"
},
alignItems: {
xs: "flex-end",
sm: "center",
md: "flex-start"
},
flexDirection: "row"
}
//
{
x: {
xs: "left",
sm: "center",
md: "left",
lg: "inherit",
xl: "space-around"
},
y: {
xs: "top",
sm: "center",
md: "bottom",
lg: "space-between",
xl: "center"
}
flexDirection: {
xs: "row",
sm: "row",
md: "column",
lg: "column",
xl: "column"
}
}
produces {
justifyContent: {
xs: "flex-start",
sm: "center",
md: "flex-end",
lg: "center",
xl: "center"
},
alignItems: {
xs: "flex-start",
sm: "center",
md: "flex-start",
lg: "inherit",
xl: "space-around"
},
flexDirection: {
xs: "row",
sm: "row",
md: "column",
lg: "column",
xl: "column"
}
}
As of v1.2.0, you can now use responsive arrays/objects for row
and column
properties, too:
{
x: "center",
y: "center",
row: [true, true, false], // xs, sm: 'row', md+: 'column'
// column: [false, false, true] // implied, not required
}
// or
{
x: "center",
y: "center",
row: { xs: true, md: false },
column: { xs: false, md: true } // implied, not required, but helps with readability
}
It supports reverse
, too:
{
x: "left",
y: "center",
reverse: true
row: true
}
produces {
justifyContent: "flex-start",
alignItems: "center",
flexDirection: "row-reverse"
}
Like FlexBox, FlexGrid is a drop-in replacement for MUI's Grid component. Note that with @mui/material v6, Unstable_Grid2
has been renamed to Grid2
, and Grid
is deprecated.
// Grid (v5), based on @mui/material/Grid
<FlexGrid container x="center" y="center">
<FlexGrid item xs={12} sm={6} md={4} lg={3}>
<Typography>Grids are cool</Typography>
</FlexGrid>
</FlexGrid>
// Grid2 (v5), based on @mui/material/Unstable_Grid2
<FlexGrid2 container x="center" y="center">
<FlexGrid2 xs={12} sm={6} md={4} lg={3}>
<Typography>Grids are cool</Typography>
</FlexGrid2>
</FlexGrid2>
// Grid2 (v6), based on @mui/material/Grid2
<FlexGrid2 container x="center" y="center">
<FlexGrid2 size={{ xs: 12, sm: 6, md: 4, lg: 3 }}>
<Typography>Grids are cool</Typography>
</FlexGrid2>
</FlexGrid2>
Both FlexBox and FlexGrid are wrapped with forwardRef, so you can pass a ref to FlexBox and FlexGrid. You can also pass a component
prop to override the default div
:
import { forwardRef } from "react";
const boxRef = useRef(null);
<FlexBox ref={boxRef} id="my-flex-box">
<Typography>{`I'm a FlexBox with id ${boxRef.current?.id}`}</Typography>
</FlexBox>;
const SpanFlex = <FlexBox component="span" x="center" y="center" />;
const TypographyFlex = <FlexBox component={Typography} x="center" y="center" variant="subtitle1" />;