What is the best way to ensure that my multiple choice code in CSS & JS only allows for the selection of one option at a time? Currently, I am able

I'm currently facing a small issue that I believe has a simple solution. My knowledge of Javascript is limited, but I am eager to improve my skills in coding for more visually appealing websites.

My problem lies in the code snippet below, where I am attempting to select between iOS and Android options. However, I want to ensure that only one option can be selected at a time. Currently, both options can be selected simultaneously. Could someone kindly guide me on how to make it so that selecting one option automatically deselects the other if it's already chosen? Your assistance would be greatly appreciated! Thank you!

Link to CodePen Demo

HTML

<h1>Device</h1>
<div class="wrap">
  <ul>
    <li><i class="fa fa-apple"></i></li>
    <li><i class="fa fa-android"></i></li>
  </ul>
</div>

CSS

@import url(https://fonts.googleapis.com/css?family=Lato:100,300,400,700);

* {
  box-sizing: border-box;
}
body {
  font-family: 'Lato', sans-serif;
  background: #222;
}

h1 {
  text-align: center;
  margin-top: 50px;
  color: tomato;
  font-weight: 300;
  word-spacing: 14px;
  text-transform: uppercase;
}
.wrap {
  width: 400px;
  height: 300px;
  margin: 0px auto;
}
ul {
  margin: 0; 
  padding: 0;
  list-style: none;
  width: 100%;
  height: 100%;
}
ul li {
  display: block;
  width: 50%;
  height: 50%;
  line-height: 150px;
  font-size: 40px;
  color: #fff;
  text-align: center;
  float: left;
  position: relative;
}
.borderOverlay {
  width: 70%;
  height: 70%;
  background: rgba(255, 255, 255, .1);
  border: 3px solid tomato;
  border-radius: 10px;
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  margin: auto;
  animation: 0.25s enter;
}
.borderOverlay i {
  position: absolute;
  font-size: 29px;
  color: #222;
  top: -15px;
  right: -13px;
  background: #fff;
  padding: 1px;
  border-radius: 50%;
  animation: 0.75s enter2;
}

@keyframes enter {
  0% {
    transform: scale(0) rotate(-90deg);
  }

  100% {
     transform: scale(1);
  }
}
@keyframes enter2 {
    0% {
     transform: scale(0);
  }
  50% {
     transform: scale(0);
  }
  75% {
     transform: scale(1.25);
  }
  100% {
     transform: scale(1);
  }
}

Javascript

$("li").click(function () {
  if($(this).find('.borderOverlay').length) {
    $(this).find('.borderOverlay').remove();
  } else {
    $(this).append('<div class="borderOverlay"><i class="fa fa-check"></i></div>');
  }
});

Answer №1

$("li").on("click", function () {
  var isSelected = $(this).find('.highlightBorder').length;
  $('.highlightBorder').remove();
  if(!isSelected) {
    $(this).append('<div class="highlightBorder"><i class="fa fa-check"></i></div>');
  }
});

Answer №2

To eliminate the presence of the other's .borderOverlay, simply remove it.

This can be achieved by utilizing $(this).siblings(), which will target all remaining li elements except for the one that was clicked on.

$("li").click(function () {
  if($(this).find('.borderOverlay').length) {
    $(this).find('.borderOverlay').remove();
  } else {
    $(this).append('<div class="borderOverlay"><i class="fa fa-check"></i></div>');
    $(this).siblings().find('.borderOverlay').remove();
  }
});
@import url(https://fonts.googleapis.com/css?family=Lato:100,300,400,700);

* {
  box-sizing: border-box;
}
body {
  font-family: 'Lato', sans-serif;
  background: #222;
}

h1 {
  text-align: center;
  margin-top: 50px;
  color: tomato;
  font-weight: 300;
  word-spacing: 14px;
  text-transform: uppercase;
}
.wrap {
  width: 400px;
  height: 300px;
  margin: 0px auto;
}
ul {
  margin: 0; 
  padding: 0;
  list-style: none;
  width: 100%;
  height: 100%;
}
ul li {
  display: block;
  width: 50%;
  height: 50%;
  line-height: 150px;
  font-size: 40px;
  color: #fff;
  text-align: center;
  float: left;
  position: relative;
}
.borderOverlay {
  width: 70%;
  height: 70%;
  background: rgba(255, 255, 255, .1);
  border: 3px solid tomato;
  border-radius: 10px;
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  margin: auto;
  animation: 0.25s enter;
}
.borderOverlay i {
  position: absolute;
  font-size: 29px;
  color: #222;
  top: -15px;
  right: -13px;
  background: #fff;
  padding: 1px;
  border-radius: 50%;
  animation: 0.75s enter2;
}

@keyframes enter {
  0% {
    transform: scale(0) rotate(-90deg);
  }

  100% {
     transform: scale(1);
  }
}
@keyframes enter2 {
    0% {
     transform: scale(0);
  }
  50% {
     transform: scale(0);
  }
  75% {
     transform: scale(1.25);
  }
  100% {
     transform: scale(1);
  }
}
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">

<h1>Device</h1>
<div class="wrap">
  <ul>
    <li><i class="fa fa-apple"></i></li>
    <li><i class="fa fa-android"></i></li>
  </ul>
</div>

Answer №3

It is important to use semantic HTML because there is a native element that serves this purpose - the input type="radio".

<h1>Device</h1>
<div class="wrap">
  <label>
    <input type="radio" class="myRadio" name="myRadio"/>
    <i class="fa fa-apple"></i>
    <div class="borderOverlay"></div>
  </label>
  <label>
    <input type="radio" class="myRadio" name="myRadio"/>
    <i class="fa fa-android"></i>
    <div class="borderOverlay"></div>
  </label>
</div>
  • Placing them within a label ensures that clicking anywhere within the label activates the radio button.
  • When one radio button is selected, all other radio buttons with the same 'name' attribute will be automatically updated.
  • This setup enables input from space/enter keys in addition to mouse clicks, unlike <button> elements.
  • Radio buttons can also be navigated and selected using keyboard controls (Tab Key), an essential accessibility feature often overlooked.

You can easily hide the actual radio buttons:

.wrap > label{
  position: relative;
}

.myRadio {
  position: absolute;
  opacity: 0;
  z-index: -1;
}

You can style the radio buttons using pure CSS:

.myRadio:checked ~ .borderOverlay {
  /* rules for showing border overlay animation */
}

Handle changes on radio buttons effectively:

var radioButtons = Array.from(document.getElementsByClassName('myRadio'));

radioButtons.map(function(radio){
  radio.addEventListener('change', function(e){
    var selectedTarget = radioButtons.filter(btn => btn.checked)[0];
    // perform actions based on **selectedTarget**
  });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JQuery fixed div bounces unpredictably when scrolling

Currently, I have a scenario on my webpage where there is a div called RightSide positioned on the far right side below another div named TopBanner. The TopBanner div remains fixed at the top of the screen even when the user scrolls down, which is exactly ...

Interactive material design drop-down menu

Currently, I am working on a dynamic drop-down menu that utilizes material-ui js. However, I have encountered an issue where clicking on one menu opens all the menus simultaneously, and vice versa when trying to close them. If you would like to view the c ...

Steps for repairing a button positioned at the top of a nested container within a form

My search form includes side filters to help users narrow down their search, with the results appearing on the right. This is just a basic example, as my actual setup involves more filters. However, there is one issue – users have to scroll down the pag ...

Tips for creating a scrolling animation effect with images

I'm currently attempting to create an animation on an image using HTML/CSS. The issue I'm facing is that the animation triggers upon page load, but I would like it to activate when scrolling down to the image. Below is my snippet of HTML: <fi ...

Exploring the possibilities of combining Selenium Code and F# with Canopy

Currently, I am facing the challenge of incorporating Selenium code into my F# project while utilizing the canopy wrapper. Canopy relies on Selenium for certain functions. My main struggle lies in converting Selenium code from Java or C# to fit within an ...

update the markers on a leafletjs map

I am aiming to create a dynamic map with markers that update every 10 minutes. The marker positions are stored in a spreadsheet document that is regularly updated. After successfully retrieving the data from the spreadsheet and positioning the markers in ...

Unusual sequence of JQuery Ajax calls

Within my website, there is a project div that is displayed using EJS. The data for the projects in EJS are rendered using a forEach loop, resulting in multiple similar divs appearing on the page. Each project div is assigned an id for identification pur ...

Utilizing AJAX and PHP to enhance Zend_Config_Ini

As I develop my own CMS, I encountered a challenging issue that I couldn't find a solution for on Google... My dilemma lies in creating an edit_settings.php file using AJAX and PHP to integrate my Zend_Config_Ini for parsing and writing purposes with ...

React Router - Implementing a <Redirect> element rather than a list of child components

Here is the code snippet I am working with: import { Redirect } from 'react-router-dom'; import QPContent from '../QPContent'; class AnswerContainer extends Component { constructor(props) { super(props); this.state = { ...

Alter the color scheme of Fancybox's background

I am looking to create a transparent background color for Fancybox. The typical method involves using ".fancybox-skin" in CSS, however this will affect all fancyboxes and I require it to be unique. Therefore, the setting must be sent with wrapCSS. Fancyb ...

Issue with automatic compiling in Sublime 2 for less2css

Whenever I try to save my style.less file, the automatic compilation doesn't happen. Is there a mistake in how I've set it up? Here's what is currently in my ox.sublime-project file: { "folders": [ { ...

Managing Server Crashes in Node.js

Is there a way to automatically update the database whenever my node.js server crashes or stops? Similar to how try{}catch(){}finally(){} works in JAVA. I am new to this. Does Node emit any events before shutting down so that I can run my function then? ...

"Learn to easily create a button within a table using the powerful functionality of the dataTable

I need to add a button to each row in a table. I managed to achieve this with the code below, but there's a problem - every time I switch between pages, the button keeps getting added again and again. It seems like the button is generated multiple tim ...

Error: The API_URL_KEY variable has not been declared

hardhat.config.js require("@nomicfoundation/hardhat-toolbox"); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: "0.8.18", }; /* @type import('hardhat/config').HardhatUserConfig* ...

Vue project encountering issue with displayed image being bound

I am facing an issue with a component that is supposed to display an image: <template> <div> <img :src="image" /> </div> </template> <script> export default { name: 'MyComponent', ...

Adjusting the timeout for a particular operation according to its unique identifier

I am looking for a solution to call a method that posts an answer after an input change in my Angular project. I want to reset the timeout if another input change occurs to avoid multiple posts. Is there a smart way to achieve this? My project involves po ...

Step-by-step guide on incorporating a new JSON object into an array to display its elements as components on a webpage

Could I adjust the state of an array by incorporating values from a data.js file as a starting point? The process involves executing the setAllThingsArray function to add a new element, determined by the setThingsArray function based on the previous state ...

Utilize the useState hook to update state when changes occur in the

I currently have a functional component that utilizes a useState hook. The values it holds are sourced from my redux store, and I aim to update the state with the new store state every time an action is dispatched. At the moment, I've manually set an ...

The final piece left in stitching together an array

Issue I have been struggling with this code for some time now and I can't seem to figure out the solution. I am receiving 3 values from inputs and trying to remove all the empty spaces "" in the array, but when I execute the code, it displays the foll ...

Quirks in TailwindCSS template literals behavior

Looking at this specific component: const SaleBadge = ({ textContent, badgeColor }) => { return ( <Badge className={`bg-${badgeColor}-200 hover:bg-${badgeColor}-300 animate-pulse align-middle ml-2`} variant="secondary"><Pe ...