What does Bootstrap datepicker refer to?
It depends on who is writing. Sometimes it means bootstrap-datepicker, the jQuery plugin the uxsolutions organization maintains on GitHub. Other times it means any picker styled to fit Bootstrap, whatever engine runs underneath.
The job is the same either way. A calendar opens from a text input, and the chosen date goes back into the field in a set format.
Pages that rank for the term mix both meanings, so two tutorials with the same title can ask for completely different scripts. The documentation pages that borrow the name don’t agree on what it is either.
- Older jQuery-era themes mean the uxsolutions plugin, started with $(‘.datepicker’).datepicker()
- Themesberg Volt uses Vanilla JS Datepicker instead, started with new Datepicker(el, { buttonClass: ‘btn’ })
- Argon Dashboard from Creative Tim runs Flatpickr, loaded from flatpickr.min.js
- CoreUI and MDB ship their own components, driven by data-coreui-toggle=”date-picker” and the Datetimepicker class in mdb-ui-kit
Copy a snippet without checking which engine it targets and the first error you hit is a missing function.
The Bootstrap framework itself ships no date component. Its 5.3 component list runs from accordion to tooltips without one.
The closest built-in option is a native date input styled with .form-control. The browser draws the calendar, so format, language and week start stay under the browser’s control.
Which Bootstrap datepicker should you use with Bootstrap 5?
On a new Bootstrap 5 build I’d go with a jQuery-free picker. Tempus Dominus covers date and time, and Vanilla JS Datepicker covers date only. The uxsolutions plugin earns its place on pages where jQuery already runs.
According to the official migration notes, Bootstrap 5.0 dropped jQuery and moved from Popper 1 to Popper 2. The uxsolutions plugin stayed on jQuery. Its package lists jQuery as a dependency, and the range in 1.10.1 runs from 3.4.0 up to, but not including, 4.0.0.
| Picker | jQuery | Bootstrap styling | Install | License |
|---|
| bootstrap-datepicker 1.10.1 | Required (npm dependency, jQuery 3.4 to 3.x) | Stylesheets for Bootstrap 2 and 3, plus standalone builds | npm, cdnjs, jsDelivr | Apache-2.0 |
| Tempus Dominus 6.10.4 | Not required (optional jQuery provider) | Bootstrap not required, Popper 2 required | npm, jsDelivr, NuGet | MIT |
| Vanilla JS Datepicker 1.3.4 | Not required | Ready-made CSS and Sass files for Bootstrap 5 and Bootstrap 4 | npm, jsDelivr | MIT |
| Flatpickr 4.6.13 | Not required | Own themes, not tied to Bootstrap | npm, cdnjs | MIT |
Maintenance status of bootstrap-datepicker
The uxsolutions repository on GitHub shows 789 open issues and 96 open pull requests (October 2026). Version 1.10.1, published in September 2025, is still the Latest release there and on npm. That backlog doesn’t settle much on its own. Flatpickr sits at 725 open issues and 135 open pull requests on the same date, and its latest npm release, 4.6.13, dates from April 2022. Vanilla JS Datepicker’s latest, 1.3.4, is from August 2023.
The release notes tell you more. The 1.10.1 notes include a pull request for the jQuery advisory CVE-2019-11358 (jQuery below 3.4.0), so load a current 3.x build instead of whatever your theme bundles.
Tempus Dominus has its own catch. Its README says the author is moving on to other projects and that new issues need to be sponsored, which counts against it if you expect free support. Its latest release, 6.10.4, came out in May 2025.
Choosing for Bootstrap 5
jQuery still runs on 64.4% of all websites, and on 85.5% of those with a known JavaScript library (W3Techs, 28 October 2026). So the jQuery plugin remains a fair pick when the library is already loaded, and with Bootstrap 3 or 4 on the page it’s the obvious one.
A new Bootstrap 5 page that needs date and time should get Tempus Dominus 6.10.4. Load Popper first and bring an icon font, since it defaults to Font Awesome 6.
For date only, Vanilla JS Datepicker 1.3.4 is a from-scratch remake of bootstrap-datepicker with similar usability and no dependencies. If the look doesn’t have to match Bootstrap at all, Flatpickr does the job.
I wouldn’t add jQuery to a page just for a date field, and size doesn’t change that. The plugin’s minified file is about 33.9 kB in the 1.10.1 package listing on jsDelivr, with jQuery loading on top of it. Vanilla JS Datepicker’s README gives 35 kB minified and 11 kB gzipped, and nothing else to load.
The older eonasdan/bootstrap-datetimepicker 4.17.49 is one to skip. It still requires jQuery 1.9.1 or newer and Moment.js 2.10.5 or newer, per Packagist, and Tempus Dominus replaced it.
How to add Bootstrap datepicker to an input field
Setup for the uxsolutions plugin follows the usual jQuery plugin order. Stylesheet first, then jQuery, then the plugin script, and after that a datepicker() call on an input.
- Add the plugin stylesheet to the head.
- Load jQuery 3.x before any script that depends on it. The package’s dependency range stops below jQuery 4 (4.0.0 shipped in January 2026), so use the latest 3.x release, 3.7.1.
- Load the plugin script after jQuery.
- Add a text input with the form-control class and initialize it.
Install the files
With npm it’s npm install bootstrap-datepicker, and jQuery gets installed separately. cdnjs is hosted by Cloudflare, though the README warns that a new version can take a few hours to appear there.
jsDelivr serves the npm package, so its version tags match npm. The manual route is copying the dist folder from the GitHub repository.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-datepicker@1.10.1/dist/css/bootstrap-datepicker.standalone.min.css">
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap-datepicker@1.10.1/dist/js/bootstrap-datepicker.min.js"></script>
In dist/css, the files with no suffix target Bootstrap 2 and the ones with a 3 suffix target Bootstrap 3. Standalone variants of both drop the dependency on Bootstrap’s own CSS.
Nothing is labeled for Bootstrap 4 or 5. On those versions, start with the standalone build and check the popup against your theme.
Add the input markup
The simplest markup is a text input with the .form-control class. Focusing it by click or tab opens the picker.
Build the field with standard Bootstrap form markup and give it an id, so a label can point at it later.
The plugin’s docs show an icon variant built on .input-group-addon, which is Bootstrap 3 markup. Bootstrap 5 dropped .input-group-append and .input-group-prepend, so .input-group-text now sits directly inside the group.
Use a label as the icon wrapper, with a calendar glyph from Bootstrap Icons inside it. A click on the label focuses the input, and focus opens the picker.
<div class="input-group">
<input type="text" class="form-control" id="start-date" placeholder="dd/mm/yyyy">
<label class="input-group-text" for="start-date"><i class="bi bi-calendar3"></i></label>
</div>
Initialize the picker
You can skip JavaScript entirely by adding data-provide=”datepicker” to the input and setting options through data-date-* attributes.
<input type="text" class="form-control" data-provide="datepicker" data-date-autoclose="true" data-date-format="dd/mm/yyyy">
The other way is to select the input and call datepicker() with an options object. I prefer this one, since the options sit next to the rest of the page logic.
$('#start-date').datepicker({
autoclose: true,
format: 'dd/mm/yyyy'
});
The data API can be switched off with $(document).off(‘.datepicker.data-api’), the same way as other Bootstrap plugins, per the docs.
Initializing on a plain div gives an inline picker that stays open. Arrow-key navigation does not work in that mode, according to the options documentation.
Bootstrap datepicker options and their defaults
Options go into an object passed to datepicker(), or into data attributes. Every one has a default, so an unconfigured picker works. The docs list more than 40, and most pages only touch a handful.
The data attribute for an option is its name in lowercase dashes, prefixed with data-date-. So startDate becomes data-date-start-date, and daysOfWeekDisabled becomes data-date-days-of-week-disabled.
The defaults you’ll run into first:
- format is mm/dd/yyyy
- autoclose is false, so the popup stays open after a pick
- weekStart is 0, which is Sunday
- todayBtn is false (true only moves the view to today, “linked” also selects it)
- clearBtn is false
- startView is 0, the days view of the current month
To change a default for every picker on the page, assign it on $.fn.datepicker.defaults before initializing.
One default is disputed inside the official docs. The todayHighlight entry says false, while the quick-reference table on the same page says true.
The 1.10.1 release notes list a pull request about a wrong todayHighlight row in the defaults table, and the docs source on GitHub now says false, yet the readthedocs page, checked in October 2026, still shows true. Set todayHighlight explicitly and the question never comes up.
Setting the date format and language
The format option controls the string written into the input. Month names, weekday names and the week start come from the language option.
Format tokens and ISO dates
A format string combines the tokens below, and the default is mm/dd/yyyy.
| Token | Output | Example |
|---|
| d, dd | Day of month, without and with leading zero | 5, 05 |
| D, DD | Weekday, abbreviated and full | Mon, Monday |
| m, mm | Month number, without and with leading zero | 7, 07 |
| M, MM | Month name, abbreviated and full | Jan, January |
| yy, yyyy | Year, 2 and 4 digits | 12, 2012 |
For server-side parsing, yyyy-mm-dd matches the ISO 8601 date format and sorts correctly as plain text.
When tokens fall short, format accepts an object with toDisplay and toValue functions. The docs example converts in both directions: its toDisplay shifts the date back seven days and returns an ISO string, and its toValue shifts it forward again. A code comment there mentions storing UTC while the interface shows local dates.
Parsing has a couple of traps. forceParse (default true) rewrites an invalid typed date into a valid one when the picker closes. And two-digit years are read literally unless assumeNearbyYear is on, so 5/1/15 means year 15, not 2015.
Language and locale files
Locale files sit in dist/locales (bootstrap-datepicker.de.min.js in 1.10.1) and load after the main plugin script. A full code such as de-DE falls back to de, and an unknown code falls back to English.
<script src="https://cdn.jsdelivr.net/npm/bootstrap-datepicker@1.10.1/dist/locales/bootstrap-datepicker.de.min.js" charset="UTF-8"></script>
$('#start-date').datepicker({
language: 'de',
format: 'dd.mm.yyyy'
});
If characters render wrong, the browser is reading the locale file with a non-Unicode encoding. The docs fix it with charset=”UTF-8″ on the script tag, as shown above.
Month and weekday names also land in the input value and go to the server on submit. A format with MM under a German locale sends German month names.
Locale files carry their own default format, and the changelogs record per-locale format fixes (Romanian uses dd/mm/yyyy). Set format explicitly so the output never depends on which locale file loaded.
A missing language can be added through $.fn.datepicker.dates before calling datepicker(), with day names, month names, today, clear, format and weekStart. Right-to-left languages add rtl: true.
Restricting dates and building a date range
startDate and endDate set the selectable window. daysOfWeekDisabled and datesDisabled remove single days, and beforeShowDay handles anything rule-based. A range uses two inputs inside an input-daterange container, which links their pickers.
Setting the selectable window
startDate and endDate accept a Date object, a string that parses with the active format, or a relative value such as “-1d” or “+6m +1y”. Valid units are d, w, m and y, and “0” means today.
The aliases yesterday, today and tomorrow save typing. Because strings must parse with the active format, changing format means rewriting any absolute date strings.
$('#arrival').datepicker({
startDate: '+1d',
endDate: '+6m'
});
That opens tomorrow through six months out, a common booking window.
Disabling weekends and specific dates
For weekends, daysOfWeekDisabled takes 0 for Sunday and 6 for Saturday, so ‘0,6’ or [0,6] blocks both. datesDisabled wants one date string or an array of them, written in the active format.
beforeShowDay is a function that receives each date and returns a Boolean, a CSS class string, or an object with enabled, classes, tooltip and content.
$('#arrival').datepicker({
format: 'dd/mm/yyyy',
daysOfWeekDisabled: [0, 6],
datesDisabled: ['24/12/2026', '25/12/2026'],
beforeShowDay: function (date) {
if (date.getDate() === 1) {
return { enabled: false, tooltip: 'Closed on the 1st' };
}
}
});
Returning nothing leaves a date untouched, so the function above only affects the first of each month.
Since 1.7.0, the data-date-dates-disabled attribute accepts a comma-separated list. Older copies need the JavaScript form for more than one date.
Linking two inputs as a range
Put two inputs inside a container with the input-daterange class, then call datepicker() on the container. Each input gets its own picker, and the markup docs say the pickers are linked so a range can be selected.
<div class="input-group input-daterange">
<input type="text" class="form-control" placeholder="Check-in">
<span class="input-group-text">to</span>
<input type="text" class="form-control" placeholder="Check-out">
</div>
$('.input-daterange').datepicker({
format: 'dd/mm/yyyy',
autoclose: true
});
Methods run on the inputs rather than the container, so clearing a range looks like $(‘.input-daterange input’).datepicker(‘clearDates’).
keepEmptyValues is false by default, which means picking one date fills the empty partner with the same value. A container that isn’t an input-daterange needs the two inputs passed through the inputs option.
Preset ranges such as last 7 days sit outside this plugin. Dan Grossman’s daterangepicker offers predefined ranges, a time picker and a single date mode, and its repository carries a Moment.js file.
Check its age before adopting it. The GitHub page shows a license notice dated 2012-2020 and no Issues tab, and the latest npm release, 3.1.0, is from May 2020.
Bootstrap datepicker events and methods
Events tell your code when the date or the calendar view changes, and methods let your code read, set or clear the date. Events attach with .on(‘changeDate’, fn), and methods run through .datepicker(‘methodName’, args).
Reacting to a date change
The Events page lists eight events, and 1.7.0 added a ninth, changeViewMode, that the page does not list.
changeDate fires when the date changes, and clearDate fires when it’s cleared, usually through the clear button. show and hide fire as the popup opens and closes. The view-movers are changeMonth, changeYear, changeDecade and changeCentury, which fire when the calendar moves but the date stays put.
Every handler receives an event object with date, dates and a format() helper. On a multidate picker, date is the latest pick and dates holds all of them.
$('#start-date')
.on('changeDate', function (e) {
$('#start-iso').val(e.format('yyyy-mm-dd'));
})
.on('clearDate', function () {
$('#start-iso').val('');
});
Bind both events. Pressing Enter on the already selected date deselects it and fires clearDate instead of changeDate, so a handler on changeDate alone keeps a stale value.
Passing the value on change usually means an Ajax request. Send the string from e.format(), not a Date object, so no timezone shift reaches the server.
Since 1.7.0, initialization no longer fires changeDate. Set any starting value in your own code.
Reading and setting dates from code
| Task | Call | Note |
|---|
| Read the date as a local Date | datepicker(‘getDate’) | Reads the first picker in the selection, and the latest date on a multidate picker |
| Read the raw UTC date | datepicker(‘getUTCDate’) | Returned as stored, with no conversion to local time |
| Set the date | datepicker(‘setDate’, new Date(2026, 9, 22)) | Local Date, converted to UTC internally |
| Clear the date | datepicker(‘clearDates’) | Takes no arguments |
| Move the limits later | setStartDate, setEndDate | Omit the argument to remove the limit |
setDate treats its argument as local, while getUTCDate hands back the internal object untouched. Mix the two and the result can differ by a day, depending on the browser’s offset.
The docs have a gap here. The Markup page’s hidden-field example calls getFormattedDate, but the Methods page has no entry for it. Inside an event handler, e.format() is the documented route to a formatted string.
Methods are chainable since 1.4.0. destroy strips the events, internal objects and added HTML, and remove stays as its alias after the 1.6.0 rename.
Why is Bootstrap datepicker not working?
Scripts loaded in the wrong order, or twice, cause most of it. The rest comes from another library claiming the .datepicker class, the wrong plugin name, CSS and JS from different versions, or a modal that buries or detaches the popup.
| Symptom | Cause | Fix |
|---|
| $(…).datepicker is not a function | Plugin file missing, loaded before jQuery, or a second jQuery load replaced the first | Load jQuery once, then the plugin, and check the Network tab for 404s |
| Another calendar appears, or options are ignored | A second library registers datepicker too, such as jQuery UI Datepicker or a UI kit | Call $.fn.datepicker.noConflict() and use the alias |
| $(…).datetimepicker is not a function | The call uses the wrong plugin name | Call datepicker, or install the separate datetimepicker plugin if time is needed |
| Popup unstyled or misplaced | CSS and JS from different versions, or a Bootstrap 3 stylesheet on a newer Bootstrap | Match the version numbers and try the standalone stylesheet |
| Popup behind, detached from or scrolling away from a modal | Stacking and container rules | Set the container option to the modal element |
The noConflict call comes from the plugin’s own docs. It returns datepicker to whatever was assigned before, so load the other library first and run it right after the plugin.
var datepicker = $.fn.datepicker.noConflict();
$.fn.bootstrapDP = datepicker;
$('#start-date').bootstrapDP({ autoclose: true });
Inside a Bootstrap modal
A Bootstrap modal uses position: fixed, and the official 5.3 docs advise keeping modal markup at the top level of the page. By default the picker’s popup is appended to body, outside the modal.
If the popup lands behind the modal, check your version first. Versions before 1.3.1 stopped the z-index calculation at the first ancestor, so updating usually fixes it.
Drifting on scroll has a different cause. A popup appended to body is positioned against the page, so it can stay put while the modal scrolls. The container option, added in 1.4.0, fixes that.
Still sitting too low? The popup z-index is the highest value among the input and its ancestors plus zIndexOffset, which defaults to 10. Raise the offset when a custom stacking context sits above.
$('#start-date').datepicker({
container: '#bookingModal',
autoclose: true
});
Append to the .modal element itself, not .modal-body. A scrollable modal body clips whatever overflows it.
Pickers that submit the form
A button inside a form submits it by default, so a calendar-icon button needs type=”button”. Pressing Enter while the popup is closed submits the form as usual, per the keyboard docs. While the popup is open, Enter toggles the focused date instead.
None of this is a plugin bug. It’s standard form behavior that shows up once a picker adds buttons and key handling.
When a datepicker plugin is the wrong choice
Skip the plugin when the form needs one date from a user who already knows it. A native date input does that job without a script.
Native date input versus the plugin
MDN rates the date input Baseline widely available (newly available since April 2021, widely since October 2023), and its value always arrives as yyyy-mm-dd, whatever the display locale.
Can I Use puts global support at 90.36% full plus 6.88% partial, 97.24% in total (data updated 22 October 2026).
The two sources read differently because they score different things. Can I Use rates date, time, datetime-local, month and week as one feature, which is the likely reason desktop Firefox and Safari show as partial.
| Need | Native date input | bootstrap-datepicker |
|---|
| Fixed display such as dd.mm.yyyy | Display follows the browser locale, value stays yyyy-mm-dd | format option |
| Block weekends or listed dates | min, max and step only | daysOfWeekDisabled, datesDisabled, beforeShowDay |
| Linked start and end dates | Two inputs and your own script | input-daterange container |
| One known date, no special rules | Fits as is | Adds jQuery plus CSS and JS files |
step counts in days, so with min set to a Saturday, step=”7″ makes only Saturdays selectable, but nothing more irregular than that.
Accessibility gaps in the plugin’s popup
Treat the popup as untested for assistive technology until someone has tested it.
The W3C ARIA Authoring Practices Guide shows a date picker dialog: a text input, a button that opens a modal dialog, and a calendar built as a grid. The page, last updated 12 August 2025, says its code is not meant for production and needs testing with assistive technologies.
That example ties a format hint to the input with aria-describedby and gives the dialog a role with aria-modal and a label. The grid supports arrow keys, Home, End, Page Up and Page Down, with Shift for year changes, and the button name changes to include the chosen date.
The bootstrap-datepicker docs describe a lot less.
- Arrow keys move by day and week, Shift by month, Ctrl by year
- Enter toggles the focused date, and Escape clears the focused date and hides and re-shows the popup, which the docs say is necessary before editing the value by hand
- No Home, End or Page keys are documented
- The keyboard, markup and options pages mention no ARIA roles or attributes
Whether the popup exposes equivalent ARIA semantics is not documented, so test it with a screen reader before shipping.
Whatever the picker, keep a labeled text field that accepts typing, with a visible format hint. That does more for accessible forms than the calendar does, and it is the part of the APG example that needs no script.
Bootstrap datepicker FAQ
How do you select more than one date?
Set multidate to true for unlimited picks, or to a number to cap them. Once the cap is exceeded, the oldest date drops off the list.
The input holds the dates joined by multidateSeparator, a comma by default. Avoid a separator that appears inside the format, such as a hyphen with yyyy-mm-dd.
Can the calendar show only months or only years?
Yes. Set minViewMode to “months” or “years” and pair it with a matching format such as mm/yyyy.
The plugin fills in what the user cannot pick: the day becomes the 1st for months, and the month becomes January for years.
How do you stop the popup from opening when the input gets focus?
Set showOnFocus to false, then open the popup yourself with the show method, for example from a button click.
A separate option, enableOnReadonly, defaults to true. Switching it to false keeps the popup closed on readonly inputs.
How do you keep the phone keyboard from opening with the calendar?
Set disableTouchKeyboard to true. No keyboard then shows on mobile devices, so the calendar becomes the only way to enter a date on touch screens.
The option arrived in 1.4.0, so older copies ignore it.
Can the previous and next arrows be replaced with icons?
Yes. The templates option takes leftArrow and rightArrow strings, and each can hold plain text or HTML.
The defaults are double angle quotation marks. An icon font tag from Font Awesome or Bootstrap Icons works in their place.
How do you highlight weekends without disabling them?
Pass ‘0,6’ or [0,6] to daysOfWeekHighlighted, where 0 is Sunday and 6 is Saturday. Unlike daysOfWeekDisabled, the days stay selectable.
The setDaysOfWeekHighlighted method changes the list after initialization.
Migrating Off jQuery Without Breaking Date Fields
Replacing the uxsolutions Bootstrap datepicker with a jQuery-free picker means rewriting the calls around the widget, not the widget itself. Every .on(‘changeDate’) handler, .datepicker(‘method’) call and input-daterange block is written against jQuery and needs new code.
Begin with a list of every picker call and handler, since that sizes the job. Then store dates as yyyy-mm-dd strings. A native date input also submits yyyy-mm-dd, so saved values survive whichever picker replaces the plugin. After that, swap one form at a time with jQuery still loaded.
The cost is a stretch where two pickers live on one site, and each needs its own check of locale output and keyboard behavior.
Verified 28 October 2026: 1.10.1 is the latest tagged release. A release with Bootstrap 5 stylesheets would remove one reason to move, though jQuery would remain a dependency.