flex-item

React components for styling grids with css flexboxes. Uses emotion under the hood.

Usage no npm install needed!

<script type="module">
  import flexItem from 'https://cdn.skypack.dev/flex-item';
</script>

README

FlexItem

CircleCI

Responsive grid components for react and emotion.

FlexItem is 3 seperate tools in 1.

  1. It is a responsive grid.
  2. It also works well for displaying rows of objects.
  3. Centering Container.

Installing

npm install flex-item

Note: flex-item requires React >= v17 and Emotion >= v11 be installed in your project.

npm install react @emotion/react

ThemeProvider Requirements

This component requires a theme provider from the emotion library. Specifically looks for a dimensions and an aspect variable. dimensions is an object that should have a columnSpacing, containerWidth, desktopBreakpoint, rowSpacing, or tabletBreakpoint attribute. aspect is a string with options "desktop", "tablet", or "mobile". This should represent the current aspect ratio the user is on.

The columnSpacing attribute provides a Flex Grid with spacing between the first tier children (columns). This defaults to 6px if nothing is set. This is only used with container prop attribute.

The containerWidth attribute provides a container or max with for the Flex Grid. If you set a containerWidth of 1200 for example, that would limit the FlexGrid to 1200px wide. This defaults to 1200px.

The desktopBreakpoint is first pixel in which the browser size is considered a desktop browser. If you set a desktopBreakpoint of 992 for example, that would start using the tablet media queries at 991px.

The rowSpacing attribute provides a Flex Grid with spacing between each row of first tier children. This defaults to 6px if nothing is set. This is only used with verticalContainer prop attribute.

The tabletBreakpoint is first pixel in which the browser size is considered a tablet browser. If you set a tabletBreakpoint of 768 for example, that would start using the mobile media queries at 767px.

Responsive Grid

FlexItem has 2 main components (FlexGrid and FlexItem).

FlexGrid starts a responsive row. FlexItem represents a column in the row.

FlexGrid has 5 props available.

  • className - Allows custom class names on component. FlexGrid always has a flex-grid class for convenience.
  • container - Adds padding around each first tier children elements.
  • maxMobileRow - Define maximum columns in a row before wrapping for mobile aspect ratio. Defaults to 1. This gives a vertical effect.
  • maxPerRow - Define maximum columns in a row before wrapping.
  • maxTabletRow - Define maximum columns in a row before wrapping for tablet aspect ratio. Defaults to 1. This gives a vertical effect.
  • style - Allows custom inline style.
  • verticalContainer - Adds padding around each first tier children elements.

FlexItem has 6 props available.

  • className - Allows custom class names on component. FlexItem always has a flex-item class for convenience.
  • mobileSize - Amount of columns used for mobile aspect ratio.
  • size - Amount of columns used.
  • style - Allows custom inline style.
  • tabletSize - Amount of columns used for tablet aspect ratio.

Responsive Grid

   <FlexGrid container verticalContainer>
     <FlexItem>
       <div>Thing1</div>
     </FlexItem>
     <FlexItem>
       <div>Thing2</div>
     </FlexItem>
     <FlexItem>
       <div>Thing3</div>
     </FlexItem>
   </FlexGrid>

image

Mobile:

image

Let's adjust this for mobile responsiveness.

   <FlexGrid maxMobileRow={2}>
     <FlexItem size={2}>
       <div>Thing1</div>
     </FlexItem>
     <FlexItem>
       <div>Thing2</div>
     </FlexItem>
     <FlexItem>
       <div>Thing3</div>
     </FlexItem>
   </FlexGrid>

image

Rows

  <FlexGrid maxPerRow={7} maxTabletRow={4}>
    <FlexItem tabletSize={4}>
      <div>Thing1</div>
    </FlexItem>
    <FlexItem size={2} tabletSize={3}>
      <div>Thing2</div>
    </FlexItem>
    <FlexItem tabletSize={1}>
      <div>Thing3</div>
    </FlexItem>
    <FlexItem size={3} tabletSize={4}>
      <div>Thing4</div>
    </FlexItem>
    <FlexItem>
      <div>Thing5</div>
    </FlexItem>
    <FlexItem>
      <div>Thing6</div>
    </FlexItem>
    <FlexItem>
      <div>Thing7</div>
    </FlexItem>
    <FlexItem>
      <div>Thing8</div>
    </FlexItem>
    <FlexItem>
      <div>Thing9</div>
    </FlexItem>
    <FlexItem>
      <div>Thing10</div>
    </FlexItem>
  </FlexGrid>

image

But on tablet the column ratios are all different.

image

Setting aspect ratio on ThemeProvider

  import React from "react";
  import { render } from "react-dom";
  import { ThemeProvider } from "emotion-theming";

  class App extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        aspect: this.fetchAspect()
      };
    }

    componentDidMount() {
      window.addEventListener("resize", () => this.updateAspect());
    }

    componentWillUnmount() {
      window.removeEventListener("resize", () => this.updateAspect());
    }

    fetchAspect() {
      const width = Math.max(
        document.body.scrollWidth,
        document.documentElement.scrollWidth,
        document.body.offsetWidth,
        document.documentElement.offsetWidth,
        document.documentElement.clientWidth
      );

      let aspect = "desktop";
      if(width < Dimensions.tabletBreakpoint) {
        aspect = "mobile";
      } else if(width < Dimensions.desktopBreakpoint) {
        aspect = "tablet";
      }
      return(aspect);
    }

    updateAspect() {
      const aspect = this.fetchAspect();
      if(aspect !== this.state.aspect) {
        this.setState({aspect: aspect});
      }
    }

    render() {
      const dimensions = {
        containerWidth: 1200,
        desktopBreakpoint: 992,
        tabletBreakpoint: 768
      };
 
      return(
       <ThemeProvider theme={{aspect: this.state.aspect, dimensions: dimensions}}>
    </ThemeProvider>
      );
    }
  }

Demo

The demo app runs Webpack.

Simply run the folling to start the app at localhost:3322

npm install
npm start

Contributing

Contributors to this project should:

  1. Fork the repository.
  2. Commit changes to a branch within the fork.
  3. Start a pull request in GitHub with a description of the fix.

Example

import React from "react";
import { ThemeProvider } from "emotion-theming";

class Example extends React.Component {
  render() {
    return(
      <ThemeProvider theme={{dimensions: {containerWidth: "1200"}}}>
        <FlexGrid>
          <FlexItem>
        <div>Thing1</div>
          </FlexItem>
          <FlexItem>
        <div>Thing2</div>
          </FlexItem>
          <FlexItem>
        <div>Thing3</div>
          </FlexItem>
        </FlexGrid>
      </ThemeProvider>
    );
  }
}

module.exports = Example;