Skip to content

Chakra UI (v2) - Troubleshooting Styling

Posted on Dec 28, 2023 in Blog Posts


Version Reference

At the time of writing, @chakra-ui/react's version is 2.8.2.

Overview

While working with Chakra UI , I've come across instances where styling did not behave as I expected. Here are a few tips for troubleshooting unexpected style behaviors in Chakra UI. In this post, I'll walk through the resources and process I use to find where to set a style in Chakra UI.

While frequenting the Chakra UI Discord and Stack Overflow tag , I've noticed repeating themes around styling tables.

Perhaps we tried to achieve setting a width for each row by adding a style directly on the Tr, but the border didn't show up. Or perhaps we tried to set our Th and Td with a fixed width, but once they all were set, the sizes no longer worked.

As an example, let's cover 3 objectives of styling a table:

  1. Setting a border bottom width for each row
  2. Allowing all table columns to be a fixed width
  3. Adjusting the padding for each table cell

Here's a Replit sandbox showing the final solution. Feel free to fork it and use it as a sandbox.

Know Your Sources

In the Chakra UI documentation, each component links to a Source and Theme source on GitHub. Both of these links are valuable when you're determining where to set a style or troubleshooting why a border color or other element isn't changing.

Let's take a look at the Table component documentation .

Theme Source

The Theme source link references the style factory Chakra UI uses to generate the styles for component parts. This is the first place to look for how Chakra UI set up the component styling and any base, variant, or size styles that could conflict with the styles we're trying to set.

Chakra UI has a layered approach for styling components.1 There are three main parts:

  1. Base Styles - Component styling that applies to all variants. Usually excludes color and size-related styling.
  2. Sizes - Component styling that applies to a specific size of a component. Usually includes margins, padding, font sizes, line heights, and other spacing.
  3. Variants - Component styling that changes the visual appearance of a component. Different styles may be solid, outline, striped, etc. This is usually where color is applied.

The theme files look different depending on whether the component is a single-part component or a multi-part component.2

Single-part components, like a Button, have one main element to style. They have a base style, variants, and sizes.

Multi-part components, like a Table, have multiple elements/components that work together to build the desired visual. They also have base styles, variants, and sizes, and each base, variant, and size is broken down into multiple elements, called parts. A common mistake for developers new to Chakra UI is to try to style a multi-part component without labeling the parts in the styles, variants, or sizes.

All components have default styles, including a base style, variant, and size. All of these work together with the base style to create the final styles displayed for the component.

Let's take a deeper look at the Table theme source .

Default Props

If the default variant, size, and other style elements for a component aren't specified in the documentation, it can typically be found in the theme source file defined in the style config exported near the end of the file.

Here's an example from the Table theme source3.

export const tableTheme = defineMultiStyleConfig({
baseStyle,
variants,
sizes,
defaultProps: {
variant: "simple",
size: "md",
colorScheme: "gray",
},
})

Looking at the defaultProps, we can infer that the Table component uses the simple variant, md size, and the gray colorScheme by default.

We can use this information to look up the simple variant, md size, and gray colorScheme to see if any of those cause a conflict with our Tr border.

Base Style

The base styles apply to all variants and sizes, unless the variants or sizes override them.

Here is the Table component's base style, pulled from the Table theme source3:

const baseStyle = definePartsStyle({
table: {
fontVariantNumeric: "lining-nums tabular-nums",
borderCollapse: "collapse", // borders collapse
width: "full", // table width is 100% - Chakra UI variable
},
th: {
fontFamily: "heading",
fontWeight: "bold",
textTransform: "uppercase",
letterSpacing: "wider",
textAlign: "start",
},
td: {
textAlign: "start",
},
caption: {
mt: 4,
fontFamily: "heading",
textAlign: "center",
fontWeight: "medium",
},
})

Here we learn that by default, the table width is set to full, and borderCollapse4 is set to collapse. That means that it's possible that the tr border style we want to add is getting merged with something else's border style.

The table width set to full is a pointer to 100%. Since it's rendering <table /> HTML elements, it's likely using the default CSS properties for table, th, and other table components. table by uses a default table-layout5 of auto, which sizes cells to their cell content. If the table is set to 100%, auto-layout is going to try to fill all of that space proportionally to the cell's content. This is why our fixed content widths aren't working.

Variant

There are no border styles on the base style, so we can check the variant. The default variant is simple, so let's try to find something like that in the theme source.

In the Table theme source3, we find variantSimple, which returns a theme style broken down into parts, like th, td, caption, and tfoot.

const variantSimple = definePartsStyle((props) => {
const {colorScheme: c} = props
return {
th: {
// ...
borderBottom: "1px",
borderColor: mode(`${c}.100`, `${c}.700`)(props),
// ...
},
td: {
borderBottom: "1px",
borderColor: mode(`${c}.100`, `${c}.700`)(props),
// ...
},
// ...
}
})

Looking through these styles, both th and td have a borderBottom and borderColor. tr is only mentioned in the context of tfoot. We can infer that Chakra UI decided to set the border styles on the th and td components rather than tr. Our tr styles may be collapsed into the th and td styles. It may make more sense to set the bottom row border on th and td.

Size

The only thing we haven't found is where to adjust our padding. Chakra UI breaks size-related items like spacing, font sizes, and line heights into sizes. This gives flexibility without needing to define sizes multiple times for each variant.

In the Table theme source3, we conveniently find a constant named sizes.

const sizes = {
// ...
md: definePartsStyle({
th: {
px: "6",
py: "3",
lineHeight: "4",
fontSize: "xs",
},
td: {
px: "6",
py: "4",
lineHeight: "5",
},
caption: {
px: "6",
py: "2",
fontSize: "sm",
},
}),
// ...
}

Here, padding, line heights, and font sizes are set for the th and td components, so that's a good place for us to adjust our cell padding.

Source

The Source link, in most cases, references the individual component package. There are a few components, like Box, Flex, Stack, HStack, VStack, etc. that are grouped into a package like layout.

The source is valuable when you've already looked at the theme source and are unable to find a conflicting style. It is rare, but there are a few components that have hard-coded styles or defaults on the component itself that may be interfering with other styles.

Putting It All Together

I won't go into depth about theme extension in this post, but let's resolve our styling objectives by extending our theme.

import {extendTheme} from "@chakra-ui/react";
export const appTheme = extendTheme({
components: {
Table: {
baseStyle: {
table: {
tableLayout: "fixed", // Use the fixed table layout algorithm
width: "min-content", // Set the table with based on minimum content
}
},
variants: {
simple: {
// Change the simple variant th and td border widths
th: {
borderBottomWidth: "3px"
},
td: {
borderBottomWidth: "3px"
}
}
},
sizes: {
// Reduce the medium size th and td padding
md: {
th: {
px: "0.25rem",
py: "0.25rem",
},
td: {
px: "0.25rem",
py: "0.25rem",
}
}
}
}
}
})

Once the exported theme extension is added to our ChakraProvider as the theme, our new default table styles are automatically applied.

Here's the Replit sandbox showing the final solution

Footnotes


1. chakra-ui Documentation : Outlines Chakra's specific approach for styling components
2. chakra-ui Documentation : Defines the differences between single- and multi-part components
3. chakra-ui GitHub : Source code for Table theme
4. MDN Documentation : CSS border-collapse reference
5. MDN Documentation : CSS table-layout reference