Firefox CSS Bug: Four-Sided Positioning With Buttons
Four-sided positioning in CSS is one of my favorite ways to "cover" an area of the viewport with an absolutely-positioned (or fixed-positioned) element. It's had perfect support in all browsers for like 15-years; but, the other day I tripped over a bug in Firefox. It seems that four-sided positioning does not work with <button>
elements in Firefox. Thankfully, one of my other favorite CSS features - Flexbox - can fix this problem.
Run this demo in my JavaScript Demos project on GitHub.
View this code in my JavaScript Demos project on GitHub.
To quickly recap, four-sided positioning entails taking a positioned element and omitting its dimensions (ie, no height
or width
); and then, applying positioning to each of its sides. The following code will stretch each edge of the given element to meet the sides of its closest positioned parent element:
.widget {
position: absolute ;
/* Stretch each side in all directions. */
bottom: 0px ;
left: 0px ;
right: 0px ;
top: 0px ;
}
It's truly an amazing feature of CSS. And, like I said, works perfectly in all browsers. Except, apparently with buttons in Firefox. To see this, I've created a positioned "box" that has explicit dimensions. Then, inside the box, I have a four-sided positioned <button>
that is intended to take up all the space of of the box:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="./main.css" />
<style type="text/css">
.box {
background-color: #f0f0f0 ;
border: 3px solid #cccccc ;
/* Give the container some dimensions. */
position: relative ;
height: 200px ;
width: 300px ;
}
.box__button {
background-color: transparent ;
border: 4px solid hotpink ;
/*
We want the button to be absolutely positioned (to its positioned
container). This should take up all the visual space by using four-sided
positioning (pulling each side to the edge of the container).
*/
position: absolute ;
bottom: 5px ;
left: 5px ;
right: 5px ;
top: 5px ;
}
</style>
</head>
<body>
<h1>
Firefox CSS Bug: Four-Sided Positioning With Buttons
</h1>
<div class="box">
<button class="box__button" onclick="console.log( 'Clicked!' )">
Take Up<br />
All The Space
</button>
</div>
</body>
</html>
As you can see, the inner button is designed to stretch to 5px
from each side of the outer box. Now, if we open this in Chrome and in Firefox, we get the following output:
As you can see, Chrome (or any browser other than Firefox) will gladly stretch the button to the designated positioned edges. Firefox, on the other hand, will stretch the button in the vertical plane; but, will leave the width of the button to match the button contents.
To overcome this Firefox bug, we can add an intermediary wrapped that will apply a CSS Flexbox layout to the button. Firefox may not like stretching a button using four-sided positioning; but, it has no problem stretching a button using Flexbox.
In this fix, we're going to wrap the <button>
element in a <div>
. The Div will using the four-sided position as well as display:flex
. Then, we'll use flex-grow:1
to stretch the button horizontally:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="./main.css" />
<style type="text/css">
.box {
background-color: #f0f0f0 ;
border: 3px solid #cccccc ;
/* Give the container some dimensions. */
position: relative ;
height: 200px ;
width: 275px ;
}
.box__wrapper {
/*
This time, instead of using four-sided positioning on the button, I'm
going to create an intermediary DIV that is positioned. Firefox has no
problem, with positioning the DIV. But, we're going to use it as a Flexbox
container that will become responsible for stretching the button.
*/
position: absolute ;
bottom: 5px ;
left: 5px ;
right: 5px ;
top: 5px ;
/*
By default, the Flexbox container will stretch its childen vertically.
Then, we can use the "flex-grow" on the children (our button) to stretch
the button in the horizontal space.
*/
display: flex ;
}
.box__button {
background-color: transparent ;
border: 4px solid hotpink ;
/* STREEEEEEEEETCH the button width to meet wrapper / flexbox edges. */
flex: 1 1 auto ;
}
</style>
</head>
<body>
<h1>
Firefox CSS Bug: Four-Sided Positioning With Buttons (Flexbox Fix)
</h1>
<div class="box">
<div class="box__wrapper">
<button class="box__button" onclick="console.log( 'Clicked!' )">
Take Up<br />
All The Space<br />
(With Flexbox!)
</button>
</div>
</div>
</body>
</html>
As you can see, we've transferred the four-sided positioning from the <button>
element to its new wrapper. And, we're allowing the button, which is now a "flex child" to grow. This time, when we open this in Firefox, we get the following output:
This time, instead of positioning the button, we're positioning a CSS Flexbox container. And, once the button is part of a Flex layout, Firefox has no problem stretching the button every which way.
At the time of this writing, Firefox is on version 113.0.1. Hopefully, in a future version this hack won't be be necessary. But, at least there's a relatively simple work-around.
Want to use code from this post? Check out the license.
Reader Comments
Adding the following style to your button will also fix the issue.
min-width: -moz-available
.@Rodney,
Oh very cool! 🙌 I tried applying that to the demo and it works perfectly. I just did some Googling and it doesn't look like there's much information on this property, so thanks for the tip.
Thanks for this write-up, Ben, which I found after discovering the same bug and then making this Pen.
And thanks for the fix, Rodney.
@Jonathan,
Team work makes the dream work!
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →