Sorry this is a question that should already have an answer online since 1990 but I can't find it. Every post online discusses how to do it with some unique app I never heard of. I just want to create a regular radio group in basic html and spread it out in 3 columns. Like this:
To create a radio group in HTML, you can use the element with the type="radio" attribute. To spread it out in 3 columns, you can use the CSS column-count property.
Try this code:
<style>
.radio-group {
display: flex;
flex-wrap: wrap;
}
.radio-group label {
flex-basis: 33.33%;
margin-bottom: 10px;
}
</style>
<div class="radio-group">
<label><input type="radio" name="group1" value="option1">Dropped</label>
<label><input type="radio" name="group1" value="option2">Heaving up</label>
<label><input type="radio" name="group1" value="option3">holding</label>
</div>
Similarly, you can keeping adding more radio buttons and they will order themselves in 3 columns.
Upvote this answer if Helpful!
Related
Consider this simple example, where we wish to layout a <legend> and its associated input content side-by-side, with no border, rather than using the default <fieldset> display. First, the markup that works as intended:
fieldset {
border: 0;
display: flex;
}
<form>
<fieldset>
<div>
<legend>Choose your favorite monster</legend>
</div>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
Now we think, "Isn't that <div> around the <legend> superfluous?" That is, can't we simply remove it, change the <legend> to display:block, and expect the same behavior?
It turns out we cannot:
fieldset {
border: 0;
display: flex;
}
legend {
display: block;
}
<form>
<fieldset>
<legend>Choose your favorite monster</legend>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
It now displays top-to-bottom, rather than side-by-side? But why? And is there a way to make it display side-by-side without the extra <div> around the <legend>?
EDIT:
Please note: I am looking for a solution that allows me to layout the two elements ("legend" and "input content") using flexbox. In particular, floating the <legend> is not a valid solution for my use case.
display: contents might be the best candidate here as it will remove the tag to keep only its content so no more issue with the behavior of <legend> tag. Then the flexbox algorithm will automatically make the text as an anonymous flex item so your legend is a flex item.
The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes and text runs as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced in the element tree by its contents ref
fieldset {
border: 0;
display: flex;
}
legend {
display: contents;
}
<form>
<fieldset>
<legend>Choose your favorite monster</legend>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
Set the legend to float:left.
The rules for fieldset are somewhat "magic", but are described in the HTML5 rendering section.
If the [fieldset] element's box has a child box that matches the conditions in the list below, then the first such child box is the 'fieldset' element's rendered legend:
The child is a legend element.
The child's used value of 'float' is 'none'.
The child's used value of 'position' is not 'absolute' or 'fixed'.
position:absolute and position:fixed causes other issues. But float is perfect, because, since it's a flex item, it won't actually behave like a float, but as a regular flex item. I've added justify-content:space-around to demonstrate that that's actually happening.
fieldset {
border: 0;
display: flex;
justify-content:space-around;
}
legend {
display: block;
float:left;
}
<form>
<fieldset>
<legend>Choose your favorite monster</legend>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
Approach 1 (the floating <legend> hack)
As #Alohci discovered, when using <legend>, the float: left hack is (still) unavoidable.
See this answer by #BorisZbarsky from 2011, more than a decade ago and long before CSS Flexbox was properly established:
Legends are special. In particular, their default rendering can't be described in CSS, so browsers use non-CSS means of rendering them. What that means is that a statically positioned legend will be treated like a legend and be separate from the actual content of the fieldset.
Source: Why won't my <legend> element display inline?
Since a float: left declaration cannot be avoided, the most concise CSS I came up with is:
fieldset {
display: flex;
border: none;
}
legend {
float: left; /* Hack to prevent browsers applying special <legend> styling */
}
Working Example:
fieldset {
display: flex;
border: none;
}
legend {
float: left; /* Hack to prevent browsers applying special <legend> styling */
}
legend::after {
content: ':';
}
<form>
<fieldset>
<legend>Choose your favorite monster</legend>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
Further Reading:
This technical blogger ran up against the same issue. It seems like the unique positioning behaviour of <legend> has been an issue for a long time:
https://morgan.cugerone.com/blog/how-to-make-a-fieldset-legend-inline/
Approach 2 (the ARIA alternative)
The <legend> element has undisputed semantic value, but we can deploy:
aria-labelledby; or
aria-describedby
in another element (eg. <div>) to replicate the semantic value of <legend>.
If we swap out <legend> for <div id="my-legend"> and support with ARIA, we gain stylability without losing semantics.
Working Example:
fieldset {
display: flex;
border: none;
}
fieldset div:first-of-type::after {
content: ':';
}
<form>
<fieldset aria-describedby="my-legend">
<div id="my-legend">Choose your favorite monster</div>
<div>
<input type="radio" id="kraken" name="monster">
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster">
<label for="sasquatch">Sasquatch</label><br />
</div>
</fieldset>
</form>
I'm trying to do a pure css Show/Hide with radio button.
As seen in below snippet, it works like a charm.
.refusal,
.acceptance {
display: none;
}
input#refusal:checked~.refusal {
display: block;
}
input#acceptance:checked~.acceptance {
display: block;
}
This example works!</br>
<input type="radio" id="refusal" name="status" value="declined">
<label for="refusal">NO</label>
<input type="radio" id="acceptance" name="status" value="accepted">
<label for="acceptance">YES</label>
<form class="refusal">Something for REFUSAL</form>
<form class="acceptance">Something for ACCEPTANCE</form>
The problem is I want to modify my html input/label like this:
<label>
<input type="radio" id="refusal" name="status" value="declined">
NO</label>
However, if I do so, my snippet doesn't work any more (a css selector problem I guess).
But I don't know how to make it work. Thanks.
When you put the input inside a label element you change the level which it resides, so the tilde(~) selector does not work. If you really need the input to be inside a label element you need to use js.
I'm using Bootstrap 3 and trying to center a radio button, an icon, and some text and am having no luck.
My form simply is simply stuffing everything inside a label tag which seems to be a lot.
The skeleton code I started with is below:
<form role="form">
<label class="radio-inline">
<input type="radio" name="optradio">
<br/>
<div class="iconOne"></div>
<br/>
Option 1
</label>
<label class="radio-inline">
<input type="radio" name="optradio">
<br/>
<div class="iconTwo"></div>
<br/>
Option 2
</label>
<label class="radio-inline">
<input type="radio" name="optradio">
<br/>
<div class="iconThree"></div>
<br/>
Icon Three
</label>
</form>
Here's the JS fiddle:
http://jsfiddle.net/4zh28rcn/4/
I'm tempted to try something like Flexbox but am wary of importing more third party libraries.
Thanks for any helpful pointers!
I'm not sure where it's coming from, but you appear to have a stray alignment pushing the <input> 20px to the left of where it ought to be.
If you add the CSS below to what you have in your fiddle already, you will see the radio buttons, the icon images and the text all centered and all lined up:
.radio-inline {
width: 100px;
padding: 0;
text-align: center;
}
input {
display: block;
position: relative;
left: 20px;
width: 100%;
}
How to create vertical Radio Button Group instead of horizontal button group in an html form?
I don't want to use a table for this. Is there any property/attribute available?
Any type of help/suggestion would be appreciated, thanks.
There are three ways you can do it: two with CSS or 1 with oldschool html:
1) The preferred way would be to use a CSS class. (ie add class="block" to the element and then .block {display:block} to your stylesheet.
2)Inline styles: Add style="display:block" to the element.
3)HTML: Add a hard break (br) element after the radio element (or enclose the elements each in a div or p element.)
Example:
<style type="text/css">
.block {
display: block;
}
</style>
...
<form>
<label class="block"><input type="radio" name="radgroup" value="A">Option A</label>
<label class="block"><input type="radio" name="radgroup" value="B">Option B</label>
<label class="block"><input type="radio" name="radgroup" value="C">Option C</label>
<label class="block"><input type="radio" name="radgroup" value="D">Option D</label>
</form>
Is it possible, with only CSS, to style an HTML label dependent on its input's state?
In my case, I want to style an <input type="checkbox"> based on whether it's checked.
I tried putting the label inside the input, but Firefox and Chrome (at least) seems to parse them as siblings, even though they're clearly nested in the input source. And I don't know how to write a CSS rule that can indirect through a for= attribute.
Do I need to whip out the Javascript on this one?
They don't need to be nested, that's what the "for" attribute is for in the <label> element.
In modern browsers (those supporting CSS 2.1), you can use a sibling selector, such as
input + label {
/* rules */
}
You would have to have your markup in a strict sibling relationship, such as:
<input name="cb" id="cb" type="checkbox"><label for="cb">Checkbox</label>
Using the adjacent/sibling selector plus the attribute selector would make it work:
<form>
<style>
INPUT[checked=checked] + LABEL {
color: #f00;
}
</style>
<div>
<input type="checkbox" id="chk1" />
<label for="chk1">Label #1</label>
</div>
<div>
<input type="checkbox" id="chk2" checked="checked" />
<label for="chk2">Label #2</label>
</div>
</form>
To make this thing work you need to put the label after the input, this goes for text type inputs, so for checkbox you can skip this, unless you want the label before checkbox.
To keep the order for label being shown before the input you need to use Flexbox and reverse order of items, for example like this.
.form-group {
display: flex;
flex-direction: column-reverse;
}
The display: flex; with flex-direction: column-reverse; reorders the divs content.
Now all you need to do is use this to affect your label style.
input:checked + label {
color: #000;
}
And HTML for completeness.
<div class="form-group">
<input type="checkbox" name="rememberPwd" id="rememberPwd" class="form-input" required/>
<label for="rememberPwd">Remember?</label>
</div>