Lightweight React Responsive Linear Layout Component
Tags: showdev, react, javascript, component
Published: 2019-12-31 22:46:09

> ### TL;DR
> A layout component that arranges children in an **automatically responsive** single row or column using CSS flexbox and has some very nice custom CSS properties with which you can easily set gaps & item sizes.
>
> It's super small and super easy to use.
>
> Licensed under [ISC license](https://gitlab.com/bsara/react-responsive-linear-layout/blob/master/LICENSE).
>
> Storybook: https://bsara.gitlab.io/react-responsive-linear-layout/
> NPM & Docs: https://www.npmjs.com/package/react-responsive-linear-layout
> Non-Responsive Version: https://www.npmjs.com/package/react-linear-layout


[I recently posted about a component package that I created called `react-linear-layout`](https://dev.to/bsara/lightweight-react-linear-layout-component-4cjl). This article covers the responsive version of `react-linear-layout`.


At it's core, `react-responsive-linear-layout` _(AKA `ResponsiveLinearLayout`)_ is basically a [CSS flexbox] (https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox) **with responsiveness baked-in for you automatically when you use the provided custom CSS properties**. As such, all flexbox properties are valid when styling a `ResponsiveLinearLayout`. `ResponsiveLinearLayout` is built on top of [`react-linear-layout`](https://dev.to/bsara/lightweight-react-linear-layout-component-4cjl).


I've listed some reasons for using something like `ResponsiveLinearLayout` in my [article about `react-linear-layout`](https://dev.to/bsara/lightweight-react-linear-layout-component-4cjl). However, there is, obviously, one big reason to use `ResponsiveLinearLayout`: The automatic responsiveness! This is accomplished when you use the supplied CSS custom property `--responsive-linear-layout-item-gap`:

```jsx
import React from 'react';
import ResponsiveLinearLayout from 'react-responsive-linear-layout';
import styled from 'styled-components'; // NOTE: You're not required to use styled-components, I just chose it for the example for the simplicity of putting all of the code in one snippet. :)

const StyledResponsiveLinearLayout = styled(ResponsiveLinearLayout)`
  --responsive-linear-layout-item-gap: 50px;
`;

export default function MyComponent() {
  return (
    <StyledResponsiveLinearLayout>
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </StyledResponsiveLinearLayout>
  );
}
```

The code above will render the three divs one after another, in a horizontal line _(horizontal is the default direction)_. The children of `StyledResponsiveLinearLayout` will have a 50 pixel gap in between them, and when the list of items wraps, it will wrap in a responsive manner such that extra gaps on the edges of the list of items won't exist while maintaining the 50 pixel gap between all items.


If we want to change the direction, we can specify the `direction` prop:

```jsx
import React from 'react';
import ResponsiveLinearLayout from 'react-responsive-linear-layout';
import styled from 'styled-components'; // NOTE: You're not required to use styled-components, I just chose it for the example for the simplicity of putting all of the code in one snippet. :)

const StyledResponsiveLinearLayout = styled(ResponsiveLinearLayout)`
  --responsive-linear-layout-item-gap: 50px;
`;

export default function MyComponent() {
  return (
    <StyledResponsiveLinearLayout direction="vertical">
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </StyledResponsiveLinearLayout>
  );
}
```

Now, the items will be stacked one on top of another when rendered.


By default, `ResponsiveLinearLayout` will span it's parent _(because it's CSS `display` property is set to `flex`)_. We can make the component render inline by specifying the `inline` prop:

```jsx
import React from 'react';
import ResponsiveLinearLayout from 'react-responsive-linear-layout';
import styled from 'styled-components'; // NOTE: You're not required to use styled-components, I just chose it for the example for the simplicity of putting all of the code in one snippet. :)

const StyledResponsiveLinearLayout = styled(ResponsiveLinearLayout)`
  --responsive-linear-layout-item-gap: 50px;
`;

export default function MyComponent() {
  return (
    <StyledResponsiveLinearLayout inline>
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </StyledResponsiveLinearLayout>
  );
}
```


Nesting of layouts also works out of the box:

```jsx
import React from 'react';
import ResponsiveLinearLayout from 'react-responsive-linear-layout';
import styled from 'styled-components'; // NOTE: You're not required to use styled-components, I just chose it for the example for the simplicity of putting all of the code in one snippet. :)

const StyledOuterResponsiveLinearLayout = styled(ResponsiveLinearLayout)`
  --responsive-linear-layout-item-gap: 50px;
`;

const StyledInnerResponsiveLinearLayout = styled(ResponsiveLinearLayout)`
  --responsive-linear-layout-item-gap: 10px;
`;
 
export default function MyComponent() {
  return (
    <StyledOuterResponsiveLinearLayout direction="horizontal">
      <a>Anchor 0</a>
      <a>Anchor 1</a>
      <a>Anchor 2</a>
 
      {/**
        * When embedding one ResponsiveLinearLayout inside another
        * (or inside a LinearLayout), an extra div is needed for
        * margins to be set correctly by both the wrapping layout
        * and the embedded layout
        */}
      <div> 
        <StyledInnerResponsiveLinearLayout direction="vertical">
          <a>Sub Anchor 0</a>
          <a>Sub Anchor 1</a>
          <a>Sub Anchor 2</a>
        </StyledInnerResponsiveLinearLayout>
      </div>
    </StyledOuterResponsiveLinearLayout>
  );
}
```


## CSS Custom Properties

`ResponsiveLinearLayout` has a few CSS custom properties available that make styling the layout's children really easy. Most notable is `--responsive-linear-layout-item-gap` which we saw an example of above.


If you want all of the children of `ReponsiveLinearLayout` to be the same size, or if you want them to all have the same min/max size, then you can use any of these custom properties:

- `--responsive-linear-layout-item-size`
- `--responsive-linear-layout-item-min-size`
- `--responsive-linear-layout-item-max-size`

If `direction` is set to `"horizontal"`, then the width of all children will be effected. If `direction` is set to `"vertical"` then the height of all of the children will be effected.


## Default CSS of `ResponsiveLinearLayout`

There is some sensible default CSS applied to `ResponsiveLinearLayout`:

> **NOTE:** _You can always override any of these defaults via CSS._

- All content is justified to `flex-start`.
- `flex-wrap` is set to `wrap`.
- `flex-grow` and `flex-shrink` of all children are both set to `0` _(this ensures that, by default, the list of items is rendered like any list you might expect rather than having each item take up a large portion of space)_


## Documentation

Full documentation can be found on the NPM package page: https://www.npmjs.com/package/react-responsive-linear-layout


## Try It Out

There is both a CommonJS (SSR compatible) and ESM build distributed in the NPM package.

Feel free to try out the public storybook for `react-responsive-linear-layout` here:
https://bsara.gitlab.io/react-responsive-linear-layout

You can find the NPM package and docs here:
https://www.npmjs.com/package/react-responsive-linear-layout

Find the source here **(contributions are always welcome)**:
https://gitlab.com/bsara/react-responsive-linear-layout

The code is licensed under the [ISC license](https://gitlab.com/bsara/react-responsive-linear-layout/blob/master/LICENSE).


## Questions?

Please feel free to ask any questions in the comments.