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) or 1fr 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>