Search code examples
htmlcssbootstrap-4bootstrap-select

Change the Background Color of a Bootstrap 4.6 Select Option When Selected or Hovered?


Using Bootstrap 4.6, all my form select dropdowns have a blue background like this:

bootstrap 4.6 select dropdown menu with options

I have a .scss file setup similar to this:

// Custom Variables

@import '../../vendor/bootstrap-4.6.0/scss/functions';
@import '../../vendor/bootstrap-4.6.0/scss/variables';

// Bootstrap Overrides
$primary: #6b37c4;
$link-color: $primary;
$link-hover-color: darken($primary, 10%);
$WHAT-GOES-HERE-BG?: $primary; // <-- what goes here?

My question:

Is there a Bootstrap 4.6 variable I could change that would change this blue background color to something else, globally?

If yes, what is the variable name(s)? I tried custom-select-bg and custom-select-background, form-select-bg, and similar.

If not, is there a way to change this blue background for Bootstrap 4.6? I have no understanding of browser compatibility, but obviously would like something long-lasting. I tried several solutions on html - Change select list option background color on hover but many were out-of-date or hacky.

Basic example

I would expect the background color of a select option to turn yellow on hover, but it doesn't. I also don't know how to prevent the select menu from closing to inspect the CSS! Going a little bit crazy.

#mySelectDiv {
  max-width: 300px;
  padding: 1rem;
}

option:hover {
  background-color: yellow;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

<div class="my-3" id="mySelectDiv">
  <select class="custom-select" id="myCustomSelect">
    <option selected>Open this select menu</option>
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
  </select>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+" crossorigin="anonymous"></script>


Solution

  • My recommendation is not to style it. For real.


    My second recommendation, if you don't take the first, would be to use a battle-tested select plugin, which already handles accessibility for you and has some decent options for styling the DOM elements. Under the hood, none of them use <select>, but generic (and style-able) DOM elements.


    Making your own is not that hard, but far from ideal, because selects (or dropdowns) are some of the trickiest UI components. For example, the .dropdown-menu is expected to overflow containers with overflow: hidden in most cases, as nobody wants a sudden scrollbar on such a container when you open a dropdown inside it. That's where it gets really tricky.

    For what it's worth, here's a "custom" solution:

    $('.dropdown-menu a').click(e => {
      $('.dropdown-item', e.target.closest('.dropdown')).removeClass('active');
      mySelect.value = e.target.innerText
      $(e.target).addClass('active')
      mySelect.focus()
    })
    #mySelect {
      background-color: #fff !important;
      margin-right: -1.5rem;
      padding-right: 1.5rem;
    }
    #mySelect:focus {
      border-color: #6b37c4;
      box-shadow: 0 0 0 0.2rem rgb(107 35 196 / 25%);
    }
    
    .dropdown-toggle {
      display: flex;
      align-items: center;
    }
    .dropdown .dropdown-menu {
      box-shadow: 0 1px 5px 0 rgb(0 0 0 / 7%), 0 2px 2px 0 rgb(0 0 0 /5%), 0 3px 1px -2px rgb(0 0 0 / 4%);
      border: 1px solid rgb(0 0 0 / 7%);
    }
    .dropdown-menu .dropdown-item:hover,
    .dropdown-menu .dropdown-item:active,
    .dropdown-menu .dropdown-item:focus {
      background-color: rgb(107 35 196 / 10%);
      color: black;
    }
    .dropdown-menu .dropdown-item.active {
      background-color: #6b37c4;
      color: white;
    }
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    
    <div style="max-width: 200px">
      <div class="m-3 position-relative dropdown">
        <div class="dropdown-toggle" data-toggle="dropdown">
          <input readonly value="" class="form-control" placeholder="Open this select menu" id="mySelect" />
        </div>
        <div class="dropdown-menu w-100">
          <a class="dropdown-item" href="#">1</a>
          <a class="dropdown-item" href="#">2</a>
          <a class="dropdown-item" href="#">3</a>
        </div>
      </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>

    It's meant as a proof of concept. Feel free to test it on all browsers/OS combinations and/or improve it, but don't count on me to update it for edge-cases.

    If you do go the custom route here's a few to-do's:

    • open/close using keyboard navigation
    • add appropriate role and aria attributes to its elements
    • make sure it renders decently on all mobile device types (ios, android). Use actual devices (or browserstack), not emulators. On emulators it will probably behave as expected.