skip to Main Content

I am building UI-kit with react tailwind.
I know that tailwind can’t find classes that made with template strings. I want to achieve this:

I have a few components in my ui kit and I want them to have same logic (for i.e. button):
Button has variant size:{
sm: "p-1",
md: "p-2"
}
I want to automatically generate:
{
sm: "md:p-1",
md: "md:p-2"
}

And etc for all screen sizes.
Finally want to do smth like this:


<Button size="sm" md={size:"md"} />

I think I can’t do this in function because tailwind couldn’t see this classes in runtime.
Maybe there is a library or a way to do this in build time. I’m kinda lost cause I already tried a lot of things. Will be glad to see your answer

Tried twind, but can’t really use it cause of deps conflicts

2

Answers


  1. In Tailwind, the screen sizes are defined using responsive breakpoints. For each breakpoint you define, Tailwind generates responsive variants for most utilities. This results in a set of classes like sm:text-2xl, md:text-2xl, etc.

    But by design, due to the way Tailwind’s PurgeCSS works, it’s not possible to define classes dynamically or programmatically at runtime through string concatenation or template strings as it would not be able to recognize those in its safelist.

    However, you could achieve what you want by re-structuring your Button component to accept different sizes for different screen breakpoints as follows:

    function Button({ size, ...props }) {
      const sizeClasses = {
        sm: {
          default: 'p-1',
          md:  'md:p-2',
          // add other sizes if needed
        },
        md: {
          default: 'p-2',
          md: 'md:p-3',
          // add other sizes if needed
        },
        // add other sizes if needed
      };
      
      const classes = sizeClasses[size];
    
      return <button className={`${classes.default} ${classes.md}`} {...props} />;
    }
    

    Then you can use it as follows:

    <Button size="sm">Click Me</Button>
    

    It’s important to clarify that this approach requires the possible combinations of sizes and breakpoints to be defined beforehand in the component. It won’t allow creating new class combinations dynamically at runtime.

    Therefore, I’d suggest considering the design and how many screen sizes you might need to handle specific cases. Most of the time, you can handle it within a few sizes comfortably and handle edge cases by creating custom classes when necessary.

    Remember also to include these classes you used in your safelist when purging css for production with PurgeCSS.

    Login or Signup to reply.
  2. Here’s a way to define them separately:

    const SIZES = {
      sm: "p-1",
      md: "p-2",
      lg: "p-3",
    };
    
    const BREAKPOINTS = {
      sm: "sm",
      md: "md",
      lg: "lg",
    };
    
    function Button({ size, adaptiveSize, ...props }) {
      let classes = `${SIZES[size]}`;
    
      if (adaptiveSize && BREAKPOINTS[adaptiveSize.breakpoint]) {
        classes += ` ${BREAKPOINTS[adaptiveSize.breakpoint]}:${SIZES[adaptiveSize.size]}`;
      }
    
      return <button className={classes} {...props} />;
    }
    

    In this structure, you can use the Button component as follows:

    <Button size='sm' adaptiveSize={{breakpoint: 'md', size: 'md'}}>Click Me</Button>
    

    The configuration {breakpoint: 'md', size: 'md'} essentially means "when the screen size hits the ‘md’ breakpoint, apply the ‘md’ size". Make sure to add fallback checks for when the sizes or breakpoints passed in adaptiveSize doesn’t exist in the SIZES/BREAKPOINTS.

    Remember to add all the classes to PurgeCSS safelist to avoid them being stripped out in production.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search