3

I am styling an integration into a 3rd party system, and need to format some radio buttons. The vendor gives us this HTML:

<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
</span>

and I need it to render it like so:

Correct layout

I tried, and failed, using flexbox to accomplish this:

span.radiocontainer {
  float: none;
  display: flex;
  align-items: left;
  justify-content: left;
  flex-direction: column;
  flex-wrap: wrap;
  align-content: left;
}

span.radiocontainer > label.selected.radiolabel {
  box-shadow: none;
  width: 50%;
  border: 0px;
}

span.radiocontainer > input {
  width: 50%;
}
<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
</span>

Current layout

Is there any way for me to format the radio buttons on the left? Or do I need to change my design?

I cannot change the HTML, as it is from a vendor, CSS is the only thing we get to customize.

Andrew Diamond
  • 6,205
  • 1
  • 14
  • 31
  • Possible duplicate of [How to align checkboxes and their labels consistently cross-browsers](https://stackoverflow.com/questions/306252/how-to-align-checkboxes-and-their-labels-consistently-cross-browsers) – Rob Jul 05 '17 at 22:30
  • Edited my answer to add Grid support for IE10+/Edge and to remove redundant styles. – Vadim Ovchinnikov Jul 06 '17 at 05:55

3 Answers3

3

You can move inputs to left by hard-coding order for each input and label.

.radiocontainer {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
}
.radiocontainer input,
.radiocontainer label {
  width: 50%;
  margin: 0;
}

input:nth-of-type(1) {order: 1}
input:nth-of-type(2) {order: 3}
label:nth-of-type(1) {order: 2}
label:nth-of-type(2) {order: 4}
<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
</span>
Nenad Vracar
  • 102,378
  • 14
  • 116
  • 136
3

CSS Grid

The most appropriate approach here is CSS Grid Layout. Approach below uses modern syntax but doesn't have IE/Edge support.

.radiocontainer {
  display: inline-grid;
  /* tells the auto-placement algorithm to attempt to fill in holes earlier in the grid if smaller items come up later */
  grid-auto-flow: dense;
  align-items: center;
}

.radiocontainer label {
  grid-column: 2;
}
<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
</span>

If you also need IE and Edge support you'll have to use old syntax. There is no auto-placement behaviour in IE/Edge implementation so you'll have to specify alignment of every item (except first) manually. If you don’t position items they will stack up in the first cell of the grid in IE/Edge. This works in IE10+:

.radiocontainer {
  display: -ms-inline-grid;
  display: inline-grid;
  align-items: center;
}

.radiocontainer label {
  display: block;
}

input:nth-of-type(2) {
  -ms-grid-row: 2;
  grid-row: 2;
}

label:nth-of-type(1) {
  -ms-grid-row: 1;
  grid-row: 1;
  -ms-grid-column: 2;
  grid-column: 2;
}

label:nth-of-type(2) {
  -ms-grid-row: 2;
  grid-row: 2;
  -ms-grid-column: 2;
  grid-column: 2;
}

input:nth-of-type(3) {
  -ms-grid-row: 3;
  grid-row: 3;
}
<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
    <input class="selector" id="asdf" name="Gender" type="radio" value="1">
</span>

Flexbox

I would improve @NenadVracar answer:

  • We can remove need for setting order for every item. We can just set flex-direction: row-reverse for container.

  • Setting percentage (50%) for both input and label is bad idea. Increasing/decreasing label length will distort our radio button list's look. We need to set fixed width for radio button.

.radiocontainer {
  display: inline-flex;
  flex-direction: row-reverse;
  flex-wrap: wrap;
  align-items: center;
}

.radiocontainer input,
.radiocontainer label {
  margin: 0;
}

.radiocontainer input {
  width: 20px;
}

.radiocontainer label {
  width: calc(100% - 20px);
}
<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
</span>

CSS Floats

This way will work even in IE9 but centering radio buttons is not working.

If you see @TejasviKarne you'll notice that .radiocontainer's width doesn't takes label's width into account. If you care about it you can do it this way:

.radiocontainer {
  display: inline-block; /* Take width of content */
}

.radiocontainer input,
.radiocontainer label {
  margin: 0;
}

.radiocontainer label {
  width: calc(100% - 15px);
  float: right;
}
<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
</span>
Vadim Ovchinnikov
  • 10,848
  • 4
  • 43
  • 73
1

I am shooting in the dark here, but comment out all your code and try this

label{float:right; width:calc(100% - 30px);}

.radiocontainer label{float:right; width:calc(100% - 30px);}
<span class="radiocontainer">
    <label for="genderMale" class="radiolabel">Male</label>
    <input class="selector" id="genderMale" name="Gender" type="radio" value="2">
    <label for="genderFemale" class="radiolabel">Female</label>
    <input class="selector" id="genderFemale" name="Gender" type="radio" value="1">
</span>

I removed all the original styles in the fiddle you provided and added just these styles. They did align as you wanted. However your stylesheet might contain other styles like line-height and margin. I think you can get the alignment you want with some tweaking. If it doesn't work you can revert back to your code and continue from there. Do let me know how it goes.

Tejasvi Karne
  • 598
  • 3
  • 12