DEV Community

Brandon Sarà
Brandon Sarà

Posted on

Lightweight React Responsive Linear Layout Component

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.

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. 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 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.

I've listed some reasons for using something like ResponsiveLinearLayout in my article about react-linear-layout. 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:

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:

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:

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:

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.

Questions?

Please feel free to ask any questions in the comments.

Top comments (0)