Tables In Figma

A ‘blow-up’ diagram view of how single cells in this approach can create a table.

Tables are often harder to prototype than to code, but taking a single cell design strategy can make them responsive and maintainable. What’s more, all you need are Components, duplication and Auto-Layout techniques. I’ve experimented with a few ways and this method seems to have the best trade-offs. I’ll give you the whirlwind tour of the core visual styles of tables, how to build the single cell design, and the reasons why I opted for this as my preferred method of prototyping tables in Figma.

Visual styles of tables

There are a few different visual styles that are floating around on the internet today. Most tables you see are variations of one of these three.

Classic table

This is the table you learn about in high school IT— humble and versatile to get your point across. With some minor tweaks to the vanilla HTML of good table design you can get an easily readable table. If you don’t know about how tables are created in code I recommend you read up on the w3schools documentation.

Striped tables

Used in places like Apple’s Pages application, these are an eye catching alternative that let the data stand out. Again, w3schools is a fantastic resource to learn more about them.

‘Lined’ tables

Looking at the Simple Table from Material Design as an example, you can see that each row is separated by a single line and each column is separated using generous spacing. Also known as a ‘horizontally divided table’.

Single-cell design

Now that we have an idea of the different major styles of table design, we can move forward to setting up Components to quickly build one in Figma. Compared to all other methods I’ve tried, the single-cell design approach is perhaps the most versatile.

Cell types

In total you can use three cell Components to develop the vast majority of your designs:

  • Default cell—this makes up the bulk of your table data

  • Header cell—usually with bold text, it makes up the top row or the left-hand column

  • Selected cell—only essential if you want to conduct user research on this state

Building the cells

We’ll be using the classic table visual style for simplicity for this walkthrough. Starting with the Default cell, create a text layer, add in some text, then adjust the width of the text layer to 50px. This should automatically change it to an Auto Height text layer — don’t worry, we can adjust this later. It forms the basis of the ‘responsive’ nature of these tables.

Next, turn it into a Component with Cmd + Option + K on Mac or Ctrl + Alt + K on Windows. Set the horizontal padding to 5px and the vertical to 4px. Reveal the Fill colour by clicking the eye icon, and click the plus ‘+’ button on the Stroke settings and use black as the colour. My screenshot says ‘Inside’ on the draw line option but you’ll want to use ‘Center’ or ‘Outside’ so that it displays properly later.

Hint: if you’re using the Striped visual style, you’ll want two types of Default cell with differing Fill colours. I like to name them ‘default flip’ and ‘default flop’.

Next, we can create the Header cell and the Selected cell if needed. Make copies of your Default cell by holding down Option on Mac or Alt on Windows and dragging, or use the copy and paste shortcuts. Header cells usually will need the text to be bold, and the Selected cell can have its Fill colour changed to a light shade of blue. Turn these into new Components so that any style updates to the Default cell are propagated downwards, but the text bolding and Fill colour overrides are maintained.

Hint: check the screenshot above if you aren’t sure you’ve set up your layers and Component subclassing correctly.

Sizing your cells

Before we start making tables it’s worth noting that in your working Design System or Palette, you’ll need a few different sizes of cells. I find it easiest to make a few using your underlying grid system as a guide. With a 12 column grid system I like to use 2, 3, and 4 column width cells, including internal guttering. Adjust the width of the text layer appropriately, and don’t forget to include the horizontal padding in your calculation.

Hint: for those that aren’t well versed in grid systems, you can use the large Bootstrap grid system as a starting point; this would result in cells of 130px, 210px, and 290px.

Constructing the table

With all that set up complete, we can now start to reap the benefits of a single cell design approach to making tables in Figma. Make sure you’ve written out the table data somewhere as it’s easier to work it out first on paper or a text editor beforehand.

Create the ‘strips’

I’m going to go by row, but you can also go by column. Assuming the first row is the header, create enough instances of your Header cell to create all the headings. The first or last cell can be larger than the rest to emphasise it. Highlight them all, Frame your selection, and add Auto layout. Ensure that there’s 0px spacing between each item in the Auto layout settings. Repeat this for a row of Default cells.

Glue it together

Duplicate your data row until you have enough data rows, select all the rows, Frame it, then add Auto layout again. Once you’ve set it to 0px spacing, it should look something like the above. All that’s left to do is add the correct data to the remaining cells and then use your table in your prototype. Congratulations, you have a table!

Handling multiple lines

One small problem with this approach is when text runs across multiple lines, it misaligns your table and leaves gaps. It’s easy to fix though. In the other cells within the same row, double-click until the cursor is at the end of the text then press Shift + Enter for each extra line needed. You can also use the text tool and click once, or use the shortcut t. It’s the least elegant part of this approach, but in my opinion, it’s a small price to pay for the speed it offers.

Why it works

There are three main principles I believe that make the single-cell design approach worthwhile.

Flexible

By building with the smallest unit possible, we can mix and match as much as we want to create tables that work. We don’t need to consider ‘merged’ cells either, as long as your cell Components all meet some standard sizing pattern you can put them together and grow the table as large as needed.

Consistent

By designing the small set of cells to all be compatible with each other, you ensure your tables remain consistent. With consistency in how it looks and how it fits together at creation time, we allow the user to do what they came for: read and understand the data written inside.

Maintainable

Above all, it’s maintainable. Keeping your Design System up to date is no easy feat and is a major driver of the DesignOps function. When there’s less parts, the job is smaller, and that opens up you and your team to iterate and evolve your design language much more easily.

One final advantage that the single cell design has is the ability to introduce other cell types. If you want a checkbox cell for example, you can more easily swap out cells in older prototypes using the single cell approach.

The single-cell approach is my favourite method for everyday prototyping of tables in Figma. It requires a bit of work to make the tables using single cells, but it means that they’re flexible, consistent, and most importantly maintainable in a Design System. Once you know the basics, you can quickly make a wide variety of tables. For larger or more complex tables you may be better off using a different approach. It’s crucial for you to consider your day-to-day use cases and select an approach that suits your most common use cases.

\

Introduction #

Imagine the table as an organism. The table cell is then a molecule which is comprised of individual atoms. In design terms, they’re cell properties.

So, let’s start with the cell. It has three properties:

Now we’ll take a closer look at each one of them.

Background #

The background will be a separate component in Figma. The size doesn’t really matter since we can stretch the component as we need, but let’s begin with setting the size to 100×36 pixels.

In this component, add a rectangle of the same size as the component itself. It will be the only object inside the component. We need to attach the rectangle’s borders to the component’s borders by using constraints (set constraints to “Left & Right” and “Top & Bottom” at the right panel in the Constraints section), so that the rectangle stretches automatically to the size of the component.

If you’d like to see this in action, watch this tutorial on how the constraints work in Figma.

The Background Component (the ‘atom’) (Large preview)

The fill color of the rectangle will determine the background color of the cell. Let’s pick the white color for it. I recommend choosing that color from the color styles that are configured at the beginning of the project.

Changing the background color (Large preview)

Border #

This one is a bit trickier than the background. You can’t just create one rectangle with a stroke. We may need different kinds of borders: one for the separate cells (with borders around), one for the whole row of cells with only top and bottom borders, or one for the table header that we might want to separate from the rest with a wider line. There are many options.

Border properties:

  • Border line (left, right, top, bottom, or absence of any of them)

  • Line width

  • Line color

  • Line style

Each line within the cell border might havea different width, color, and style. For example, the left one could be a continuous red line, and the top one a dotted grey line.

Let’s create a component with a size of 100×36 pixels (the same as we did before). Inside the component, we need to add 4 lines for each border. Now pay attention to how we are going to do this.

  1. Add a line for the bottom border with the length of the component width;

  2. Set its position to the bottom border and constraints to stretch horizontally and stick to the bottom border;

  3. For the top border, duplicate the line for the bottom border, rotate it by 180 degrees and stick to the top of the component. (Don’t forget to change its constraints to stick to the top and stretch horizontally.);

  4. Next, for the left border, simply rotate by -90 degrees and set its position and constraints to be at the left side sticking to the left border and stretching vertically;

  5. Last but not least, you can create the right border by rotating it by 90 degrees and setting its position and constraints. Set stroke color and stroke width for each line to gray (select from the color styles) and 1 pixel respectively.

Note: You may be asking yourself why we rotated the line for the bottom border. Well, when you change the stroke width for a line in Figma, it will rise. So we had to set this “rise” direction to the center of the component. Changing the line’s stroke width (in our case it is the border size) won’t expand outside the component (cell).

Now we can hide or customize the styles separately for every border in the cell.

A border component with 1px stroke (Large preview)

If your project has several styles for table borders (a few border examples shown below), you should create a separate component for each style. Simply create a new master component as we did before and customize it the way you need.

A few extra examples of border styles. Note that the white background is not included in the component. (Large preview)

The separate stroke component will save up lots of your time and add scalability. If you change the stroke color inside the master component, the whole table will adjust. Same as with the background color above, each individual cell can have its own stroke parameters.

Changing border’s width and color (Large preview)

Content #

This is the most complex component of all.

We need to create all possible variations of the table content in the project: plain text, a text with an icon (left or right, different alignment), checkboxes, switches, and any other content that a cell may possibly contain. To simplify this tutorial, please check the components in the mockup file. How to create and organize components in Figma is a topic for another article.

However, there are a few requirements for content components:

  • Components should stretch easily both vertically and horizontally to fit inside a cell;

  • The minimum size of the component should be less than the default cell size (especially height, keep in mind possible cell paddings);

  • Avoid any margins, so the components can align properly inside a cell;

  • Avoid unnecessary backgrounds because a cell itself has it already.

Examples of cell content in components. This is not a complete list; you can use most of the components of your design system inside a table. (Large preview)

Content components can be created gradually: start with the basic ones like text components and add new ones as the project grows in size.

The reason we want the content to be in components is the same as with other elements — it saves uptime. To change the cell’s content, we just need to switch it in the component.

Editing the table using cells components (Large preview)

Creating A Cell Component #

We created all the atoms we need: background, border, content. It’s time to create a cell component, i.e. the molecule made from atoms. Let’s gather all the components in a cell.

The cell component (the ‘molecule’) (Large preview)

Set the background component as the bottom layer and stretch it to the whole cell size (set constraints to “Left & Right” and “Top & Bottom”).

Add the border component with the same constraints as the background component.

Now to the most complicated part — the content content.

The cell has paddings, so you need to make a frame with the component’s content. That frame should be stretched to the whole cell size except for the paddings. The content component should also be stretched to the whole frame size. The content itself needs to be deprived of any margins, so all paddings will be set by the cell.

At the end of the day, cell paddings are the only property in a component that we will set only once without an opportunity to change it later. In the example above, I made it 4px for all sides.

Note: As a fix, you can create columns with empty cells (with no content and width of 16px for example) left and right to the column where extra margin is needed. Or if your table’s design allows, you can add horizontal paddings inside the cell component. For example, cells in Google Material Design have 16px paddings by default.

Don’t forget to remove the “Clip content” option for the cell and frame (this can be done at the right-hand panel in the Properties section). The cell’s content can go out of its borders; for example, when a dropdown is inside your cell and you want to show its state with a popup.

Note: We’ll be using this cell style as the main one. Don’t worry if your table has additional styles — we’ll cover that in the Table States and Components, Not Overrides sections.

Cell Options For A Standard Table #

This step could be optional but if your table needs states then you can’t go without it. And even more so if there is more than one border style in the table.

So let’s create additional cell components from which it’d be easier to build up a table. When working with a table, we will select the appropriate component depending on its position in the table (e.g. depending on the type of borders).

In order to do that, let’s take our cell component and create eight more masters from it. We also need to disable the appropriate layers responsible for borders. The result should look like the image below.

The cell options we need to build a table. Note that there could be a few extra depending on your table borders styles. (Large preview)

The top row is for the cells on top and in the middle of the table. The bottom row is only for the cells at the bottom. This way we’ll be able to put the cells one after another with no gaps and keep the same stroke width.

A few examples:

If each cell in the table has a border, we’d only need cells 1, 4, 5 and 8. (Large preview)If there are merged cells or border absence, we must apply the rest 2 and 3 cells as well as 6 and 7 to the bottom row. (Large preview)If the table design considers the absence of vertical borders, cells 2 and 6 would be enough. (Large preview)

Note: For each border style created above, it’d be good to add master components like the ones described earlier.

So we have excluded the necessity of overriding cell’s instances (disabling the appropriate layers, to be precise). Instead of that, we use various components. Now if, for example, a column uses a different style from the default (the fill color or border), you can choose this column and simply change the relative component. And everything will be alright. On the opposite side, changing a border of each cell manually (disabling the appropriate borders) is a pain you don’t want to bother with.

Now we are ready to create tables (in terms of Atomic Design — organisms) from the various cell components (molecules) we made.

Customizing The Table #

Changing the row’s height in the whole table is relatively easy: highlight the table, change the element height (in this case, the cell’s height, H in the right-hand panel in the Properties section), and then change the vertical margin from the element to 0. That’s it: changing the line height took two clicks!

Changing the row height for the whole table (Large preview)

Changing the column width: highlight the column and change the width size. After moving the rest of the table close up, select the whole table by using the Tide Up option in the Alignment panel as well as the first item in the dropdown list under the rightmost icon.

Changing the column width. (Large preview)

Note: I wouldn’t recommend grouping rows and columns. If you change the column size extending the elements, you’ll get fractional values for width and height. If you don’t group them and snap to the pixel grid, the cell size will remain an integer number.

The background color, stroke type, and content data can be changed in the appropriate component or in one of the eight cells master components (cells that had different stroke styles). The only parameter that can’t be changed right away is the cell margins, e.g. content paddings. The rest are easily customizable.

Components, Not Overrides #

Looking at what we got in the end, it might seem like overkill. And it is if there is only one table in your project. In this case, you can simply create one cell component and leave the background and stroke components off. Simply include them in the cell component, create the table and do the necessary customization for each separate cell.

But if components are included in a library that is used by a number of other files, here comes the most interesting stuff.

Note: *I do not recommend changing the background color and stroke in components’ instances. Change them only in the master. By doing so, those instances with overrides won’t get updated. This means you would have to do that manually and that’s what we’re trying to avoid. So let’s stick to the master components.*

If we need to create an additional type of table cells (e.g. the table header), we add the necessary set of master components for cells with the appropriate styles (just like we did above with the eight cells that had different stroke styles), and use it. Yes, it takes longer than overriding components’ instances but this way you will avoid the case when changing the masters will apply those changes to all layouts.

Table States #

Let’s talk about the states of the table’s elements. A cell can have three states: default, hover, and selected. Same for columns and rows.

If your project is relatively small, all states can be set by overrides inside instances of your table components. But if it’s a big one, and you’d want to be able to change the look of the states in the future, you’ll have to create separate components for everything.

You’ll need to add all eight cells with different stroke variants for each of the states (maybe less, depends on the stroke style). And yes, we’ll need separate components for the background color and the stroke for the states as well.

In the end, it’ll look similar to this:

The cells’ states (hover and selected) (Large preview)

Here’s where a bit of trouble comes in. Unfortunately, if we do everything as described above (when changing the component’s state from one to another), there is a risk of losing the cell’s content. We’ll have to update it apart from the case when the content type is the same as in the master cell. At this point, we can’t do anything about it.

Table with various rows’ states. (Large preview)

I added tables in the mockup file that were made in a few different ways:

  • Using this tutorial (separate components for cells’ styles);

  • Using the cell component (components for borders, background, and content);

  • Using the cell component that unites everything (with only content components in addition).

Try to play around and change the cell’s styles.

Changing the state of the row. (Large preview)

Conclusion #

If you’re using the same components library in several projects and you’ve got a reasonable number of tables in each of them, you can create a local copy of components (cells components with stroke styles and, if needed, cells components with different states), customize them, and use them in the project. The cell content can be set based on local components.

Also, if you’re using the table for one large project with different kinds of tables, all the above-mentioned components are easily scaled. The table components can be improved to infinity and beyond, like creating the cell states when hovering and other kinds of interactions.

Questions, feedback, thoughts? Leave a comment below, and I’ll do my best to help you!

FIGMA TABLE MOCKUP DOWNLOAD #

As promised, I created a complete version of the Figma table mockup that you’re welcome to use for learning purposes or anything else you like. Enjoy!

USEFUL RESOURCES #

  • Figma YouTube Channel The official Figma channel on YouTube — it’s the first thing to watch if you are new to Figma.

  • Google Sheets Sync A Figma plugin that helps you get data from Google Sheets into your Figma file. This should work fine with the techniques from this tutoria, but you’ll need to invest some time into renaming all the text layers for this to work properly.

Last updated