magic bean
magic bean

Reputation: 797

how to make custom select with JavaScript

I have some options and I want them to be selectable.

<div class="row">
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 1</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 2</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 3</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 4</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 5</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 6</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 7</div>
  </div>
</div>
.new__order__choice .juice__box {
  border: 2px solid var(--second-sub-color);
  color: var(--second-sub-color);
  display: block;
  font-weight: 600;
  padding: 10px 0;
  text-align: center;
  text-decoration: none;
  border-radius: 8px;
  margin: 10px 0;
  cursor: pointer;
}

As you see I have 7 items and I want them to be selectable. I can add CSS for this but the thing that makes me confused is when I select the other ones, I want to deselect the selected one.

It should be like this:

enter image description here

If you could help me with it, I would be really glad. Thanks.

Upvotes: 0

Views: 78

Answers (3)

Rory McCrossan
Rory McCrossan

Reputation: 337560

To achieve this using HTML and CSS alone you can convert the .juice-box elements to labels and add a hidden radio input. Then you can listen for the :checked state of the input and apply the CSS styling to highlight the selected item.

As only one radio can be selected from a group you get the deselect behaviour by default, without the need for any JS code.

:root {
  --second-sub-color: #00C;
}

.new__order__choice .juice__box {
  border: 2px solid var(--second-sub-color);
  color: var(--second-sub-color);
  display: block;
  font-weight: 600;
  padding: 10px 0;
  text-align: center;
  text-decoration: none;
  border-radius: 8px;
  margin: 10px 0;
  cursor: pointer;
}
.new__order__choice input {
  display: none;
} 
.new__order__choice input:checked + .juice__box  {
  background-color: var(--second-sub-color);
  color: #FFF;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<div class="new__order__choice">
  <div class="row">
    <div class="col-lg-3 col-md-12 col-sm-12">
      <input type="radio" name="juice" id="juice1" value="1" />
      <label class="juice__box" for="juice1">Juice 1</label>
    </div>
    <div class="col-lg-3 col-md-12 col-sm-12">
      <input type="radio" name="juice" id="juice2" value="2" />
      <label class="juice__box" for="juice2">Juice 2</label>
    </div>
    <div class="col-lg-3 col-md-12 col-sm-12">
      <input type="radio" name="juice" id="juice3" value="3" />
      <label class="juice__box" for="juice3">Juice 3</label>
    </div>
    <div class="col-lg-3 col-md-12 col-sm-12">
      <input type="radio" name="juice" id="juice4" value="4" />
      <label class="juice__box" for="juice4">Juice 4</label>
    </div>
    <div class="col-lg-3 col-md-12 col-sm-12">
      <input type="radio" name="juice" id="juice5" value="5" />
      <label class="juice__box" for="juice5">Juice 5</label>
    </div>
    <div class="col-lg-3 col-md-12 col-sm-12">
      <input type="radio" name="juice" id="juice6" value="6" />
      <label class="juice__box" for="juice6">Juice 6</label>
    </div>
    <div class="col-lg-3 col-md-12 col-sm-12">
      <input type="radio" name="juice" id="juice7" value="7" />
      <label class="juice__box" for="juice7">Juice 7</label>
    </div>
  </div>
</div>

The added benefit of this is that you don't need any further JS to retrieve the value of the selected items from the div elements you originally had when sending the selections in a request to the server, as they are already contained in a form control.

Upvotes: 1

Fabrizio Calderan
Fabrizio Calderan

Reputation: 123377

No need to use JS for this task, you may use instead a group of radiobox and labels instead of divs.

.row {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 12px;
}

.row > div {
  flex: 0 0 calc(25% - 9px);
}

.juice__box {
  padding: .25rem;
  display: block;
  cursor: pointer;
  border: 2px currentColor solid;
  color: #335;
  background: #ccc;
}

input {
  position: absolute;
  clip: rect(0,0,0,0);
}

:checked + .juice__box {
  color: #ccc;
  background: #335;
}
<div class="row">
  <div class="col-lg-3 col-md-12 col-sm-12">
    <input type="radio" name="juice" value="1" id="j1" />
    <label for="j1" class="juice__box">Juice 1</label>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <input type="radio" name="juice" value="2" id="j2" />
    <label for="j2" class="juice__box">Juice 2</label>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <input type="radio" name="juice" value="3" id="j3" />
    <label for="j3" class="juice__box">Juice 3</label>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <input type="radio" name="juice" value="4" id="j4" />
    <label for="j4" class="juice__box">Juice 4</label>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <input type="radio" name="juice" value="5" id="j5" />
    <label for="j5" class="juice__box">Juice 5</label>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <input type="radio" name="juice" value="6" id="j6" />
    <label for="j6" class="juice__box">Juice 6</label>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
   <input type="radio" name="juice" value="7" id="j7" />
    <label for="j7" class="juice__box">Juice 7</label>
  </div>
</div>

Upvotes: 1

Dendenzilla
Dendenzilla

Reputation: 610

If i understood correctly what you want is that the background color only apply to the last selected, if so you can do this in css:

.juice__box.selected{
  background-color:blue;
}

and this in jquery

$('.juice__box').click(function(){
    $('.juice__box').removeClass('selected');
 $(this).addClass('selected');
  
});

see it live in the snippet

$('.juice__box').click(function(){
    $('.juice__box').removeClass('selected');
 $(this).addClass('selected');
  
});
.juice__box {
  border: 2px solid var(--second-sub-color);
  color: var(--second-sub-color);
  display: block;
  font-weight: 600;
  padding: 10px 0;
  text-align: center;
  text-decoration: none;
  border-radius: 8px;
  margin: 10px 0;
  cursor: pointer;
}
.juice__box.selected{
  background-color:blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 1</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 2</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 3</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 4</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 5</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 6</div>
  </div>
  <div class="col-lg-3 col-md-12 col-sm-12">
    <div class="juice__box">Juice 7</div>
  </div>
</div>

Upvotes: 2

Related Questions