---
layout: docs
title: Tailwind CSS JavaScript - Flowbite
description: Learn how to set up a Tailwind CSS project with the JavaScript from Flowbite and start working with the interactive UI components based on the Flowbite API and data attributes interface
group: getting-started
toc: true
requires_javascript: true

previous: Quickstart
previousLink: getting-started/quickstart/
next: TypeScript
nextLink: getting-started/typescript/
---

[JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) is one of the most popular programming languages in the world, basically powering the client side of nearly 98% percent of all websites alongside HTML and CSS. It is a high-level language which uses dynamic typing and supports features such as object orientation, first-class functions and the web based API allows you access to the DOM (Document Object Model).

Flowbite uses JavaScript to power the interactivity of the more complex UI components such as datepickers, dropdowns, and modals while also leveraging the utility classes from Tailwind CSS. 

There are two main ways you can use JavaScript to power the interactive UI components:

- use the data attributes interface and include the Flowbite JavaScript via NPM or CDN
- programmatically create instances of the UI components and call methods and attach events to elements

On this page you will learn how to leverage the Flowbite API to work with the interactivity part of the UI library and how you can customize the default behaviour of the UI components using JavaScript.

## Flowbite API

Flowbite is written in JavaScript with optional support for TypeScript and provides an extensive API for the interactive UI components that you use by creating new instances of the objects, setting them up with various options, calling methods such as to show or hide a component and even access a global instance manager to get access to the initialised objects.

Each component page on the documentation has a section called "JavaScript Behaviour" that documents how you can create and manage an object such as a Modal, Carousel, Dropdown, or any other interactive UI components that requires JavaScript to function.

Here is an extensive example on how you can work with the Modal component:

{{< code lang="javascript" icon="file" file="app.js" >}}
// set the modal menu element
const $targetEl = document.getElementById('modalEl');

// options with default values
const options = {
  placement: 'bottom-right',
  backdrop: 'dynamic',
  backdropClasses: 'bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-40',
  closable: true,
  onHide: () => {
      console.log('modal is hidden');
  },
  onShow: () => {
      console.log('modal is shown');
  },
  onToggle: () => {
      console.log('modal has been toggled');
  }
};
{{< /code >}}

Create a new Modal object based on the options above.

{{< code lang="javascript" icon="file" file="app.js" >}}
import { Modal } from 'flowbite';

/*
* $targetEl: required
* options: optional
*/
const modal = new Modal($targetEl, options);
{{< /code >}}

Use the `show` and `hide` methods to show and hide the modal component directly from JavaScript.

{{< code lang="javascript" icon="file" file="app.js" >}}
// show the modal
modal.show();

// hide the modal
modal.hide();
{{< /code >}}

Use the `toggle` method to toggle the visibility of the modal.

{{< code lang="javascript" icon="file" file="app.js" >}}
// toggle the modal
modal.toggle();
{{< /code >}}

Use the `isHidden` or `isVisible` method to check if the modal is visible or not.

{{< code lang="javascript" icon="file" file="app.js" >}}
// true if hidden
modal.isHidden();

// true if visible
modal.isVisible();
{{< /code >}}

Please take into consideration that for this example you also need to have the appropriate HTML markup available on the page where the JS is loaded:

{{< code lang="html" icon="file" file="index.html" >}}

<!-- Main modal -->
<div id="modalEl" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
    <div class="relative p-4 w-full max-w-2xl max-h-full">
        <!-- Modal content -->
        <div class="relative bg-neutral-primary-soft border border-default rounded-base shadow-sm p-4 md:p-6">
            <!-- Modal header -->
            <div class="flex items-center justify-between border-b border-default pb-4 md:pb-5">
                <h3 class="text-lg font-medium text-heading">
                    Terms of Service
                </h3>
                <button type="button" class="text-body bg-transparent hover:bg-neutral-tertiary hover:text-heading rounded-base text-sm w-9 h-9 ms-auto inline-flex justify-center items-center" data-modal-hide="modalEl">
                    <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18 17.94 6M18 18 6.06 6"/></svg>
                    <span class="sr-only">Close modal</span>
                </button>
            </div>
            <!-- Modal body -->
            <div class="space-y-4 md:space-y-6 py-4 md:py-6">
                <p class="leading-relaxed text-body">
                    With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.
                </p>
                <p class="leading-relaxed text-body">
                    The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.
                </p>
            </div>
            <!-- Modal footer -->
            <div class="flex items-center border-t border-default space-x-4 pt-4 md:pt-5">
                <button data-modal-hide="default-modal" type="button" class="text-white bg-brand box-border border border-transparent hover:bg-brand-strong focus:ring-4 focus:ring-brand-medium shadow-xs font-medium leading-5 rounded-base text-sm px-4 py-2.5 focus:outline-none">I accept</button>
                <button data-modal-hide="default-modal" type="button" class="text-body bg-neutral-secondary-medium box-border border border-default-medium hover:bg-neutral-tertiary-medium hover:text-heading focus:ring-4 focus:ring-neutral-tertiary shadow-xs font-medium leading-5 rounded-base text-sm px-4 py-2.5 focus:outline-none">Decline</button>
            </div>
        </div>
    </div>
</div>
{{< /code >}}

Each component that requires JavaScript is well documented on their respective pages under the "JavaScript Behaviour" section as described above.

## Data attributes

The recommended and quickest way of using Flowbite is to use the data attributes interface that automatically creates instances and behaviour for the UI components by applying inline data attributes to the HTML elements, thus making them interactive via the Flowbite JavaScript API.

All of the examples on the Flowbite Docs already have the data attributes applied and they are also documented just above the component preview. 

Here's an example of how you can set up the modal behaviour and apply "show" and "hide" actions:

{{< example github="components/modal.md" class="flex justify-center" show_dark=true iframeHeight="600" >}}
<!-- Modal toggle -->
<button data-modal-target="default-modal" data-modal-toggle="default-modal" class="text-white bg-brand box-border border border-transparent hover:bg-brand-strong focus:ring-4 focus:ring-brand-medium shadow-xs font-medium leading-5 rounded-base text-sm px-4 py-2.5 focus:outline-none" type="button">
  Toggle modal
</button>

<!-- Main modal -->
<div id="default-modal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
    <div class="relative p-4 w-full max-w-2xl max-h-full">
        <!-- Modal content -->
        <div class="relative bg-neutral-primary-soft border border-default rounded-base shadow-sm p-4 md:p-6">
            <!-- Modal header -->
            <div class="flex items-center justify-between border-b border-default pb-4 md:pb-5">
                <h3 class="text-lg font-medium text-heading">
                    Terms of Service
                </h3>
                <button type="button" class="text-body bg-transparent hover:bg-neutral-tertiary hover:text-heading rounded-base text-sm w-9 h-9 ms-auto inline-flex justify-center items-center" data-modal-hide="default-modal">
                    <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18 17.94 6M18 18 6.06 6"/></svg>
                    <span class="sr-only">Close modal</span>
                </button>
            </div>
            <!-- Modal body -->
            <div class="space-y-4 md:space-y-6 py-4 md:py-6">
                <p class="leading-relaxed text-body">
                    With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, companies around the world are updating their terms of service agreements to comply.
                </p>
                <p class="leading-relaxed text-body">
                    The European Union’s General Data Protection Regulation (G.D.P.R.) goes into effect on May 25 and is meant to ensure a common set of data rights in the European Union. It requires organizations to notify users as soon as possible of high-risk data breaches that could personally affect them.
                </p>
            </div>
            <!-- Modal footer -->
            <div class="flex items-center border-t border-default space-x-4 pt-4 md:pt-5">
                <button data-modal-hide="default-modal" type="button" class="text-white bg-brand box-border border border-transparent hover:bg-brand-strong focus:ring-4 focus:ring-brand-medium shadow-xs font-medium leading-5 rounded-base text-sm px-4 py-2.5 focus:outline-none">I accept</button>
                <button data-modal-hide="default-modal" type="button" class="text-body bg-neutral-secondary-medium box-border border border-default-medium hover:bg-neutral-tertiary-medium hover:text-heading focus:ring-4 focus:ring-neutral-tertiary shadow-xs font-medium leading-5 rounded-base text-sm px-4 py-2.5 focus:outline-none">Decline</button>
            </div>
        </div>
    </div>
</div>

{{< /example >}}

In order to create a modal with Tailwind CSS you only have to add `data-modal-target="modalId"` data attribute where `modalId` is the ID of the modal that you are targeting.

If you want to toggle the visibility, show, or hide the modal you can use the following data attributes where the value is the unique ID of the modal component:

- `data-modal-toggle="modalID"` - toggle the modal
- `data-modal-show="modalID"` - show the modal

This is just one example that shows you how Flowbite leverages the data attributes and sets up the JavaScript API, without having to create new instances of the objects yourself.

## Init functions

If you want to programmatically call the initialisation functions when using data attributes (for example, you might want to call it after the DOM re-rendered) then you can use the `initFlowbite()` function or the separate component initialisation functions such as `initModals()` or `initDropdowns()` wherever you want in your JS code:

{{< code lang="javascript" icon="file" file="index.html" >}}
<script type="application/javascript">
import { initFlowbite } from 'flowbite'

// initialize components based on data attribute selectors
initFlowbite();
</script>
{{< /code >}}

Basically, the `initFlowbite()` function parses your DOM for all of the data attributes and creates new instances of the appropriate components like modals or dropdowns and sets up the behaviour of the examples from the Flowbite Docs - applying the functionality of showing and hiding the components such as hiding the modal when clicking on the "X" (close) button.

## Instance manager

Since version `2.0.0`, the Flowbite JS API also provides a way to globally access all of the instances even if they were created via the data attributes interface. This allows you to programmatically handle the components while also giving you the possibility to use the recommended and quick way of accessing the data attributes interface and UI component examples.

After the window has loaded and the UI components from Flowbite have been initialised (either via CDN or the `initFlowbite()` function) you can use the following global object and methods to get access to the object instances:

{{< code lang="javascript" icon="file" file="app.js" >}}
window.addEventListener('load', function() {
    const modal = FlowbiteInstances.getInstance('Modal', 'modal-id');
})
{{< /code >}}

As you can see, the `FlowbiteInstances` global object has two main parameters:

- the first parameter is the component type which can be `Modal`, `Carousel`, `Dropdown` (ie. the name of the object class)
- the second parameter is the target ID or parent ID of the main element and it's always a string

If you provide the wrong category or ID then the console will give you a warning.

If you have provided the correct category and element ID then you can now access the object as if you've created it yourself and work with it programmatically via JavaScript:

{{< code lang="javascript" icon="file" file="app.js" >}}
// show the modal
modal.show();

// hide the modal
modal.hide();
{{< /code >}}

You can even remove the instance from the instance manager:

{{< code lang="javascript" icon="file" file="app.js" >}}
// remove the instance object from the global FlowbiteInstances manager
modal.removeInstance();
{{< /code >}}

You can also both destroy and remove the instance at the same time:

{{< code lang="javascript" icon="file" file="app.js" >}}
modal.destroyAndRemoveInstance();
{{< /code >}}

This in turn will basically remove the object instance from the global `flowbiteStorage` instance manager - you might want to do this if you want to reset certain elements from the DOM in single page applications.

Another example if you want to show or hide a tooltip that was created via data attributes would be:

{{< code lang="javascript" icon="file" file="app.js" >}}
const tooltip = FlowbiteInstances.getInstance('Tooltip', 'tooltip-id');
{{< /code >}}

And now you can show or hide the tooltip programmatically:

{{< code lang="javascript" icon="file" file="app.js" >}}
// show the tooltip
tooltip.show();

// hide the tooltip
tooltip.hide();
{{< /code >}}

You can call the `destroy()` and `init()` methods to re-calculate the positioning of the tooltip:

{{< code lang="javascript" icon="file" file="app.js" >}}
// destroy the tooltip event listeners
tooltip.destroy();

// re-init the tooltip object and event listeners
tooltip.init();

// show the tooltip
tooltip.show();
{{< /code >}}

A component is added to the `flowbiteStorage` global instance manager automatically when it's created via the `constructor` method of the object class, regardless of which component is being used from Flowbite.

Finally, you can also access all of the instances by calling the following method:

{{< code lang="javascript" icon="file" file="app.js" >}}
FlowbiteInstances.getAllInstances();
{{< /code >}}

Alternatively, you can also get all of the instances from one component pool such as from the modals:

{{< code lang="javascript" icon="file" file="app.js" >}}
FlowbiteInstances.getInstances('Modal');
{{< /code >}}

## Instance options

When creating a new object you can also use the last parameter to set the `instanceOptions` object through which you can set custom options for the Instance manager:

{{< code lang="javascript" icon="file" file="app.js" >}}
import type { InstanceOptions } from 'flowbite';

const instanceOptions: InstanceOptions = {
    id: "my-unique-id",
    override: true,
};

const modal = new Modal($targetEl, options, instanceOptions);
{{< /code >}}

In this example, the ID of the instance that you can get it from the `FlowbiteInstances` global instance manager object will be `my-unique-id` instead of the `$targetEl` unique ID.

This can be used to override existing instances if you want to re-initialise the same component with different options, such as when using the collapse object for the same object ID.

In our default UI components we use this when we want to toggle the mobile navigation both with the hamburger menu icon and the search icon, even though the target element is the same.

## TypeScript support

Flowbite has support for type declarations of the Flowbite JS API which helps you to keep your code more maintainable and predictable by giving you safety constraints for the parameters and object methods that you're using through your application.

Learn more about Flowbite and TypeScript in the [introduction guide](https://flowbite.com/docs/getting-started/typescript/).

## Frameworks support

You can use all of the JS frameworks for the UI components that don't require JavaScript to function (such as buttons, badges, cards) and for the UI components that require JS to work you need to set up the `initFlowbite()` function whenever the DOM has rendered so that you can re-apply the event listeners and object instances to the HTML elements that have data attributes. Otherwise, you need to create the objects and set the event listeners yourself.

We have written integration guides for all major front-end and back-end frameworks - generally we have standalone libraries for the major front-end frameworks such as [Flowbite React](https://www.flowbite-react.com/), [Flowbite Svelte](https://www.flowbite-svelte.com/), and [Flowbite Vue](https://flowbite-vue.com/).

For all of the back-end frameworks we recommend the vanilla JS version of Flowbite which integrates very well with frameworks such as [Laravel](https://flowbite.com/docs/getting-started/laravel/), [Django](https://flowbite.com/docs/getting-started/django/), or [Flask](https://flowbite.com/docs/getting-started/flask/).
