Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I'm trying to put a <button> inside an <input type="radio">'s <label>

Tags:

html

css

Edit: The original answer did not work for mobile devices. Go here for a solution that does.

I already know how to make an <input type="radio">'s <label> look like the button of any specific browser's default <button> by playing with the CSS until it looks identical to the <button> I'm trying to replicate. But this will look out of place whenever someone views it from a browser that has a different default <button>. (Even if I could replicate every default <button> for every browser, a new one will probably be invented tomorrow.)

Therefore, I want to use an actual button to get the default styling appropriate to the browser.

A recreation of the code so far:

<h1>Choose A or B</h1>
<label><button type="button"><input type="radio" name="choice" value="A">A</button></label>
<label><button type="button"><input type="radio" name="choice" value="B">B</button></label>

Later I'll change <input type="radio" name="choice" value="A"> to <input type="radio" name="choice" value="A" hidden> and use some other styling to show if it's checked or not, but for now I'm leaving it in for diagnostic reasons.

If you run the snippet, you'll notice that clicking the <input type="radio"> works as intended, but clicking the <button>itself does nothing.

Here is another failed attempt:

<h1>Choose A or B</h1>
<input type="radio" name="choice" value="A" id="a"><label for="a"><button type="button">A</button></label>
<input type="radio" name="choice" value="B" id="b"><label for="b"><button type="button">B</button></label>

I even tried adding the disabled attribute. Nothing is working as intended. Should I give up and style the <label> manually, or is there a way to access <button>'s default appearance anyway?

(Yes, I already know I could use javascript to simulate <input type="radio">'s behaviour on a <button> but I'm going to have lots of buttons in lots of groups throughout the website. So I'll just style <label> manually if it means the website will be easier to maintain. Likewise for installing an entire library just for this one problem.)

like image 698
Jonathon Philip Chambers Avatar asked Nov 26 '19 09:11

Jonathon Philip Chambers


2 Answers

An idea is to add pointer-events:none; to the button but you won't have the styles of the :focus,:active and :hover state.

button {
  pointer-events:none;
}
<h1>Choose A or B</h1>
<input type="radio" name="choice" value="A" id="a"><label for="a"><button type="button">A</button></label>
<input type="radio" name="choice" value="B" id="b"><label for="b"><button type="button">B</button></label>

You can, however, add your own custom :focus :active :hover and :checked state with:

input[type="radio"]:focus + label button{
    /*add checked style here*/
label:hover > button {
    /*add hover style here*/
}
label:active > button {
    /*add active style here*/
}
input[type="radio"]:checked + label button{
    /*add checked style here*/
like image 52
3 revs, 2 users 71% Avatar answered Sep 23 '22 11:09

3 revs, 2 users 71%


It will not work, as you are doing. You need to do it like this.

[type="radio"]:checked,
[type="radio"]:not(:checked) {
    position: absolute;
    left: -9999px;
}
[type="radio"]:checked + label,
[type="radio"]:not(:checked) + label
{
    position: relative;
    padding-left: 28px;
    cursor: pointer;
    line-height: 20px;
    display: inline-block;
    color: #666;
}
[type="radio"]:checked + label:before,
[type="radio"]:not(:checked) + label:before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    width: 100px;
    height: 30px;
    border: 1px solid #ddd;
    border-radius: 5px;
    background: #fff;
    z-index: -1;
}
[type="radio"]:checked + label:after,
[type="radio"]:not(:checked) + label:after {
    content: '';
    width: 94px;
    height: 24px;
    background: #F87DA9;
    position: absolute;
    top: 4px;
    left: 4px;
    border-radius: 5px;
    -webkit-transition: all 0.2s ease;
    transition: all 0.2s ease;
    z-index: -1;
}
[type="radio"]:not(:checked) + label:after {
    opacity: 0;
    -webkit-transform: scale(0);
    transform: scale(0);
}
[type="radio"]:checked + label:after {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
}
<form action="#">
  <p>
    <input type="radio" id="test1" name="radio-group" checked>
    <label for="test1">Apple</label>
  </p>
  <p>
    <input type="radio" id="test2" name="radio-group">
    <label for="test2">Peach</label>
  </p>
  <p>
    <input type="radio" id="test3" name="radio-group">
    <label for="test3">Orange</label>
  </p>
</form>

You can do it using CSS :before and :after pseudo-classes without using any button. You can modify the above example as per your requirements.

Code is copied from https://codepen.io/manabox/pen/raQmpL and is used after modifications in the above example.

like image 41
Optimum Creative Avatar answered Sep 21 '22 11:09

Optimum Creative