At first: It is not a bug it is a feature
And unfortunately the way mobile browsers handle the viewport height this is really intentional. The base problem is that if the user scrolls down the visible area changes dynamically.
If the browser would update the CSS viewport height appropriately it should be done while scrolling. The result will be changing layouts all the time, super messy, or like Benjamin wrote as a comment “ it would look like shit ”.
So how can you solve it?
In Tailwind CSS you can use the utility “.h-screen” or “.min-h-screen” to set the height or min-height of an element. Tailwind uses logically the value “100vh” to make this possible and here comes the approach.
The Solution with Tailwind CSS - works in every other CSS framework too…
…is to overwrite the “x-screen” definitions in Tailwind CSS with the dynamic value of a CSS custom property also known as CSS variable.
Overwrite the utility with “var(—vh)” and define the custom property dynamically with javascript on-load and on-resize. I use this approach in all my VueJS applications and websites - it works perfectly.
export default {
// ...
methods: {
setViewHeight: function() {
let vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', `${vh}px`)
},
},
mounted: function() {
this.setViewHeight()
window.addEventListener('resize', () => {
this.setViewHeight()
})
},
// ...
}
Redefine the utility classes in Tailwind CSS
Redefining the CSS class in the tailwind.css file is not the best solution because Tailwind CSS doesn’t know the new values.
So if you would use “h-screen” with Tailwinds directives you would get the old - and wrong - value. The best way is to redefine the height and min height utility or use a plugin function to redefine the utilities you want.
module.exports = {
// ...
theme: {
// ...
height: theme => ({
auto: 'auto',
...theme('spacing'),
full: '100%',
screen: 'calc(var(--vh) * 100)',
}),
minHeight: theme => ({
'0': '0',
...theme('spacing'),
full: '100%',
screen: 'calc(var(--vh) * 100)',
}),
// ...
},
// ...
}
You can find the code example in my collection of best practices in VueJS and Tailwind CSS at Github: App.vue and tailwind.config.js .
This fix with CSS custom properties is not the only way of handling this situation - an alternative way is to use “-webkit-fill-available”. If you are interested in this way you can find it here .