skies.dev

Learn Flexbox With Tailwind CSS and React

9 min read

Our Plan

Today, let's learn how to use Flexbox with Tailwind CSS.

Note, this article is not meant to be a comprehensive guide to Flexbox. The goal here is to make things as simple as possible so that you can start to feel more comfortable using Flexbox.

My hope is that after reading this guide, you will feel confident enough to start filling in the rest of the pieces as you need them.

Setting Up

I'm going to assume you have a project with Tailwind already set up. If not, just follow their documentation to get set up. The easiest option is to link to the Tailwind CSS stylesheet on their CDN.

Also, in the examples we look at, I'm going to export some common utilities so that our examples look prettier. But more importantly, I do this to abstract away details that are not important to the discussion of learning Flexbox.

If you want to follow along directly, then add a utils.js file to your project with the following exports.

export const styles = {
  container: 'my-8 lg:my-12 p-2 bg-gray-200 rounded-md shadow-inner',
  li: 'rounded-md border border-gray-300 p-3 text-blue-900 bg-blue-200',
};
export const threeItems = ['1', '2', '3'];
export const fiveItems = ['1', '2', '3', '4', '5'];

Flex Direction

Let's start out with a basic React component that renders an unordered list.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul>
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

Most of the time when working with Flexbox, we apply the Flexbox properties to the parent element.

We are going to target the <ul> element, which is a parent of several <li> elements.

Let's apply Flexbox to the <ul> element now.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex">
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

As you can see, the elements are now positioned side-by-side. This is because the default flex direction is row.

We can change the direction so that the elements are on top of one another as follows. For this, we are setting the flex direction to column.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex flex-col">
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

Now the list looks how it did before. This is because the natural direction of a list is vertical.

We can also explicitly declare the default behavior with flex-row. This would be useful if we needed to override an already existing flex direction.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex flex-row">
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

The flex direction determines the orientation of the main axis.

The main axis determines how the elements are naturally positioned.

For example,

  • flex-row sets a horizontal main axis. This is why the <li> elements were side-by-side when flex-row was set on the <ul> element.
  • flex-col sets a vertical main axis. This is why the <li> elements were on top of one another when flex-col was set on the <ul> element.

Next, we'll look at how we can position elements along this main axis.

Justify Content

Justify content is how we can position elements along the main axis.

For example, we can center the elements inside the flex container with justify-center.

Remember, the default flex direction is row, so we don't need to explicitly set it with flex-row.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex justify-center">
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

We can push the list elements to the end of the main axis with justify-end.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex justify-end">
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

And we can bring things back to the start with justify-start.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex justify-start">
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

Note: justify-start is the default behavior so we could actually just omit it.

Next, we'll look at justify-between.

This is for adding space so that the children elements occupy the full size of the main axis.

import React from 'react';
import {threeItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex justify-between">
        {threeItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3

We'll add more elements so that we can see how it behaves.

import React from 'react';
import {fiveItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex justify-between">
        {fiveItems.map((item) => (
          <li key={item} className={styles.li}>
            {item}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3
4
5

I use justify content all the time in my own projects.

Two other useful properties to look at are

  • justify-around
  • justify-evenly

I will defer you to Tailwind CSS documentation to learn the behavior of these properties. They're similar to justify-between and are also useful in certain situations.

Next, let's look at how we can position elements across the cross axis.

Align Items

Align items is how we can position things along the cross axis.

The cross axis refers to the axis perpendicular to the main axis.

  • If the main axis is oriented horizontally via flex-row, then the cross axis is oriented vertically.
  • If the main axis is oriented vertically via flex-col, then the cross axis is oriented horizontally.

We'll add some height to our <ul> element so we can see how elements are positioned along the cross axis.

We'll start by vertically centering the elements along the cross axis with items-center.

import React from 'react';
import {fiveItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex h-24 items-center">
        {fiveItems.map((element) => (
          <li key={element} className={styles.li}>
            {element}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3
4
5

We can also align the items along the end of the cross axis with items-end.

import React from 'react';
import {fiveItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex h-24 items-end">
        {fiveItems.map((element) => (
          <li key={element} className={styles.li}>
            {element}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3
4
5

Similarly, we can align the items to the start of the cross axis with items-start.

import React from 'react';
import {fiveItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex h-24 items-start">
        {fiveItems.map((element) => (
          <li key={element} className={styles.li}>
            {element}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3
4
5

Check out Tailwind CSS documentation to see all the available options. They also show examples similar to the ones you see in this article.

Now that we know how to position items along the main axis and cross axis, we can compose multiple utilities together.

For example, we can horizontally and vertically center the elements as follows.

import React from 'react';
import {fiveItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex h-24 items-center justify-center">
        {fiveItems.map((element) => (
          <li key={element} className={styles.li}>
            {element}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3
4
5

Space Between

The next set of utilities that I reach for all the time are the space between utilities.

Note, these aren't part of the Flexbox API but they are nonetheless useful when working with Flexbox.

In all the previous examples, the elements are all squished together. We can use the space between utilities to give some elements some room to breathe.

We will use space-x-2 to give a bit of margin between each item.

import React from 'react';
import {fiveItems, styles} from './utils';

export default function Example() {
  return (
    <div className={styles.container}>
      <ul className="flex h-24 items-center justify-center space-x-2">
        {fiveItems.map((element) => (
          <li key={element} className={styles.li}>
            {element}
          </li>
        ))}
      </ul>
    </div>
  );
}

Output:

1
2
3
4
5

You can also get vertical space between elements with space-y-*. This is often useful when flex-col is set on the flex container.

Next steps

These are the utilities that I use most often when working with Flexbox in my own projects.

There is more you can do with Flexbox such as:

  • Override Flexbox rules on specific child elements.
  • Control the order of the elements inside a flex container.
  • Control the size of individual flex items with flex grow and flex shrink.

Tailwind CSS documentation has examples for the flex utilities it provides. Their examples are often what I refer to when I need help remembering a certain Flexbox property.

Hey, you! 🫵

Did you know I created a YouTube channel? I'll be putting out a lot of new content on web development and software engineering so make sure to subscribe.

(clap if you liked the article)

You might also like