How to Integrate FormKit and Bootstrap
Tags: javascript, vue, css, webdev
Published: 2023-01-16 11:26:31

FormKit is powerful, but for the most part, it leaves styling your forms to you. In this article, you'll learn how to style your FormKit forms with Bootstrap. 

You’ll discover how to style forms individually, and how you can create an application-wide form theme that is easy to reuse in other projects.
 

## Prerequisites and Assumptions
This guide assumes the following:
- You have a working knowledge of [FormKit](https://formkit.com/getting-started/what-is-formkit), [Bootstrap](https://getbootstrap.com/docs/5.3/getting-started/introduction/), and npm.
- You understand the Vue 3 Composition API.

## Setup

If you want to follow along with this guide, you'll need to do some setup work first.

### Installation
Your first task is to create a Vue project with Vite. Start by navigating to the location you want your project to live in the terminal. Next, run the following command in your terminal:

```bash
npm create vite@latest
```

The `create-vite` command will ask you a few questions. Answer them as shown in the screenshot below:
![command line screenshot](https://i.imgur.com/kPg57j8.png)


Then `cd` into the project folder and install the necessary dependencies:

```sh
cd formkit-bootstrap
npm install
```

Next, start the dev server by running: `npm run dev`. Visit [localhost:5173](http://localhost:5173) to see your application.

Now that you've set up your base Vue project, it's time to install the other dependencies you'll need: FormKit, Bootstrap, and Sass. Open another terminal window and run this code:

```sh
npm i bootstrap sass @formkit/vue @formkit/themes @formkit/utils
```

Your last setup task is to clean up boilerplate you don't need. At this point, your project directory should have a structure that looks like this:

![screenshot of directory structure](https://i.imgur.com/tONlNdL.png)

Delete the `src/assets` folder, `src/components/HelloWorld.vue`, and `src/style.css`.

Replace the content of `src/App.vue` with an empty template and script like so:

```html
<script setup></script>

<template></template>
```

Next, import all Bootstrap's classes by creating a file called `styles.scss` in `src`, with the following content:

```sass
// Import all of Bootstrap's CSS
@import "../node_modules/bootstrap/scss/bootstrap";
```

If you only want to import some of Bootstrap's CSS, you can find the [relevant import statements](https://getbootstrap.com/docs/5.3/customize/sass/#importing) for the parts you want in their docs.

Then import the styling and register Formkit with your Vue app by replacing the content of `src/main.js` with the following:

```javascript
import { createApp } from 'vue'
import { plugin, defaultConfig } from '@formkit/vue'
import './styles.scss'
import App from './App.vue'

createApp(App).use(plugin, defaultConfig).mount('#app')
```
And you're done with the setup.

## Styling forms individually
Next, you'll learn how to style individual forms separately.

Start by creating a basic, unstyled login form by adding the following code to the `template` of `src/App.vue`:

```html
 <div class="row m-0">
  <FormKit
    type="form"
    submit-label="Log in"
  >
    <h2 class="mb-3"> Log In </h2>

    <FormKit type="email"
             placeholder="john@xyz.com"
             label="Email"
    ></FormKit>

    <FormKit type="password"
             placeholder="***********"
             label="Password"
    ></FormKit>

  </FormKit>
</div>
```

After that, your Vue application should render a form that looks like this:

![form screenshot](https://i.imgur.com/UugKyhf.png)

So, how will you style this? FormKit provides [several methods](https://formkit.com/essentials/styling#outer-attributes) for styling form inputs, from writing CSS that targets the inputs with attribute values to applying classes to inputs via props.

Before you go on, you need to understand some FormKit jargon: input sections. A section is a specific part of the rendered HTML of a FormKit input. You can find a list and description of the sections for each input in FormKit’s docs for the input. 

In general, the `outer` section refers to an input's outermost wrapper, the `input` section refers to the core rendered input, and the `label` section targets the generated label.  

The approach to styling you'll use here is to use `{section}-class` props to apply classes to the form inputs. 

Here's what the code for the login form looks like when you style it this way:

```html
<FormKit
    type="form"
    form-class="col-md-4 col-lg-3 mt-5 mx-auto 
                p-5 border rounded"
    :submit-attrs="{
      inputClass: 'btn btn-primary'
    }"
    submit-label="Log in"
  >
    <h2 class="mb-3"> Log In </h2>

    <FormKit type="email"
             placeholder="john@xyz.com"
             outer-class="mb-3"
             input-class="form-control"
             label="Email"
             label-class="form-label"
    ></FormKit>

    <FormKit type="password"
             placeholder="***********"
             outer-class="mb-3"
             input-class="form-control"
             label="Password"
             label-class="form-label"
    ></FormKit>

  </FormKit>
```

Since you already imported Bootstrap's classes during setup, all you need to style the form is the name of the classes you want to apply to the input.

The code applies classes to sections of each input with `{section}-class` props that take the name of the class FormKit will apply to that section. In your login form, the `outer` sections get a class of `mb-3`, the `input` sections get `form-control`, and the `label` gets `form-label`.

Here's what the login form should look like after you style it:
![styled form](https://i.imgur.com/IzX3e2W.jpg)

And to illustrate how section classes are applied, here's what the rendered HTML for the email input might look like:

![rendered input](https://i.imgur.com/afKEP7R.png)


That's the general process for styling individual forms: you apply CSS to the input sections, one input at a time.

While this works, it can become tedious and difficult to maintain if you have several forms in your app. It can also become clumsy if your app has large forms.

The solution to this is to create a theme. A theme is a baseline set of styles that FormKit applies to every form in your app. 
 
## Creating a Bootstrap theme
Before you build the theme, you'll create a new form to demo how the theme styles forms automatically.

In `App.vue`, replace the template for the login form with this registration form:

```html
<FormKit
        type="form"
        submit-label="Register"
    >
      <h2 class="mb-3"> Register </h2>

      <FormKit type="text"
               placeholder="John Doe"
               label="Full Name"
      ></FormKit>

      <FormKit type="email"
               placeholder="john@xyz.com"
               label="Email"
      ></FormKit>

      <FormKit type="range"
               label="Age"
               min="0"
               max="100"
               :help="`You are ${age} years old`"
               v-model="age"
      ></FormKit>

      <FormKit type="password"
               placeholder="***********"
               label="Password"
      ></FormKit>

    </FormKit>
```

Then add this code to the `script` section:

```javascript
import {ref} from "vue";

let age = ref(18);
```

At this point, your registration form should have zero styling, and should look like this:

![reg form](https://i.imgur.com/AqBBLdv.png)


Next, you'll create your form theme. Add a file to the root of your `formkit-bootstrap` directory called `formkit.config.js`, then put the following code in it:

```javascript
import { generateClasses } from '@formkit/themes'

const config = {
  config: {
    classes: generateClasses({
      global: { // classes
        outer: '$reset mb-3',
        input: 'form-control',
        label: 'form-label',
        help: 'form-text'
      },
      form: {
        form: "col-md-4 col-lg-3 mt-5 mx-auto p-5 border rounded"
      },
      range: {
        input: '$reset form-range',
      },
      submit: {
        outer: '$reset mt-3',
        input: '$reset btn btn-primary'
      }
    })
  }
}

export default config
```

This code is what's responsible for your theme, so let's break it down. The code relies on the `generateClasses` function from the `@formkit/themes` package to apply a list of classes to each section of each input type you specify.

The `$reset` keyword at the beginning of a class list tells FormKit to disregard any styling applied to that section before that point.

The theme you created is pretty minimal. All it does is apply Bootstrap classes to the inputs you used in your form, and define some default styling for the form container and submit buttons.

Now that you have your theme, the next step is to register it in your app. To do that, replace the code in `main.js` with this:

```javascript
import { createApp } from 'vue'
import { plugin, defaultConfig } from '@formkit/vue'
import customConfig from '../formkit.config.js'
import './styles.scss'
import App from './App.vue'


createApp(App).use(plugin, defaultConfig({
  config: customConfig.config
})).mount('#app')
```
And wait for your dev server to reload.


After your server has reloaded, check your application's page. You should see that your registration form is completely styled, and it should look like this:

![styled reg form](https://i.imgur.com/fH5Zodz.png)

If you feel like testing your theme a bit, you can copy the unstyled version of the login form to `App.vue` to see how the styling applies to it. 

Here's a great thing about FormKit’s themes: all they are is a convenient baseline. Applying form-specific styling to an input will override the theme styling without conflicts. This makes it easy for you to tweak the styling of individual forms.


As an example, if you wanted to change the color of the register button to green, you could apply section styles like earlier in the article:

```html
 <FormKit
        type="form"
        submit-label="Register"
        :submit-attrs="{
          inputClass: 'btn btn-success'
        }"
    >
```
And voila.

![green button reg form](https://i.imgur.com/7pMWlWx.png)

Note:
Themes are framework-agnostic. As long as the classes you put in your config are part of your app's stylesheet, you can create a theme with anything from vanilla CSS to [Tailwind](https://formkit.com/guides/create-a-tailwind-theme).

## Floating labels

If you want to use floating labels in your forms, you can use a plugin from this [GitHub issue](https://github.com/formkit/formkit/issues/500#issuecomment-1338203487). Since Boostrap's floating labels are CSS-only, they won't conflict with Vue or FormKit. Just keep in mind: registering the plugin globally will give all `type=text` inputs floating labels.

## Conclusion

At this point, you've learned how to build your forms with FormKit and style them with Bootstrap, both disparately and by creating a theme. If you need further assistance, FormKit has a [Discord server](https://discord.gg/Vhu97pAC76) where you can ask for help.