Home > Software design >  How to create custom radio buttons that can pick only one choice
How to create custom radio buttons that can pick only one choice

Time:10-03

I have created custom radio buttons using HTML, CSS, JS.

Now, it can pick multiple choices at one time like 2, 3, or 4 choices. What I want to do is to only pick one choice at a time.

And, I want to know if there is a way, instead of adding multiple ::after with the same values for all divs, can I add one ::after for all 4 divs.

let mainBtns = document.querySelectorAll('#container');


mainBtns.forEach(btn => {   
    btn.addEventListener('click', () => {
        btn.classList.toggle('active');
    });
});
.main {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    gap: 20px;
}

.first, .second, .third, .forth {
    display: flex;
    place-content: center;
    place-items: center;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background-color: rgb(202, 202, 202);
    cursor: pointer;
    position: relative;
    box-shadow: 0 0 6px 1px #e8eef6;
    
}

.first::after {
    content: '';
    height: 70px;
    width: 70px;
    border-radius: 50%;
    background-color: rgb(78, 78, 78);
    position: absolute;
    vertical-align: middle; 
    visibility: hidden;  
}

.second::after {
    content: '';
    height: 70px;
    width: 70px;
    border-radius: 50%;
    background-color: rgb(78, 78, 78);
    position: absolute; 
    visibility: hidden;
}

.third::after {
    content: '';
    height: 70px;
    width: 70px;
    border-radius: 50%;
    background-color: rgb(78, 78, 78);
    position: absolute; 
    visibility: hidden;
}

.forth::after {
    content: '';
    height: 70px;
    width: 70px;
    border-radius: 50%;
    background-color: rgb(78, 78, 78);
    position: absolute;
    visibility: hidden;
}

.active::after {
    visibility: visible;
}
.deActive::after {
    visibility: hidden;
}
<div >
    <div id="container" ></div>
    <div id="container" ></div>
    <div id="container" ></div>
    <div id="container" ></div>
</div>

CodePudding user response:

The default behavior of HTML <input type="radio"> is already what you want. You can directly style them with CSS.

.main {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  gap: 20px;
}

.main>input {
  appearance: none;
  position: relative;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background-color: rgb(202, 202, 202);
  cursor: pointer;
  box-shadow: 0 0 6px 1px #e8eef6;
}

.main>input::after {
  content: '';
  position: absolute;
  top: 15px;
  left: 15px;
  height: 70px;
  width: 70px;
  border-radius: 50%;
  background-color: rgb(78, 78, 78);
  visibility: hidden;
}

.main>input:checked::after {
  visibility: visible;
}
<div >
  <input type="radio" id="apple" name="fruit" value="apple" checked>
  <input type="radio" id="orange" name="fruit" value="orange">
  <input type="radio" id="banana" name="fruit" value="banana">
</div>

CodePudding user response:

To avoid repeating ::after for each button you can use element > element selector;

And for picking one choice at a time, you need to reset the class name of the buttons (remove active class name from all buttons) then add active to the selected one

const mainBtns = document.querySelectorAll(".btn");

mainBtns.forEach(btn => {
  btn.addEventListener("click", () => {
    if (btn.classList.contains("active")) return btn.classList.remove("active");
    mainBtns.forEach(btn => (btn.className = "btn"));
    btn.classList.add("active");
  });
});
.main {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  gap: 20px;
}

.main>div {
  display: flex;
  place-content: center;
  place-items: center;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background-color: rgb(202, 202, 202);
  cursor: pointer;
  position: relative;
  box-shadow: 0 0 6px 1px #e8eef6;
}

.main>div::after {
  content: "";
  height: 70px;
  width: 70px;
  border-radius: 50%;
  background-color: rgb(78, 78, 78);
  position: absolute;
  vertical-align: middle;
  visibility: hidden;
}

.main>.active::after {
  visibility: visible;
}
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

CodePudding user response:

You cant use id property for multiple elements

And for your Code

You can modify your code like this

HTML

<div id="custom-radio-button" >
    <div  onclick="selectMe(this)"></div>
    <div  onclick="selectMe(this)"></div>
    <div  onclick="selectMe(this)"></div>
    <div  onclick="selectMe(this)"></div>
</div>

CSS

.first::after,
.scond::after,
.third::after,
.forth::after {
    content: '';
    height: 70px;
    width: 70px;
    border-radius: 50%;
    background-color: rgb(78, 78, 78);
    position: absolute;
    vertical-align: middle;
    visibility: hidden;
}

JavaScript

let mainBtns = document.getElementById("custom-radio-button").children

function selectMe(element) {
    for (let index = 0; index < mainBtns.length; index  ) {
        if (mainBtns[index] === element) {
            mainBtns[index].classList.add("active")
        } else {
            mainBtns[index].classList.remove("active")
        }
    }
}

CodePudding user response:

Functionality already exists in html, you can customize them with css.

.container {
  width: 50%;
  height: 300px;
  text-align: center;
  margin: auto;
  display: flex;
  align-items: center;
  justify-content: space-evenly;
}

.container [type="radio" i] {
  transform: scale(1);
  appearance: none;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 25px solid #999;
}

.container [type="radio" i]:checked {
  border: 8px solid #999;
  background-color: #000;
}
<div >
  <input type="radio" name="radio-group">
  <input type="radio" name="radio-group">
  <input type="radio" name="radio-group">
  <input type="radio" name="radio-group">
</div>

  • Related