Using n Column grids on React Native

Ahmed Tokyo
6 min readDec 31, 2022

--

The problem

  • When it comes to building scalable UIs, having a grid system is a critical requirement.
  • The most common choice of grid for web design is 8px 12 column grid, which is used by a lot of design libraries like bootstrap, tailwind and ant design.
  • All of these libraries work quite well with web, but not at all or at least not to the same level with react-native.
  • If you have a web app and a native app, it would be ideal to unify the design language across both platforms. This means it would be ideal to unify grid system you use across both.
  • Hence, react-native-flex-grid

React-native-flex-grid is built on top of react-native’s flex design system. It provides a {n}px {n} column grid (defaults: 8px, 12 columns).

Strategizing a solution

The strategy to build the grid system was as follows:

  • We need to build a grid system, similar to bootstrap’s, using react-native and flex.
  • We need support for grid breakpoints to render a different layout based on the screen size. For example: we might want a row to have 4 items inline on iPad but one item per row stacked in a vertical fashion for iPhone.
  • We need the grid to be 100% configurable, this way it’s reusable in any project regardless of the design.
  • We need media queries on react-native just like we have on web.
  • We need support for both react-native and react-native-web.
  • We need to write code that is consistent with react for web as well.
  • We need a way to visualize and test the components, ie: Storybook.

Grid architecture

• When it comes to design, the gold standard is to follow a 8px grid. • On web, the gold standard is to follow a 12 column grid (eg: bootstrap, react-flex-grid, tailwind). • On native, however, there’s no community consensus on a gold standard for the column count. Some libraries use 4 columns, some use 8 or 12. Apple design guideline recommends any column count between 1 & 9 (Docs).

• The decision was to go with an 8px 12 column grid.

  • We get to unify react web and react-native code
  • We can still achieve the commonly used 4 and 8 columns

Code Structure:

We have 3 main components: Container, Row and Column.

Container used to contain pages or sections of pages. Similar to bootstrap.

<Contianer /> // container with a max width, gutters x and margin auto
<Contianer fluid /> // container fluid with gutters x<Contianer fluid gx={0} /> // container fluid with no gutters. spanning the width of the screen

Row used to contain columns, All columns inside a row can stack on each other.

<Row>
// ... add columns here
</Row>
// Row with no gutter x
<Row gx={0}>
// ... add columns here
</Row>
// Row with custom gutter x
<Row gx={1}>
// ... add columns here
</Row>
// Row with dir="rtl"
<Row dir="rtl">
// ... add columns here
</Row>

Column

Used to contain our display content, eg: Text, Images or any other components. Here we display a row with 2 columns.

Both columns have different sizes based on the viewport width. i.e.: on xs (iPhone SE) it has the size 6, on sm (iPhone 14) it has the size 4, on md (iPad) it has the size 3, on lg (iPad pro) it has the size 2.

<Row>
<Col xs={6} sm={4} md ={3} lg={2}><Text>.col-6 .col-sm-4 .col-md-3 .col-lg-2</Text></>
<Col xs={6} sm={4} md ={3} lg={2}><Text>.col-6 .col-sm-4 .col-md-3 .col-lg-2</Text></>
</Row>
// custom gutter x
<Row gx={1}>
<Col gx={1} xs={6} sm={4} md ={3} lg={2}><Text>.col-6 .col-sm-4 .col-md-3 .col-lg-2</Text></>
<Col gx={1} xs={6} sm={4} md ={3} lg={2}><Text>.col-6 .col-sm-4 .col-md-3 .col-lg-2</Text></>
</Row>
// dir="rtl"
<Row dir="rtl">
<Col dir="rtl" xs={6} sm={4} md ={3} lg={2}><Text>.col-6 .col-sm-4 .col-md-3 .col-lg-2</Text></>
<Col dir="rtl" xs={6} sm={4} md ={3} lg={2}><Text>.col-6 .col-sm-4 .col-md-3 .col-lg-2</Text></>
</Row>

Utils

Grid

All aspects of the grid are configurable. So one can easily override breakpoints, column count, gutters and other options.

Here’s the default configuration:

{
/** Grid Breakpoints */
breakpoints: {
xs: 0,
sm: 375,
md: 768,
lg: 1024,
xl: 1200,
},
/** Grid column count */
colCount: 12,
/** Common gutters used */
gutters: {
0: 0,
1: SPACER * 0.25,
2: SPACER * 0.5,
3: SPACER,
4: SPACER * 1.5,
5: SPACER * 3,
},
/** Container max widths */
containerMaxWidths: {
xs: '100%',
sm: '100%',
md: '100%',
lg: '100%',
xl: 1140,
},
/** Container paddings horizontal */
containerPaddingsHorizontal: {
xs: 16,
sm: 20,
md: 40,
lg: 48,
xl: 48,
},
};

To override the defaults, call the setConfig anywhere in your app before rendering the grid, eg: in App.{j,t}sx or index.{j/t}s.

import { getConfig, setConfig } from 'react-native-flex-grid';
const config = getConfig();// update a single breakpoints
setConfig({
breakpoints: {
...config.breakpoints,
xl: 1400,
}
});
// update col count
setConfig({
colCount: 4,
});

Responsive:

Media Queries similar to web:

  • mediaQuery checks if the screen size matches a media query and returns a boolean. Ideal to use in JSX to manipulate dom.
import { mediaQuery } from 'react-native-flex-grid';
mediaQuery({ up: 'sm' }); // true or false
mediaQuery({ down: 'md' }); // true or false
mediaQuery({ exact: 'lg' }); // true or false
  • mediaQueryStyles checks if the screen size matches a media query and returns a style object that was provided. Ideal to use when creating react-native styles.
import { StyleSheet } from 'react-native';
import { mediaQueryStyle } from 'react-native-flex-grid';
const styles = StyleSheet.create({
item: {
backgroundColor: 'blue',
height: 50,
...mediaQueryStyle({ down: 'sm', style: { width: 20 } }), // `{ width: 20 }` or `null`
...mediaQueryStyle({ up: 'md', style: { width: 30 } }), // `{ width: 30 }` or `null`
...mediaQueryStyle({ exact: 'xl', style: { width: 40 } }), // `{ width: 40 }` or `null`
},
});
const Item = () => <View style={styles.item} />;export default Item;

Demo and Detailed docs

Storybook is used to visualize the library and adding detailed docs. This way, users can easily view, test or play around with the grid on both browsers and real devices.

We have two instances of storybook. A react-native-web instance on browser, and a react-native instance on device. The web instance is deployed to Netlify as a static website, and the on device instance is deployed by building iOS and android expo apps.

A few add-ons were added to storybook to ease the development process and ensure a pixel perfect UI. The main add-on is storybook-addon-grid, it allows us to display and overlay of the 8px square grid and the 12 columns grid. This way we can check if our grid code exactly aligns to the pixels and columns. To toggle the grid overlays, click on the grid icons in the top bar.

Helpful Resources:

Conclusion

We now have the library react-native-flex-grid. We can replicate our web design patterns in react-native in a consistent way, and we can configure the grid based on the design needs of the project.

Let’s get started on building pixel perfect UIs for react native today!

Inspiration

Claudia, my muse

--

--

No responses yet