Mastering React MUI Container: Building Flexible Page Layout Wrappers
When building React applications with Material-UI (MUI), one of the most fundamental yet powerful components you'll use is the Container. After spending years architecting front-end systems, I've found that proper layout management is critical for creating responsive, maintainable applications. The Container component serves as the cornerstone of MUI layouts, providing consistent spacing and width constraints that adapt to different screen sizes.
In this guide, I'll walk you through everything you need to know about the MUI Container component - from basic implementation to advanced customization techniques. You'll learn how to leverage this component to create professional layouts that maintain proper spacing, alignment, and responsiveness across all devices.
Learning Objectives
By the end of this article, you'll be able to:
- Understand the purpose and fundamental concepts of the MUI Container component
- Implement basic and advanced Container configurations
- Create responsive layouts with proper spacing and margins
- Customize Container behavior with various props and styling approaches
- Integrate Container with other MUI components for complex layouts
- Avoid common pitfalls and performance issues when working with Container
Understanding the MUI Container Component
The Container component is a layout utility that centers your content horizontally with appropriate padding. It's designed to be the main wrapper for your page content, providing consistent spacing and alignment across different screen sizes.
When I first started working with MUI, I underestimated how important proper container management would be. The Container component follows Material Design's responsive layout grid principles, helping maintain visual consistency while adapting to various screen sizes. It's essentially a div with margin-left: auto
, margin-right: auto
, and some predefined padding.
The Container automatically adjusts its maximum width based on the current breakpoint, making it perfect for responsive designs. This means it will have different maximum widths at different screen sizes, following Material Design's layout guidelines.
Core Container Props
Let's examine the essential props that control Container behavior:
Prop | Type | Default | Description |
---|---|---|---|
children | node | - | The content of the container. |
component | elementType | 'div' | The component used for the root node. |
disableGutters | boolean | false | If true, the left and right padding is removed. |
fixed | boolean | false | If true, the Container width is set to the maxWidth value rather than being fluid. |
maxWidth | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false | 'lg' | Determines the max-width of the container. Can be a breakpoint or false for no max-width. |
sx | object | - | The system prop that allows defining system overrides as well as additional CSS styles. |
Understanding these props is crucial for effective use of the Container component. Let's look at how each of these affects the Container's behavior.
Default Behavior and Responsive Widths
By default, the Container has a responsive width with predefined maximum widths at each breakpoint. Here's a breakdown of the default maximum widths:
Breakpoint | Value | Default maxWidth |
---|---|---|
xs | 0px or larger | 444px |
sm | 600px or larger | 600px |
md | 900px or larger | 900px |
lg | 1200px or larger | 1200px |
xl | 1536px or larger | 1536px |
The Container also adds default padding (gutters) of 24px on both sides. This ensures your content doesn't touch the edges of the screen on small devices while maintaining proper spacing on larger ones.
Basic Container Implementation
Let's start with a basic implementation of the Container component. This is often one of the first components I add when setting up a new MUI project.
import React from 'react';
import { Container, Typography } from '@mui/material';
function BasicPage() {
return (
<Container>
<Typography variant="h4" component="h1" gutterBottom>
Welcome to My Application
</Typography>
<Typography paragraph>
This content is wrapped in a Container component, which provides
consistent spacing and a maximum width based on the current screen size.
</Typography>
</Container>
);
}
export default BasicPage;
In this simple example, the Container centers our content horizontally and applies appropriate padding. The content will have a maximum width of 1200px (the default 'lg' setting) and will be centered on larger screens.
Configuring Container Width
You can control the maximum width of a Container using the maxWidth
prop. This is particularly useful when you need different content sections to have different widths.
import React from 'react';
import { Container, Typography, Box } from '@mui/material';
function VariableWidthContainers() {
return (
<>
<Container maxWidth="xs">
<Box sx={{ bgcolor: '#e0f7fa', p: 2, mb: 2 }}>
<Typography>Extra Small Container (maxWidth="xs")</Typography>
</Box>
</Container>
<Container maxWidth="sm">
<Box sx={{ bgcolor: '#b2ebf2', p: 2, mb: 2 }}>
<Typography>Small Container (maxWidth="sm")</Typography>
</Box>
</Container>
<Container maxWidth="md">
<Box sx={{ bgcolor: '#80deea', p: 2, mb: 2 }}>
<Typography>Medium Container (maxWidth="md")</Typography>
</Box>
</Container>
<Container maxWidth="lg">
<Box sx={{ bgcolor: '#4dd0e1', p: 2, mb: 2 }}>
<Typography>Large Container (maxWidth="lg") - Default</Typography>
</Box>
</Container>
<Container maxWidth="xl">
<Box sx={{ bgcolor: '#26c6da', p: 2, mb: 2 }}>
<Typography>Extra Large Container (maxWidth="xl")</Typography>
</Box>
</Container>
<Container maxWidth={false}>
<Box sx={{ bgcolor: '#00bcd4', p: 2 }}>
<Typography>Full Width Container (maxWidth=false)</Typography>
</Box>
</Container>
</>
);
}
export default VariableWidthContainers;
This example demonstrates all available maxWidth
options. Notice how each Container has a different maximum width, but they all maintain proper spacing and center alignment. Setting maxWidth={false}
removes any width constraint, making the Container take up the full available width (minus the default gutters).
Fixed vs Fluid Containers
The fixed
prop changes how the Container behaves across different screen sizes:
import React from 'react';
import { Container, Typography, Box } from '@mui/material';
function FixedVsFluidContainer() {
return (
<>
<Container maxWidth="md">
<Box sx={{ bgcolor: '#bbdefb', p: 2, mb: 4 }}>
<Typography variant="h6" gutterBottom>
Fluid Container (Default)
</Typography>
<Typography>
This container adjusts its width based on the screen size, up to a maximum
of "md" (900px). On smaller screens, it will take up 100% of the available width.
</Typography>
</Box>
</Container>
<Container fixed maxWidth="md">
<Box sx={{ bgcolor: '#90caf9', p: 2 }}>
<Typography variant="h6" gutterBottom>
Fixed Container
</Typography>
<Typography>
This container is fixed at exactly "md" width (900px) on all screen sizes
where possible. On smaller screens, it will still be constrained by the
viewport width.
</Typography>
</Box>
</Container>
</>
);
}
export default FixedVsFluidContainer;
The key difference:
- A regular Container (fluid) will adjust its width based on the screen size, up to the maximum specified by
maxWidth
. - A fixed Container (
fixed={true}
) will always be exactly the width specified bymaxWidth
, regardless of screen size (unless the screen is smaller than that width).
In my experience, fluid containers (the default) are generally more useful for responsive layouts, while fixed containers make sense when you need precise control over the layout width.
Creating a Page Layout System with Container
Now let's build a complete page layout system using Container. I'll show you how to create a structured layout with header, main content, and footer sections.
import React from 'react';
import {
AppBar,
Box,
Container,
Toolbar,
Typography,
Paper,
Grid,
Button,
Divider
} from '@mui/material';
function PageLayout() {
return (
<Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
{/* Header */}
<AppBar position="static">
<Container>
<Toolbar disableGutters>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
My Application
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</Container>
</AppBar>
{/* Hero Section with Full Width */}
<Box sx={{ bgcolor: '#e3f2fd', py: 6 }}>
<Container>
<Typography variant="h3" component="h1" gutterBottom>
Welcome to Our Platform
</Typography>
<Typography variant="h5" component="div" sx={{ mb: 4 }}>
Build amazing layouts with MUI Container
</Typography>
<Button variant="contained" size="large">
Get Started
</Button>
</Container>
</Box>
{/* Main Content */}
<Container sx={{ py: 4, flex: 1 }}>
<Grid container spacing={4}>
<Grid item xs={12} md={8}>
<Paper sx={{ p: 3 }}>
<Typography variant="h5" gutterBottom>
Main Content Area
</Typography>
<Typography paragraph>
This is where your main content goes. Notice how the Container
component ensures proper spacing and width constraints. The content
is well-aligned and doesn't stretch too wide on large screens.
</Typography>
<Typography paragraph>
Using Container for layout management helps maintain consistent
spacing throughout your application. It's a fundamental building
block for creating professional-looking UIs.
</Typography>
</Paper>
</Grid>
<Grid item xs={12} md={4}>
<Paper sx={{ p: 3 }}>
<Typography variant="h5" gutterBottom>
Sidebar
</Typography>
<Typography paragraph>
A sidebar for additional navigation or supplementary content.
The Grid system works well inside Containers to create multi-column
layouts.
</Typography>
<Divider sx={{ my: 2 }} />
<Button variant="outlined" fullWidth>
Call to Action
</Button>
</Paper>
</Grid>
</Grid>
</Container>
{/* Footer */}
<Box sx={{ bgcolor: '#f5f5f5', py: 3, mt: 'auto' }}>
<Container>
<Typography variant="body2" color="text.secondary" align="center">
© 2023 My Application. All rights reserved.
</Typography>
</Container>
</Box>
</Box>
);
}
export default PageLayout;
This example demonstrates a comprehensive page layout with several key techniques:
- Consistent Container Usage: Every major section uses a Container for proper spacing and width constraints.
- Flexible Header: The AppBar contains a Container to align the header content with the rest of the page.
- Full-Width Sections: The hero section has a colored background that extends edge-to-edge, while its content remains properly contained.
- Grid System Integration: The Container works seamlessly with MUI's Grid system for multi-column layouts.
- Sticky Footer: Using flexbox with
minHeight: '100vh'
andmt: 'auto'
ensures the footer stays at the bottom.
This approach creates a cohesive layout where all content sections maintain proper alignment and spacing, regardless of screen size.
Managing Container Spacing and Gutters
The Container component applies default horizontal padding (gutters) of 24px. There are times when you might want to modify or remove this padding.
Removing Gutters
The disableGutters
prop removes the default horizontal padding:
import React from 'react';
import { Container, Box, Typography } from '@mui/material';
function GutterManagement() {
return (
<>
<Container>
<Box sx={{ bgcolor: '#e8eaf6', p: 2, mb: 4 }}>
<Typography variant="h6" gutterBottom>
Container with Default Gutters
</Typography>
<Typography>
This container has the default 24px padding on the left and right sides.
Notice the space between the content and the edges of the container.
</Typography>
</Box>
</Container>
<Container disableGutters>
<Box sx={{ bgcolor: '#c5cae9', p: 2 }}>
<Typography variant="h6" gutterBottom>
Container with Gutters Disabled
</Typography>
<Typography>
This container has no horizontal padding. The content extends all the way
to the edges of the container. This is useful for creating edge-to-edge
sections while maintaining the container's width constraints.
</Typography>
</Box>
</Container>
</>
);
}
export default GutterManagement;
Disabling gutters is particularly useful when:
- You need edge-to-edge content within a constrained width
- You're nesting Containers and want to avoid compounding padding
- You want to implement your own custom padding system
Custom Spacing with the sx Prop
For more fine-grained control over spacing, you can use the sx
prop:
import React from 'react';
import { Container, Box, Typography } from '@mui/material';
function CustomContainerSpacing() {
return (
<>
<Container sx={{ px: { xs: 1, sm: 2, md: 4 }, py: 3 }}>
<Box sx={{ bgcolor: '#dcedc8', p: 2, mb: 4 }}>
<Typography variant="h6" gutterBottom>
Container with Custom Responsive Padding
</Typography>
<Typography>
This container has custom horizontal padding that changes based on the
screen size: 8px on extra small screens, 16px on small screens, and 32px
on medium screens and up. It also has 24px padding on top and bottom.
</Typography>
</Box>
</Container>
<Container
disableGutters
sx={{
maxWidth: { sm: '100%', md: 900 },
mx: { xs: 0, md: 'auto' }
}}
>
<Box sx={{ bgcolor: '#c5e1a5', p: 2 }}>
<Typography variant="h6" gutterBottom>
Custom Width Container
</Typography>
<Typography>
This container has custom width settings. It's full width on small screens
but has a maximum width of 900px on medium screens and larger. We've also
customized the margins to be 0 on small screens.
</Typography>
</Box>
</Container>
</>
);
}
export default CustomContainerSpacing;
The sx
prop is incredibly powerful for customizing Container spacing and dimensions. In this example:
- The first Container has responsive padding that increases with screen size
- The second Container has custom width constraints and margin settings
This approach allows for precise control over how your layout adapts to different screen sizes.
Nested Containers and Layout Composition
In complex applications, you might need to nest Containers for more sophisticated layouts. Here's a pattern I often use:
import React from 'react';
import {
Container,
Box,
Typography,
Paper,
Divider
} from '@mui/material';
function NestedContainers() {
return (
<>
{/* Outer full-width container */}
<Container maxWidth={false} disableGutters>
<Box sx={{ bgcolor: '#bbdefb', py: 4 }}>
{/* Inner constrained container for content */}
<Container maxWidth="lg">
<Typography variant="h4" gutterBottom>
Full-Width Section with Contained Content
</Typography>
<Typography paragraph>
This pattern uses a full-width outer Container with an inner
constrained Container. The colored background extends edge-to-edge,
while the content maintains proper width constraints.
</Typography>
</Container>
</Box>
</Container>
<Divider sx={{ my: 4 }} />
{/* Multi-level nesting example */}
<Container maxWidth="lg">
<Typography variant="h4" gutterBottom>
Nested Container Layout
</Typography>
<Typography paragraph>
Here's an example of multi-level Container nesting for complex layouts.
</Typography>
<Paper sx={{ p: 0, overflow: 'hidden', mb: 4 }}>
<Box sx={{ bgcolor: '#e1f5fe', p: 3 }}>
<Typography variant="h5" gutterBottom>
Primary Content Area
</Typography>
<Container maxWidth="md" disableGutters>
<Box sx={{ bgcolor: '#b3e5fc', p: 3 }}>
<Typography variant="h6" gutterBottom>
Narrower Content Section
</Typography>
<Typography paragraph>
This content is in a nested Container with a narrower maxWidth.
This technique is useful for creating visual hierarchy and
focusing attention on important content.
</Typography>
<Container maxWidth="sm" disableGutters>
<Box sx={{ bgcolor: '#81d4fa', p: 3 }}>
<Typography variant="subtitle1" gutterBottom>
Focused Content
</Typography>
<Typography>
The most important content can be placed in an even narrower
container to increase readability and focus.
</Typography>
</Box>
</Container>
</Box>
</Container>
</Box>
</Paper>
<Typography>
When nesting Containers, consider using disableGutters on inner Containers
to avoid compounding padding. Also be mindful of the performance impact of
deeply nested components.
</Typography>
</Container>
</>
);
}
export default NestedContainers;
This example demonstrates two common nesting patterns:
-
Full-Width Background with Constrained Content: An outer Container with
maxWidth={false}
anddisableGutters
combined with an inner Container that constrains the content width. -
Progressive Width Reduction: Nested Containers with progressively smaller
maxWidth
values to create visual hierarchy and guide the user's attention.
When nesting Containers, keep these tips in mind:
- Use
disableGutters
on inner Containers to avoid compounding padding - Be mindful of the performance impact of deeply nested components
- Consider using the Box component instead of Container for some nesting levels if you don't need the Container's specific features
Customizing Container Styling
Let's explore different approaches to customizing the Container's appearance beyond its spacing properties.
Styling with the sx Prop
The sx
prop is the most direct way to customize a Container:
import React from 'react';
import { Container, Typography } from '@mui/material';
function CustomStyledContainer() {
return (
<Container
sx={{
bgcolor: '#f5f5f5',
borderRadius: 2,
boxShadow: 1,
p: 3,
mt: 4,
border: '1px solid #e0e0e0',
'&:hover': {
boxShadow: 3,
bgcolor: '#fafafa'
}
}} >
<Typography variant="h5" gutterBottom>
Styled Container with sx Prop
</Typography>
<Typography>
This Container is styled directly using the sx prop. We've added a background
color, border radius, shadow, custom padding, and even a hover effect.
The sx prop offers a convenient way to apply styles without creating
separate styled components.
</Typography>
</Container>
);
}
export default CustomStyledContainer;
The sx
prop accepts any CSS properties using MUI's custom shorthand (like p
for padding and mt
for margin-top). It also supports nested selectors like &:hover
for interactive styles.
Custom Container with styled API
For more complex or reusable styling, you can create custom Container components using the styled
API:
import React from 'react';
import { Container, Typography } from '@mui/material';
import { styled } from '@mui/material/styles';
// Card-like container
const CardContainer = styled(Container)(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
borderRadius: theme.shape.borderRadius,
boxShadow: theme.shadows[2],
padding: theme.spacing(3),
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
transition: 'all 0.3s ease-in-out',
'&:hover': {
boxShadow: theme.shadows[4],
transform: 'translateY(-4px)'
}
}));
// Hero section container
const HeroContainer = styled(Container)(({ theme }) => ({
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
padding: theme.spacing(6, 3),
borderRadius: '0 0 16px 16px',
position: 'relative',
overflow: 'hidden',
'&::after': {
content: '""',
position: 'absolute',
bottom: 0,
right: 0,
width: '30%',
height: '60%',
backgroundColor: 'rgba(255, 255, 255, 0.1)',
borderTopLeftRadius: '50%'
}
}));
function StyledContainers() {
return (
<>
<HeroContainer maxWidth={false} disableGutters>
<Container>
<Typography variant="h3" gutterBottom>
Welcome to Our Platform
</Typography>
<Typography variant="h6">
Custom styled containers create distinctive UI sections
</Typography>
</Container>
</HeroContainer>
<CardContainer maxWidth="sm">
<Typography variant="h5" gutterBottom>
Card-like Container
</Typography>
<Typography>
This is a custom Container styled to look like a card with hover effects.
Creating reusable styled components like this helps maintain consistency
across your application while keeping your JSX clean.
</Typography>
</CardContainer>
<CardContainer maxWidth="sm">
<Typography variant="h5" gutterBottom>
Another Card Container
</Typography>
<Typography>
By creating styled components, we can reuse the same styles across
multiple instances. This ensures visual consistency and reduces
code duplication.
</Typography>
</CardContainer>
</>
);
}
export default StyledContainers;
The styled
API is powerful because:
- It provides access to the theme object for consistent styling
- It creates reusable components that encapsulate specific styling
- It keeps your JSX clean by moving style definitions outside the component
- It allows for complex styles including pseudo-elements and pseudo-classes
Theming Container Defaults
For application-wide Container customization, you can override the default styles in your theme:
import React from 'react';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { Container, Typography, CssBaseline } from '@mui/material';
// Custom theme with Container overrides
const theme = createTheme({
components: {
MuiContainer: {
styleOverrides: {
root: {
backgroundColor: '#fcfcfc',
borderRadius: 8,
padding: '24px',
marginTop: '16px',
marginBottom: '16px',
boxShadow: '0 2px 8px rgba(0,0,0,0.05)'
},
maxWidthSm: {
maxWidth: 600, // Custom max-width for sm
},
maxWidthMd: {
maxWidth: 960, // Custom max-width for md
}
},
defaultProps: {
maxWidth: 'md', // Change the default maxWidth
}
}
}
});
function ThemedContainers() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Container>
<Typography variant="h5" gutterBottom>
Themed Container (Default)
</Typography>
<Typography paragraph>
This Container uses the default styling from our custom theme.
All Containers in the application will have this styling unless
specifically overridden.
</Typography>
</Container>
<Container maxWidth="sm">
<Typography variant="h5" gutterBottom>
Small Themed Container
</Typography>
<Typography paragraph>
This Container uses the custom maxWidth value for 'sm' defined in our theme.
</Typography>
</Container>
<Container
sx={{
boxShadow: 3,
bgcolor: '#f5f5f5',
borderRadius: 4
}}
>
<Typography variant="h5" gutterBottom>
Container with Overridden Styles
</Typography>
<Typography paragraph>
This Container has theme defaults but overrides some properties using the sx prop.
</Typography>
</Container>
</ThemeProvider>
);
}
export default ThemedContainers;
Theme overrides are useful when:
- You want consistent Container styling throughout your application
- You need to modify the default behavior of all Containers
- You're building a design system with specific layout requirements
Advanced Container Patterns
Let's explore some advanced patterns that solve common layout challenges using Container.
Responsive Container Switching
Sometimes you need different layout approaches based on screen size:
import React from 'react';
import { Container, Typography, Box, useMediaQuery } from '@mui/material';
import { useTheme } from '@mui/material/styles';
function ResponsiveContainerSwitching() {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md'));
return (
<Box>
{isMobile ? (
// Mobile layout - Full width, minimal padding
<Container
disableGutters
sx={{ px: 1 }} >
<Typography variant="h5" gutterBottom>
Mobile Layout
</Typography>
<Box sx={{ bgcolor: '#ffecb3', p: 2, borderRadius: 1 }}>
<Typography>
On mobile devices, we use a full-width container with minimal padding
to maximize the available space for content.
</Typography>
</Box>
</Container>
) : isTablet ? (
// Tablet layout - Medium width container
<Container maxWidth="sm">
<Typography variant="h5" gutterBottom>
Tablet Layout
</Typography>
<Box sx={{ bgcolor: '#ffe082', p: 3, borderRadius: 1 }}>
<Typography>
On tablet devices, we use a medium-width container with standard
padding to provide a comfortable reading experience.
</Typography>
</Box>
</Container>
) : (
// Desktop layout - Wider container with custom styling
<Container maxWidth="md" sx={{ py: 4 }}>
<Typography variant="h5" gutterBottom>
Desktop Layout
</Typography>
<Box sx={{ bgcolor: '#ffd54f', p: 4, borderRadius: 2 }}>
<Typography>
On desktop devices, we use a wider container with more generous
spacing to take advantage of the larger screen real estate.
</Typography>
</Box>
</Container>
)}
<Box sx={{ mt: 4 }}>
<Typography variant="body2" color="text.secondary" align="center">
Current device type: {isMobile ? 'Mobile' : isTablet ? 'Tablet' : 'Desktop'}
</Typography>
</Box>
</Box>
);
}
export default ResponsiveContainerSwitching;
This pattern uses useMediaQuery
to conditionally render different Container configurations based on screen size. It's particularly useful when you need significantly different layouts across device types.
Conditional Container Rendering
Here's a pattern for conditionally applying Container based on content needs:
import React from 'react';
import { Container, Typography, Box, Button } from '@mui/material';
// Component that conditionally applies Container
function ContainerWrapper({ children, useContainer = true, ...props }) {
if (useContainer) {
return <Container {...props}>{children}</Container>;
}
return children;
}
function ConditionalContainers() {
const [useContainers, setUseContainers] = React.useState(true);
return (
<Box sx={{ p: 2 }}>
<Button
variant="outlined"
onClick={() => setUseContainers(!useContainers)}
sx={{ mb: 3 }} >
{useContainers ? 'Disable Containers' : 'Enable Containers'}
</Button>
<ContainerWrapper
useContainer={useContainers}
maxWidth="md"
sx={{ mb: 4, bgcolor: '#e8f5e9', p: 3, borderRadius: 2 }}
>
<Typography variant="h5" gutterBottom>
First Section
</Typography>
<Typography>
This section {useContainers ? 'uses' : 'doesn't use'} a Container component.
The ContainerWrapper component allows us to conditionally apply Container
wrapping based on a prop or state.
</Typography>
</ContainerWrapper>
<ContainerWrapper
useContainer={useContainers}
maxWidth="sm"
sx={{ bgcolor: '#c8e6c9', p: 3, borderRadius: 2 }}
>
<Typography variant="h5" gutterBottom>
Second Section
</Typography>
<Typography>
This section also {useContainers ? 'uses' : 'doesn't use'} a Container,
but with a different maxWidth. This pattern is useful for creating flexible
layout systems that can adapt to different content needs.
</Typography>
</ContainerWrapper>
</Box>
);
}
export default ConditionalContainers;
The ContainerWrapper
component is a higher-order component that conditionally applies Container wrapping. This is useful for:
- Creating flexible layout systems
- Building components that can work both inside and outside Containers
- Toggling layout constraints based on user preferences or content types
Sticky Header and Footer with Scrollable Container
Here's a pattern for creating a fixed-height layout with scrollable content:
import React from 'react';
import {
Box,
Container,
AppBar,
Toolbar,
Typography,
Paper,
List,
ListItem,
ListItemText,
Divider
} from '@mui/material';
function ScrollableContainer() {
// Generate dummy content
const generateItems = (count) => {
return Array.from({ length: count }, (_, i) => (
<ListItem key={i} divider>
<ListItemText
primary={`Item ${i + 1}`}
secondary="Click to view details"
/>
</ListItem>
));
};
return (
<Box sx={{
height: '100vh',
display: 'flex',
flexDirection: 'column',
overflow: 'hidden'
}}>
{/* Fixed Header */}
<AppBar position="static">
<Container>
<Toolbar disableGutters>
<Typography variant="h6">
Application with Scrollable Content
</Typography>
</Toolbar>
</Container>
</AppBar>
{/* Main Content Area */}
<Box sx={{
display: 'flex',
flex: 1,
overflow: 'hidden'
}}>
{/* Sidebar */}
<Paper sx={{
width: 240,
overflow: 'auto',
display: { xs: 'none', md: 'block' }
}}>
<List dense>
{generateItems(20)}
</List>
</Paper>
{/* Scrollable Content Area */}
<Box sx={{
flex: 1,
overflow: 'auto',
bgcolor: '#f5f5f5'
}}>
<Container sx={{ py: 3 }}>
<Typography variant="h4" gutterBottom>
Scrollable Content Area
</Typography>
<Typography paragraph>
This Container is inside a scrollable Box. The Container provides
proper width constraints and spacing, while the parent Box handles
the scrolling behavior.
</Typography>
<Paper sx={{ p: 3, mb: 3 }}>
<Typography variant="h5" gutterBottom>
Content Section
</Typography>
<Typography paragraph>
The Container ensures that this content doesn't stretch too wide,
maintaining readability even in a scrollable context.
</Typography>
</Paper>
{/* Long content to demonstrate scrolling */}
{Array.from({ length: 10 }, (_, i) => (
<Paper key={i} sx={{ p: 3, mb: 3 }}>
<Typography variant="h6" gutterBottom>
Section {i + 1}
</Typography>
<Typography paragraph>
This is a content section to demonstrate scrolling behavior.
Notice how the Container maintains proper width and spacing
while allowing the content to scroll.
</Typography>
<Divider sx={{ my: 2 }} />
<Typography>
Additional content for section {i + 1}.
</Typography>
</Paper>
))}
</Container>
</Box>
</Box>
{/* Fixed Footer */}
<Box sx={{ bgcolor: '#f5f5f5', borderTop: '1px solid #e0e0e0' }}>
<Container>
<Box sx={{ py: 2 }}>
<Typography variant="body2" color="text.secondary" align="center">
© 2023 My Application. All rights reserved.
</Typography>
</Box>
</Container>
</Box>
</Box>
);
}
export default ScrollableContainer;
This pattern creates a fixed-height layout with:
- A static header with Container for proper content alignment
- A scrollable main content area that contains a Container
- A static footer with Container for consistent alignment
The key technique is separating the scrolling behavior from the width constraints:
- The Box components handle layout structure and scrolling behavior
- The Container components handle width constraints and horizontal spacing
Performance Considerations and Best Practices
When working with Container, keep these performance considerations and best practices in mind:
Avoid Unnecessary Nesting
Excessive nesting of Container components can impact performance:
import React from 'react';
import { Container, Typography, Box, Divider } from '@mui/material';
function ContainerBestPractices() {
return (
<>
<Typography variant="h4" gutterBottom sx={{ px: 2 }}>
Container Best Practices
</Typography>
<Divider sx={{ mb: 4 }} />
{/* Anti-pattern: Excessive nesting */}
<Box sx={{ bgcolor: '#ffebee', p: 2, mb: 4 }}>
<Typography variant="h6" gutterBottom>
Anti-pattern: Excessive Nesting
</Typography>
<Container>
<Container maxWidth="md">
<Container maxWidth="sm">
<Typography paragraph>
This example shows excessive Container nesting. Each Container adds
DOM elements and can impact performance. It also compounds padding
and creates unnecessary layout calculations.
</Typography>
</Container>
</Container>
</Container>
</Box>
{/* Better approach: Minimal nesting */}
<Box sx={{ bgcolor: '#e8f5e9', p: 2, mb: 4 }}>
<Typography variant="h6" gutterBottom>
Better Approach: Minimal Nesting
</Typography>
<Container maxWidth="sm">
<Typography paragraph>
This approach uses a single Container with the desired maxWidth.
It achieves the same layout goal with fewer DOM elements and less
complexity.
</Typography>
</Container>
</Box>
{/* When nesting is appropriate */}
<Box sx={{ bgcolor: '#e3f2fd', p: 2 }}>
<Typography variant="h6" gutterBottom>
When Nesting is Appropriate
</Typography>
<Container maxWidth={false} disableGutters sx={{ bgcolor: '#bbdefb', p: 3 }}>
<Typography paragraph>
Full-width background section
</Typography>
<Container>
<Typography paragraph>
Nesting is appropriate when you need different width constraints
or when creating full-width sections with constrained content.
In this case, the outer Container creates a full-width section,
while the inner Container constrains the content width.
</Typography>
</Container>
</Container>
</Box>
</>
);
}
export default ContainerBestPractices;
Use Fragment to Avoid Extra DOM Nodes
When rendering multiple Containers, use React Fragment to avoid extra wrapper elements:
import React from 'react';
import { Container, Typography, Box } from '@mui/material';
function OptimizedContainers() {
return (
<>
<Container maxWidth="md">
<Typography variant="h5" gutterBottom>
First Section
</Typography>
<Typography paragraph>
Using React Fragment to wrap multiple Container components
avoids adding unnecessary DOM elements.
</Typography>
</Container>
<Container maxWidth="md">
<Typography variant="h5" gutterBottom>
Second Section
</Typography>
<Typography paragraph>
Each Container is a direct child of the Fragment, keeping the
DOM structure clean and efficient.
</Typography>
</Container>
</>
);
}
export default OptimizedContainers;
Memoize Container Components When Appropriate
For complex applications, consider memoizing Container sections that don't change frequently:
import React, { memo } from 'react';
import { Container, Typography, Box } from '@mui/material';
// Memoized container section
const StaticSection = memo(function StaticSection() {
console.log('StaticSection rendered');
return (
<Container maxWidth="md" sx={{ mb: 4 }}>
<Box sx={{ bgcolor: '#e0f7fa', p: 3, borderRadius: 2 }}>
<Typography variant="h5" gutterBottom>
Memoized Static Content
</Typography>
<Typography>
This section is wrapped in React.memo() to prevent unnecessary
re-renders when parent components update. This is useful for
static content that doesn't change based on props or state.
</Typography>
</Box>
</Container>
);
});
function MemoizedContainers() {
const [count, setCount] = React.useState(0);
return (
<>
<Container maxWidth="md" sx={{ mb: 4 }}>
<Box sx={{ p: 3, bgcolor: '#f5f5f5', borderRadius: 2 }}>
<Typography variant="h5" gutterBottom>
Dynamic Content
</Typography>
<Typography paragraph>
This section will re-render when state changes: {count}
</Typography>
<button onClick={() => setCount(count + 1)}>
Increment Count
</button>
</Box>
</Container>
{/* This won't re-render when count changes */}
<StaticSection />
<Container maxWidth="md">
<Typography variant="body2" color="text.secondary">
Check the console to see which components are rendering.
</Typography>
</Container>
</>
);
}
export default MemoizedContainers;
Common Container Issues and Solutions
Here are solutions to common Container-related problems:
import React from 'react';
import { Container, Typography, Box, Divider } from '@mui/material';
function ContainerTroubleshooting() {
return (
<Container maxWidth="md">
<Typography variant="h4" gutterBottom>
Common Container Issues and Solutions
</Typography>
<Divider sx={{ mb: 4 }} />
{/* Issue 1: Unexpected padding */}
<Box sx={{ mb: 5 }}>
<Typography variant="h6" gutterBottom>
Issue: Unexpected Padding in Nested Containers
</Typography>
<Box sx={{ bgcolor: '#fff3e0', p: 2, mb: 2 }}>
<Typography variant="subtitle2" gutterBottom>
Problem:
</Typography>
<Typography paragraph>
Nested Containers can lead to compounding padding, causing content
to have more spacing than intended.
</Typography>
<Typography variant="subtitle2" gutterBottom>
Solution:
</Typography>
<Typography paragraph>
Use disableGutters on inner Containers or use Box components instead
of nested Containers when you don't need width constraints.
</Typography>
<Box sx={{ bgcolor: '#ffe0b2', p: 2 }}>
<Typography variant="subtitle2">Example:</Typography>
<pre>
{`<Container>
<Container disableGutters>
{/* Content */}
</Container>
</Container>`}
</pre>
</Box>
</Box>
</Box>
{/* Issue 2: Content not centered */}
<Box sx={{ mb: 5 }}>
<Typography variant="h6" gutterBottom>
Issue: Content Not Centered Properly
</Typography>
<Box sx={{ bgcolor: '#e1f5fe', p: 2, mb: 2 }}>
<Typography variant="subtitle2" gutterBottom>
Problem:
</Typography>
<Typography paragraph>
Sometimes content inside a Container doesn't appear centered, especially
when using fixed positioning or absolute elements.
</Typography>
<Typography variant="subtitle2" gutterBottom>
Solution:
</Typography>
<Typography paragraph>
Ensure that the Container itself is properly centered, and use text alignment
or flexbox for content centering. For absolute elements, position relative to
the Container.
</Typography>
<Box sx={{ bgcolor: '#b3e5fc', p: 2 }}>
<Typography variant="subtitle2">Example:</Typography>
<pre>
{`<Container sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}>
{/* Content will be centered */}
</Container>`}
</pre>
</Box>
</Box>
</Box>
{/* Issue 3: Container overflowing */}
<Box sx={{ mb: 5 }}>
<Typography variant="h6" gutterBottom>
Issue: Container Overflowing on Small Screens
</Typography>
<Box sx={{ bgcolor: '#f3e5f5', p: 2, mb: 2 }}>
<Typography variant="subtitle2" gutterBottom>
Problem:
</Typography>
<Typography paragraph>
Content inside Containers sometimes overflows on small screens, causing
horizontal scrolling or content truncation.
</Typography>
<Typography variant="subtitle2" gutterBottom>
Solution:
</Typography>
<Typography paragraph>
Ensure all content inside Containers is responsive. Use responsive typography,
proper image sizing with max-width, and responsive tables. Consider using
overflow properties for specific content types.
</Typography>
<Box sx={{ bgcolor: '#e1bee7', p: 2 }}>
<Typography variant="subtitle2">Example:</Typography>
<pre>
{`<Container>
<img
src="large-image.jpg"
alt="Responsive image"
style={{ maxWidth: '100%', height: 'auto' }}
/>
<div style={{ overflowX: 'auto' }}>
{/* Wide content like tables */}
</div>
</Container>`}
</pre>
</Box>
</Box>
</Box>
</Container>
);
}
export default ContainerTroubleshooting;
Building a Reusable Page Layout System
Let's create a complete, reusable page layout system based on Container:
import React from 'react';
import {
Box,
Container,
AppBar,
Toolbar,
Typography,
Button,
Paper,
Divider,
useMediaQuery
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
// Reusable layout components based on Container
// PageContainer - Main wrapper for page content
function PageContainer({ children, maxWidth = 'lg', ...props }) {
return (
<Container
maxWidth={maxWidth}
sx={{
py: { xs: 2, sm: 3, md: 4 },
...props.sx
}}
{...props} >
{children}
</Container>
);
}
// Section - Container for page sections
function Section({ children, fullWidth = false, bgColor, ...props }) {
return (
<Box
sx={{
py: { xs: 3, md: 5 },
bgcolor: bgColor,
width: '100%',
...props.sx
}} >
<Container
maxWidth={fullWidth ? false : 'lg'}
disableGutters={fullWidth}
{...props} >
{children}
</Container>
</Box>
);
}
// ContentCard - Paper-based container for content
function ContentCard({ children, title, ...props }) {
return (
<Paper
sx={{
p: { xs: 2, sm: 3 },
mb: 3,
...props.sx
}}
elevation={2}
{...props} >
{title && (
<>
<Typography variant="h5" component="h2" gutterBottom>
{title}
</Typography>
<Divider sx={{ mb: 2 }} />
</>
)}
{children}
</Paper>
);
}
// Header component with responsive container
function Header() {
const theme = useTheme();
const isSmall = useMediaQuery(theme.breakpoints.down('sm'));
return (
<AppBar position="static">
<Container>
<Toolbar
disableGutters
sx={{
flexDirection: isSmall ? 'column' : 'row',
py: isSmall ? 1 : 0
}} >
<Typography
variant="h6"
component="div"
sx={{
flexGrow: 1,
mb: isSmall ? 1 : 0
}} >
Layout System
</Typography>
<Box>
<Button color="inherit">Home</Button>
<Button color="inherit">Features</Button>
<Button color="inherit">About</Button>
</Box>
</Toolbar>
</Container>
</AppBar>
);
}
// Footer component
function Footer() {
return (
<Box sx={{ bgcolor: '#f5f5f5', py: 3, mt: 4 }}>
<Container>
<Typography variant="body2" color="text.secondary" align="center">
© 2023 My Application. All rights reserved.
</Typography>
</Container>
</Box>
);
}
// Example usage of the layout system
function PageLayoutSystem() {
return (
<Box sx={{ minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>
<Header />
<Section fullWidth bgColor="#e3f2fd">
<Container>
<Typography variant="h3" component="h1" gutterBottom>
Page Layout System
</Typography>
<Typography variant="h5">
A reusable system based on MUI Container
</Typography>
</Container>
</Section>
<PageContainer>
<ContentCard title="Main Content">
<Typography paragraph>
This layout system uses Container as its foundation, combined with
custom components that encapsulate common layout patterns. This approach
makes it easy to maintain consistent spacing and alignment throughout
your application.
</Typography>
<Typography paragraph>
Each component in this system handles a specific aspect of layout:
PageContainer for overall page structure, Section for full-width or
contained sections, and ContentCard for individual content blocks.
</Typography>
</ContentCard>
<Box sx={{ display: 'flex', flexDirection: { xs: 'column', md: 'row' }, gap: 3 }}>
<ContentCard title="Feature One" sx={{ flex: 1 }}>
<Typography>
Using a component-based layout system makes it easy to create
consistent, responsive layouts with minimal effort.
</Typography>
</ContentCard>
<ContentCard title="Feature Two" sx={{ flex: 1 }}>
<Typography>
Each component encapsulates layout logic, making your page
components cleaner and more focused on content.
</Typography>
</ContentCard>
</Box>
</PageContainer>
<Section bgColor="#f5f5f5">
<Typography variant="h4" align="center" gutterBottom>
Additional Section
</Typography>
<Typography align="center">
Sections can have different background colors to create visual separation.
</Typography>
</Section>
<Footer />
</Box>
);
}
export default PageLayoutSystem;
This layout system demonstrates several best practices:
- Composition: Breaking down layout into reusable components (PageContainer, Section, ContentCard)
- Consistent Spacing: Using theme spacing and responsive padding/margins
- Flexibility: Components accept props for customization while maintaining defaults
- Responsiveness: Adapting to different screen sizes with appropriate spacing
- Encapsulation: Each component handles its specific layout concerns
This approach makes it easy to maintain consistent layouts across an entire application while keeping individual page components focused on content rather than layout details.
Wrapping Up
The MUI Container component is a fundamental building block for creating well-structured, responsive layouts in React applications. By understanding its core features and capabilities, you can create professional-looking UIs that maintain proper spacing and alignment across all devices.
In this guide, we've covered everything from basic implementation to advanced customization techniques. We've explored how to integrate Container with other MUI components, how to create reusable layout systems, and how to avoid common pitfalls.
Remember that good layout management is about finding the right balance between consistency and flexibility. The Container component gives you the tools to achieve this balance, providing a solid foundation for your application's UI while allowing for customization when needed.