Search code examples
cssreactjsnext.jstailwind-css

Tailwind CSS: How to Apply Dynamic Width Only on Large Screens While Keeping Full Width on Small Screens?


I'm working on a React component where I want to dynamically set the width of a modal on large screens (using Tailwind CSS), while keeping the modal full width on small screens.

Here is the code snippet I'm using:

import React, { useEffect, useState, ReactNode } from 'react';

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  children: ReactNode;
  width?: string; // Optional width prop
}

const MainModalComponent: React.FC<ModalProps> = ({ isOpen, children, width }) => {
  const [showModal, setShowModal] = useState(false);
  const [animateModal, setAnimateModal] = useState(false);

  useEffect(() => {
    if (isOpen) {
      setShowModal(true);
      setTimeout(() => setAnimateModal(true), 50);
    } else {
      setAnimateModal(false);
      setTimeout(() => setShowModal(false), 500);
    }
  }, [isOpen]);

  return (
    <>
      {showModal && (
        <div className="fixed z-100 inset-0 bg-black bg-opacity-75 flex items-end sm:items-center justify-center">
          <div
            className={`
              bg-white 
              p-6 
              rounded-t-lg 
              shadow-lg 
              w-full
              lg:w-[${width || '450px'}]
              sm:w-auto
              sm:min-h-[200px] 
              sm:rounded-lg  
              transition-transform 
              duration-500 
              ${animateModal ? 'translate-y-0 sm:translate-y-0' : 'translate-y-[100vh] sm:translate-y-[100vh]'}
            `}
          >
            {children}
          </div>
        </div>
      )}
    </>
  );
};

export default MainModalComponent;

The value I use, "250px", seems to be appearing in the className, but it's not applying the style. I have tried adding inline, style={{ width: width || '450px' }} and it works, but it doesn't respect the small screen breakpoint (w-full), and instead, it applies the dynamic width across all screen sizes.

How can I use Tailwind CSS to apply a full width (w-full) on small screens and a dynamic width only on large screens (lg and above)? Is there a way to achieve this using Tailwind classes, or do I need to rely on a different approach?


Solution

  • Why does the dynamically spliced class in Tailwind not work:

    The most important implication of how Tailwind extracts class names is that it will only find classes that exist as complete unbroken strings in your source files.

    Therefore, in general, dynamically changing styles are typically applied using the style attribute. In your case, you want to dynamically change the style when the viewport is larger, while using a fixed value for smaller viewports. You can use ! to increase the specificity of the Tailwind utility classes for smaller viewports, allowing them to override the dynamic values set by style.

    <script src="https://cdn.tailwindcss.com/3.4.5"></script>
    
    <!-- 128px can be a dynamic value👇 -->
    <div class="h-32 bg-amber-200 max-sm:!w-full" style="width: 128px"></div>

    (👆Resize the viewport width down to 640px to see the effect.)

    Demo on Tailwind Play.