DEV Community

loading...
Cover image for Getting started with Tailwind and React: A simple login form tutorial.

Getting started with Tailwind and React: A simple login form tutorial.

ms_yogii profile image Yogini Bende Updated on ・6 min read

Hello folks,

Few days ago, I was searching for some good CSS solutions for my side project and during that I came across Tailwind. Tailwind is surely becoming popular amongst many developers these days, and after using it, I understood the reason. It is a utility-first CSS framework, and when they say utility-first, it means it provides some low-level CSS classes which can be used to write CSS without writing CSS.

After using Tailwind, initially it started feeling a little weird looking at the long list of class names I needed to add to components. But later, after following some practices, it started getting better. Though it's been only a few days I am using Tailwind, but I thought of writing this tutorial as a starter for anyone who wants to use Tailwind with React.

In this tutorial, we will be creating a simple login page in React using Tailwind and exploring some methods to use tailwind. While reading ahead, please note, these are some practices which I follow and if you know some better ways, I would love to know them! So do share them in comments.

To get started, I created a project using create-react-app and added tailwind to it as a dependency by following simple steps mentioned in Tailwind’s official documentation. You can follow the same steps as I have not included them in this article considering the scope.

Moving ahead, I created a component called login.js for our login page. Initially it looked something like this -


import React from 'react';

const Login = () => {
    const handleFormSubmit = (e) => {
        e.preventDefault();

        let email = e.target.elements.email?.value;
        let password = e.target.elements.password?.value;

        console.log(email, password);
    };
    return (
        <div>
            <div>
                <h1>Log in to your account 🔐</h1>

                <form onSubmit={handleFormSubmit}>
                    <div>
                        <label htmlFor='email'>Email</label>
                        <input
                            type='email'
                            id='email'
                            placeholder='Your Email'
                        />
                    </div>
                    <div>
                        <label htmlFor='password'>Password</label>
                        <input
                            type='password'
                            id='password'
                            placeholder='Your Password'
                        />
                    </div>

                    <div>
                        <button>Login</button>
                    </div>
                </form>
            </div>
        </div>
    );
};

export default Login;


Enter fullscreen mode Exit fullscreen mode

The above code looks something like this -
Basic Login Page

Bare minimum! Now the first thing we need to do is to create a card like structure around this form and center it to the page. In Tailwind, we don't have bootstrap like ready-made components, so we will be using all the utility classes to structure our own. I started off with the most outer div element and give it basic three classes which is - h-screen flex bg-gray-100. This list is adding three CSS properties to our outer div, which are height, flex property and a background color. You must be thinking, whoa.. 3 classes for 3 CSS properties??, that’s the utility-first approach used in Tailwind. But bear with this, it will soon start making sense!!

Similarly, we will add styles to the form card by adding these classes w-full max-w-md m-auto bg-white rounded-lg border border-gray-200 shadow-default py-10 px-16. Here because we have added max width to the card as md (28 rem), it will get restricted to 28px width and m-auto will set margin auto making it center into the page. All other classes are just to add more aesthetics to the card. The thumb rule for getting started with Tailwind would be, think of which CSS properties you would add to your element and start searching for those classes in Tailwind documentation. After adding some basic tailwind classes, our login page will look something like this -

Login Page

Here is the code for above page -


import React from 'react';

const Login = () => {
    const handleFormSubmit = (e) => {
        e.preventDefault();

        let email = e.target.elements.email?.value;
        let password = e.target.elements.password?.value;

        console.log(email, password);
    };
    return (
        <div className='h-screen flex bg-gray-bg1'>
            <div className='w-full max-w-md m-auto bg-white rounded-lg border border-primaryBorder shadow-default py-10 px-16'>
                <h1 className='text-2xl font-medium text-primary mt-4 mb-12 text-center'>
                    Log in to your account 🔐
                </h1>

                <form onSubmit={handleFormSubmit}>
                    <div>
                        <label htmlFor='email'>Email</label>
                        <input
                            type='email'
                            className={`w-full p-2 text-primary border rounded-md outline-none text-sm transition duration-150 ease-in-out mb-4`}
                            id='email'
                            placeholder='Your Email'
                        />
                    </div>
                    <div>
                        <label htmlFor='password'>Password</label>
                        <input
                            type='password'
                            className={`w-full p-2 text-primary border rounded-md outline-none text-sm transition duration-150 ease-in-out mb-4`}
                            id='password'
                            placeholder='Your Password'
                        />
                    </div>

                    <div className='flex justify-center items-center mt-6'>
                        <button
                            className={`bg-green py-2 px-4 text-sm text-white rounded border border-green focus:outline-none focus:border-green-dark`}
                        >
                            Login
                        </button>
                    </div>
                </form>
            </div>
        </div>
    );
};

export default Login;


Enter fullscreen mode Exit fullscreen mode

Instead of providing CSS classes for full components, Tailwind gives you some low level utility classes, using which you can design your own custom components. I have mostly used Bootstrap for most of the projects, but I was fed up with overwriting its classes most of the time. Also, it used to give the same UI look and feel for each and every project and I was looking for some change.

Two things to notice here -
Some classnames seems different than the documentation for e.g. bg-green, border-green-dark and text-primary
Many things are repetitive and the classNames list is too long which is losing the readability of components.

As you see, all the different classNames are about the customisations which we can make into the Tailwind’s config. In your project, while you add Tailwind, you will create one file called tailwind.config.js which will be responsible for all the customisations you will want to make in your app. It may include adding new color schemes, adding new font-sizes etc. For e.g. config file for this project will look something like this


module.exports = {
    purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
    darkMode: false, // or 'media' or 'class'
    theme: {
        colors: {
            transparent: 'transparent',
            current: 'currentColor',
            white: {
                DEFAULT: '#ffffff',
            },
            green: {
                light: '#6fcf97',
                DEFAULT: '#27AE60',
                dark: '#219653',
                darker: '#1e874b',
            },
            red: {
                light: '#FFEAEA',
                DEFAULT: '#EB5757',
                dark: '#C20D0D',
            },
            orange: {
                light: '#FFEBDA',
                DEFAULT: '#F66A0A',
                dark: '#A04100',
            },
            primary: {
                DEFAULT: '#24292E',
            },
            warning: {
                DEFAULT: '#D1711C',
            }
        },
        extend: {
            boxShadow: {
                default: '0px 10px 20px rgba(150, 150, 187, 0.1)',
            },
            fontSize: {
                '2rem': '2rem',
            },
        },
    },
    variants: {
        extend: {},
    },
    plugins: [],
};


Enter fullscreen mode Exit fullscreen mode

Moving to the second issue, few components are getting repetitive, like input and buttons. An obvious solution to that would be creating components for such elements. But even creating components won’t solve the issue of long className lists. For that, let's create variables and assign classLists to them. In that case, your css will be completely different than JS, your code will be more readable and you can reuse those variables. Even it will add scalability to certain extent.

Let’s see how this looks in a code -


import React from 'react';
import { PrimaryButton } from '../components/FormElements/Button';
import Input from '../components/FormElements/Input';

const Login = () => {
    const handleFormSubmit = (e) => {
        e.preventDefault();

        let email = e.target.elements.email?.value;
        let password = e.target.elements.password?.value;

        console.log(email, password);
    };

    const classes = {
        pageBody: 'h-screen flex bg-gray-bg1',
        formContainer:
            'w-full max-w-md    m-auto bg-white rounded-lg border border-primaryBorder shadow-default py-10 px-16',
        formHeading: 'text-2xl  font-medium text-primary mt-4 mb-12 text-center',
        btnContainer: 'flex justify-center items-center mt-6',
    };
    return (
        <div className={classes.pageBody}>
            <div className={classes.formContainer}>
                <h1 className={classes.formHeading}>
                    Log in to your account 🔐
                </h1>

                <form onSubmit={handleFormSubmit}>
                    <Input
                        id='email'
                        label='Email'
                        type='email'
                        placeholder='Your email'
                    />
                    <Input
                        id='password'
                        label='Password'
                        type='password'
                        placeholder='Your Password'
                    />

                    <div className={classes.btnContainer}>
                        <PrimaryButton type='submit'>
                            Continue with Email
                        </PrimaryButton>
                    </div>
                </form>
            </div>
        </div>
    );
};

export default Login;

Enter fullscreen mode Exit fullscreen mode

In the code above, I have created an object called classes and added a long classNames list to it as a key value pair. This separated CSS classes from JS and made the code easily readable. Apart from that, I also created some basic components for Inputs and Buttons

In the code above, I have created an object called classes and added a long classNames list to it as a key value pair. This separated CSS classes from JS and made the code easily readable. Apart from that, I also created some basic components for Inputs and Buttons.

So, That’s it!! We have already created a simple login form. I know this is still a dumb component and we have not included error handling, responsiveness and API calls. But I am keeping this out of scope for this article and will cover that in my next one.

Till then, please share your thoughts and approaches of handling integrating Tailwind CSS into your React projects! Keep learning :)

Discussion (11)

Collapse
chema profile image
José María CL

Nice! I think this is a great utility to build our own components without spending time creating our CSS as the project demands. It's good to have options.

Collapse
chema profile image
José María CL

BTW, In the last code snnipet you imported the components in this way:

import { PrimaryButton } from '../components/FormElements/Button';
import Input from '../components/FormElements/Input';
Enter fullscreen mode Exit fullscreen mode

I would recommend to export them all using an index.js file in favor of a cleaner way to import them.

// Supose we have this modules
- components
  |- form-elements
    |- primary-button
    |- input
    |- index.js
  |- index.js
- pages
Enter fullscreen mode Exit fullscreen mode
// components/form-items/index.js
export * from "primary-button";
export { default as Input } from "input";
Enter fullscreen mode Exit fullscreen mode
// components/index.js
export * as FormItems from "form-items";
Enter fullscreen mode Exit fullscreen mode

So you can import them in one of these ways

import FormItems from "../components";

return (
  <div>
    <FormItems.Input />
    <FormItems.PrimaryButton />
  <div>
);

// or
import { PrimaryButton, Input  } from "../components/form-items";

return (
  <div>
    <Input />
    <PrimaryButton />
  <div>
);
Enter fullscreen mode Exit fullscreen mode
Collapse
ms_yogii profile image
Yogini Bende Author

Thanks Jose. That's a good catch. I sometimes avoid creating index.js for small projects. But surely, that makes code more cleaner.

Collapse
vaibhavkhulbe profile image
Vaibhav Khulbe

Nice! I've been a Tailwind fan since it was in beta :)

Collapse
ms_yogii profile image
Yogini Bende Author

Yess, its awesome 🙌

Collapse
aalphaindia profile image
Pawan Pawar

Good One, Keep Sharing!!

Collapse
bugb profile image
bugb

upvoted for the emoji 🔐, awesome!

Collapse
carlitorweb profile image
Carlos Rodriguez

Tailwind added recently a official plugin for handle form styles. Check it out, will save you some class inside your form fields, keeping the nice look.

Collapse
ms_yogii profile image
Yogini Bende Author

Oh great! I will surely check that.. thanks Carlos 🙌

Forem Open with the Forem app