Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tailwind CSS fallback for new screen length types such as "lvh", "svh"

I wrote tailwind.config.js as bellows to use new CSS length types such as lvh, svh.

module.exports = {
  theme: {
    extend: {
      height: {
        "screen": "100dvh",
        "screen-small": "100svh",
        "screen-large": "100lvh"
      }
    }
  }
}

then it successfully exports

.h-screen {
    height: 100dvh;
}

But I want to get with fallback properties like

.h-screen {
  height: 100vh; /* fallback for Opera, IE and etc. */
  height: 100dvh;
}

Is there any nice way to export fallback properties with Tailwind CSS?

like image 891
Hiroki Yokoiwa Avatar asked Nov 17 '25 02:11

Hiroki Yokoiwa


2 Answers

Pass an array as property

module.exports = {
  theme: {
    extend: {
      height: {
        screen: ['100vh /* fallback for Opera, IE and etc. */', '100dvh'],
      }
    }
  }
}

This will generate

.h-screen {
  height: 100vh /* fallback for Opera, IE and etc. */;
  height: 100dvh;
}

DEMO

Note: I'm not 100% sure it is supposed way to do it as editor shows error because we are passing not string but array of strings.

Another way is to create utility with layer

@layer utilities {
  .h-my-screen {
    height: 100vh; /* fallback for Opera, IE and etc. */
    height: 100dvh;
  }
}

In case if you wish to use reserved h-screen name approach is similar but it will stack default (100vh) and new value (100dvh) in correct order you need - but it is just coincidence

@layer utilities {
  .h-screen {
    height: 100dvh;
  }
}

Same thing using Tailwind plugin

const plugin = require('tailwindcss/plugin')

/** @type {import('tailwindcss').Config} */
module.exports = {
  // ...

  plugins: [
    plugin(function ({ addBase, addComponents, addUtilities, theme }) {
      addUtilities({
        '.h-screen': {
          height: '100dvh',
        }
      })
    })
  ],
}

Created both way utility h-screen will now generate

.h-screen {
  height: 100vh;
  height: 100dvh;
}

Note: when using JS syntax object CANNOT contain similar keys (height in your case) but it may accept an array of values in defined order

// Wrong
addUtilities({
  '.h-my-screen': {
    height: '100vh /* fallback for Opera, IE and etc. */',
    height: '100dvh',
  }
})

// Correct
addUtilities({
  '.h-my-screen': {
    height: ['100vh /* fallback for Opera, IE and etc. */', '100dvh'],
  }
})
like image 124
Ihar Aliakseyenka Avatar answered Nov 18 '25 21:11

Ihar Aliakseyenka


Since 2023, dynamic values have become part of the default template.

  • tailwindcss PR #11317 - GitHub
  • Dynamic Viewport Height: h-dvh - Tailwind CSS Docs
  • Large Viewport Height: h-lvh - Tailwind CSS Docs
  • Small Viewport Height: h-svh - Tailwind CSS Docs

In general, Tailwind CSS v3.0 is designed for and tested on the latest stable versions of Chrome, Firefox, Edge, and Safari. It does not support any version of IE, including IE 11.


Source: Browser Support - Tailwind CSS Docs

Browsers released around 2022 started supporting dynamic viewport values. However, if you'd like to assign fallback values, you can use the CSS @supports and not operators to inject additional CSS, assigning fallback values to the mentioned 3 classes.

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2015.


Source: @supports - MDN Docs

@supports not (height: 100dvh) {
  .h-dvh {
    height: 100vh;
  }

  /* ... */
}


With the help of a Tailwind CSS plugin, you can dynamically add fallback values for all screens:

TailwindCSS v4.0 or above

  • @utility directive (instead of @layer utilities) - TailwindCSS v4 Docs
  • TailwindCSS v4 Playground with new utilities
@utility h-dvh {
  @supports (height: 100dvh) {
    height: 100dvh;
  }
  @supports not (height: 100dvh) {
    height: 100vh;
  }
}

@utility h-lvh {
  @supports (height: 100lvh) {
    height: 100lvh;
  }
  @supports not (height: 100lvh) {
    height: 100vh;
  }
}

@utility h-svh {
  @supports (height: 100svh) {
    height: 100svh;
  }
  @supports not (height: 100svh) {
    height: 100vh;
  }
}

And, you can dynamically declare h-dvh-{number}, h-lvh-{number}, and h-svh-{number} classes just like h-{number}.

/* Example: h-dvh-50 will be height: 50dvh; */
/* - if dvh not supported then will be height: 50vh; */
@utility h-dvh-* {
  @supports (height: 100dvh) {
    height: calc(--value(integer) * 1dvh);
  }
  @supports not (height: 100dvh) {
    height: calc(--value(integer) * 1vh);
  }
}

/* Example: h-lvh-50 will be height: 50lvh; */
/* - if lvh not supported then will be height: 50vh; */
@utility h-lvh-* {
  @supports (height: 100lvh) {
    height: calc(--value(integer) * 1lvh);
  }
  @supports not (height: 100lvh) {
    height: calc(--value(integer) * 1vh);
  }
}

/* Example: h-svh-50 will be height: 50svh; */
/* - if svh not supported then will be height: 50vh; */
@utility h-svh-* {
  @supports (height: 100svh) {
    height: calc(--value(integer) * 1svh);
  }
  @supports not (height: 100svh) {
    height: calc(--value(integer) * 1vh);
  }
}

/* Example: h-screen-50 will be height: 50vh; */
@utility h-screen-* {
  height: calc(--value(integer) * 1vh);
}
  • Browser support - TailwindCSS v4 Docs

Note: TailwindCSS v4 primarily focuses on supporting browsers from 2023-2024 to leverage many new CSS developments that are designed for long-term use. Therefore, the dynamic heights injected into all browsers in 2022 should not pose a problem - in theory. If you're curious about the {number} utilities or want to use them without support, here they are:

  • TailwindCSS v4 Playground with new utilities
/* Example: h-dvh-50 will be height: 50dvh; */
@utility h-dvh-* {
  height: calc(--value(integer) * 1dvh);
}

/* Example: h-lvh-50 will be height: 50lvh; */
@utility h-lvh-* {
  height: calc(--value(integer) * 1lvh);
}

/* Example: h-svh-50 will be height: 50svh; */
@utility h-svh-* {
  height: calc(--value(integer) * 1svh);
}

/* Example: h-screen-50 will be height: 50vh; */
@utility h-screen-* {
  height: calc(--value(integer) * 1vh);
}


TailwindCSS v3.4 or above

const plugin = require('tailwindcss/plugin');

module.exports = {
  plugins: [
    plugin(function ({ addUtilities }) {
      const fallbackHeightUtilities = {
        '@supports not (height: 100dvh)': {
          '.h-dvh': { height: '100vh' },
          '.min-h-dvh': { 'min-height': '100vh' },
          '.max-h-dvh': { 'max-height': '100vh' },
        },
        '@supports not (height: 100lvh)': {
          '.h-lvh': { height: '100vh' },
          '.min-h-lvh': { 'min-height': '100vh' },
          '.max-h-lvh': { 'max-height': '100vh' },
        },
        '@supports not (height: 100svh)': {
          '.h-svh': { height: '100vh' },
          '.min-h-svh': { 'min-height': '100vh' },
          '.max-h-svh': { 'max-height': '100vh' },
        },
      };

      addUtilities(fallbackHeightUtilities, ['responsive']);
    }),
  ],
};


TailwindCSS v3.3 or below

const plugin = require('tailwindcss/plugin');

module.exports = {
  plugins: [
    plugin(function ({ addUtilities }) {
      const heightUtilities = {
        '.h-dvh': { height: '100dvh' },
        '.h-lvh': { height: '100lvh' },
        '.h-svh': { height: '100svh' },

        '.min-h-dvh': { 'min-height': '100dvh' },
        '.min-h-lvh': { 'min-height': '100lvh' },
        '.min-h-svh': { 'min-height': '100svh' },

        '.max-h-dvh': { 'max-height': '100dvh' },
        '.max-h-lvh': { 'max-height': '100lvh' },
        '.max-h-svh': { 'max-height': '100svh' },
      };

      const fallbackHeightUtilities = {
        '@supports not (height: 100dvh)': {
          '.h-dvh': { height: '100vh' },
          '.min-h-dvh': { 'min-height': '100vh' },
          '.max-h-dvh': { 'max-height': '100vh' },
        },
        '@supports not (height: 100lvh)': {
          '.h-lvh': { height: '100vh' },
          '.min-h-lvh': { 'min-height': '100vh' },
          '.max-h-lvh': { 'max-height': '100vh' },
        },
        '@supports not (height: 100svh)': {
          '.h-svh': { height: '100vh' },
          '.min-h-svh': { 'min-height': '100vh' },
          '.max-h-svh': { 'max-height': '100vh' },
        },
      };

      addUtilities(heightUtilities, ['responsive']);
      addUtilities(fallbackHeightUtilities, ['responsive']);
    }),
  ],
};
like image 38
rozsazoltan Avatar answered Nov 18 '25 21:11

rozsazoltan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!