Reference:

Wikipedia: Grid design

Deep good article! How to layout a Web interface with a Grid system

Very full! Summary of grid system and its application in background design

8 Point Grid

MDN-Grid

Antd component library is the best component library 😎

preface

Recently, I encountered the processing of Grid layout component in the NoCode project. I have studied it deeply and found it interesting. Therefore, THIS paper records the Grid design concept and its React technology implementation in Antd component library.

Grid component is actually a classic layout and typesetting component often used in front-end development. It may be no problem to use it to realize functions, but few people know about its design concept and React technology implementation.

For example, what are the basic components of a grid? Why AntDesign recommends 16+8n px for the Row gutter property (n is a natural number)? Why do common grid systems have 12 or 24 columns? How does React technology implement grids? And so on, all very interesting and worth exploring.

PS: This article will use the words Grid and Grid intermixed, as long as the reader knows that they mean the same thing.

What is a Grid

define

First of all, grids are a design concept, and a classic graphic design concept. Here’s a wikipedia description:

Grid design system (also known as grid design system, standard size system, program layout design, Swiss graphic design style, internationalist graphic design style) is a graphic design method and style. The use of fixed grid design layout, its style neat and simple, after the World War II, has become one of the mainstream style of publication design.

In 1629, King Louis XIV of France ordered a special royal commission to govern the printing press, headed by mathematician Nicolas Jaugeon. The committee proposed a new typeface design: based on the Roman style and using squares as the design basis, each typeface square was divided into 64 basic square units, and each square unit was divided into 36 subunits, so that a printing layout would consist of 2,304 subunits. It was the world’s first scientific experiment with fonts and layouts. It was also the prototype of the grid system.

In the 1950s, grid design systems were finally perfected in former West Germany and Switzerland. Through the publicity of Swiss graphic Design magazine, the results explored by the designers of Zurich and Basel from the 1940s were fully displayed, which influenced the countries of the world, so it is also called “Swiss Design”. Due to its simplicity, clarity and accurate conveying function, this Style was quickly recognized worldwide and became the most influential graphic design Style after the war as well as the most popular Style in the world. Therefore, it was also known as “International Typographic Style”.

In popular understanding, grid layout is a way to achieve two-dimensional layout in the form of grids. As shown in the figure below, it is a classic grid design style:

Part of the

Grid atomic unit

From microscopic perspective, the grid system will reduce the viewing area is divided into a series of specifications consistent small grid, the grid will assist designers more specification typesetting and layout, these small grid is the smallest unit of the whole grid system, it is important to note that for research and development, general won’t notice the existence of the grid atomic unit.

Most design languages, such as AntDesign, use 8 as the atomic unit of the grid. Why 8 instead of some other number?

If in 4, 6, 8, 10, 12 as the atomic unit of grid, you can see the current mainstream below divided exactly by the screen resolution and their relations, can see 4 is divisible, the highest rate of unit 4 as atomic unit is so small, but seem to increase or decrease difference is not obvious, so in the divisible rate and the right to seek a balance between, Choose 8 as the atomic unit of the Grid, which explains why AntDesign’s Grid component uses (16+8n) px for the Grid spacer tank.

Columns and Gutter

We talked about grid atomic units above, but in use we divide the entire visual area into columns, and we will directly declare how many columns a content area occupies horizontally to indicate the width of the entire content area.

Usually the Grid component in the component library we use divides the visible area directly into 12 or 24 columns, so why 12 and 24? I also specially looked up this question, and got the answer (Zhihu) :

Because 12 is the least common multiple of 1, 2, 3, 4, and 6, the 12-column raster system is relatively flexible, allowing rows to be divided into 1, 2, 3, 4, and 6 columns. If you want to support 5 columns, the least common multiple of 1,2,3,4,5 is 60, and 60 is too large for a grid system. Can 18 be divided into 4 columns? 12 can do everything 24 can do, so 12 is the best choice.

A sink is the space between two adjacent column widths, which is used to regulate the space between content on a page. The larger the sink value, the looser the visual effect of the white space on the page, and the less dense the page is. The sink is usually set to a fixed value.

React component implementation

The article is only part of the code, the full code address: github.com/erdong-fe/t…

In order to explore the React component’s implementation for Grid, I read the source code of Antd for Grid.

The key to the React Grid implementation is to use one-dimensional Flex layout to simulate two-dimensional effects. It separates two components, namely Row and Col, to realize the layout of rows and columns. Therefore, the research on React Grid focuses on the two components, Row and Col.

Row

The Row component’s main function is to create a Dom container for a Flex layout and receive rows related arguments. For simplicity, I will only implement the Row to receive the gutter argument. The Row argument is defined as follows:

interface RowProps extendsReact.HTMLAttributes<HTMLDivElement> { gutter? : number }Copy the code

For the Grid layout below, there would be a gutter between columns. This would be easier to achieve. For the leftmost and right-most columns, the margins would be redundant. So we need to make adjustments in the Row code

Adjust the code as follows:

function Row(props: RowProps) {
// ...
  const rowStyle: React.CSSProperties = {};

  if (gutter && gutter > 0) {
      rowStyle.marginLeft = gutter / -2;
      rowStyle.marginRight = gutter / -2;
  }
// ...
}
Copy the code

The rest of the code is to implement the Row structure to include Col, and pass the parameters accepted by Row to the Col component and the associated style code. The complete code is as follows:


/** RowContext file **/

import { createContext, Context } from 'react';

exportinterface RowContextState { gutter? : number }const RowContext: Context<RowContextState> = createContext({});

export default RowContext;
  
/** Row file **/
  
import React from 'react';
import RowContext from './RowContext';
import './style.scss';

interface RowProps extendsReact.HTMLAttributes<HTMLDivElement> { gutter? : number }function Row(props: RowProps) {
    const {
        gutter = 0,
        children
    } = props;

    const rowStyle: React.CSSProperties = {};

    if (gutter && gutter > 0) {
        rowStyle.marginLeft = gutter / -2;
        rowStyle.marginRight = gutter / -2;
    }

    const rowContext = React.useMemo(() = > ({ gutter }), [gutter])

    return (
        <RowContext.Provider value={rowContext}> 
            <div className="row" style={{... rowStyle}}>
                { children }
            </div>
        </RowContext.Provider>)}/** style.scss **/

.row {
    display: flex;
}
Copy the code

Col

Column component implementation points are:

Reads its own span parameter and implements its own width according to 24 bisects

Read the gutter parameter from the Row component and change it to the corresponding “sink” width

First implement the read span parameter and implement its own width:


/** style.scss **/

@for $index from 1 to 24 {
    .col-#{$index} {
        flex: 0 0 percentage($number: $index / $grid-columns);
    }
}
.col {
    box-sizing: border-box;
}

/** Col file **/

interface ColProps extends React.HTMLAttributes<HTMLDivElement> {
    span: number
}

function Col(props: ColProps) {
    const {
        children,
        span
    } = props;

    const classObj = {
        [`col-${span}`]: span ! = =void 0
    }
    const classes = classNames('col', classObj);

    return (
        <div className={classes}>
            { children }
        </div>)}Copy the code

Read the gutter parameter from the Row component and change it to the appropriate width of the “gutter”. The complete code looks like this:

import React, { useContext, CSSProperties } from 'react';
import classNames from 'classnames';
import RowContext from './RowContext';
import './style.scss';

interface ColProps extends React.HTMLAttributes<HTMLDivElement> {
    span: number
}

function Col(props: ColProps) {
    const {
        children,
        span
    } = props;

    const classObj = {
        [`col-${span}`]: span ! = =void 0
    }
    const classes = classNames('col', classObj);

    const { gutter } = useContext(RowContext);
    const styleObj: CSSProperties = {};
    if (gutter && gutter > 0) {
        const horizontalGutter = gutter / 2;
        styleObj.paddingLeft = horizontalGutter;
        styleObj.paddingRight = horizontalGutter;
    }

    return (
        <div className={classes} style={{... styleObj}}>
            { children }
        </div>)}Copy the code

In summary, a basic Grid React component is implemented

conclusion

In addition to code implementation, front-end components also have a lot of design ideas, understanding the design ideas may be more meaningful than simply implementing the code