Home > Mobile >  CSS only: horizontal buttons
CSS only: horizontal buttons

Time:10-13

I am trying to create 2 horizontal buttons with the same width - based on the width of the longest one.

  • The text content of each button can be adjusted by users on a separate page... thus I have no control over the length of their text / the length of the 1st vs 2nd button text.
  • I would like to buttons to adjust to the length of the longest text, but not exceed the width of the page (on mobile for ex.).
  • I would like the buttons to be displayed horizontally by default, but stacked as columns if they don't fit horizontally.
  • I need to text of buttons to break into multiple lines if the whole text does not fit.
<div >
     <div  data-role="yes">Yes</div>
     <div  data-role="no">No, sorry - I cannot make it</div>
</div>

I have tried multiple options... without being able to make it work!

  • When using grid width grid-template-colums: 1fr 1fr, I can't find a way to 'stack' the buttons as columns when required.
  • When using flex with flex:1 1 0, I can't find a way to make the buttons width adapt to the length of the text.

Please help!

1,000 thanks! Damien.

CodePudding user response:

Let's try this option. What do you dislike about this approach?

div {
  background-color: rgba(0, 0, 0, 0.1);
}

.button-container {
  padding: 16px;
  display: flex;
  gap: 16px;
}

.horizontal-button {
  padding: 16px;
  flex: 1;
  text-align: center;
  word-wrap: hypens;
}

@media (max-width: 360px) {
  .button-container {
    flex-direction: column;
  }
}
<div >
  <div  data-role="yes">Yes</div>
  <div  data-role="no">No, sorry - I cannot make it</div>
</div>

A: In this case, the container / the buttons take the full width of the page... they don't adjust to the width of the text

Q: Okay then so:

div {
  background-color: rgba(0, 0, 0, 0.1);
}

.button-container {
  margin: auto;
  padding: 16px;
  box-sizing: border-box;
  display: flex;
  align-items: stretch;
  gap: 16px;
  max-width: max-content;
}

.horizontal-button {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 16px;
  flex: 1;
  text-align: center;
  max-width: 50%;
}

@media (max-width: 360px) {
  .button-container {
    flex-direction: column;
  }
  .horizontal-button {
    hyphens: auto;
    max-width: unset;
  }
}
<div >
  <div  data-role="yes">Yes</div>
  <div  data-role="no">No, sorry - I cannot make it</div>
</div>

CodePudding user response:

You'll have to dive in to a bit of Javascript imho. You look at the resize event take the largest width and set the width of all buttons to that. However with display:flex, if you crush the screen size too much, the smaller buttons will shrink.

window.onresize = () => {
  resizeButtons();
}

window.onload = () => {
  resizeButtons();
}

function resizeButtons() {
  const element = document.querySelector('.button-container');
  const buttons = element.querySelectorAll('.horizontal-button');
  var maxWidth = 0;
  buttons.forEach(button => {
    button.style.width = "";
  });
  buttons.forEach(button => {
    maxWidth = Math.max(button.offsetWidth, maxWidth);
  });
  buttons.forEach(button => {
    button.style.width = (maxWidth)   "px";
  });
}
.button-container {
  display: flex;
  gap: 0.25rem;
}

.horizontal-button {
  border-radius: 0.25rem;
  padding: 0.25rem 0.5rem;
  border: 1px solid darkgray;
  background-color: lightgray;
  cursor: pointer;
}

.horizontal-button:hover {
  background-color: gray;
}
  <div >
    <div  data-role="yes">Yes</div>
    <div  data-role="no">No, sorry - I cannot make it</div>
  </div>

CodePudding user response:

Here is a potential solution. You say that the text content of the buttons is user generated. This means you could do some calculation to find the longest length string and use it as an inline style to make both the buttons the same width.

* {
  box-sizing: border-box;
}

.button-container {
  margin: auto;
  padding: 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.horizontal-button {
  padding: 10px 20px;
  text-align: center;
}
<div >
  <button  data-role="yes" style="width: 28ch">Yes</button>
  <button  data-role="no" style="width: 28ch">No, sorry - I cannot make it</button>
</div>

<div >
  <button  data-role="yes" style="width: 65ch">Yes</button>
  <button  data-role="no" style="width: 65ch">No, sorry - I cannot make it, here is more text to make it longer</button>
</div>

How you go about calculating the longest string is dependant on what framework you are using.

For example Vue:

:style="`${yes.length > no.length ? yes.length : no.length}ch``"

And this could easily be converted to work with PHP, React, Laravel etc...

  • Related