DEV Community

Cover image for Responsive components with grid and TailwindCSS
Sebastian Sdorra
Sebastian Sdorra

Posted on • Originally published at

Responsive components with grid and TailwindCSS

If we want to build real responsive components, it is often no longer enough to let something slide into the next line. Sometimes it is necessary to change the structure of a component and this can quickly become complicated. I would like to use the following example to show how the problem can be solved with Flexbox and Grid.

The Example

Let's assume that we want to implement the following card:

Card with avatar, title and description

The card consists of an avatar, a title and a short description text.
In the mobile view the avatar and the title should be in the same line and the description should take up the whole line below.

For larger viewports, we want the avatar to be larger and the description to be next to the avatar as well.

Card with avatar, title and description for larger viewports

Ok, let's see how we can implement this.

Flex solution

We start with a flexbox implementation, because I always start with flexbox.
An initial implementation of the mobile variant could look like this:

  <div className="flex items-center gap-4">
    <Avatar className="h-16 w-16" />
    <h3 className="text-2xl font-bold">Title</h3>
  <p className="mt-5">Description</p>
Enter fullscreen mode Exit fullscreen mode

But when we try to implement the larger viewports, it gets difficult quickly.
The problem is that the structure changes.
The only solution I can think of here is to duplicate the description:

  <div className="flex items-center gap-4">
    <Avatar className="h-16 w-16 flex-shrink-0 sm:h-24 sm:w-24" />
    <div className="w-full">
      <h3 className="text-2xl font-bold">Title</h3>
      <p className="mt-5 hidden sm:block">Description</p>
  <p className="mt-5 sm:hidden">Description</p>
Enter fullscreen mode Exit fullscreen mode

To solve the problem we had to group the title and description with a div,
hide the description (hidden) and
only show it when we are in a larger viewport (sm:block).
The description for the small viewport is displayed by default and
is hidden when we are in a larger viewport (sm:hidden).

But we need to do more.
The grouping of the title can cause the avatar to be squeezed,
so we need to add a w-full to the grouping div and a flex-shrink-0 to the avatar.

This solution is far from optimal.
We had to include more markup and we had to duplicate content.
There is probably a better way to solve this problem with Flexbox,
but I couldn't think of one.

If you know of a better solution, please leave a comment

Grid to the rescue

Lets try to implement the same layout with grid instead of flexbox.
We start again with the mobile view:

<section className="grid grid-cols-[5rem,1fr] items-center">
  <Avatar className="h-16 w-16" />
  <h3 className="text-2xl font-bold">Title</h3>
  <p className="col-span-2 mt-5">Description</p>
Enter fullscreen mode Exit fullscreen mode

Except for the arbitrary value for grid-cols, the whole thing is pretty simple.
We create a grid with 2 columns, the first is 5rem wide (1rem wider than the avatar) and the second is 1fr wide (grid grid-cols-[5rem,1fr]).
In the first column of the first row is the avatar,
in the second column is the title.
We have extended the description to two columns (col-span-2) and
it is in the second row.

Grid for mobile viewport

In the case of the larger viewport,
we actually only need to draw the avatar over 2 lines and
take back the col span of the description.

Grid for larger viewports

The whole thing could look like this:

<section className="grid grid-cols-[5rem,1fr] items-center sm:grid-cols-[7rem,1fr]">
  <Avatar className="row-span-2 h-16 w-16 sm:h-24 sm:w-24" />
  <h3 className="text-2xl font-bold">Title</h3>
  <p className="col-span-2 mt-5 sm:col-span-1">Description</p>
Enter fullscreen mode Exit fullscreen mode

With the row-span-2 we could draw the avatar over both lines and
with sm:col-span-1 we reset the col span of the description.
We also had to reserve more space for the avatar in the first column of the grid (sm:grid-cols-[7rem,1fr]).


With the grid solution we needed much less markup.
We also didn't need duplication anymore and it's also much easier to understand.

Top comments (0)