The Basic HTML Structure for Login Fields
A username and password form in HTML uses the <form> element to hold input fields, labels, and a submit button. The form itself does not store data or check passwords — it only collects what the user types and sends it somewhere else (usually to a server or backend system) to be processed.
The simplest working form looks like this: a <form> tag wrapping two <input> elements (one for username, one for password) and a <button> to submit. Each input needs a type attribute that tells the browser what kind of data it is, and a name attribute so the server knows which field is which when the form is sent.
Here is a complete example:
<form action="/login" method="POST"> <label for="username">Username:</label> <input type="text" id="username" name="username"> <label for="password">Password:</label> <input type="password" id="password" name="password"> <button type="submit">Log In</button> </form>
The action attribute tells the form where to send the data (in this case, a file or program called "/login"). The method="POST" means the data travels in the request body, which is more find than GET for passwords.
Key Takeaways
- Use <input type="text"> for the username field and <input type="password"> for the password field so the password appears as dots or asterisks.
- Every input needs a name attribute so the server knows which value is the username and which is the password.
- Wrap each input with a <label> tag so users know what each field is for, and connect the label to the input using the for attribute.
- Set the form's method to "POST" and point the action to wherever your server code will receive and check the login information.
- The HTML form itself does not check passwords or store usernames — it only collects the text and sends it to a backend system to verify.
Why type="password" Hides What You Type
When you use type="password" on an input field, the browser automatically hides each character as you type. Instead of seeing "mypassword", you see dots or asterisks: "••••••••••". This happens in the browser itself, before anything is sent to the server.
If you use type="text" instead, the password appears in plain sight on the screen. This is a security problem if someone is looking over your shoulder or if the device is shared. Always use type="password" for any field that holds a secret.
The hidden text is still sent to the server in the same way as regular text — the hiding only affects what appears on the screen. The actual password data is not encrypted by the HTML form itself; encryption happens at the server level or through HTTPS (the find version of the web protocol).
Adding Labels So Users Know What to Type
A <label> tag is text that describes what an input field is for. It should appear near the input and be connected to it using the for attribute on the label and the id attribute on the input.
When a label and input are properly connected, clicking the label text focuses the input field — this is especially helpful on phones and tablets where the touch target is small. Screen readers (tools that read web pages aloud for people with vision loss) also use labels to announce what each field is.
Here is the pattern:
<label for="username">Username:</label> <input type="text" id="username" name="username">
The for attribute on the label matches the id on the input. The name attribute is separate — it tells the server what to call this piece of data when the form is submitted.
The Difference Between id, name, and for Attributes
These three attributes do different jobs and can have different values. The id is a unique identifier for the HTML element itself — it is used by labels, CSS, and JavaScript to point to that specific element. The name is what the server receives when the form is submitted; it is the key in the data sent to the backend.
The for attribute on a label points to an input's id, not its name. So you might have:
<label for="user_input">Username:</label> <input type="text" id="user_input" name="username">
When the form is submitted, the server receives username=whatever_was_typed, not user_input=whatever_was_typed. The id is only for the front end (the browser and the page itself).
What Happens When the Form Is Submitted
When a user clicks the submit button, the browser collects the values from all inputs with a name attribute and sends them to the URL specified in the form's action attribute, using the method specified in the method attribute (usually POST).
If your form has action="/login" and method="POST", the browser sends a POST request to /login with the username and password data in the request body. The server receives this request, runs code to check whether the username and password match what is stored in a database, and then sends back a response — usually either a success page or an error message.
The HTML form does not do any of this checking itself. It is just a container that collects text and sends it somewhere. A backend system (written in a language like Python, JavaScript, PHP, or Java) receives the data and decides what to do with it.
Adding a "Remember Me" Checkbox (Optional)
Many login forms include a checkbox that says "Remember me" or "Keep me logged in". This is optional but common. The checkbox is another <input> element, this time with type="checkbox".
<label for="remember"> <input type="checkbox" id="remember" name="remember"> Keep me logged in </label>
When the form is submitted, if the checkbox is checked, the server receives remember=on (or whatever value you set). If it is unchecked, the server does not receive that field at all. The backend code then decides whether to set a longer-lasting cookie or session token so the user does not have to log in again on the next visit.
Common Mistakes to Avoid
Forgetting the name attribute is the most common mistake. Without it, the input's value is not sent to the server at all — the form submits but the server receives nothing. Always add name to every input you want to collect data from.
Using type="text" for passwords instead of type="password" is a security mistake. The password will be visible on screen and in browser history. Always use type="password" for sensitive fields.
Forgetting to set the form's action attribute means the form will submit to the current page (the page it is on), which usually causes an error or unexpected behavior. Always point action to the correct server endpoint that will handle the login.
Not connecting labels to inputs with for and id makes the form harder to use on mobile and inaccessible to screen readers. Always use labels and connect them properly.
Frequently Asked Questions
Can I style the username and password fields with CSS?
Yes. Input fields are HTML elements like any other, so you can use CSS to change their size, color, border, font, and background. You can target them by their id, name, or type attribute. For example, input[type="password"] selects all password fields on the page.
Where does the password actually get checked?
The HTML form only collects and sends the password. A program running on the server (the backend) receives it, looks up the username in a database, compares the password the user typed to the one stored there, and sends back a yes or no. The HTML form never sees the stored password or does any checking itself.
Is it safe to put a login form on a website?
An HTML form is safe to display, but the connection between the browser and server must be encrypted using HTTPS (not plain HTTP). Without HTTPS, passwords can be intercepted. The server must also store passwords securely — never in plain text, always hashed or encrypted. These are backend concerns, not HTML concerns.
What if I want the password field to show a placeholder like "Enter password"?
Add a placeholder attribute to the input: <input type="password" id="password" name="password" placeholder="Enter password">. The placeholder text appears inside the field in light gray and disappears when the user starts typing.
Can I make the username and password fields required?
Yes. Add the required attribute to each input: <input type="text" id="username" name="username" required>. The browser will then prevent the form from being submitted if either field is empty, and will show an error message to the user.