reactjsnext.jstailwind-css

Custom styles or creating a shared component


We're about to start a Next.js project using Tailwind for styling. We're fairly new to both technologies but we've started to pull together the UI and so far so good. However, we're seeing a lot of replication in styling. For example every text box has the same set of Tailwind styling applied to it.

To reduce that duplication of styling I think we've got two options:

  1. Use custom styles in Tailwind
  2. Create a text box component which is passed the name, id etc. to use and contains the styles

My question is, is breaking down text boxes into a component too fine grained? I've got an eye on down the line where things may get more complicated - for example supporting show/hide password options, input masks etc. and that component may become very heavy.

I'm leaning towards the answer being custom styles in tailwind but I wanted to ask other peoples opinions.

Thanks in advance.


Solution

  • The official Tailwind documentation has guidelines on this question. They recommend reusing styles in the form of components rather than by combining styles.

    If you need to reuse some styles across multiple files, the best strategy is to create a component if you’re using a front-end framework like React, Svelte, or Vue, or a template partial if you’re using a templating language like Blade, ERB, Twig, or Nunjucks.

    Unless a component is a single HTML element, the information needed to define it can’t be captured in CSS alone. For anything even remotely complex, the HTML structure is just as important as the CSS.

    You can wrap <input /> to just add the default styles and keep the rest of the input and return. This way your component can be modified at the finest level of granularity.

    import { DetailedHTMLProps, InputHTMLAttributes } from "react";
    
    export default function MyStylizedInput({className, ...props}: DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>) {
      return <input {...props} className={`bg-transparent ${className}`} />
    }