Bootstrap Select: Style Select Dropdowns in Bootstrap 5
A Bootstrap select is a native HTML <select> dropdown styled to match Bootstrap’s text inputs. It keeps everything the browser does well, such as keyboard support and the native picker on phones, and only changes how the closed box looks. This guide covers the class, sizes, placeholders, multiple selection, validation, floating labels, selects in input groups, changing the arrow and colors, reading the value with JavaScript, and what to do when you need a searchable select. Everything is for Bootstrap 5.3.
A styled select
<label for="country" class="form-label">Country</label>
<select class="form-select" id="country" name="country">
<option value="us">United States</option>
<option value="ca">Canada</option>
<option value="uk">United Kingdom</option>
</select>
.form-select gives the select Bootstrap’s border, padding, focus ring, and a custom arrow. It needs no JavaScript. Always pair it with a <label>, or an aria-label if there is no visible label.
.form-select is for <select> elements, and .form-control is for text inputs. Using .form-control on a select is a Bootstrap 4 habit and leaves the arrow unstyled.
A placeholder option
A select has no placeholder attribute. Add a first option with an empty value instead:
<select class="form-select" id="plan" name="plan" required>
<option value="" selected disabled>Choose a plan</option>
<option value="free">Free</option>
<option value="pro">Pro</option>
</select>
disabled stops people from picking it again, and with required, the form can’t be sent while it is still selected. To show the placeholder in a lighter color, gray it out until a real choice is made:
.form-select:has(option[value=""]:checked) { color: var(--bs-secondary-color); }
Sizes
<select class="form-select form-select-lg" aria-label="Large select">...</select>
<select class="form-select" aria-label="Default select">...</select>
<select class="form-select form-select-sm" aria-label="Small select">...</select>
The sizes match form-control-lg, form-control-sm, and the button sizes, so a select lines up with inputs and buttons next to it. For a narrower select, set a width with a grid column or a utility such as w-auto.
Multiple selection and visible rows
<select class="form-select" multiple size="4" aria-label="Skills" name="skills">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="react">React</option>
<option value="sass">Sass</option>
</select>
multiple lets people pick several options with Ctrl or Cmd, and size sets how many rows are visible. Many people don’t know the Ctrl-click trick, so for a short list, checkboxes are usually easier.
Option groups and disabled selects
<select class="form-select" aria-label="Time zone">
<optgroup label="Europe">
<option value="Europe/London">London</option>
<option value="Europe/Paris">Paris</option>
</optgroup>
<optgroup label="America">
<option value="America/New_York">New York</option>
</optgroup>
</select>
<select class="form-select" disabled aria-label="Region">
<option>Not available</option>
</select>
Validation
Bootstrap’s validation styles work on selects the same way as on inputs:
<form class="needs-validation" novalidate>
<label for="size" class="form-label">Size</label>
<select class="form-select" id="size" required>
<option value="" selected disabled>Choose a size</option>
<option>Small</option>
<option>Medium</option>
</select>
<div class="invalid-feedback">Please choose a size.</div>
</form>
The script that turns on these styles is in the Bootstrap forms guide. For server-side errors, add is-invalid to the select directly.
A select with a floating label
<div class="form-floating">
<select class="form-select" id="floating-plan" aria-label="Plan">
<option value="free" selected>Free</option>
<option value="pro">Pro</option>
</select>
<label for="floating-plan">Plan</label>
</div>
The label sits inside the box, above the selected value. Floating labels always look filled for selects, because a select always shows a value.
A select in an input group
<div class="input-group">
<label class="input-group-text" for="currency">Currency</label>
<select class="form-select" id="currency">
<option value="usd">USD</option>
<option value="eur">EUR</option>
</select>
<button class="btn btn-outline-secondary" type="button">Convert</button>
</div>
Change the arrow and colors
The arrow is a background image set by a CSS variable:
.form-select {
--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%232f55ff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
border-color: #c9d4ff;
border-radius: .75rem;
}
.form-select:focus {
border-color: #2f55ff;
box-shadow: 0 0 0 .25rem rgba(47, 85, 255, .25);
}
Change %232f55ff (an encoded #2f55ff) to recolor the arrow. In Sass, $form-select-indicator-color, $form-select-border-radius, and $form-select-focus-box-shadow set the defaults, and the focus color follows the primary color.
You can’t style the open list. The list of options is drawn by the browser and operating system, so its font, colors, and spacing mostly can’t be changed with CSS. That is why phones show their own picker. If you need a fully designed menu, use a Bootstrap dropdown for actions and links, or a select library for form values.
Read and set the value with JavaScript
const select = document.querySelector('#country')
select.addEventListener('change', () => {
console.log(select.value) // "ca"
console.log(select.options[select.selectedIndex].text) // "Canada"
})
select.value = 'uk' // select an option by its value
For a multiple select, read every chosen value with [...select.selectedOptions].map(o => o.value).
Searchable selects
Bootstrap has no searchable or tag-style select. For a long list such as countries, the options are:
- A native
<datalist>: an input with suggestions, built into the browser, with no library. - Tom Select: a small library with search, tags, and remote data, and a Bootstrap 5 theme.
- Choices.js: a similar library without jQuery.
The old “bootstrap-select” plugin was built for Bootstrap 3 and 4 and needs jQuery, so it’s a poor choice for new Bootstrap 5 projects.
<label for="city" class="form-label">City</label>
<input class="form-control" list="city-options" id="city" placeholder="Type to search">
<datalist id="city-options">
<option value="Amsterdam"><option value="Berlin"><option value="Lisbon">
</datalist>
FAQ
How do I style a select in Bootstrap 5?
Add the form-select class to the <select> element. It applies Bootstrap’s border, padding, focus ring, and a custom arrow. Use form-select-sm or form-select-lg to change its size.
How do I add a placeholder to a Bootstrap select?
Add a first option with an empty value, selected, and disabled, such as <option value="" selected disabled>Choose a plan</option>. Add required to the select so the form can’t be sent until a real option is chosen.
How do I change the arrow of a Bootstrap select?
Set the --bs-form-select-bg-img CSS variable on .form-select to a new SVG image. To change only its color, edit the stroke color in the default SVG, or set $form-select-indicator-color in Sass.
How do I make a searchable select in Bootstrap?
Bootstrap doesn’t include one. Use an input with a <datalist> for simple suggestions, or a library such as Tom Select, which has search, tags, and a Bootstrap 5 theme.
Why should I use form-select instead of form-control?
In Bootstrap 5, form-control is for text inputs and form-select is for <select> elements. Using form-control on a select leaves out the custom arrow and the right padding.
Try it in the builder
Make these changes visually with a live preview, then export clean Bootstrap Sass or CSS.
Open the Builder