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?
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'],
}
})
Since 2023, dynamic values have become part of the default template.
h-dvh - Tailwind CSS Docsh-lvh - Tailwind CSS Docsh-svh - Tailwind CSS DocsIn 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:
@utility directive (instead of @layer utilities) - TailwindCSS v4 Docs@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);
}
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:
/* 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);
}
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']);
}),
],
};
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']);
}),
],
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With