What Is a Bootstrap Search Box?
Bootstrap doesn’t ship a search component. Nothing in the Bootstrap framework carries that name. The box is ordinary form markup that Bootstrap styles, and it needs no custom CSS.
Query handling, results display, filtering and autocomplete all sit outside the markup, and Bootstrap has no JavaScript plugin for any of them.
Results come from somewhere else. A form action can point at a backend script, or JavaScript can filter content that’s already on the page. Hosted search services are the other route.
Directory and service sites often give the box a larger spot of its own.
How Do You Write the HTML for a Bootstrap Search Box?
You need a form, an input with type=”search” and a submit button. Bootstrap’s form-control and btn classes style them, and d-flex on the form keeps the two on one row.
For the query to reach the server, the form needs an action and method=”get”, and the input needs a name. Skip the name and the browser submits nothing for that field.
With method=”get”, the query lands in the URL as ?q=term, which also makes result pages linkable.
Standalone input and button with d-flex
This follows the form example in the Bootstrap 5.3 navbar documentation, with an action and a name added.
<form class="d-flex" role="search" action="/search" method="get">
<input class="form-control me-2" type="search" name="q" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
The role=”search” attribute marks the form as a search landmark. me-2 is the gap between input and button. As for btn-outline-success, that’s only the button style, and any btn variant can replace it.
Bootstrap’s input styling makes the field full width, pads it, and adds a focus state. Drop d-flex and the button falls below the input, because form-control is a block-level element.
Input group version
An input group joins the field and the button into one block with shared edges.
<form action="/search" method="get" role="search">
<div class="input-group">
<input type="search" name="q" class="form-control" placeholder="Search" aria-label="Search">
<button class="btn btn-primary" type="submit">Search</button>
</div>
</form>
Bootstrap’s input group documentation says labels belong outside the group. A visible label goes above it, and aria-label covers the input when no label shows.
The markup is plain HTML, so any server-side template renders it unchanged.
My habit is the input group for anything with an icon or a spot in a form column, and plain d-flex inside a navbar.
How to Add a Bootstrap Search Box to a Navbar, Modal or Offcanvas Panel
The navbar is the default home, and the form goes inside .navbar-collapse. Modals take it in .modal-body and offcanvas panels in .offcanvas-body, which suits overlay search and phone layouts.
| Placement | Container class | Opens with | Best for |
|---|
| Navbar | .navbar-collapse | .navbar-toggler below the expand breakpoint | Persistent site header |
| Modal | .modal-body | Button with data-bs-toggle=”modal” | Full overlay search |
| Offcanvas | .offcanvas-body | Button with data-bs-toggle=”offcanvas” | Side panel on phones |
Navbar
Bootstrap’s navbar component collapses responsively only when .navbar carries an expand class such as .navbar-expand-lg. The .navbar-collapse wrapper holds whatever hides behind the toggler (Bootstrap 5.3 documentation).
With the lg suffix, the collapse happens below 992px.
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="/">Brand</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navSearch" aria-controls="navSearch" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navSearch">
<form class="d-flex ms-auto" role="search" action="/search">
<input class="form-control me-2" type="search" name="q" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
The usual mistake is putting the form outside .navbar-collapse. It never hides, so on a phone it sits in the row with the brand and the toggler.
Modal and offcanvas
In a Bootstrap modal the autofocus attribute has no effect, so listen for shown.bs.modal and call focus() on the input yourself (Bootstrap documentation).
const modal = document.getElementById('searchModal')
const input = document.getElementById('modalSearch')
modal.addEventListener('shown.bs.modal', () => input.focus())
Offcanvas has no default placement, so add .offcanvas-start, .offcanvas-end, .offcanvas-top or .offcanvas-bottom.
Responsive classes such as .offcanvas-lg arrived in Bootstrap 5.2.0. Below the lg breakpoint the content slides in as a panel, and above it the same markup renders as normal page content.
Outside those containers, the form goes in a .container and takes a column class such as .col-md-6.
How Do You Control the Width and Size of a Bootstrap Search Box?
Grid columns and width utilities handle width, with a max-width cap when you need one. Height comes from the form sizing classes.
In practice, col-* classes on a wrapper set the width relative to the row, while w-25, w-50, w-75, w-100 and w-auto set it relative to the parent. mw-100 caps the box at the parent width. Height is the job of form-control-lg and form-control-sm.
Width and centering
The width utilities in Bootstrap’s own sizing documentation come in 25%, 50%, 75%, 100% and auto.
To center the box, wrap it in a row with justify-content-center and a column such as col-md-6, or give the form w-50 and mx-auto. The grid system handles the width, so the input needs no extra class.
For a full-width bar, set w-100 on the form or the input group and place it inside a container-fluid.
Size classes
| Class | Goes on | Result |
|---|
| form-control-lg | The input | Taller field, larger text |
| form-control-sm | The input | Shorter field, smaller text |
| input-group-lg | .input-group | Input and button grow together |
| input-group-sm | .input-group | Input and button shrink together |
Add the size class to the .input-group itself and the contents resize with it. Repeating form-control-lg on each child is unnecessary.
Showing the box at one breakpoint only
Display utilities let you hide the full box below a breakpoint and show it above.
Bootstrap defines six default breakpoints, from extra small (under 576px) to xxl (1400px and up), per its breakpoints documentation.
On the small side, put d-lg-none on a compact button that opens a modal or offcanvas panel. From lg up, the full form gets d-none d-lg-flex.
Use d-lg-flex, not d-lg-block, so the form keeps its flex layout. The swap follows standard responsive design practice: a small trigger on phones, the full field where there is room.
Adding a Search Icon and Styling the Box
The icon goes in an .input-group-text addon next to the input, using bi-search from Bootstrap Icons or the matching class from Font Awesome.
Bootstrap Icons offers the search glyph both as a downloadable SVG and as an icon-font class (bi bi-search), per its icon page.
<div class="input-group">
<span class="input-group-text" id="search-addon"><i class="bi bi-search"></i></span>
<input type="search" class="form-control" placeholder="Search" aria-label="Search" aria-describedby="search-addon">
</div>
I’d take inline SVG over the icon font when the search icon is the only icon on the page. One glyph should not cost a font download.
For shape, .rounded-pill reads $border-radius-pill, which defaults to 50rem in Bootstrap 5.3. On a standalone input that works directly.
A pill-shaped box with an attached icon or button is a Sass job. Set $input-border-radius to 50rem, then check the joined edge in the browser.
For colors, $input-border-color sets the resting border and $input-focus-border-color handles focus. The focus default is tint-color($component-active-bg, 50%), and $component-active-bg is $primary.
@import "bootstrap/scss/functions";
$input-border-radius: 50rem;
$input-focus-border-color: #198754;
@import "bootstrap/scss/bootstrap";
Any replacement color needs enough color contrast against the page background, or the focus state disappears for low-vision users.
These variables change every form control on the site, not only the search box. Scope the change with a custom class when other forms must keep the defaults.
How to Make a Bootstrap Search Box Accessible
The input’s name is where most search boxes fail. The rest is a unique label when a page holds more than one search region, a visible focus state, and real text inside any icon-only button.
Name the input
WCAG 2.2 success criterion 4.1.2 (Level A) requires a programmatically determinable name for every interface component, and the W3C’s Understanding document allows that name to be invisible.
Two W3C examples show the range. The ARIA Authoring Practices search example uses aria-label alone. WCAG technique H44 goes the other way and pairs the input with a visible label element.
For a Bootstrap search box, a label hidden with visually-hidden keeps the compact look and still gives screen readers a real label element. The placeholder never replaces it, because MDN calls the placeholder a weaker way to explain a field.
<label for="site-q" class="visually-hidden">Search the site</label>
<input id="site-q" class="form-control" type="search" name="q" placeholder="Search">
The same naming rules run through the wider guidance on accessible forms, and the search field is no exception.
Two search boxes on one page
A navbar box plus a modal or in-page filter puts two search regions on one page, and each needs its own name.
The ARIA authoring guidance asks for a unique label on every search landmark when a page has more than one.
On a form with role=”search”, add a distinct aria-label, such as “Site search” and “Catalog search”. The native search element carries the landmark without the role attribute.
The search element became Baseline newly available on 2023-10-13, with support from Chrome 118, Firefox 118, Edge 118 and Safari 17, and the web-features project set 2026-04-13 as its Widely available date (web-features project). Bootstrap’s own navbar examples still use role=”search”, so keep that attribute when the site must serve older browsers.
Icon-only buttons and focus
An icon-only submit button has no name until text sits inside it. Bootstrap’s badge examples use the same fix, hidden text in a span with visually-hidden.
<button class="btn btn-primary" type="submit">
<i class="bi bi-search" aria-hidden="true"></i>
<span class="visually-hidden">Search</span>
</button>
WCAG 2.2 criterion 2.4.7 (Focus Visible) requires a visible keyboard focus indicator. Bootstrap draws the form-control focus state with $input-focus-border-color and $input-focus-box-shadow rather than the browser outline, so custom CSS that sets box-shadow: none removes it.
An easy check is to press Tab to the field, then to the button. If you can’t see where focus sits, the style is gone.
What Changed in Bootstrap 5 Search Box Markup Compared With Bootstrap 4?
Moving a search box from Bootstrap 4 to 5 means swapping a handful of classes and attributes.
| Bootstrap 4 | Bootstrap 5 | Where it shows up |
|---|
| form-inline | d-flex on the form | One-row layout |
| input-group-append, input-group-prepend | Button or addon as a direct child of .input-group | Attached search button |
| mr-2, ml-2 | me-2, ms-2 | Gap between input and button |
| data-toggle, data-target | data-bs-toggle, data-bs-target | Navbar toggler, modal trigger |
| sr-only | visually-hidden | Hidden label text |
Three of those are plain renames. form-inline and the append and prepend wrappers are the ones that need markup changes.
Bootstrap’s v5 migration guide points inline forms toward the grid, while the navbar documentation uses d-flex. For a single input and button, d-flex is the lighter option.
Paste a Bootstrap 4 box into a Bootstrap 5 page and it loses its one-row layout and its toggles, because form-inline no longer exists and the plugins respond only to data-bs-* attributes.
The migration guide also records that jQuery is gone, so any jQuery code bundled with a snippet runs only if you load the library yourself. Labels gain a requirement too. v5 expects the form-label class, which the Bootstrap form components cover in full.
How to Make a Bootstrap Search Box Actually Search
Match the method to where the content lives. A JavaScript filter works when the content is already on the page. Anything in a database needs a form submit to a server, and a documentation site can get by with a hosted index.
Which search method fits the project
| Method | Needs a server | Best fit | Main limit |
|---|
| JavaScript filter | No | Tables, lists and card grids already on the page | Searches only what is rendered |
| datalist suggestions | No | A short, fixed list of terms | Browser draws the list, no styling |
| Form submit to a server | Yes | Database or catalog content | Page reload unless fetched with script |
| Hosted index | No (hosted) | Documentation, site-wide search | Eligibility, ads or fees by service |
Bootstrap’s own documentation uses Algolia DocSearch, according to the Bootstrap README. DocSearch is free for developer documentation and technical blogs, so a store or portfolio site does not qualify.
In the end the content decides which method you use.
Build a live filter in plain JavaScript
- Give each searchable element a shared hook such as data-filter-item, and give the input an id.
- Listen for the input event, which fires on every keystroke.
- Lowercase the query and each item’s text, then compare with includes().
- Toggle Bootstrap’s d-none class on items that do not match.
- Show a no-results message when every item is hidden.
const input = document.getElementById('filter-q')
const items = document.querySelectorAll('[data-filter-item]')
input.addEventListener('input', () => {
const q = input.value.trim().toLowerCase()
items.forEach(el => {
el.classList.toggle('d-none', !el.textContent.toLowerCase().includes(q))
})
})
A handful of lines of JavaScript does the work, and Bootstrap’s d-none class does the hiding.
A form holding one text field submits on Enter and reloads the page. A JavaScript-only filter needs neither a form nor a submit button, so dropping the form is the simplest fix.
Autocomplete suggestions
With datalist, you link the input to it through the list attribute and the browser draws the suggestions.
<input class="form-control" type="search" name="q" list="suggestions" aria-label="Search">
<datalist id="suggestions">
<option value="Buttons">
<option value="Modals">
</datalist>
MDN says the values are suggestions, not requirements. It also warns that some screen reader and browser pairs, NVDA with Firefox among them, do not announce the popup contents, and that the list cannot be styled for high-contrast mode.
A menu fed by script gives full styling control. With a Bootstrap dropdown, the keyboard and ARIA behavior of a combobox is yours to build.
When the list is too long to ship in the page, either approach can talk to a server through the Fetch API. fetch(‘/suggest?q=’ + encodeURIComponent(q)) returns JSON to render.
When a Bootstrap Search Box Is the Wrong Choice
A Bootstrap search box works until the content outgrows the page or users expect ranked results. Browser quirks in the search input can get in the way too.
Client-side filtering on large lists
Lighthouse warns when the body element has more than about 800 nodes and reports an error above about 1,400, according to Chrome’s documentation.
A filter only hides rows that already exist, so every row stays in the DOM. At seven elements per row, the warning threshold arrives at roughly 115 rows, before counting the rest of the page.
Past that range, send the query to a server or render only the visible page of results. Lighthouse’s own advice is to create DOM nodes only when they are needed.
Ranking, typo tolerance and facets
Bootstrap gives you an input and a button, and nothing about search quality. includes() returns matches in page order, not by relevance. Typos match nothing at all. Facets like category or price are extra work, with their own controls and logic.
When users expect those, a server-side or hosted engine does the work and the Bootstrap box stays as the front end.
Browser differences in the search input
MDN says browsers handle type=”search” differently from type=”text”. Chromium draws an x icon inside the field. Firefox draws none, because its clear-button layout still sits behind a preference that is off by default.
Escape clears a search field in Chrome, and Firefox 141 added the same behavior (Mozilla Bugzilla bug 1055085).
If a clear control belongs in the design, build the button yourself and check it across engines for cross-browser compatibility.
Hosted search services and their deadlines
As of October 2026, Google’s Custom Search JSON API is closed to new customers and retires on January 1, 2027 (Google’s Programmable Search Engine documentation).
On Programmable Search Engine, new engines cannot enable “Search the entire web”, and existing engines keep it until the same date. The free search element is ad-supported, and the ad-free version costs $5 per 1,000 queries.
A site that does not qualify for DocSearch can start on Algolia’s free plan, which includes 50,000 records and 10,000 search requests a month according to Algolia’s pricing page, so a large or busy site may need a paid plan.
Check these terms before wiring a Bootstrap box to either service.
A site that does not load Bootstrap anywhere else gains little from adding it for one input. A hand-written CSS search box does the same job with a few rules.
Bootstrap Search Box FAQ
How do I add a clear button to the search field?
Place a button with type=”button” after the input inside the input group. On click, set the input value to an empty string and call focus() on the field.
On a live filter, also dispatch an input event so the list resets.
Can I put a category dropdown next to the input?
Yes. Add a select with the form-select class as the first child of the input group, before the input.
Give it an aria-label such as “Category” and read its value on submit as a second query parameter.
How do I change the placeholder color?
Target the pseudo-element with a rule like .form-control::placeholder and set its color. In a Sass build, $input-placeholder-color does the same before the Bootstrap import.
Keep the result readable. A pale placeholder on a white field is hard to see.
Where can I find free Bootstrap search box templates?
Colorlib publishes free search form templates, and Bootsnipp and CodePen host community snippets.
Check the license on each one. Confirm the snippet targets Bootstrap 5 too, because many older snippets rely on classes that version removed.
What to Test Before Launching a Bootstrap Search Box
Before launch, check keyboard and screen reader access first, then whether a query actually reaches the results page, then the layout at narrow widths.
That order follows how many visitors a failure affects. A missing accessible name blocks every assistive technology user, a dropped query breaks every search, and a narrow-width fault hits one viewport.
The cost is time. Manual keyboard and screen reader passes run slower than a visual check, and they still come first.
A fuller web accessibility checklist carries the first pass beyond the search field to the rest of the page.