17 Tailwind CSS Tips & Tricks You Probably Don't Know
Tags: css, webdev, tailwindcss, beginners
Published: 2024-06-05 10:05:31

**This post contains interactive demos that can only be accessed in the original post at https://devaradise.com/tailwind-css-tips-tricks/**

Tailwind CSS has been an increasingly popular CSS library today. Although it still not beat Bootstrap's popularity in terms of global usage, Tailwind CSS is the most loved CSS library according to [State of CSS survey 2023](https://2023.stateofcss.com/en-US/css-frameworks/).

More and more developers are adopting Tailwind CSS into their workflow. Some of the latest popular UI component libraries like shadcn ui and Nextui even use Tailwind CSS for their component styling.

Although it's popular and has decent documentation, some developers often skip to specific class documentation without knowing there is cool and useful stuff that is rarely known.

In this post, I'm going to summarize some Tailwind CSS features and utilities you might not know, along with examples. Some of them are even not documented well in the official documentation.

## Styling Based on Other Elements

Tailwind CSS has some features that allow you to style an element based on another element.

### 1. Styling children from parent element (`&_*`)

Generally, you can just put utility classes on any element to style it. But, there is a case where you don't have control over certain elements, like when you are using an external component.

In that case, you can use this class to style the element inside that component. There are 2 ways to style an element from its parent:
- Using `*:{utility-class}` to style direct children which is [documented here](https://tailwindcss.com/docs/hover-focus-and-other-states#styling-direct-children)
- Using `[&_{children-selector}]:{utility-class}` to style any descendant for the parent element. I don't know why, but this way is not documented in official documentation.

#### Example:

![Styling children from parent element](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dc1y7ftv5vguj7dtoxse.jpg)

The underscore in the code is a replacement for space. You can also use `id` and `class` selectors.

### 2. Styling based on Parent state (`group-*`)

Let's say you have a card component that has text, a link, and an icon inside it. When the user hovers over the card, you want to apply a style to text, link, and icon. To do that, you can put `group` class to the card element and put `group-hover:{utility-class}` to the text, link, and icon that you want to style.

The `group` state is not limited to hover. You can also apply it for other states like `active`, `focus`, and `checked`.

#### Example:

![Styling based on Parent state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w4cejy1xka3iex4irurj.jpg)

In the code above, you can see there are `group-hover:text-white` inside the element with `group` class 

### 3. Styling based on Sibling state (`peer-*`)

You can use `peer-{state}:{utility-class}` to style an element based on its sibling state. 

#### Example

![Styling based on Sibling state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ycdrkh99qucplb0bsjij.jpg)

In the demo above, you can see that the error message will only be visible when the input element (sibling) has `invalid` state.

### 4. Styling based on descendant (`has-*`)

There is also a way to style an element based on its children or descendants. The example use case for this is when looping a post list that the post item can contain an image or not.

#### Example

![Styling based on descendant](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e5sjyk2z635bp8es4v5l.jpg)

In real use cases, you probably will use javascript logic instead of using `has-[{element-selector}]` to style based on the descendant element. But, `has-*` also supports for descendant state. 

In the demo above, you can see that I used `has-[img:hover]` to change the background when the image hovered. You can use another state like `invalid`, `disabled`, `focus`, etc. This is the best use case where you can use `has-*` selector.

You can also combine `has-*` with another modifier like `peer-has-*`.

## Writing and Customizing Classes

Tailwind CSS supports some ways to write and customize utility classes

### 5. Custom class with Arbitrary Values

Custom class with Arbitrary Values is like writing css directly inside the class. It looks something like `text-[#09836d]` or `mr-[75px]`. You can use a class with Arbitrary as a last resort when you can't find a predefined utility class that fulfills your use case.

You can pass any value that is valid as css property value to a custom class. You can even pass Tailwind CSS variables. You can find more examples of Arbitrary values in [official documentation](https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values).

One thing that usually becomes an issue when using a class with arbitrary value is when you need to pass a value with space. For example, when you want to pass `box-shadow` value `0 0 2px 0 #abcdef`. In this case, you can replace the space with `_`, so the class will be `shadow-[0_0_2px_0_#abcdef]`.

Keep in mind that a css class can't contain whitespace.

### 6. Color Opacity

Did you know that you can apply opacity to your color classes?. It work on classes that contain color values like `bg-{color}`, `text-{color}`, `border-{color}`. You just need to add `/{opacity-value}` after the class. The opacity value is 0 to 100 with interval 5.

#### Example

![Color Opacity](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4jn6b7gqpvoltipdrkx8.jpg)

### 7. Dynamic utility classes

When using a Front-end framework like React, Next.js, or Vue with Tailwind CSS, you often encounter the case when you have to generate Tailwind CSS class based on the variables or states.

For example in a React project, you want to conditionally put a `bg-color` to a component based on `colors` variable.

```jsx
const ConditionalColor = () => {
  const colors = ['red', 'green', 'blue'];
  return (
    <>
      {
        colors.map(() => <div className={`size-8 bg-${color}-500`}>The tailwind class wont work</div>)
      }
    </>
 );
};
```

Although it will generate `bg-red-500` which is a valid Tailwind CSS class, it won't generate the css for `bg-red-500`. This is because the Tailwind CSS scans your project files and generates the class & css styles in Build time, while in the code above, the `bg-red-500` will only be available in Run time.

To solve this issue, you have to define the Tailwind CSS classes so they will get scanned in build time.

```jsx
const ConditionalColor = () => {
  const colors = ['bg-red-500', 'bg-green-500', 'bg-blue-500'];
  return (
    <>
      {
        colors.map(() => <div className={`size-8 ${color}`}>The tailwind class will work</div>)
      }
    </>
 );
};
```

### 8. Customize / Disable Tailwind container class

Tailwind CSS comes with a built-in responsive container class. The container will adjust in `xs`, `sm`, `md`, and `lg` breakpoints. By default, the container class has no padding and center positioning. But if you want to customize it, you can add container configurations in `tailwind.config.js` file.

```ts {5-8} title="tailwind.config.js"
/** @type {import('tailwindcss').Config} */
module.exports = {
 ...,
  theme: {
    container: {
      center: true,
      padding: '1rem'
 },
 },
}
```

You can also disable or remove the container class by setting `container: false` in `corePlugins` configuration.

```ts {5} title="tailwind.config.js"
/** @type {import('tailwindcss').Config} */
module.exports = {
 ...,
  corePlugins: {
    container: false
 },
}
```

## Combining Utility Classes

Some utility classes can be combined with other classes in certain cases.

### 9. Combine Text size and Line height in 1 class

Usually, when you want to put a text size and line height class, you will put 2 classes, for example, `text-base` and `leading-6`. You can actually shorten them into a single class `text-base/6`. This will also work with arbitrary values or other line-height values like `text-base/[40px]` or `text-base/small`.

#### Example

![Combine text-size and leading](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i17i5hscnv32x021vwpb.jpg)

### 10. Combine Width and Height in 1 class (`size`)

If you want to create a square element with the same width and height, you combine your width `w-8` and height `h-8` class into a single class `size-8`.

#### Example

![Combine width and height](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yrhccdezlni0fa6cvbjb.jpg)


### 11. Space between element (`space-*` & `gap-*`)

When displaying a list or grid, we usually need spacing between list or grid items. We often use `padding-{top/bottom/left/right}` or `margin-{top/bottom/left/right}` and end up with excess spacing in the last item.

You can solve this by using `space-*` or `gap-*` in the list or grid container. `space` works for all element displays (`block`, `flex`, `grid`, etc), while `gap-*` only works for `flex` and `grid` element.

If you use `space-*`, you have to define the direction whether vertical or horizontal spacing. Use `space-x-*` for horizontal space and `space-y-*` for vertical spacing.

#### Example

![Space between element](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsn5fpd6rqhec3misrm3.jpg)

## Rarely Known Cool Stuff

Some useful Tailwind CSS utility classes you probably don't know.

### 12. Replace  js `substring()` with `truncate` and `line-clamp-*`

Before I knew `truncate` and `line-clamp-*`, I usually used the javascript function `substring(0, n)` to truncate a string. However, the sentences often have inconsistent widths because each letter has a different width.

`truncate` and `line-clamp-*` solve this because they don't care about the number of letters, they only care about the number of lines.

You can use `truncate` to truncate sentences into 1 line. If you want to truncate a paragraph after, let's say 3 lines, you can use `line-clamp-3`. 

#### Example

![truncate and line-clamp](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2rtsbsi078fyl5p3zvb.jpg)


### 13. Changing Checkbox & Radio Color (`accent-*`)

A native browser color for checkbox and radio input sometimes doesn't match your design color. Luckily, we can change their colors with `accent-*`.

#### Example

![Checkbox and Radion custom color](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51resltjmj8ydrg7qu0c.jpg)

### 14. Customize Input file button (`file:*`)

You can also customize the design for the browser file input button with `file:*`.

#### Example

![Customize Input file button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lr548she5p5zcv8gwnky.jpg)

### 15. Blur and Color filters

You can apply blur or color filters to any element such as image, text, heading, background, etc. Just put a class `blur`, `grayscale`, or any filter class into the parent element.

For backdrop filter, you can add `backdrop-blur` class. Just Go to the [official documentation](https://tailwindcss.com/docs/blur) to learn more about it.

#### Example

![Blur and Color filters](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4plx3h5dkc7b3x74qtur.jpg)

## Tailwind CSS VSCode Extensions

When working with Tailwind CSS, I recommend installing these extensions in your VSCode to improve your productivity.

### 16. Tailwind CSS IntelliSense

[![Tailwind CSS IntelliSense](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8yjd9r7r4k6fcl96gr3j.png)](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)

Tailwind CSS IntelliSense is the official Tailwind CSS extension for VSCode. It will help you with class autocomplete, linting, syntax highlighting, and a tooltip that contains a class overview.

### 17. Tailwind Docs

[![Tailwind Docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2fptptl8vo47th6n495.gif)](https://marketplace.visualstudio.com/items?itemName=austenc.tailwind-docs)

Tailwind Docs is an unofficial Tailwind CSS extension that will help you to explore Tailwind CSS documentation from VSCode.

## Do you have other Tailwind CSS tips & tricks?

If you know any tip or trick that isn't shared here, please do not hesitate to share it in the comment below. Sharing is caring :smile:

Thank you, have a nice day!