Checkout Form Using Tailwind.css & Vue.js
In modern web development, creating user-friendly and visually appealing forms is essential, especially for tasks like online purchases. In this article, we’ll guide you through building a checkout form using two popular technologies: Tailwind CSS for styling and Vue.js for dynamic behaviour.
Output Preview:
Prerequisites:
Approach
- Initialize a new Vue.js project and install Tailwind CSS and its dependencies.
- Create a Vue.js component named
CheckoutForm.vue
to contain the form. - Structure the form with HTML, including sections for billing address and payment details.
- Define data properties to store form values and methods to handle form submission and interactions.
- Prevent default form submission with
@submit.prevent
and handle submission in a method, updating thesubmitted
property. - Use Tailwind CSS utility classes to style the form components for a clean and responsive layout.
Steps to Create the Application
Step 1: Create the Vue project using the following command:
npx @vue/cli create checkout-form
Step 2: Now follow the provided instructions and get into the project directory:
cd checkout-form
Step 3: Install the necessary packages/libraries in your project using the following commands.
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
npx tailwindcss init -p
Project Structure:
The updated dependencies in package.json file will look like:
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.8.3",
"vue": "^3.2.13"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"autoprefixer": "^10.4.19",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3"
}
Example: Implementation to design the checkout form
<!-- src/components/CheckoutForm.vue -->
<template>
<div id="app"
class="container mx-auto py-8 px-4">
<h1 class="text-3xl font-bold
mb-8 text-center">
Checkout Form
</h1>
<form @submit.prevent="submitForm"
class="max-w-lg mx-auto bg-white
p-8 rounded-lg shadow-md">
<!-- Billing Address -->
<div>
<div class="text-2xl my-4">
Billing Address
</div>
<div class="grid grid-cols-1
md:grid-cols-2 gap-4">
<div class="mb-4">
<label for="firstName"
class="block text-gray-700 mb-2">
First Name
</label>
<input v-model="formData.firstName"
type="text" id="firstName"
name="firstName"
class="w-full form-input p-1
border rounded-md
shadow-sm" required>
</div>
<div class="mb-4">
<label for="lastName"
class="block text-gray-700 mb-2">
Last Name
</label>
<input v-model="formData.lastName"
type="text" id="lastName" name="lastName"
class="w-full form-input p-1 border
rounded-md shadow-sm" required>
</div>
</div>
<div class="mb-4">
<label for="email"
class="block text-gray-700 mb-2">
Email Address
</label>
<input v-model="formData.email"
type="email" id="email" name="email"
class="w-full form-input p-1 border
rounded-md shadow-sm" required>
</div>
<div class="mb-4">
<label for="address"
class="block text-gray-700 mb-2">
Address
</label>
<textarea v-model="formData.address"
id="address" name="address" rows="5"
class="w-full form-textarea p-1 border
rounded-md shadow-sm" required>
</textarea>
</div>
<div class="mb-4 grid grid-cols-1
md:grid-cols-3 gap-4">
<div>
<label for="city"
class="block text-gray-700 mb-2">
City
</label>
<input v-model="formData.city"
type="text" id="city" name="city"
class="w-full form-input p-1 border
rounded-md shadow-sm" required>
</div>
<div>
<label for="zip"
class="block text-gray-700 mb-2">
ZIP Code
</label>
<input v-model="formData.zip"
type="text" id="zip" name="zip"
class="w-full form-input p-1 border
rounded-md shadow-sm" required>
</div>
<div>
<label for="country"
class="block text-gray-700 mb-2">
Country
</label>
<input v-model="formData.country"
type="text" id="country" name="country"
class="w-full form-input p-1 border
rounded-md shadow-sm" required>
</div>
</div>
<div class="mb-4">
<input v-model="sameAsBilling"
type="checkbox"
@change="toggleShippingAddress"/>
<label class="ml-2">
Shipping address is the
same as my billing address
</label>
</div>
<div class="mb-8">
<input v-model="saveInfo" type="checkbox"/>
<label class="ml-2">
Save this information
for next time
</label>
</div>
</div>
<!-- Payment -->
<div class="text-2xl mb-4">
Payment
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="mb-4">
<label for="nameOnCard"
class="block text-gray-700 mb-2">
Name on Card
</label>
<input v-model="formData.nameOnCard"
type="text" id="nameOnCard"
name="nameOnCard"
class="w-full form-input p-1 border
rounded-md shadow-sm" required>
</div>
<div class="mb-4">
<label for="cardNumber"
class="block text-gray-700 mb-2">
Card Number
</label>
<input v-model="formData.cardNumber"
type="text" id="cardNumber" name="cardNumber"
class="w-full form-input p-1
border rounded-md
shadow-sm" required>
</div>
</div>
<div class="grid grid-cols-2
md:grid-cols-4 gap-4">
<div class="mb-4">
<label for="expiration"
class="block text-gray-700 mb-2">
Expiration
</label>
<input v-model="formData.expiration"
type="text" id="expiration" name="expiration"
class="w-full form-input p-1
border rounded-md shadow-sm" required>
</div>
<div class="mb-4">
<label for="cvv"
class="block text-gray-700 mb-2">
CVV
</label>
<input v-model="formData.cvv" type="text"
id="cvv" name="cvv"
class="w-full form-input p-1 border
rounded-md shadow-sm" required>
</div>
</div>
<button type="submit"
class="mt-8 w-full bg-green-500
hover:bg-green-700 text-white
font-bold py-2 px-4 rounded">
Continue to Checkout
</button>
</form>
<!-- Display submitted data -->
<div v-if="submitted"
class="fixed inset-0 flex
items-center justify-center">
<div class="bg-white p-8 rounded-lg shadow-md">
<h2 class="text-xl font-bold mb-4">
Successfully Checked Out!
</h2>
<p>
Your order has been
processed successfully.
</p>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
formData: {
firstName: '',
lastName: '',
email: '',
address: '',
city: '',
zip: '',
country: '',
nameOnCard: '',
cardNumber: '',
expiration: '',
cvv: ''
},
sameAsBilling: false,
saveInfo: false,
submitted: false,
submittedData: {}
};
},
methods: {
submitForm() {
this.submitted = true;
// Your form submission logic goes here
setTimeout(() => {
// Close dialog box after a short delay
this.submitted = false;
// Close dialog box after 3 seconds
// (adjust the time as needed)
}, 3000);
},
toggleShippingAddress() {
if (this.sameAsBilling) {
this.formData.shippingAddress =
this.formData.address;
} else {
this.formData.shippingAddress = {};
}
}
}
};
</script>
<!-- src/App.vue -->
<template>
<div id="app" class="bg-gray-100">
<CheckoutForm />
</div>
</template>
<script>
import CheckoutForm from './components/CheckoutForm.vue';
import "./assets/main.css";
export default {
name: 'App',
components: {
CheckoutForm
}
};
</script>
/* src/assets/main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
// tailwind.config.js
module.exports = {
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};
Step to Run Application: Run the application using the following command from the root directory of the project
npm run serve
Output: Your project will be shown in the URL http://localhost:8080/