Mastering MUI Divider: Building Section Dividers with Labels in React
As a front-end developer working with Material UI, you'll often need visual separators to organize your UI into logical sections. The MUI Divider component is a versatile tool that goes beyond simple horizontal lines. In this guide, I'll show you how to leverage the full potential of MUI Divider to create professional section dividers with labels, exploring various customization options and real-world implementations.
What You'll Learn
By the end of this article, you'll be able to:
- Implement basic and advanced MUI Dividers in your React applications
- Create section dividers with centered, inset, and custom-positioned labels
- Style and customize dividers to match your design system
- Handle responsive divider layouts
- Integrate dividers with other MUI components for cohesive interfaces
- Troubleshoot common divider implementation issues
Understanding the MUI Divider Component
The Divider component in Material UI provides a thin line that groups content in lists and layouts. While it may seem simple at first glance, it offers significant flexibility for creating visual separation with semantic meaning in your interfaces.
Basic Divider Implementation
At its core, the Divider component renders an <hr>
element with styling that aligns with Material Design principles. Let's start with the most basic implementation:
import * as React from 'react';
import { Box, Divider } from '@mui/material';
function BasicDivider() {
return (
<Box sx={{ width: '100%', maxWidth: 500, bgcolor: 'background.paper' }}>
<Box sx={{ my: 2, px: 2 }}>Content above the divider</Box>
<Divider />
<Box sx={{ my: 2, px: 2 }}>Content below the divider</Box>
</Box>
);
}
This creates a simple horizontal line that spans the width of its container. The divider inherits its color from the theme's divider
value by default, typically a light gray that provides subtle separation without being visually overwhelming.
Divider Variants and Orientations
MUI Divider supports both horizontal (default) and vertical orientations, allowing you to create boundaries in different directions based on your layout requirements.
import * as React from 'react';
import { Box, Divider } from '@mui/material';
function DividerVariants() {
return (
<Box sx={{ display: 'flex', alignItems: 'center', width: '100%', height: 100 }}>
<Box sx={{ p: 2 }}>Left content</Box>
{/* Vertical divider */}
<Divider orientation="vertical" flexItem />
<Box sx={{ p: 2 }}>Middle content</Box>
{/* Vertical divider with variant */}
<Divider orientation="vertical" variant="middle" flexItem />
<Box sx={{ p: 2 }}>Right content</Box>
</Box>
);
}
The orientation
prop accepts either "horizontal" or "vertical" values. When using vertical dividers, the flexItem
prop is particularly useful as it makes the divider take the height of its flex container.
Divider Props Deep Dive
Let's explore the comprehensive set of props available for the Divider component to understand its full capabilities.
Prop | Type | Default | Description |
---|---|---|---|
absolute | boolean | false | If true, the divider will have an absolute position, useful when used in a list item. |
children | node | - | The content of the component, typically used to add text within the divider. |
classes | object | - | Override or extend the styles applied to the component. |
component | elementType | 'hr' for horizontal, 'div' for vertical | The component used for the root node. |
flexItem | boolean | false | If true, the divider will have flex item behavior, adapting to flex container. |
light | boolean | false | If true, the divider will have a lighter color. |
orientation | 'horizontal' | 'vertical' | 'horizontal' | The divider orientation. |
textAlign | 'center' | 'left' | 'right' | 'center' | The text alignment when the divider has children. |
variant | 'fullWidth' | 'inset' | 'middle' | 'fullWidth' | The variant to use. |
sx | object | function | - | The system prop that allows defining system overrides as well as additional CSS styles. |
Understanding Divider Variants
The variant
prop offers three options that affect the divider's width and positioning:
- fullWidth (default): The divider extends across the full width of its container
- inset: The divider is indented, starting with a margin from the left
- middle: The divider has margins on both left and right sides
import * as React from 'react';
import { Box, List, ListItem, ListItemText, Divider } from '@mui/material';
function DividerVariantDemo() {
return (
<List sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
<ListItem>
<ListItemText primary="Default fullWidth divider" />
</ListItem>
<Divider />
<ListItem>
<ListItemText primary="Inset divider" />
</ListItem>
<Divider variant="inset" />
<ListItem>
<ListItemText primary="Middle divider" />
</ListItem>
<Divider variant="middle" />
<ListItem>
<ListItemText primary="Last item" />
</ListItem>
</List>
);
}
The inset
variant is particularly useful in list contexts when you want to align the divider with the text content, creating a more polished look by indenting the divider to match list item content.
Creating Dividers with Text Labels
One of the most powerful features of MUI Divider is the ability to include text labels within the divider itself. This is especially useful for section headers or to provide context between content blocks.
Basic Text Divider
Let's create a simple divider with centered text:
import * as React from 'react';
import { Box, Divider, Typography } from '@mui/material';
function TextDivider() {
return (
<Box sx={{ width: '100%', maxWidth: 500, my: 4 }}>
<Typography variant="body1" gutterBottom>
Content above the divider
</Typography>
<Divider>SECTION</Divider>
<Typography variant="body1" sx={{ mt: 2 }}>
Content below the divider
</Typography>
</Box>
);
}
By default, the text is centered within the divider. The divider creates lines on both sides of the text, creating a clean and professional section header.
Controlling Text Alignment
You can control the text alignment using the textAlign
prop, which accepts 'center', 'left', or 'right':
import * as React from 'react';
import { Box, Divider, Stack } from '@mui/material';
function AlignedTextDividers() {
return (
<Stack spacing={3} sx={{ width: '100%', maxWidth: 500 }}>
<Divider textAlign="left">Left Aligned</Divider>
<Divider textAlign="center">Center Aligned (Default)</Divider>
<Divider textAlign="right">Right Aligned</Divider>
</Stack>
);
}
This allows you to create visual hierarchies and align section headers with other content in your layout. Left-aligned divider text works well for forms or content with a left-aligned reading pattern, while right-aligned can be useful for RTL languages or special design cases.
Custom Content in Dividers
You're not limited to just text in dividers. You can include any React node, such as icons, badges, or custom components:
import * as React from 'react';
import { Box, Divider, Chip, Avatar } from '@mui/material';
import StarIcon from '@mui/icons-material/Star';
function CustomContentDivider() {
return (
<Box sx={{ width: '100%', maxWidth: 500, my: 4 }}>
{/* Divider with an icon */}
<Divider sx={{ mb: 4 }}>
<StarIcon color="primary" />
</Divider>
{/* Divider with a chip */}
<Divider sx={{ mb: 4 }}>
<Chip
label="FEATURED SECTION"
color="primary"
size="small"
/>
</Divider>
{/* Divider with an avatar */}
<Divider>
<Avatar
alt="User Avatar"
src="/static/images/avatar/1.jpg"
sx={{ width: 24, height: 24 }}
/>
</Divider>
</Box>
);
}
This flexibility allows you to create highly customized section dividers that match your application's design language and provide additional context or visual interest.
Step-by-Step Guide: Building a Section Divider with Label
Let's build a complete example of a section divider with a label that you can use in your React applications. We'll start from the basics and progressively enhance the component.
Step 1: Set Up Your Project Environment
First, ensure you have the necessary dependencies installed:
npm install @mui/material @emotion/react @emotion/styled @mui/icons-material
If you're using yarn:
yarn add @mui/material @emotion/react @emotion/styled @mui/icons-material
These packages provide the core MUI components, styling solutions, and icons we'll use in our implementation.
Step 2: Create a Basic Section Divider Component
Let's start by creating a reusable section divider component that accepts a label:
import React from 'react';
import { Divider, Box } from '@mui/material';
function SectionDivider({ label, ...props }) {
return (
<Box sx={{ width: '100%', my: 2 }}>
<Divider {...props}>{label}</Divider>
</Box>
);
}
export default SectionDivider;
This component wraps the MUI Divider with some default spacing and allows passing a label as a prop. The spread operator (...props
) enables passing any additional Divider props to customize the component further.
Step 3: Implement the Divider in a Layout
Now, let's use our SectionDivider component in a real layout:
import React from 'react';
import {
Box,
Typography,
Card,
CardContent,
Container
} from '@mui/material';
import SectionDivider from './SectionDivider';
function ProductPage() {
return (
<Container maxWidth="md">
<Typography variant="h4" component="h1" gutterBottom sx={{ mt: 4 }}>
Product Details
</Typography>
<Card sx={{ mb: 4 }}>
<CardContent>
<Typography variant="body1">
This is the product overview section with basic information.
</Typography>
</CardContent>
</Card>
<SectionDivider label="SPECIFICATIONS" />
<Card sx={{ mb: 4 }}>
<CardContent>
<Typography variant="body1">
Detailed product specifications and technical details.
</Typography>
</CardContent>
</Card>
<SectionDivider label="CUSTOMER REVIEWS" textAlign="left" />
<Card>
<CardContent>
<Typography variant="body1">
Reviews and ratings from verified customers.
</Typography>
</CardContent>
</Card>
</Container>
);
}
export default ProductPage;
In this example, we've created a product page layout with multiple sections, each separated by our custom SectionDivider component. We've also demonstrated how to customize the text alignment for different sections.
Step 4: Enhance the Divider with Custom Styling
Let's enhance our SectionDivider component with more customization options and better styling:
import React from 'react';
import { Divider, Box, Typography, useTheme } from '@mui/material';
function EnhancedSectionDivider({
label,
textAlign = 'center',
fontSize = 'subtitle2',
color,
dividerColor,
spacing = 2,
fontWeight = 'medium',
...props
}) {
const theme = useTheme();
// Determine colors with fallbacks
const textColor = color || theme.palette.text.secondary;
const lineColor = dividerColor || theme.palette.divider;
return (
<Box sx={{ width: '100%', my: spacing }}>
<Divider
textAlign={textAlign}
sx={{
'&::before, &::after': {
borderColor: lineColor,
},
'& .MuiDivider-wrapper': {
paddingLeft: textAlign === 'left' ? 0 : undefined,
paddingRight: textAlign === 'right' ? 0 : undefined,
},
}}
{...props} >
<Typography
variant={fontSize}
component="span"
sx={{
color: textColor,
fontWeight: fontWeight,
letterSpacing: '0.5px',
}} >
{label}
</Typography>
</Divider>
</Box>
);
}
export default EnhancedSectionDivider;
This enhanced version provides:
- Custom text color and divider color options
- Typography variant control for the label
- Custom spacing around the divider
- Font weight customization
- Special handling for left and right alignment padding
Step 5: Use the Enhanced Divider in Different Contexts
Now let's implement our enhanced divider in different contexts to showcase its versatility:
import React from 'react';
import {
Box,
Container,
Typography,
Paper,
List,
ListItem,
ListItemText,
useTheme
} from '@mui/material';
import EnhancedSectionDivider from './EnhancedSectionDivider';
function DividerShowcase() {
const theme = useTheme();
return (
<Container maxWidth="md" sx={{ py: 4 }}>
<Typography variant="h4" gutterBottom>
Divider Showcase
</Typography>
{/* Standard usage */}
<EnhancedSectionDivider label="DEFAULT SECTION" />
<Paper sx={{ p: 2, mb: 4 }}>
<Typography>Standard section content</Typography>
</Paper>
{/* Custom colors */}
<EnhancedSectionDivider
label="IMPORTANT SECTION"
color={theme.palette.primary.main}
dividerColor={theme.palette.primary.light}
fontWeight="bold"
/>
<Paper sx={{ p: 2, mb: 4 }}>
<Typography>Section with primary color theme</Typography>
</Paper>
{/* Left aligned with custom spacing */}
<EnhancedSectionDivider
label="LIST ITEMS"
textAlign="left"
spacing={3}
fontSize="body2"
/>
<List>
{['Item 1', 'Item 2', 'Item 3'].map((item) => (
<ListItem key={item} divider>
<ListItemText primary={item} />
</ListItem>
))}
</List>
{/* Right aligned for special cases */}
<Box sx={{ mt: 4 }}>
<EnhancedSectionDivider
label="ADDITIONAL INFO"
textAlign="right"
color={theme.palette.text.disabled}
/>
<Paper sx={{ p: 2 }}>
<Typography variant="body2">
Supplementary information with right-aligned header
</Typography>
</Paper>
</Box>
</Container>
);
}
export default DividerShowcase;
This showcase demonstrates different configurations of our enhanced divider component, highlighting its flexibility across various UI contexts.
Step 6: Create a Responsive Section Divider
For responsive designs, we might want our divider to adapt to different screen sizes. Let's enhance our component to handle this:
import React from 'react';
import { Divider, Box, Typography, useTheme, useMediaQuery } from '@mui/material';
function ResponsiveSectionDivider({
label,
textAlign = { xs: 'center', md: 'left' },
fontSize = { xs: 'body2', md: 'subtitle2' },
spacing = { xs: 1.5, md: 2.5 },
...props
}) {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
// Convert string values to responsive objects if needed
const resolvedTextAlign = typeof textAlign === 'string'
? { xs: textAlign }
: textAlign;
const resolvedFontSize = typeof fontSize === 'string'
? { xs: fontSize }
: fontSize;
const resolvedSpacing = typeof spacing === 'number'
? { xs: spacing }
: spacing;
// Determine the effective text alignment for the current breakpoint
const effectiveTextAlign = isMobile
? resolvedTextAlign.xs || 'center'
: resolvedTextAlign.md || resolvedTextAlign.xs || 'left';
return (
<Box sx={{ width: '100%', my: resolvedSpacing }}>
<Divider
textAlign={effectiveTextAlign}
{...props} >
<Typography
variant={isMobile ? resolvedFontSize.xs : resolvedFontSize.md || resolvedFontSize.xs}
component="span"
sx={{
fontWeight: isMobile ? 'regular' : 'medium',
letterSpacing: isMobile ? '0.25px' : '0.5px',
}} >
{label}
</Typography>
</Divider>
</Box>
);
}
export default ResponsiveSectionDivider;
This responsive version allows you to:
- Define different text alignments for different breakpoints
- Adjust the font size based on screen size
- Change spacing around the divider for different devices
- Apply different typographic styles based on viewport
Advanced Customization Techniques
Beyond the basic implementation, there are several ways to customize MUI dividers to perfectly match your design system.
Custom Styling with the sx Prop
The sx
prop is the most direct way to apply custom styles to your divider:
import React from 'react';
import { Divider, Box } from '@mui/material';
function CustomStyledDividers() {
return (
<Box sx={{ width: '100%', maxWidth: 500 }}>
{/* Gradient divider */}
<Divider
sx={{
my: 4,
height: 3,
backgroundImage: 'linear-gradient(to right, rgba(0,0,0,0), rgba(25,118,210,1), rgba(0,0,0,0))',
border: 'none'
}}
/>
{/* Dotted divider */}
<Divider
sx={{
my: 4,
borderStyle: 'dotted',
borderWidth: 2,
borderColor: 'primary.light'
}}
/>
{/* Thick divider with rounded ends */}
<Divider
sx={{
my: 4,
height: 6,
borderRadius: 3,
bgcolor: 'secondary.main'
}}
/>
{/* Divider with shadow */}
<Divider
sx={{
my: 4,
height: 1,
bgcolor: 'background.paper',
boxShadow: '0 1px 2px rgba(0,0,0,0.2)'
}}
/>
</Box>
);
}
export default CustomStyledDividers;
These examples showcase various visual styles you can achieve with the sx
prop, from gradients to shadows to custom border styles.
Theme Customization
For consistent styling across your application, you can customize the Divider component through the theme:
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { CssBaseline, Box, Divider } from '@mui/material';
// Create a custom theme with divider overrides
const theme = createTheme({
components: {
MuiDivider: {
styleOverrides: {
// Apply to all dividers
root: {
borderColor: '#e0e0e0',
'&::before, &::after': {
borderColor: '#e0e0e0',
},
},
// Apply to dividers with text
withChildren: {
'&::before, &::after': {
borderWidth: '1px',
},
'& .MuiDivider-wrapper': {
padding: '0 16px',
},
},
// Apply to dividers with textAlign="left"
textAlignLeft: {
'&::before': {
width: '5%',
},
},
// Apply to middle variant
middle: {
marginLeft: 24,
marginRight: 24,
},
},
// Default props for all dividers
defaultProps: {
light: true, // Use lighter color by default
},
},
},
});
function ThemedDividers() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Box sx={{ p: 3 }}>
<Divider>Themed Divider</Divider>
<Box sx={{ my: 2 }} />
<Divider textAlign="left">Left Aligned</Divider>
<Box sx={{ my: 2 }} />
<Divider variant="middle">Middle Variant</Divider>
</Box>
</ThemeProvider>
);
}
export default ThemedDividers;
Theme customization ensures consistent styling across your application and reduces the need for repetitive inline styling.
Creating a Custom Divider Component
For more complex dividers or frequently used patterns, creating a custom component is often the best approach:
import React from 'react';
import { Divider, Box, Typography, styled } from '@mui/material';
// Create styled components for custom divider parts
const StyledDivider = styled(Divider)(({ theme, color = 'primary' }) => ({
'&::before, &::after': {
borderColor: theme.palette[color].light,
},
'& .MuiDivider-wrapper': {
backgroundColor: theme.palette.background.paper,
borderRadius: 16,
padding: theme.spacing(0, 2),
boxShadow: theme.shadows[1],
},
}));
const LabelWrapper = styled(Box)(({ theme, color = 'primary' }) => ({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
color: theme.palette[color].main,
}));
function CustomDividerWithIcon({
label,
icon: Icon,
color = 'primary',
...dividerProps
}) {
return (
<StyledDivider color={color} {...dividerProps}>
<LabelWrapper color={color}>
{Icon && <Icon fontSize="small" />}
<Typography
variant="button"
component="span"
sx={{ fontWeight: 'medium' }} >
{label}
</Typography>
</LabelWrapper>
</StyledDivider>
);
}
export default CustomDividerWithIcon;
This custom component provides a consistent way to create dividers with icons and labels, with customizable colors and styling.
Integrating Dividers with Other MUI Components
Dividers are particularly useful when integrated with other MUI components to create cohesive interfaces.
Dividers in Lists
Lists are one of the most common places to use dividers:
import React from 'react';
import {
List,
ListItem,
ListItemText,
ListItemIcon,
Divider,
Box
} from '@mui/material';
import InboxIcon from '@mui/icons-material/Inbox';
import DraftsIcon from '@mui/icons-material/Drafts';
import SendIcon from '@mui/icons-material/Send';
function DividedList() {
return (
<Box sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
<List component="nav" aria-label="mailbox folders">
<ListItem button>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Inbox" />
</ListItem>
{/* Standard divider */}
<Divider />
<ListItem button>
<ListItemIcon>
<DraftsIcon />
</ListItemIcon>
<ListItemText primary="Drafts" />
</ListItem>
{/* Inset divider aligns with text */}
<Divider variant="inset" component="li" />
<ListItem button>
<ListItemIcon>
<SendIcon />
</ListItemIcon>
<ListItemText primary="Sent Items" />
</ListItem>
{/* Divider with text label */}
<Divider component="li">ARCHIVES</Divider>
<ListItem button>
<ListItemText primary="Archived Mail" secondary="From previous months" />
</ListItem>
</List>
</Box>
);
}
export default DividedList;
In lists, the inset
variant is particularly useful as it aligns the divider with the text content, creating a more polished look.
Dividers in Cards and Panels
Dividers can effectively separate content within cards:
import React from 'react';
import {
Card,
CardHeader,
CardContent,
CardActions,
Button,
Typography,
Divider,
Box
} from '@mui/material';
function DividedCard() {
return (
<Box sx={{ maxWidth: 400 }}>
<Card>
<CardHeader title="Product Information" />
<Divider />
<CardContent>
<Typography variant="body2" color="text.secondary">
Main product description and details go here.
</Typography>
</CardContent>
<Divider>PRICING</Divider>
<CardContent>
<Typography variant="h6" color="primary" sx={{ fontWeight: 'bold' }}>
$99.99
</Typography>
<Typography variant="caption" color="text.secondary">
*Price may vary by location
</Typography>
</CardContent>
<Divider />
<CardActions>
<Button size="small">Learn More</Button>
<Button size="small" color="primary">Add to Cart</Button>
</CardActions>
</Card>
</Box>
);
}
export default DividedCard;
In cards, dividers help organize different types of information and actions, making the content more scannable and structured.
Dividers in Forms
Dividers can help organize form sections:
import React from 'react';
import {
Box,
TextField,
Button,
Divider,
Grid,
Typography,
FormControlLabel,
Checkbox
} from '@mui/material';
function DividedForm() {
return (
<Box
component="form"
sx={{
width: '100%',
maxWidth: 600,
mx: 'auto',
p: 3,
}} >
<Typography variant="h5" gutterBottom>
Registration Form
</Typography>
<Divider textAlign="left">PERSONAL INFORMATION</Divider>
<Grid container spacing={2} sx={{ mt: 2, mb: 4 }}>
<Grid item xs={12} sm={6}>
<TextField
required
fullWidth
label="First Name"
autoFocus
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
required
fullWidth
label="Last Name"
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
label="Email Address"
type="email"
/>
</Grid>
</Grid>
<Divider textAlign="left">ACCOUNT DETAILS</Divider>
<Grid container spacing={2} sx={{ mt: 2, mb: 4 }}>
<Grid item xs={12}>
<TextField
required
fullWidth
label="Username"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
required
fullWidth
label="Password"
type="password"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
required
fullWidth
label="Confirm Password"
type="password"
/>
</Grid>
</Grid>
<Divider textAlign="left">PREFERENCES</Divider>
<Box sx={{ mt: 2, mb: 4 }}>
<FormControlLabel
control={<Checkbox color="primary" />}
label="Receive email notifications"
/>
<FormControlLabel
control={<Checkbox color="primary" />}
label="Subscribe to newsletter"
/>
</Box>
<Divider />
<Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end', gap: 2 }}>
<Button variant="outlined">Cancel</Button>
<Button variant="contained" color="primary" type="submit">
Register
</Button>
</Box>
</Box>
);
}
export default DividedForm;
In forms, dividers with labels create clear sections that help users understand the form structure and complete it more efficiently.
Accessibility Considerations
When using dividers with labels, proper accessibility is crucial for users with screen readers or other assistive technologies.
Semantic HTML and ARIA Attributes
import React from 'react';
import { Divider, Box, Typography } from '@mui/material';
function AccessibleDivider({ label, headingLevel = 'h3', ...props }) {
// Determine the heading component based on the level
const HeadingComponent = headingLevel;
return (
<Box role="presentation" sx={{ width: '100%', my: 2 }}>
{/* Screen reader only heading */}
<Typography
variant="srOnly"
component={HeadingComponent}
>
{label}
</Typography>
{/* Visual divider with label */}
<Divider
aria-hidden="true" // Hide from screen readers since we have the heading
{...props}
>
{label}
</Divider>
</Box>
);
}
export default AccessibleDivider;
This approach ensures that:
- Screen readers announce the section properly via a semantic heading
- The visual divider is hidden from screen readers to avoid duplicate announcements
- The visual hierarchy is maintained for sighted users
Keyboard Navigation
For interactive dividers (like collapsible section headers), ensure keyboard navigation works properly:
import React, { useState } from 'react';
import {
Divider,
Box,
Typography,
Collapse,
IconButton
} from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
function CollapsibleSection({ title, children }) {
const [expanded, setExpanded] = useState(false);
const toggleExpanded = () => {
setExpanded((prev) => !prev);
};
return (
<Box sx={{ width: '100%', my: 2 }}>
<Divider
textAlign="left"
sx={{
cursor: 'pointer',
'&:hover': {
bgcolor: 'action.hover',
},
}} >
<Box
component="button"
onClick={toggleExpanded}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
toggleExpanded();
}
}}
sx={{
display: 'flex',
alignItems: 'center',
gap: 1,
border: 'none',
background: 'none',
padding: 0,
cursor: 'pointer',
color: 'inherit',
font: 'inherit',
}}
aria-expanded={expanded}
aria-controls={`section-${title.replace(/\s+/g, '-').toLowerCase()}`} >
<Typography variant="subtitle1" component="span">
{title}
</Typography>
<IconButton
size="small"
edge="end"
aria-label={expanded ? "collapse section" : "expand section"}
sx={{ p: 0 }}
tabIndex={-1} // Remove from tab order as the whole button is focusable >
{expanded ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</IconButton>
</Box>
</Divider>
<Collapse
in={expanded}
id={`section-${title.replace(/\s+/g, '-').toLowerCase()}`}
>
<Box sx={{ pt: 2, pb: 1 }}>
{children}
</Box>
</Collapse>
</Box>
);
}
export default CollapsibleSection;
This implementation ensures that:
- The section can be toggled with both mouse and keyboard
- Proper ARIA attributes inform screen readers about the expanded state
- The content is properly associated with its header via ID references
Best Practices and Common Issues
Best Practices
-
Use semantic dividers: Choose the appropriate variant based on the context (fullWidth, inset, middle).
-
Consistent spacing: Maintain consistent spacing around dividers throughout your application.
-
Typography hierarchy: Use appropriate typography variants for divider labels that match your design system's hierarchy.
-
Color contrast: Ensure sufficient contrast between divider lines, labels, and backgrounds.
-
Responsive considerations: Adjust divider text alignment and styling for different screen sizes.
import React from 'react';
import { useTheme, useMediaQuery, Divider, Box } from '@mui/material';
function BestPracticeDivider({ label }) {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
return (
<Box sx={{ my: { xs: 2, md: 3 } }}>
<Divider
textAlign={isMobile ? "center" : "left"}
sx={{
'&::before, &::after': {
borderColor: theme.palette.divider,
},
'& .MuiDivider-wrapper': {
color: theme.palette.text.secondary,
fontSize: isMobile ? '0.875rem' : '1rem',
fontWeight: 'medium',
},
}} >
{label}
</Divider>
</Box>
);
}
export default BestPracticeDivider;
Common Issues and Solutions
Issue 1: Divider Not Spanning Full Width
If your divider isn't spanning the full width as expected, check container styling:
import React from 'react';
import { Divider, Box } from '@mui/material';
// Problem: Divider not spanning full width
function ProblemExample() {
return (
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Divider /> {/* May not span full width in some flex layouts */}
</Box>
);
}
// Solution: Use width: '100%'
function SolutionExample() {
return (
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Divider sx={{ width: '100%' }} />
</Box>
);
}
export { ProblemExample, SolutionExample };
Issue 2: Vertical Divider Height Problems
Vertical dividers often need special handling for height:
import React from 'react';
import { Divider, Box } from '@mui/material';
// Problem: Vertical divider not taking full height
function ProblemExample() {
return (
<Box sx={{ display: 'flex', height: 100 }}>
<Box>Left content</Box>
<Divider orientation="vertical" /> {/* May not take full height */}
<Box>Right content</Box>
</Box>
);
}
// Solution: Use flexItem prop
function SolutionExample() {
return (
<Box sx={{ display: 'flex', height: 100 }}>
<Box>Left content</Box>
<Divider orientation="vertical" flexItem />
<Box>Right content</Box>
</Box>
);
}
export { ProblemExample, SolutionExample };
Issue 3: Text Alignment in RTL Layouts
For right-to-left languages, you need to handle text alignment differently:
import React from 'react';
import { Divider, Box, ThemeProvider, createTheme } from '@mui/material';
import rtlPlugin from 'stylis-plugin-rtl';
import { prefixer } from 'stylis';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
// Create RTL cache
const rtlCache = createCache({
key: 'muirtl',
stylisPlugins: [prefixer, rtlPlugin],
});
// Create RTL theme
const rtlTheme = createTheme({
direction: 'rtl',
});
function RTLDivider() {
return (
<CacheProvider value={rtlCache}>
<ThemeProvider theme={rtlTheme}>
<Box sx={{ width: '100%', dir: 'rtl' }}>
{/* In RTL, "left" actually appears on the right side */}
<Divider textAlign="left">القسم الأول</Divider>
<Box sx={{ my: 2 }} />
{/* For RTL interfaces, "right" appears on the left side */}
<Divider textAlign="right">القسم الثاني</Divider>
</Box>
</ThemeProvider>
</CacheProvider>
);
}
export default RTLDivider;
Issue 4: Inconsistent Spacing Around Dividers
To maintain consistent spacing around dividers:
import React from 'react';
import { Box, Divider, styled } from '@mui/material';
// Create a consistent spacing wrapper
const DividerSpacing = styled(Box)(({ theme }) => ({
marginTop: theme.spacing(3),
marginBottom: theme.spacing(3),
}));
function ConsistentDividers() {
return (
<Box>
<DividerSpacing>
<Divider>SECTION ONE</Divider>
</DividerSpacing>
{/* Content here */}
<DividerSpacing>
<Divider>SECTION TWO</Divider>
</DividerSpacing>
{/* More content */}
<DividerSpacing>
<Divider>SECTION THREE</Divider>
</DividerSpacing>
</Box>
);
}
export default ConsistentDividers;
Wrapping Up
The MUI Divider component offers a powerful way to organize your React applications with visually appealing section dividers. We've explored everything from basic implementation to advanced customization techniques, responsive designs, and accessibility considerations.
By leveraging the flexibility of the Divider component with labels, you can create clear visual hierarchies that guide users through your interface. Whether you're building forms, product pages, dashboards, or any complex UI, well-designed dividers with labels can significantly improve the user experience by providing context and structure.
Remember to keep accessibility in mind, maintain consistent styling through your theme, and consider the responsive behavior of your dividers across different device sizes. With these considerations in place, you'll be able to create professional, polished interfaces that are both visually appealing and functional.