Skip to main content
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Sharon DiOrio
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Sharon DiOrio ( @sharondio )

Firefox CSS Bug: Four-Sided Positioning With Buttons

By on
Tags:

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:

A four-sided button is fully streched both vertically and horizontally in Chrome; but, only vertically in Firefox (leaving width the size of the button text).

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:

Fifefox is now stretching the button element in both the vertical and the horizontal plane.

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

15,666 Comments

@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.

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel