Create a sign-up form using only HTML, CSS, and JavaScript.
The goal is to make the sign-up form responsive (adaptable to different screen sizes) and interactive (something happens when the user clicks the buttons).
We’ll be following this design by Natalia K as inspiration guidance.
Notice this sign-up form allows the user to Sign In if they already have an account.
Clicking Sign In will bring up a login form a user with an account can use to sign in. We’ll implement this toggle behavior between the two different forms – sign up and sign in – using JavaScript.
The final result should be this:
See the Pen Untitled by Klea Merkuri (@thehelpfultipper) on CodePen.
Lay down your sign up form’s HTML
Start with a form-container and place inside it a form-inner-container which will be the one holding the sign-up form.
Need help setting up your HTML document? Check out HTML For Beginners – A Step-by-Step Guide To HTML Tags.
<div id="form-container">
<div id="form-inner-container"></div>
</div>
We are nesting a container <div>
within another div so we can center our form in the middle of the page (more on that later).
Let’s add some styles to our containers to get a good idea of what we’re looking at.
Setting a grey backdrop
Start by removing the default browser settings from the <body>
and adding a background color. We used ColorZilla’s color picker to get our colors to match those on the design – totally up to you.
body {
background-color: #F3F4F9;
margin: 0;
padding: 0;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
Centering the sign up form
To center the div holding the sign-up form use flexbox.
Give the form-container a height of 100vh – the full height of the viewing window – and a display of flex.
#form-container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
- Not setting a height makes form-container default to
height: auto
. In such a case, there isn’t any vertical room for the element to move across so you won’t see any vertical centering take place. - Use a flex display to set justify-content (horizontal centering) and align-items (vertical centering) as center.
Style the form-inner-container giving it a white background, dimensions, box-shadow, and slightly rounded corners.
#form-inner-container {
background-color: white;
width: 70%;
height: 80%;
border-radius: 8px;
box-shadow: 0 0 20px gainsboro;
}
Adding the sign up form element
Looking at the main container, we can divide it into two div
s: the form div
and the image div
.
Let’s tackle the form div
first. Inside of sign-up-container add the form title and the form itself.
The form consists of 3 different types of input fields – text for the user’s name, email for the user’s email, and password for the entered password.
Though all inputs could be a type of text, assigning the appropriate type to an input adds built-in browser validation for email and makes the password not visible by replacing characters with dots.
Complete the form for the moment by adding a button with a type of submit.
<div id="sign-up-container">
<h3>Get Started</h3>
<form>
<label for="name">Name</label>
<input type="text" name="name" id="name">
<label for="email">Email</label>
<input type="email" name="email" id="email">
<label for="password">Password</label>
<input type="password" name="password" id="password">
<button type="submit">Sign Up</button>
</form>
</div>
You should end up with this:
We still need to add two more elements to our form:
- the Sign In link/button which will be our toggle between the sing up and sign in forms
- the checkbox asking the user to agree to terms and service
<div id="sign-up-container">
<h3>Get Started</h3>
<form>
<label for="name">Name</label>
<input type="text" name="name" id="name">
<label for="email">Email</label>
<input type="email" name="email" id="email">
<label for="password">Password</label>
<input type="password" name="password" id="password">
<button type="submit">Sign Up</button>
<button type="button">Sign In</button>
<input type="checkbox" name="terms" id="terms">
<label for="terms">I agree to the <a href="#" class="termsLink">Terms of service</a> and <a href="#" class="termsLink">Privacy Policy</a>.</label>
</form>
</div>
Add form styles
Give sign-up-container a width and some padding.
#sign-up-container {
padding: 60px 80px;
width: 320px;
}
To get a stacked form instead of the horizontal one we currently have, set the display of all form inputs except the last one as block.
Add styles to all input fields except the last checkbox by setting paddings, background colors, and margins.
form input:not(:last-of-type) {
display: block;
margin-bottom: 20px;
border: 1px solid #E5E9F5;
background-color: #F6F7FA;
padding: 20px;
margin-top: 10px;
border-radius: 10px;
}
Notice we use :not(:last-of-type) to select all input elements in the form except the last input – the checkbox.
Go back to your HTML code and add a placeholder for each of the input fields. Use the HTML entity ●
to get black dots as password placeholders.
This is what we have so far:
Let’s fix the inline behavior of the buttons and checkbox so the checkbox and its label lie beneath the buttons.
Just wrap the buttons in a div (a block-level element) with an id of form-controls. Give it a margin at the bottom.
#form-controls {
margin-bottom: 25px;
}
Add some color and adjust the font size for the form title, labels, and placeholders.
h3 {
color: red;
font-size: 150%;
font-weight: 500;
}
label {
color: #7369AB;
}
::placeholder {
color: #C0C7DB;
font-size: larger;
letter-spacing: 1.2px;
}
To style the placeholders, we use a special CSS selector ::placeholder. For more on CSS selectors, read Common CSS Selectors To Know And How To Use Them.
Remove height: 80% from form-inner-container to let the div take up an automatic height based on its contents. Give all inputs except the last one full-container width, width: 100%.
First, get rid of the border on the buttons and increase their font-size. Turn the cursor into a pointer to indicate to the user they’re clickable elements.
#form-controls button {
border: none;
font-size: 110%;
}
#form-controls button:hover {
cursor: pointer;
}
Give the first button, the one with a type of submit, a red background color, and some padding. Then make the background transparent for the second button that’s going to toggle the Sign In form.
button[type="submit"] {
padding: 16px 75px;
background-color: #ED4B5E;
border-radius: 10px;
color: white;
}
button[type="submit"]:hover {
background-color: #ff6678;
}
button[type="button"] {
padding: 16px 0 16px 35px;
background-color: transparent;
color: #ED4B5E;
}
Even though we are using a type CSS selector, feel free to assign classes or ids to each button.
Read: How To Use Classes & IDs To Select Elements In CSS
Adding custom styles to the checkbox with CSS
Increase the size of the checkbox by setting a width and height. Then to add styles to the checkbox, we first need to override the default browser styles otherwise our custom styles won’t take effect.
Use the appearance property set as none to add a custom design to a checkbox like a thicker border with round corners.
#terms {
width: 30px;
height: 30px;
appearance: none;
border: 2px solid #7369AB;
border-radius: 4px;
}
If you click on the checkbox, you’ll notice we lost the main functionality of adding a check once we directly manipulated the appearance.
To add a check after selecting the checkbox, we’ll work with the CSS pseudo-class :check:after
and insert the checkmark as the CSS code equivalent of an HTML entity in content.
#terms:checked:after {
content: '\2713';
color: #7369AB;
font-size: 24px;
position: absolute;
top: 0;
left: 3px;
}
But this places the checkmark all the way to the top left corner of the page which isn’t where we want it to go. To fix this, set position: relative on the checkbox so the checkmark is positioned absolutely relative to the checkbox, not the body.
Moving onto the checkbox label, set its display to inline-block to prevent the second line of text from moving under the checkbox.
Then reduce the width so the label fits in the same line as the checkbox and style the links.
label[for="terms"] {
display: inline-block;
width: 80%;
margin-left: 10px;
}
.termsLink {
color: #EF7886;
text-decoration: none;
}
We will use the same styles to create a uniform form with the role of signing in instead of signing up. All we need to do is tweak the HTML code slightly:
<div id="sign-in-container">
<h3>Welcome Back</h3>
<form>
<label for="username">Username</label>
<input type="text" name="username" id="username" placeholder="[email protected]">
<label for="password">Password</label>
<input type="password" name="password" id="password" placeholder="●●●●●●">
<div id="form-controls">
<button type="submit">Sign In</button>
<button type="button">Sign Up</button>
</div>
<input type="checkbox" name="terms" id="terms">
<label for="terms">
I agree to the
<a href="#" class="termsLink">Terms of service</a> and
<a href="#" class="termsLink">Privacy Policy</a>.
</label>
</form>
</div>
Now add sign-in-container to the CSS selector for sign-up-container to apply the same styles like so:
#sign-up-container, #sign-in-container {
padding: 60px 80px;
width: 320px;
}
Note: If you opt to exclude the checkbox, you will need to tweak more on your CSS code (hint: the password input is going to lose its style because it’ll be the last of type).
Lastly, let’s hide the sign-in form as it shouldn’t be visible if the user doesn’t click the Sign In button. Assign a class of hide to the sign-in-container that has a display of none.
.hide {
display: none;
}
So this should be what it looks like once the sign-in form is hidden:
Inserting Lottie animation in HTML code
Feel free to insert an image of your choice – we’ll go with a free Lottie animation from LottieFiles which you can get right here.
You might be prompted to make an account that is free – you can even sign up using a Google account (if you have one).
Getting the Lottie animation
Once you’re logged in and click on the link, you should be on this page:
Deselect Controls so they’re not visible on the animation. Then scroll to the Generated Code section where you will find a <script>
tag holding the JavaScript that powers the animation and the <lottie-player>
tag that holds the animation.
Back in the HTML file add an animation-container and place the <lottie-player>
code inside.
<div id="animation-container">
<lottie-player
src="https://assets3.lottiefiles.com/packages/lf20_aesgckiv.json"
background="transparent"
speed="1"
style="width: 300px; height: 300px;"
loop
autoplay>
</lottie-player>
</div>
Add the script tag towards the end of your body tag where you typically place external JavaScript files.
For how to insert JavaScript in HTML check out How To Link Javascript To HTML, 3 Ways.
Your Lottie animation should now display on the page. Let’s move it so it lies beside the form on the right-hand side.
First, give the sign-up-form and sign-in-form containers each a display of inline-block so a single form container doesn’t take up the entire width. This will undo the hide class we added to the sign-in form, but easily reinforce it by specifying !important.
.hide {
display: none!important;
}
Also, give animation-container a display of inline-block. This is what you should have so far:
Make the Lottie animation larger by changing the width and height under the style attribute on the <lottie-player>
tag.
Hint: If you want a static “image” instead of an animation, delete the autoplay attribute in the
<lottie-player>
tag.
How to toggle between the Sign-Up and Sign-In forms
When an existing user lands on the page and clicks on the Sign In button, three things will happen:
- the sign-up form will be replaced with a sign-in form
- the Sign In button will change into a Sign-Up button
- the Sign-Up button will change into a Sign In button
The user can toggle back to a Sign-Up form by clicking the right Sign Up button. We can set this behavior using basic vanilla JavaScript.
Show the sign-in form
We’ll use an external JavaScript file to write our click actions. If you use an external file don’t forget to include it towards the end of the body after your Lottie animation script tag.
<script type="text/JavaScript" src="./my-script.js"></script>
In the JavaScript file, select the button with a type of button and store it as a variable called toggleBtn. This element will always have a toggle function whether it’s to bring up the Sign-In form or to bring the Sign-Up form if a user is viewing the Sign-In form.
As a little check to verify the JavaScript file is linked correctly with the HTML file, on toggleBtn listen for a click event then execute a little message alert. So when you click on the Sign In button, you will get an alert prompt.
const toggleBtn = document.querySelector('button[type="button"]');
toggleBtn.addEventListener('click', () => {
alert('You clicked the button!');
});
Now, instead of alerting a message, we want to do two things:
- show the Sign-In form
- hide the Sign-Up form
To start, add identifiers to the two different toggle buttons (the ones with the type of button). Here we gave the toggle button in the sign-up form an id of toggleSignIn and the one on the sign-in form an id of toggleSignUp.
Then grab the two toggle buttons and form containers, storing each in variables so we can point to them.
const signInBtn = document.querySelector('#toggleSignIn');
const signUpBtn = document.querySelector('#toggleSignUp');
const signUpForm = document.querySelector('#sign-up-container');
const signInForm = document.querySelector('#sign-in-container');
Since toggling the hide class between the two different forms will be a repeated action, to avoid re-writing the same lines of code we can create a function.
We called the function changeForm but you can name it anything you want. This function takes in two parameters – form1 and form2. These are generic names (again, you can call them whatever you want), basically stand-ins for the two forms we are going to pass into the function so we can toggle the hide class.
const changeForm = (form1, form2) => {
form1.classList.toggle('hide');
form2.classList.toggle('hide');
}
When the user clicks on the Sign In button, show the sign-in form:
signInBtn.addEventListener('click', () => {
changeForm(signUpForm, signInForm);
});
Toggle between the sign in and sign up forms
This time, when the user clicks on the Sign-Up button, show the sign-up form:
signUpBtn.addEventListener('click', () => {
changeForm(signUpForm, signInForm);
})
Note: There are different ways to do this – try to come up with another method as an extra challenge!
Make the forms responsive
One more thing to do before wrapping up this project is to make the forms responsive for smaller screen sizes.
For smaller screens, we’ll hide the animation and present the user with a clean, straightforward form.
We’ll use CSS media queries and Google’s Inspect tool to determine and set different breakpoints.
At first, let’s decrease the width of the Lottie animation to 300px for screen sizes less than 1438px.
@media(max-width:1438px) {
lottie-player {
width: 300px!important;
}
}
Then hide the animation-container when the screen size is smaller than 1124px and center the form in the inner-form-container.
Then hide the animation-container when the screen size is smaller than 1124px and center the form in the inner-form-container.
@media(max-width:1124px) {
#animation-container {
display: none;
}
#form-inner-container{
display: flex;
justify-content: center;
}
}
Lastly, for any device with a screen size of less than 684px let’s do a few things:
- center the form-controls container and make the buttons full-width
- adjust the width of the form inputs and dimensions of the checkbox and those of its label
- correct the padding on the two form-control buttons
@media(max-width: 684px) {
#form-controls {
text-align: center;
margin: 0;
padding: 0;
}
button {
width: 100%;
}
form input:not(:last-of-type) {
width: 85%;
}
#toggleSignIn, #toggleSignUp {
padding: 16px 75px;
}
#terms {
width: 20px;
height: 20px;
}
label[for="terms"] {
display: inline-block;
font-size: smaller;
}
}
And that’s it – pat yourself in the back, you deserve it! You can grab the full code on Github.
Follow THT on social media – we’re Instagram-ing, Tweet-ing, and Facebook-ing these days 😉
Check out another JavaScript project on 5 Ways To Access HTML Elements With JavaScript.