Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to style radio buttons differently if they fit in a single row?

PLAYGROUND HERE

I'd like to style radio buttons differently if they fit in a single row. For example:

enter image description here

The first container doesn't have enough space to fit all the radio buttons in a single row. Therefore, they appear vertically as normal radio buttons.

The second container has enough space. Therefore, the radio buttons appear as buttons.

Is that possible to achieve this behaviour using CSS only?

If not, Javascript "hack" is welcome.

PLAYGROUND HERE


HTML

<div class="container radio">
  <div>
    <input id="a1" type="radio" name="radio">
    <label for="a1">Yes,</label>
  </div>
  <div>
    <input id="a2" type="radio" name="radio">
    <label for="a2">it</label>
  </div>
  <div>
    <input id="a3" type="radio" name="radio">
    <label for="a3">is</label>
  </div>
  <div>
    <input id="a4" type="radio" name="radio">
    <label for="a4">possible</label>
  </div>
  <div>
    <input id="a5" type="radio" name="radio">
    <label for="a5">to</label>
  </div>
  <div>
    <input id="a6" type="radio" name="radio">
    <label for="a6">achieve</label>
  </div>
  <div>
    <input id="a7" type="radio" name="radio">
    <label for="a7">this</label>
  </div>
</div>
<div class="container buttons">
  <div>
    <input id="b1" type="radio" name="buttons">
    <label for="b1">Yes,</label>
  </div>
  <div>
    <input id="b2" type="radio" name="buttons">
    <label for="b2">it</label>
  </div>
  <div>
    <input id="b3" type="radio" name="buttons">
    <label for="b3">is</label>
  </div>
  <div>
    <input id="b4" type="radio" name="buttons">
    <label for="b4">possible</label>
  </div>
</div>

CSS (LESS)

.container {
  display: flex;
  width: 220px;
  padding: 20px;
  margin-top: 20px;
  border: 1px solid black;

  &.radio {
    flex-direction: column;
  }

  &.buttons {
    flex-direction: row;

    > div {
      input {
        display: none;

        &:checked + label {
          background-color: #ADFFFE;
        }
      }

      label {
        padding: 5px 10px;
        margin: 0 1px;
        background-color: #ccc;
      }
    }
  }
}
like image 900
Misha Moroshko Avatar asked May 07 '15 11:05

Misha Moroshko


People also ask

Can radio buttons be styled?

With some simple and modern CSS, we can now style radio button input elements even easier. Below are three different options, each having its pros and cons.

How do I display radio buttons horizontally?

To make a horizontal radio button set, add the data-type="horizontal" to the fieldset . The framework will float the labels so they sit side-by-side on a line, hide the radio button icons and only round the left and right edges of the group.

How do you group radio buttons together?

You group radio buttons by drawing them inside a container such as a Panel control, a GroupBox control, or a form. All radio buttons that are added directly to a form become one group. To add separate groups, you must place them inside panels or group boxes.

Should radio buttons be stacked?

Based on research from the Neilson Norman Group as well as the various human interface guidelines for Apple and Microsoft, radio buttons should have the circle to the left of the label, and the list should be stacked vertically.


1 Answers

Not possible in CSS, but it doesn't take much JavaScript.

In CSS, add flex-shrink: 0 to > div. This will prevent .container's children from shrinking smaller than their extent.

In JavaScript:

  1. Apply the buttons class.
  2. Use Element.getBoundingClientRect to determine if the last child of .container is outside the extent of .container. If so, switch to the radio class. (You also need to take the right padding into account. Thanks to @Moob for pointing that out.)

Javascript

var container = document.querySelector('.container'),
    lastChild= document.querySelector('.container > :last-child'),
    paddingRight= parseInt(window.getComputedStyle(container, null).getPropertyValue('padding-right')),
    timer;

window.onresize = function() {
  clearTimeout(timer);
  timer= setTimeout(function() {
    container.classList.remove('radio');
    container.classList.add('buttons');
    if (container.getBoundingClientRect().right-paddingRight <
        lastChild.getBoundingClientRect().right) {
      container.classList.add('radio');
      container.classList.remove('buttons');
    }
  });
}

Updated JSBin

like image 159
Rick Hitchcock Avatar answered Oct 03 '22 14:10

Rick Hitchcock