DIY: React Grid Components
Grid components like Row and Col have become essential tools for creating responsive designs. While there are many grid systems available, such as Bootstrap and Material-UI, building your own can be a great learning experience and can help you tailor the layout to your specific needs. In this blog post, we’ll walk through the process of creating a simple and reusable grid system in React, consisting of custom Row and Col components. By understanding and constructing these fundamental components, you’ll not only enhance your coding skills but also gain the flexibility to design layouts that precisely fit your project requirements.
Before we begin: If you’re eager to see the final result, feel free to scroll to the bottom of the page where I’ve included the complete code in a CodeSandbox link.
Creating the Grid Components
We’ll create two components: Row and Col. These components will use CSS Flexbox to handle the layout.
- Creating the
RowComponent:
TheRowcomponent will act as a container for our columns. It will applyFlexboxstyles to ensure that its children (theColcomponents) are laid out correctly.
Create a new file named Row.js in the src folder:
// src/Row.js
import React from 'react';
import './Row.css';
const Row = ({ children, className = '', style = {} }) => {
return (
<div className={`row ${className}`} style={style}>
{children}
</div>
);
};
export default Row;Add the corresponding CSS in a file named Row.css :
/* src/Row.css */
.row {
display: flex;
flex-wrap: wrap;
margin-left: -15px;
margin-right: -15px;
}2. Creating the Col Component:
The Col component will handle the column layout. It will accept props to determine the column span across different screen sizes.
Create a new file named Col.js in the src folder:
// src/Col.js
import React from "react";
import "./Col.css";
const Col = ({
children,
xs,
sm,
md,
lg,
cl,
className = "",
...restProps
}) => {
const getColClass = (size, prefix) => (size ? `${prefix}-${size}` : "");
const colClasses = [
getColClass(xs, "col-xs"),
getColClass(sm, "col-sm"),
getColClass(md, "col-md"),
getColClass(lg, "col-lg"),
getColClass(xl, "col-xl"),
].join(" ");
return (
<div className={`col ${colClasses} ${className}`} {...restProps}>
{children}
</div>
);
};
export default Col;Add the CSS for the Col component in Col.css :
/* src/Col.css */
.col {
padding-left: 15px;
padding-right: 15px;
}
.col-xs-1 { flex: 0 0 8.33%; max-width: 8.33%; }
.col-xs-2 { flex: 0 0 16.66%; max-width: 16.66%; }
.col-xs-3 { flex: 0 0 25%; max-width: 25%; }
.col-xs-4 { flex: 0 0 33.33%; max-width: 33.33%; }
.col-xs-5 { flex: 0 0 41.66%; max-width: 41.66%; }
.col-xs-6 { flex: 0 0 50%; max-width: 50%; }
.col-xs-7 { flex: 0 0 58.33%; max-width: 58.33%; }
.col-xs-8 { flex: 0 0 66.66%; max-width: 66.66%; }
.col-xs-9 { flex: 0 0 75%; max-width: 75%; }
.col-xs-10 { flex: 0 0 83.33%; max-width: 83.33%; }
.col-xs-11 { flex: 0 0 91.66%; max-width: 91.66%; }
.col-xs-12 { flex: 0 0 100%; max-width: 100%; }
@media (min-width: 576px) {
.col-sm-1 { flex: 0 0 8.33%; max-width: 8.33%; }
.col-sm-2 { flex: 0 0 16.66%; max-width: 16.66%; }
.col-sm-3 { flex: 0 0 25%; max-width: 25%; }
.col-sm-4 { flex: 0 0 33.33%; max-width: 33.33%; }
.col-sm-5 { flex: 0 0 41.66%; max-width: 41.66%; }
.col-sm-6 { flex: 0 0 50%; max-width: 50%; }
.col-sm-7 { flex: 0 0 58.33%; max-width: 58.33%; }
.col-sm-8 { flex: 0 0 66.66%; max-width: 66.66%; }
.col-sm-9 { flex: 0 0 75%; max-width: 75%; }
.col-sm-10 { flex: 0 0 83.33%; max-width: 83.33%; }
.col-sm-11 { flex: 0 0 91.66%; max-width: 91.66%; }
.col-sm-12 { flex: 0 0 100%; max-width: 100%; }
}
@media (min-width: 768px) {
.col-md-1 { flex: 0 0 8.33%; max-width: 8.33%; }
.col-md-2 { flex: 0 0 16.66%; max-width: 16.66%; }
.col-md-3 { flex: 0 0 25%; max-width: 25%; }
.col-md-4 { flex: 0 0 33.33%; max-width: 33.33%; }
.col-md-5 { flex: 0 0 41.66%; max-width: 41.66%; }
.col-md-6 { flex: 0 0 50%; max-width: 50%; }
.col-md-7 { flex: 0 0 58.33%; max-width: 58.33%; }
.col-md-8 { flex: 0 0 66.66%; max-width: 66.66%; }
.col-md-9 { flex: 0 0 75%; max-width: 75%; }
.col-md-10 { flex: 0 0 83.33%; max-width: 83.33%; }
.col-md-11 { flex: 0 0 91.66%; max-width: 91.66%; }
.col-md-12 { flex: 0 0 100%; max-width: 100%; }
}
@media (min-width: 992px) {
.col-lg-1 { flex: 0 0 8.33%; max-width: 8.33%; }
.col-lg-2 { flex: 0 0 16.66%; max-width: 16.66%; }
.col-lg-3 { flex: 0 0 25%; max-width: 25%; }
.col-lg-4 { flex: 0 0 33.33%; max-width: 33.33%; }
t .col-lg-5 { flex: 0 0 41.66%; max-width: 41.66%; }
.col-lg-6 { flex: 0 0 50%; max-width: 50%; }
.col-lg-7 { flex: 0 0 58.33%; max-width: 58.33%; }
.col-lg-8 { flex: 0 0 66.66%; max-width: 66.66%; }
.col-lg-9 { flex: 0 0 75%; max-width: 75%; }
.col-lg-10 { flex: 0 0 83.33%; max-width: 83.33%; }
.col-lg-11 { flex: 0 0 91.66%; max-width: 91.66%; }
.col-lg-12 { flex: 0 0 100%; max-width: 100%; }
}
@media (min-width: 1200px) {
.col-xl-1 { flex: 0 0 8.33%; max-width: 8.33%; }
.col-xl-2 { flex: 0 0 16.66%; max-width: 16.66%; }
.col-xl-3 { flex: 0 0 25%; max-width: 25%; }
.col-xl-4 { flex: 0 0 33.33%; max-width: 33.33%; }
.col-xl-5 { flex: 0 0 41.66%; max-width: 41.66%; }
.col-xl-6 { flex: 0 0 50%; max-width: 50%; }
.col-xl-7 { flex: 0 0 58.33%; max-width: 58.33%; }
.col-xl-8 { flex: 0 0 66.66%; max-width: 66.66%; }
.col-xl-9 { flex: 0 0 75%; max-width: 75%; }
.col-xl-10 { flex: 0 0 83.33%; max-width: 83.33%; }
.col-xl-11 { flex: 0 0 91.66%; max-width: 91.66%; }
.col-xl-12 { flex: 0 0 100%; max-width: 100%; }
}Given the CSS above, if you adhere to the DRY (Don’t Repeat Yourself) principle, you will want to refactor the code to reduce redundancy. By leveraging SCSS, we can minimize duplication and enhance maintainability. Below is the refactored Col.scss file.
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
);
@mixin generate-col-classes($breakpoint, $min-width) {
@media (min-width: $min-width) {
@for $i from 1 through 12 {
.col-#{$breakpoint}-#{$i} {
flex: 0 0 percentage($i / 12);
max-width: percentage($i / 12);
}
}
}
}
.col {
padding-left: 15px;
padding-right: 15px;
}
@each $breakpoint, $min-width in $breakpoints {
@include generate-col-classes($breakpoint, $min-width);
}Detailed Breakdown of Flex-Basis and Max-Width in a Grid Layout:
You must be wondering where the values of flex: 0 0 8.33% came from?, The values for flex-basis and max-width are calculated based on the fraction of the total number of columns in the grid system. In a 12-column grid system, each column represents a fraction of 12.
Here’s the detailed calculation for each value:
1. Total Columns in Grid System: 12
2. Percentage Calculation:
- For col-xs-1: This column spans 1 out of 12 columns.
- Calculation: 1/12 * 100% = 8.33%
- For col-xs-2: This column spans 2 out of 12 columns.
- Calculation: 2/12 * 100% = 16.66%
- For col-xs-3: This column spans 3out of 12 columns.
- Calculation: 3/12 * 100% = 25%
And so forth for other columns.If you want to understand how flex: 0 0 auto works, please read my blog for more details.
Using the Grid Components
With the Row and Col components ready, you can now use them to build a responsive layout. Open src/App.js and replace its contents with the following:
// src/App.js
import React from 'react';
import Row from './Row';
import Col from './Col';
import './App.css';
function App() {
return (
<div className="App">
<Row>
<Col xs={12} sm={6} md={4} lg={3} xl={2}>
<div className="box">1</div>
</Col>
<Col xs={12} sm={6} md={4} lg={3} xl={2}>
<div className="box">2</div>
</Col>
<Col xs={12} sm={6} md={4} lg={3} xl={2}>
<div className="box">3</div>
</Col>
<Col xs={12} sm={6} md={4} lg={3} xl={2}>
<div className="box">4</div>
</Col>
<Col xs={12} sm={6} md={4} lg={3} xl={2}>
<div className="box">5</div>
</Col>
<Col xs={12} sm={6} md={4} lg={3} xl={2}>
<div className="box">6</div>
</Col>
</Row>
</div>
);
}
export default App;Create a CSS file named App.css in the src folder to style the boxes:
/* src/App.css */
.box {
background-color: #ddd;
padding: 20px;
text-align: center;
margin-bottom: 15px;
}Conclusion
You now have a responsive grid system in React with a custom Row and Col components. This grid system uses Flexbox and CSS media queries to adapt to different screen sizes, ensuring your application looks great on any device. By building your grid system, you gain a deeper understanding of responsive design and Flexbox, and you can customize it to fit your specific needs. Happy coding! ⌨️

