Build a Login Page with HTML, CSS & JavaScript

Have you ever wondered what’s happening behind the scenes when you click the login button on your favorite website? There are a a lot of ways that apps and websites handle form submissions like login forms. One way is to call a function (a group of commands) when the button is click. The commands in the function check to see that the data that was entered in the login form is valid (it’s in an acceptable format that the server expects). If everything’s OK, the function will send the data to a server for further verification. If something went wrong, the function can produce an error like “Incorrect username or password”.

In this tutorial, I’ll show you how to build your own login form and do basic login validation. We’ll start by writing out the HTML code. Then, we’ll style the form with some CSS. Finally, we’ll do all the validation in JavaScript. To follow along with the tutorial, it’s best if you have a basic understanding of how HTML and JavaScript works. Here are some other tutorials on the site that cover these topics.

For this tutorial, we’ll be using CodePen to write our HTML, CSS and JavaScript code. To get started, login to CodePen, and create a new pen. We won’t be neding any external styles or scripts.

Creating an HTML Form

Whenever I create a web page, I like to have some kind of container. Having a container element allows you to control the responsiveness of the page. That means you’ll be able to define how the content on the page behaves on different screen sizes.

Inside the container, we need a title to let users know that this is the login page. I’ve given the h1 tag a title class so that I can style it later. This isn’t necessary ,but it’s nice to have because it mens that I can apply the same title styles to any element on the page.

<main class="container">
	...
</main>	<!-- .container -->

Now we can start building the form. In HTML, all the elements in a form belong in a form tag. That tells the browser that all the elements inside the form are collecting data that will go to the same place. It is possible to have multiple form son a page. For example, we could have a search form in the header and a login form on the same page. the browser needs to know which form fields belong to which form. Normally, a form would have an action attribute that points to a file where the data from the form is sent to be handled once the submit button is clicked. We won’t be sending our login data to a different page. We want to run a function when the submit button is clicked. To do that, we use the onsubmit attribute and call a function that we’ll write later.

<main class="container">
	<h1 class="title">Login</h1>
	<form class="form" onsubmit="login(event)">
		...
	</form>	<!-- .form -->
</main>	<!-- .container -->

Every field in the form will have two elements, so we’ll wrap them in a paragraph tag to group them together and make the styling easier later. Each form field needs a label and an input. The label is the text that appears next to the input and the input is the text box that you type into.

The label has a for attribute that tells the browser which input it belongs to. It should have the same value as the ID on the input field that it’s labeling. For the Email field the label’s for attribute has a value of email and the input field below it also has an ID of email. This same pattern is used for the password field.

The text that appears on the page goes in between the two label tags.

Along with the ID attribute, the input field also has a type attribute. This lets the browser know what type of information to expect. For the password field, the input has a type of password which tells the browser that we’re expecting a password. For security, the browser won’t show the text that the user enters in an input of type password. It’ll show a black circle in the place of each character.

The input field also has a name attribute. This is the name that can be used to access the text that the user entered..

The last attribute on the input field is the placeholder. That’s the gray text that appears in the text box that disappears when you start typing.

<main class="container">
	<h1 class="title">Login</h1>
	<form class="form" onsubmit="login(event)">
		<p class="form__field">
			<label for="email" class="form__label">Email</label>
			<input type="email" name="email" id="email" class="form__input" placeholder="Email">
		</p>	<!-- .form__group -->
		<p class="form__field">
			<label for="password" class="form__label">Password</label>
			<input type="password" name="password" id="password" class="form__input" placeholder="Password">
		</p>	<!-- .form__field -->
	</form>	<!-- .form -->
</main>	<!-- .container -->

The last part of the form is the footer which will contain the submit button and an error message. The error message is just a paragraph with some text to tell the user that the information they entered was incorrect. We’ll use CSS classes to hide the message when the page loads. Later, we’ll use JavaScript to change the class to show the message if something went wrong.

The submit button is also an input that has a type of submit. This input will appear on the page as a button instead of a text field. The submit type also tells the browser that when the user clicks the button, they are done with the form and the data is ready to be processed. The submit button doesn’t have a label, but we can tell the user it’s a login button by adding the word Login to the value attribute.

<main class="container">
	<h1 class="title">Login</h1>
	<form class="form" onsubmit="login(event)">
		...
		<footer class="form__footer">
			<p id="error" class="form__msg--hidden">
				Incorrect Email or Password
			</p>
			<input type="submit" value="Login" class="form__submit">
		</footer>
	</form>	<!-- .form -->
</main>	<!-- .container -->

Styling the Form with CSS

Now that we have all of our HTML elements on the page, we can start making them look a little better. Each element on the page has a class. In CSS we can select the elements by their class and add styles to them. The nice thing about classes is that we can use the same styles throughout the page.

About CSS

In CSS, we use selectors to apply styles to HTML elements. You can select elements by tag names like h1 or p. When you do that, you’re telling the browser that you want these styles to be applied to every h1 or p element on the page.

You can also select elements by class. All you need to do is place a dot (.) before the class name. That tells the browser that you want the styles to be applied to all elements that have the class you specified.

You can make your CSS selectors as specific as you need to. Let’s say you only want to select the links that are inside a paragraph. The selector would look like this

p a {

}

You can also apply two selectors to the same set of styles. All you need to do is separate the selectors with a coma. The following code selects both main elements and footer elements

main, footer {

}

All the styles that apply to the selected elements go between the curly braces that come after the selector. Styles have two components: a property and a value. The property and the value are separated by a colon and each style must end with a semi colon.

Usually, a property only takes one value. For example, the background-color property takes a single color. The browser has some default colors that you can use by name like black and white. The following code adds a light blue background to a paragraph element

p {
	background-color: lightblue;
}

Some properties combine other properties. these properties require multiple values. The border property combines the border-width, border-style and border-color properties so it takes three values. The following code adds a thin blue solid border around a paragraph element

p {
	border 1px solid blue;
}

BEM Naming Convention

When working with CSS classes it’s good to have a system for naming your classes so that you know what they’re for. In this tutorial we’ll be using the BEM naming convention. BEM stands for Block Element Modifier.

A Block is a section on the page that we want to be able to reuse. In our case, the form is our block. If we wanted to,we could reuse these styles and create another form like a sign up or checkout form. If we use the use the same classes, the forms will look consistent throughout the site.

The Elements are the different parts of the Block. For example, the input tags have a class of form__input. That tells us that the input belongs to a form block.

The Modifier lets us change the way the elements look in different states. The form__msg--hidden class tells us that this is a message element in the form block and that it’s in the hidden state. The styles in this class should hide the element. Later, we’ll use JavaScript to change the modifier to say error and the styles will change so that the text appears and looks like an error message.

Reset

All web browser provide default styles to HTML elements. For example, the headings are bold, have a large font size and some margin on the top and bottom. When providing your own styles, it can be helpful to reset some of those properties. This can prevent some confusion later if you’re styles don’t seem to be working the way you expect them to.

To perform a reset, you need to select all the elements on the page using the * wildcard selector.

I like to reset the margin to 0 and give the padding 1 pixel. That ensures that all elements have no spacing and that the margins that I add later don’t spill out of their parent element.

The last attribute to reset is the box-sizing which should have a value of border-box. Normally, when you add padding to an element, the dimensions (width and height) of the element will change. By setting the box-sizing to border-box, we’re saying that we want the dimensions of the element to stay the same.

* {
	margin: 0;
	padding: 1px;
	box-sizing: border-box;
}

Page Layout

We want the form to be centered on the screen both horizontally and vertically. To do that, we need to add some styles to the body tag. We’ve never added a body tag in CodePen because It’s already added for us behind the scenes. Every web page need a body tag, so the developers at CodePen decided to add it by default in every project.

To center the content on the page, we need to give the body a display property with flex as its value. This allows us to use a feature in CSS called flex box which makes it easy to position elements inside the body. With the display set to flex, we get access to the justify-content and align-items properties. The justify-content property works like the text justification buttons in a word processor. The align-items property works in a similar way but it aligns the elements vertically. Both of these properties should be set to center.

Now the content is centered horizontally and not vertically. That’s because the body element only takes up just enough height to fit the elements inside of it. We need to ensure that no matter what’s inside the body, it’ll at least cover the entire screen. For that, we set the height property to 100vh. vh stands for Viewport Height and it works in percentages. The Viewport is the area of the browser where the page is being shown. We’re saying that the body element should take up the full height of the viewport.

body {
	display: flex;
	justify-content: center;
	align-items: center;
	height: 100vh;
}

Container Styles

To make the form pop out, we can add a card styling to the container. A card is a UI element that groups content in a box with some padding, a slight drop shadow and slightly rounded corners. Also, cards don’t typically take up the full width of the screen, so we’ll need to tell the browser how wide we want the element to be.

Let’s start with that. All we need to do is set the width property to something like 300 pixels. Pixels are small squares on your screen. The computer assigns a color to each of these squares and they make up the visual display that you see on the screen. Pixels are a unit of measurement that developers ue when talking about the size of something like the width, height, margin or padding on an element. The average iPhone screen is about 375 pixels wide, so our container is taking up most of that space on a small screen. As the screen gets bigger, the size of the container will stay the same.

To add padding to the container, use the padding property. Padding is spacing that goes inside the element. You’ll notice this when we place the border around the container next. Since we set the box-sizing to border-box the padding will cause the content area of the element to shrink and the overall width of the element to stay the same. Since we only set the with, the content will wrap over to the next line, causing the height, which is unrestricted, to increase.

To give the container rounded corners, use the border-radius property and give it a value of 0.5rem. rem is a unit of measurement in CSS. it means that we want to set the border radius relative to the base font size. We can set the base font size by selecting the html element (another tag provided by CodePen behind the scenes) and giving it a font-size of 20 pixels. That makes our border radius 10 pixels

html {
	font-size: 20px;
}

Note: CSS works from top to bottom, so I like to order my selectors by the way the appear on the page. I placed the html styles between the reset and body selectors.

But what does it mean for a border radius to be 10 pixels? Imagine that there is a circle at each corner. The distance from the center of the circle to the edge of the circle is 10 pixels. Instead of having a sharp corner, the edge of the container element will wrap around that circle, giving it a slightly rounded edge.

The border property takes three values. It needs the width of the border, the border style and the color. Usually, the border width is only 1 pixel and the style is solid. There are other styles like dashed or inset. The last value is the color which we’ll give the hexadecimal color #fafafa. It’s a very light gray and you’ll find it used all over the web.

The last property we need to set for the container is the box-shadow that will add a shadow to the bottom of the container. This property takes a whole bunch of values, but we’ll only use four: the X offset, Y offset, blur radius and color. The X and Y offset tells the browser how far out the shadow should go in each direction. The blur radius tells the browser how soft you want the shadow to be. Since we only want a shadow at the bottom of the container, we’ll leave the X offset at 0 and give the Y offset a value of 20 pixels. The blur radius should also be 20 pixels, making the shadow a smooth transition from color to the background. Lastly, we’ll set the color to a hexadecimal #ccc which is another light gray that’s slightly darker than the border.

.container {
	width: 300px;
	padding: 20px;
	border-radius: 0.5rem;
	border: 1px solid #fafafa;
	box-shadow: 0 20px 20px #ccc;
}

Title Styles

It would be nice if the title was in the center of the screen and had some spacing from the form fields.

To center the text, set the text-align property to center.

To add spacing between elements, set the margin property. The margin property takes up to four values, but we’ll only provide two. The first value tells the browser how much spacing we want on the top and bottom, and the second value tells the browser how much spacing we want on the left and right. We only want margin on the top and bottom and not the left and right, so we’ll give the margin property a value of 1.5rem 0. That means that the margin on the top and bottom will be 1.5 times the font-size that we set in the html element (30 pixels).

Optionally, you can set the font-size of the title element to something like 2rem to make it a little bigger, but it’s not required since the browser has default styles that make the h1 tag larger by default.

.title {
	margin: 1.5rem 0;
	text-align: center;
	font-size: 2rem;
}

Form Layout

Our form should take up the entire width of the container. We could set the width property to 100%, but that’s not the only way we can make the element full width. We can also set the display property to have a value of block. Elements that have a display of block automatically take up the full width of their parent element.

.form {
	display: block;
}

Styling the Form Fields

Since each field in our form has two elements, a label and an input, we grouped them under a single form__field element. To make the form easier to read, we’ll add spacing between the form elements. This will cause the label and input elements to be grouped together visually. To set spacing between the form elements, give them a margin of 0.5rem on the to and bottom and 0 on the left and right

.form__field {
	margin: 0.5rem 0;
}

Currently, the label and the input are on the same line, to make the form easier to read, we want them on separate lines with some spacing between them. The reason that the label and the input are on the same line is because by default, the browser sets the display property of these elements to be inline. To fix that, we can override the default style by assigning the form__label element a display type of block. Then , the label will take up the entire width of the form, causing the input to move to the next line. The only thing left to do for the label is to give it 0.25rem margin on the bottom of the element using the margin-bottom property.

.form__label {
	display: block;
	margin-bottom: 0.25rem;
}

We also want the inputs (the text boxes) in the form to take up the full width of the form, so we can set those to display: block, just like the label.

I don’t like the default styles that the browser has for inputs, so we’ll be changing a few of them. First, lets get rid of that ugly inset border by giving it a with of 1 pixel, style of solid and a gray color. Then we can round the corners by setting the border-radius property to something small like 0.5rem. Finally, we can add some padding so that the text inside the input has some room to breathe. I like to add a little more padding on the left and right because it looks a little nicer when you have rounded corners.

.form__input {
	display: block;
	border: 1px solid #ccc;
	border-radius: 0.5rem;
	padding: 0.5rem 0.75rem;
}

Interactive elements like inputs and buttons have different states, so we can make them look different when the user has selected the input to type in it. To do that, we use something called a pseudo selector. First, select the form__input class, then add a colon and the word focus. That means that the styles that we specify here will only apply when the user has selected the input by clicking on it or when you’ve selected it with a screen reader. A similar pseudo selector is :active. We also want our styles to apply to this pseudo selector so add a comma after the last selector and add another one selecting the same class. Then addd the colon and then typing active.

.form__input:focus,
.form__input:active {
	...
}

When the input is in focus, the browser adds an ugly black box around the element to indicate that it has been selected. We can get rid of that by setting the outline property to none. Now we need to provide our own indicator to let the user know that the input has been selected. A good way to do that is by changing the border-color.

.form__input:focus,
.form__input:active {
	outline: none;
	border-color: cornflowerblue;
}

Footer Styles

The last section of the login form is the footer. It’ll have some spacing on the top, followed by a light border, and some padding on the inside. To accomplish this, we’ll set the margin, top border and padding, so you’ll be able to see the difference between margin and padding. The margin is the spacing outside of the border and the padding is the spacing inside the border.

Also, all the text in the footer needs to be centered, so we can set the text-align property to center in this element, and it’ll get applied to all the elements within the footer.

.form__footer {
	margin-top: 1rem;
	border-top: 1px solid #eee;
	padding: 1rem 0;
	text-align: center;
}

Next, let’s style the error message. Go back into the HTML and change the class from form__msg--hidden to form__msg--error. The form__message--error is the class that’ll be used when we want to show the error message. The styles for this element are simple. It has rounded corners, some padding, a pink background color and red text.

The form__msg--hidden class only has one property. It sets the display property to none. This tells the browser to act like that element doesn’t exist. It doesn’t appear visually on screen and a screen reader will skip over it.

.form__msg--error {
	border-radius: 0.5rem;
	padding: 0.75rem;
	background-color: pink;
	color: red;
}

.form__msg--hidden {
	display: none;
}

Once you’ve added these styles, go back to the HTML and change the class so that the error message is hidden. That will be the default when the page loads. When the user clicks the submit button, the JavaScript code will change the class to show the error if it needs to.

The last element to style is the submit button. It has rounded corners, a blue background, some padding and white text. When the users’s mouse hovers over the button, or a screen reader focuses on it, the colors are inverted so that the text color and border are blue and the background is white. Lastly, don’t forget to get rid of that ugly outline on the focus and active pseudo selectors.

.form__submit {
	border: none;
	border-radius: 0.5rem;
	padding: 0.5rem 1rem;
	background-color: cornflowerblue;
	color: white;
	transition: 0.25s;
}

.form__submit:hover,
.form__submit:focus {
	border: 1px solid cornflowerblue;
	background-color: white;
	color: cornflowerblue;
	cursor: pointer;
}

.form__submit:focus,
.form__submit:active {
	outline: none;
}

Validating the Form with JavaScript

In our HTML code, the form tag has an onsubmit attribute which calls a function called login. The login function takes a single event parameter. In our JavaScript code, we need to define this function.

What’s a Function?

A function is a group of instructions that performs a task. Just like mathematical functions, they can take in some values, do some calculations and give us back a different value. The values that a function takes in are called parameters. Not every function has them, but our login function has one. Based on the parameters, the function executes some instructions. When it’s finished with all the instructions, it can sometimes give us back (or return) a value. Our login function will only return a value if something went wrong.

To write a function, start by typing the function keyword in the JavaScript section on CodePen. Then, give the function the name login. followed by opening and closing parentheses. Whenever we use the word login followed by the parentheses, the browser will execute the instructions. The parameter for the function goes inside the parentheses. Our function has a parameter called event. It doesn’t matter what you call the parameter inside the JavaScript section. It’s just a variable name that you can use in the function’s instructions. The instructions that the function executes go between curly braces after the parentheses.

function login(event) {
	...
}

What’s a Variable?

You can think of a variable like a box. Inside the box, we can store different things like numbers, text, true/fale values, functions and objects. In our login function, our event parameter is also a variable. It’s a box that’s labeled “event”. Whenever we use the word event, the browser goes into the box and takes out whatever’s inside. The stuff inside the box is called the value.

The value of the event parameter/variable is an object. Objects are groups of variables, like placing a bunch of smaller boxes in a bigger box. To get to the variables inside of an object (called properties), place a dot (.) after the object’s variable name and then use the property name. for example, the first thing we need to do in our loginfunction is to call a function on the event object called preventDefault.

function login(event) {
	event.preventDefault();
}

The event.preventDefault function doesn’t take any parameters and it doesn’t give us back anything, it just does stuff. What does it do? it prevents the browser from performing the default behavior when the form is submitted. Normally, when a form is submitted, the data (and the user) get sent to a new page. We don’t want that to happen, we want to process all the data right here in this function on this page.

So far, we’ve only used a parameter as a variable, but we can also create variables inside our function. Throughout the function, we’ll need to keep track of whether the form is valid or not. That’s a true/false value (a.k.a. boolean). To create a variable (initialize it), start by typing the keyword let followed by the variable name isValid.

Variable names can be anything you want, but it’s best if you name them something that’ll help you remember what the variable is for or the kind of data it stores. Variable names can have letters, numbers and underscores, but it can’t start with a number. Also, a variable name cannot be a keyword, so we can’t have a variable called let or function or any other keyword.

After the variable name, you might want to set a default value for the variable by typing an = sign after the variable name, followed by the value (tru, for the isValid variable).

function login(event) {
	event.preventDefault();
	
	let isValid = true;

}

Variables aren’t the only way we can store information. We can also store information in constants. Constants work almost exactly like variables, except they can’t be changed. With variables, we don’t need to specify a default value, but with constants we do. Initializing a constant is similar to initializing a variable. Just replace the let keyword with the const keyword.

Inside the login function, we need to get the values out of the input fields into constants. Why constants and not variables? Because we want to be sure they never change. Variables could accidentally get changed and cause a bug. Bugs are what we call it when a program doesn’t work the way we want it to. To get the values from the inputs we need to get the inputs from the page using the document.getelementBydId function. The browser gives us a variable called document by default. It’s an object that has a function called getElementById that searches the page for an element that has the ID that we specify as a parameter. The function gives us back another object that represents the input element. That element has a value property which we can get and assign in a constant. Here, we’re getting the email and password that the user has typed into the text inputs before clicking the submit button.

function login(event) {
	event.preventDefault();
	const email = document.getElementById('email').value;
	const password = document.getElementById('password').value;

	let isValid = true;

}

Whenever you pull elements off the page and into variables, it’s good to check that the you got the value that you expected to get. Your browser has a tool called the console that developers use to check that the app is running correctly by writing messages to it at different points in the application. To write a message to the console, use the log function on the console object that the browser gives you by default. The log function takes one parameter: the text you want to show in the console. Here, we’ll print the email and the password that we got from the inputs.

function login(event) {
	event.preventDefault();
	const email = document.getElementById('email').value;
	const password = document.getElementById('password').value;

	let isValid = true;

	console.log(email);
	console.log(password);
}

To see the message, you’ll need to open the console that CodePen provides. The button to open the console is in the bottom left corner of the screen. When you first open it, you might see an error message (some text highlighted in red). Click the Clear button in the top right corner of the console and save the pen. Wait a few seconds.

If you see another error message, that mens that the browser can’t understand your code and you need to fix it before trying to submit the form. Check that your code looks exactly like the code provided. Once you’ve fixed it, clear the console and save the pen again. When all the errors are gone you can test out your form.

When you click the submit button, You should see the text you entered in two separate messages in the console. They’ll be wrapped in quotation marks. If you didn’t get that, check that the ID you provided to the getElementByID function is exactly the same as the ID you provided to the input If you do see the correct messages, you can delete the condole.log statements. We don’t need them anymore.

Note: If you’re still getting errors, try to copy and paste the message into Google to see if anyone else is having the same problem and how they fixed it. If that doesn’t work, leave the eror message and your JavaScript code in the comments and I’ll help you out!

Checking the Email Field

Now we can start checking to see if the fields are valid. Why do we need to check that the user entered valid information? In order to log the user in, you’d need to send the data off to a server (we won’t be doing that in this tutorial). That means making a request to a server. Making a request to a server takes time, and some web hosting services will charge you (as the developer) every time your app make a request. That means we need to be sure that we’re sending the right data to the server.

Let’s start with the email field. We need to be sure that the user entered a valid email address. You know, some user name followed by an at sign and then some domain name (example.com). When we need to check the formatting in a string (text), we use something called regular expressions (regex for short). With regular expressions, we’re providing JavaScript (or whatever language you’re using), with some kind of pattern. The browser will search for the pattern inside the string and can tell you if the string follows the pattern or not. We can store the regex in a constant like this.

Note: Writing regular expressions is outside the scope of the tutorial, so you can simply copy/paste this line into CodePen.

const emailRegex = /^(([^<>()[\\]\\\\.,;:\\s@"]+(\\.[^<>()[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;

That’s the pattern that the browse will look for in our email variable.

We want to show an error message if the email is not valid, so we should check if the email is NOT valid, using an if statement.

if (!emailRegex.test(email)) {
		...
	}

The browser will first evaluate the code inside the parentheses. If it’s true, then the code inside the curly braces will run. If it’s false, the code in the curly braces will be skipped.

Inside the parentheses of the if statement, we’re using the regex constant (a regex is an object) and using its test function. By providing the email variable as a parameter to the test function, we tell the browser to test the regex against the email string that the user entered. The function returns true if the email is valid and false if the email is not valid. The ! at the beginning of the statement flips the value. So, if the test function returns true (meaning the email was valid) the ! will switch it to false and the code in the curly braces will be skipped. If the test function returned false (meaning the email was invalid) the ! will switch it to true and the instructions inside the curly braces will be executed.

The only thing we need to do in the curly braces is set the isValid variable to false. At the start of the function, we set this variable to true, so we’re assuming the form dat is valid. If at any point in the function, we find that the data is not valid, we set this variable to false.

if (!emailRegex.test(email)) {
	isValid = false;
}

Checking the Password Field

We use a similar process to validate the password field. For security reasons, passwords are usually required to be 6 characters or longer. There are other requirements like numbers and special characters, but we’ll keep it simple for this tutorial. In JavaScript, we can treat a string of text like an object. In fact, in JavaScript everything is an object. A string object has a property called length that gives us the number of characters in the string. We just have to check that the string is less thant 6 characters long so we can set the isValid variable to false.

if (password.length < 6) {
	isValid = false;
}

Showing the Error Message.

So far, we’ve checked that the user entered a valid email. If they didn’t, the isValid variable was set to false. If it was, the variable remained true. Then, we checked if the user entered a password with more than 6 characters. If they didn’t the isValid variable was sett to false. If the email was invalid, the variable will remain false.

The isValid variable tells us whether the user submitted the form correctly. If it was submitted correctly, the isValid variable would have remained true. If any of the information (email or password) was invalid, the variable would be false. Knowing whether the form is valid or not will help us determine whether we should show an error message or not.

First, we can get the message element using the document.getElementById function and accessing its classList property. This property keeps track of the classes that are applied to the element. In our case, form__msg--hidden is the only class applied to the element when the page loads.

const messageClass = document.getElementById('error').classList;

Next, we can check if the form is not valid. if the form isn’t valid, we want to remove the hidden class and add the error class. The classList variable has a function called add and another one called remove. We can use these to add and remove the classes.

If the form is invalid, we want the user to be able to fix their input and try again. To make that hapen, we must return a value of false. When a function returns, the browser will jump out of the function and not execute any more code inside the function. If the function in a form’s onsubmit attribute returns false, that means the form wasn’t actually submitted and the user can try to submit it again.

if (!isValid) {
		messageClass.remove('form__msg--hidden');
		messageClass.add('form__msg--error');

		return false;
	}

If the form is valid and the browser skipped the above code, we want to remove the error class if it’s there because that mans that the user fixed their email and password. We also need to put back the hidden class.

messageClass.add('form__msg--hidden');
messageClass.remove('form__msg--error');

If the form was invalid, the function would have returned false and the above code would have been ignored.

Final Function

function login(event) {
	event.preventDefault();
	const email = document.getElementById('email').value;
	const password = document.getElementById('password').value;

	let isValid = true;

	const emailRegex = /^(([^<>()[\\]\\\\.,;:\\s@"]+(\\.[^<>()[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;

	if (!emailRegex.test(email)) {
		isValid = false;
	}

	if (password.length < 6) {
		isValid = false;
	}

	const messageClass = document.getElementById('error').classList;

	if (!isValid) {
		messageClass.remove('form__msg--hidden');
		messageClass.add('form__msg--error');

		return false;
	}

	messageClass.add('form__msg--hidden');
	messageClass.remove('form__msg--error');
}

Wrapping Up

Wow, we covered a lot in this tutorial. First, we used HTML to build the page structure. Then, we styled it with CSS, Finally we used JavaScript to validate the form and show an error message.

But there’s still more you can do with the project. You could show a different message when the user has entered a valid email and password. Or, you could turn the form into a signup form that asks for a username, email, password and password confirmation.

Leave a comment

Your email address will not be published. Required fields are marked *