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, Bootstrap, 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:
npm create vite@latest
The create-vite
command will ask you a few questions. Answer them as shown in the screenshot below:
Then cd
into the project folder and install the necessary dependencies:
cd formkit-bootstrap
npm install
Next, start the dev server by running: npm run dev
. Visit 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:
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:
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:
<script setup></script>
<template></template>
Next, import all Bootstrap's classes by creating a file called styles.scss
in src
, with the following content:
// 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 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:
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
:
<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:
So, how will you style this? FormKit provides several methods 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:
<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:
And to illustrate how section classes are applied, here's what the rendered HTML for the email input might look like:
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:
<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:
import {ref} from "vue";
let age = ref(18);
At this point, your registration form should have zero styling, and should look like this:
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:
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:
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:
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:
<FormKit
type="form"
submit-label="Register"
:submit-attrs="{
inputClass: 'btn btn-success'
}"
>
And voila.
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.
Floating labels
If you want to use floating labels in your forms, you can use a plugin from this GitHub issue. 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 where you can ask for help.
Top comments (2)
Excellent guide! Thank you for putting this together.
Thank you!