Tailwind CSS Contact Form with a node.js Form Handler - Part 1
Andy Griffiths
Posted on February 10, 2021
The chances are, if you have a website you’ll need a way for your customers to be able to contact you. Step up the humble contact form.
Using some basic HTML and the power of Tailwind CSS, we can quickly build out a stylish contact form and add it to our website.
We’ll also need a way to receive any form requests, so in Part 2 we’ll build a simple mail server API using node.js, Express and SendGrid.
Check out the DEMO
Download the SOURCE CODE
Front-end first
Both our front-end (contact form) and back-end (form handler) are going to be using npm for some dependencies, so make sure you have the latest version installed locally on your computer.
npm comes bundled with node.js, so you can get the download from nodejs.org.
Once you have node.js & npm installed locally, create a new folder for your project mkdir contact-form
.
Next, navigate to our project with cd contact-form
.
Now let’s initiate npm with the npm init -y
command in the terminal. The -y
flag simply answers yes to all the default questions, feel free to manually set this up by omitting this flag, or in the package.json file later.
Before we go any further, I just wanted to point out that Tailwind CSS can be used by simply using their dedicated CDN, as per their docs - however, this does not give us all of the functionality we need and is not recommended.
Instead, we are going to install this and use it as a PostCSS plugin.
So, let’s get the dependencies we require installed with npm i tailwindcss@latest @tailwindcss/forms postcss@latest autoprefixer@latest postcss-cli
.
Once this has finished installing, we need to set up a couple more things before we can code our form.
Open the package.json
file, as we need to add a couple of scripts to allow us to compile our Tailwind CSS later.
"build": "postcss ./src/styles.css -o ./public/dist/styles.css",
"prod": "NODE_ENV=production postcss ./src/styles.css -o ./public/dist/styles.css"
As a follow on from my last post Build a JavaScript and Tailwind CSS Theme Switcher I want to be able to use dark mode, so we need to set this up in Tailwind.
Build a JavaScript and Tailwind CSS Theme Switcher
Andy Griffiths ・ Feb 4 '21
In your terminal, run npx tailwindcss init -p
to create our tailwind.config.js and postcss.config.js files, then open up the tailwind.config.js
file.
First add the forms plugin.
plugins: [
require('@tailwindcss/forms')
],
Then change darkMode
to class
.
Before we can compile our CSS, we need to create the source CSS file.
Create the src folder mkdir src
then cd src
in to the directory and create the CSS file touch styles.css
.
Add the included to the styles.css file
@tailwind base;
@tailwind components;
@tailwind utilities;
Then run npm run build
. This should output our compiled styles to our public/dist/styles.css
file.
With all the setup out of the way, let’s get some coding done. Create an index.html
file in our public directory touch public/index.html
and then open it up.
As I’m using Visual Studio Code as my text editor, I'll add my HTML boilerplate code by pressing !
and then tab
.
Next, update the title
, add our CSS as a link
tag and pull in Font Awesome.
<title>HTML & Tailwind CSS Contact Form</title>
<link rel="stylesheet" href="dist/styles.css">
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
Tailwind CSS is a bit different from other CSS frameworks that you may have used before, such as Bootstrap or Foundation. Tailwind CSS does not assume any styles on your HTML elements.
With this in mind, we’ll need to style each of our HTML elements with CSS classes, as they will not have any default styles out-of-the-box. As this will all be controlled by adding utility classes to our HTML markup, this means we won’t need to write a single line of CSS.
The structure of our HTML is going to be straight forward, as we’re just going to create a form centralised on the page. Let’s create the bare-bones.
<form>
<div>
<!-- heading -->
</div>
<div>
<!-- message field -->
</div>
<div>
<!-- name field -->
</div>
<div>
<!-- email field -->
</div>
<div>
<!-- button -->
</div>
</form>
This now gives us a good skeleton - let’s start populating these sections with our content.
Let’s create the styles for our form element. Remember, we do this by adding various CSS classes directly to the HTML markup.
<form action="" class="mt-20 p-10 max-w-xl mx-auto shadow-md sm:border-0 md:border md:border-gray-900 md:dark:border-gray-100 bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100">
<!-- form content -->
</form>
There’s quite a few classes required to get the desired design, so I’ll briefly explain what each one does. If you need further clarification, then check out the Tailwind CSS Documentation.
my-20 <!-- adds 5rem vertical margin -->
p-10 <!-- adds 2.5rem padding -->
max-w-xl <!-- sets the max width to 36rem -->
mx-auto <!-- sets left and right margin auto to center -->
shadow-md <!-- adds a medium box shadow -->
sm:border-0 <!-- removes any border on small devices -->
md:border <!-- adds a border on medium devices and above -->
md:border-gray-900 <!-- sets the border color to a dark grey (light mode) -->
md:dark:border-gray-100 <!-- sets the border color to a light grey (dark mode) -->
bg-gray-100 <!-- sets the background color to a light grey (light mode) -->
dark:bg-gray-800 <!-- sets the background color to a dark grey (dark mode) -->
text-gray-900 <!-- sets the text color to a dark grey (light mode) -->
dark:text-gray-100 <!-- sets the text color to a light grey (dark mode) -->
Now that you have a better idea how to style HTML elements with Tailwind CSS’s utility classes, I’ll give you the rest of the markup verbatim. Feel free to look over the styles and reference these in the Tailwind CSS Documentation to see what each class does.
<body class="bg-white dark:bg-gray-900">
<div class="flex w-full justify-around items-center bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-white py-5">
<div class="theme-switcher">
<button class="theme-switcher-button theme-switcher-light bg-gray-200 border-gray-200 border-2 dark:bg-black dark:border-black p-2 focus:outline-none" title="Light"><i class="fas fa-sun pointer-events-none"></i> Light</button><button class="theme-switcher-button theme-switcher-dark bg-gray-200 border-gray-200 border-2 dark:bg-black dark:border-black p-2 focus:outline-none" title="Dark"><i class="fas fa-moon pointer-events-none"></i> Dark</button><button class="theme-switcher-button theme-switcher-auto bg-gray-200 border-gray-200 dark:bg-black border-2 dark:border-black p-2 focus:outline-none" title="Auto"><i class="fas fa-adjust pointer-events-none"></i> Auto</button>
</div>
</div>
<form action="" class="my-20 p-10 max-w-xl mx-auto shadow-md sm:border-0 md:border md:border-gray-900 md:dark:border-gray-100 bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100">
<div class="mb-10">
<h1 class="font-bold text-4xl mb-3">Get in touch</h1>
<p class="font-medium text-lg mb-5">Send us a quick message and we'll get back to you shortly.</p>
<hr class="border-gray-900 dark:border-gray-100">
</div>
<div class="mb-5">
<label for="message" class="text-lg flex justify-between items-end"><span>Message</span><span class="text-xs text-red-500">Required</span></label>
<textarea name="message" id="message" cols="30" rows="10" class="shadow-md mt-1 block w-full sm:text-sm rounded-none border-gray-900 dark:border-gray-100 bg-white dark:bg-gray-900"></textarea>
</div>
<div class="mb-5">
<label for="name" class="text-lg flex justify-between items-end"><span>Name</span><span class="text-xs text-red-500 ">Required</span></label>
<div class="mt-1 flex shadow-md">
<span class="inline-flex items-center px-3 rounded-none border border-r-0 border-gray-900 dark:border-gray-100"><i class="fas fa-user"></i></span>
<input type="text" name="name" class="flex-1 block w-full sm:text-sm rounded-none border border-gray-900 dark:border-gray-100 bg-white dark:bg-gray-900">
</div>
</div>
<div class="mb-5">
<label for="email" class="text-lg flex justify-between items-end"><span>Email</span><span class="text-xs text-red-500">Required</span></label>
<div class="mt-1 flex shadow-md">
<span class="inline-flex items-center px-3 rounded-none border border-r-0 border-gray-900 dark:border-gray-100"><i class="fas fa-envelope"></i></span>
<input type="email" name="email" class="flex-1 block w-full sm:text-sm rounded-none border border-gray-900 dark:border-gray-100 bg-white dark:bg-gray-900">
</div>
</div>
<div>
<button type="button" class="font-medium shadow-md rounded-none p-2 w-full focus:outline-none focus:ring-2 focus:ring-offset-2 border border-gray-900 dark:border-gray-100 bg-gray-800 dark:bg-gray-200 text-gray-200 dark:text-gray-800 hover:bg-gray-900 dark:hover:bg-gray-100"><i class="fas fa-check"></i> Send</button>
</div>
</form>
</body>
You should now have a pretty nice looking contact form built with HTML and Tailwind CSS.
That wraps up this part of the tutorial.
In the next part, we’re going to look at building a form handler which will email us when a user submits a form. This will be built with node.js, Express and SendGrid. We’ll also look at some client-side and server-side form validation.
Please make sure you follow me here on dev.to and Twitter so you don’t miss out when the next part is available.
Posted on February 10, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.