Need all elements in a row to be the length of the longest sibling
I have some dynamically generated buttons, the button text may be a single word, or a small sentence. So I need the buttons to autosize to their content (i.e. can't use a fixed width).
But I also need all the buttons to be the same size, based on the size of the largest button. I know I can do this in JavaScript quite easily. I've provided an example of that below so you can see the expected result.
But I wondered if there was a way to do it just using CSS?
// Quick and dirty just for example purposes
document.addEventListener("DOMContentLoaded", function(event) {
var buttons = document.querySelectorAll('.container_two > button'),
biggest = {w:0, h:0};
buttons.forEach((btn) => {
var size = btn.getBoundingClientRect();
biggest.w = biggest.w < size.width ? size.width : biggest.w;
biggest.h = biggest.h < size.height ? size.height : biggest.h;
});
//console.log(biggest);
buttons.forEach((btn) => {
btn.style.width = Math.ceil(biggest.w)+'px';
// btn.style.height = biggest.h+'px'; -- flexbox will do this for us
});
});
strong { display: block; text-align:center;margin-bottom:1em; font-size: 20px; }
hr { margin: 1.5em 0 1em; }
button {
background: black;
color: white;
font-size: 16px;
padding: 0.5em 1em;
outline: none;
border-width: 0;
border-radius: 0.5em;
}
.container {
display: flex;
justify-content: center;
gap: 1em;
}
<strong>Original</strong>
<div class="container container_one">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>
<hr />
<strong>Javascript Solution</strong>
<div class="container container_two">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>
Try this:
- Set the width of the container to shrink wrap the content (
width: fit-content
) - Use grid properties to distribute container space equally, which will set all buttons to the width of the longest element. (
grid-template-columns: repeat(3, 1fr)
or1fr 1fr 1fr
).
.container {
display: grid;
width: fit-content;
grid-template-columns: 1fr 1fr 1fr;
gap: 1em;
margin: 0 auto;
}
button {
background: black;
color: white;
font-size: 16px;
outline: none;
border-width: 0;
border-radius: 0.5em;
}
<div class="container">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>
Tested in Chrome, Firefox and Edge. Check fit-content
in caniuse.com for full compatibility data.
I would recommend using flex-grow, just add it to the button and all buttons will grow to the same ratio if you make the ratio the same:
strong {
display: block;
text-align:center;
margin-bottom:1em;
font-size: 20px;
}
button {
background: black;
color: white;
font-size: 16px;
flex: 1; /* you can also use flex-grow: 1; */
padding: 0.5em 1em;
outline: none;
border-width: 0;
border-radius: 0.5em;
}
.container {
display: flex;
justify-content: center;
gap: 1em;
max-width: 813px;
margin: 0 auto;
/* change the width of the container in order to not fill the entire screen and keep to the required size */
}
<strong>Original</strong>
<div class="container container_one">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>