Skip to content

Lab 02: Creating an HTML Form

This lab activity explores some more features including those in HTML forms and intermediate CSS. We will attempt to create a Student Record Form in HTML utilizing these features (minus information retrieval, this will be covered when we go through PHP).

We will attempt to recreate a form resembling the one as shown below:

Lab 02 Form

Note

Right-cick on the image and select "Open Image in New Tab" to have a clearer view of the image.

General Requirements

If you'd like to take a crack at this on your own, here are some requirements to satisfy. Otherwise, skip over to #getting-started to follow through.

Image Assets

For this activity, you will require some image assets to work with. Download them HERE.

External Font

The font used to create this form is called Urbanist, and it can be found in Google Fonts. Click HERE to open the Google Fonts page showcasing the font and to get details on incorporating it into your web form.

Project Folder Structure

It is suggested that you follow this project folder structure. Just in case you do not, though, ensure that the proper modifications are made.

project
|-- css
  |-- main.css
|-- images
  |-- logo.png
  |-- taylors-bg.jpg
|-- index.html

For Status under Personal Particulars, include the following in the drop-down list:

  • Please select status (disabled, selected)
  • Active
  • Deferred
  • Graduated
  • Terminated

For Enrolled Program under Academic Record, include the following:

  • Please select a program (disabled, selected)
  • Foundation in Computing (FIC)
  • Diploma in Information Technology (DIT)

Form Submission

Upon selecting the Submit button, redirect it to a different webpage called form-submitted.html. In this page, create a webpage that essentially lets the website visitor know that the details entered into the form have been successfully collected. Include any other element/text/etc. that can be considered relevant here.

Extra Task

Consider someone who may open your form on a mobile device such as a smartphone or tablet. Web developers or designers make use of the following meta tag in the <head> section:

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

This will set the viewport of the webpage, which will give the browser instructions on how to control the page's dimensions and scaling.

Apart from that, media queries were used to cater for different screen sizes. Look up media queries online and try to incorporate it into your web form. You may use your browser's inspector tool to simulate viewing the webpage from a mobile device of your own choosing.

Getting Started

Let's begin.

Initial Setup

Start with the typical HTML boilerplate code. If you're using VSCode, you may use this shortcut: type html and select html:5 in the dropdown menu that appears (selecting just html is fine too, but I think you'll need to populate it a little bit more). It should then produce the following boilerplate code (along with some changes):

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Student Record Form <!-- (1)!--></title>

    <link rel="stylesheet" href="css/main.css" />
  </head>
  <body></body>
</html>
  1. Set the <title> attribute value to "Student Record Form".

Apart from this, we will start with an empty main.css file.

Video Walkthrough

If you would like a step-by-step walkthrough to complete this form, you may view it below. I have placed several timestamps to mark down a few steps to producing this HTML form.

Otherwise, you may follow the steps laid out in the next section. The steps follow the order in which I took to create this form as per in the video walkthrough.

Steps

Font Implementation

From the Google Font page containing the Urbanist font, click on Get Embed Code. Select the @import radio button in the "Web" tab, and copy the import statement. Do not include the <style> tags, this will cause errors otherwise since it's not CSS syntax.

Correct Options for Font Embedding from Google Fonts

Paste that @import statement as the first line in main.css, followed by specifying it as the font to use throughout the webpage.

1
2
3
4
5
@import url("https://fonts.googleapis.com/css2?family=Urbanist:ital,wght@0,100..900;1,100..900&display=swap");

* {
  font-family: "Urbanist", Arial, sans-serif;
}

Form Element

Back in index.html, let's add in a <form> element inside the <body> section. For our student record form, this will be considered the parent element containing all structural aspects of the form. Ensure that the action and method attributes are entered correctly. The method value being post over get is not important now, but it's important later on once we implement information retrieval in a subsequent lab activity.

Form Element
1
2
3
4
5
6
7
8
9
<form action="form-submitted.html" method="post">
  <!-- Letterhead -->
  <header class="center" id="top-title"></header>

  <!-- Personal Particulars -->
  <fieldset class="container" id="personal-particulars"></fieldset>

  <!-- Academic Record -->
</form>

Inside the <header> section created inside the <form> element, insert the letterhead logo logo.png and an <h1> element with text "Student Record Form". Set the alt attribute of the <img> element created as "Taylor's Logo". I happen to keep all the images in this project in a subfolder called images, so I will reference that in the <img> element's src attribute. You'll want to place in an appropriate path to logo.png as appropriate, more appropriately at least within your project folder.

Letterhead Logo Header
1
2
3
4
<header class="center" id="top-title">
  <img src="images/logo.png" alt="Taylor's Logo" />
  <h1>Student Record Form</h1>
</header>

Adding the "center" class inside the <header> element, as well as the ID #top-title to this same element allows us to target it with new CSS styling. We will use the "center" class to specify that for each container element that has this class, all the text will be centered.

Letterhead Logo CSS Styling
1
2
3
.center {
  text-align: center;
}

You should now see that the contents in the <header> element are properly centered, proper for the letterhead in our web form.

Personal Particulars

A <fieldset> element tends to go along with a child <legend> attribute. Inside this <legend> attribute, rather than just inserting the text "Personal Particulars" directly, let's place it as an <h2> element instead. This is merely just to make it stand out a little bit - you can get by with other ways like using <p> or <span> elements, but that may require a different set of CSS styling altogether.

Personal Particulars Fieldset
1
2
3
4
5
<fieldset class="container" id="personal-particulars">
  <legend>
    <h2>Personal Particulars</h2>
  </legend>
</fieldset>

The .container class given to this fieldset (including the other fieldsets in this form) borrows from how we have a container class readily available in CSS frameworks like Bootstrap or Tailwind CSS. While we're not necessarily going to create something that's as complex, this is a nice reusable class we can use for various visual aspects of our webpage. We will set our .container style as follows:

1
2
3
4
5
.container {
  width: 87.5%;
  margin: 0 auto;
  padding: 0 1.5rem 1.5rem;
}

Back in the HTML code, let's structure our textfields. We will introduce a section.row element; borrowing again from Bootstrap and Tailwind CSS, the .row class, this will enable us to use .column-x classes to prepare a visually clean column layout on wider screens (such as on laptops and desktops) and return to a single layout in narrower screens (such as on mobile devices).

We should structure our HTML first before getting to styling them in CSS - realistically I believe it's better than speculating what styles should be present before including the scaffolding in our code. We house the required textfields inside each of the section.column-50 elements accordingly. (The naming convention column-50 (generally, column-x where x is an integer) indicates 50% of the browser window's width.)

Row 1: First Name, Last Name

For each of the textfields (First Name and Last Name), we will keep their respective name and id attribute values the same. Including an id value will help especially when involving JavaScript code, whilst name is important for PHP later on. The required attribute will ensure that the textfield is filled up first before form submission is allowed, while autofocus makes it so that specific textfield which has this attribute will be focused on as soon as the page loads (you can see this textfield highlighted upon the page being fully loaded).

Personal Particulars Fieldset
<fieldset class="container" id="personal-particulars">
  <legend>
    <h2>Personal Particulars</h2>
  </legend>

  <section class="row">
    <section class="column-50">
      <label for="first-name">First Name</label><br />
      <input
        type="text"
        name="first-name"
        id="first-name"
        placeholder="First Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="last-name">Last Name</label><br />
      <input
        type="text"
        name="last-name"
        id="last-name"
        placeholder="Last Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- /section.row -->
</fieldset>

By this point, you should see that without placing in the CSS styling, the arrangement of these two textfields do not match. It's fine, let's carry on with the rest of the HTML code in this fieldset first.

Row 2: Student ID, Status

Let's create another section.row element with two more section.column-50 child elements again, this time for the Student ID and Status.

  • For the Student ID textfield, we make use of a pattern attribute, which generally takes in a regular expression (regex) value that will restrict what string inputs are accepted. You can generate regular expressions you require easily here. Learn more about them here. (Try to figure out what kinds of input string patterns are allowed based on the used regex used.)
  • Status input will be in the form of a dropdown input list using the <select>, where users get to choose any of the given options (each as its own <option> element). For each <option> element, a value attribute is expected. The selected attribute makes it so that this <option> is pre-selected immediately once the webpage is fully loaded. We can also use the disabled attribute to prevent anyone from selecting this option (greyed out, similar to a disabled checkbox or radio button).
Personal Particulars Fieldset
<fieldset class="container" id="personal-particulars">
  <legend>
    <h2>Personal Particulars</h2>
  </legend>

  <section class="row">
    <section class="column-50">
      <label for="first-name">First Name</label><br />
      <input
        type="text"
        name="first-name"
        id="first-name"
        placeholder="First Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="last-name">Last Name</label><br />
      <input
        type="text"
        name="last-name"
        id="last-name"
        placeholder="Last Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- /section.row -->

  <section class="row">
    <section class="column-50">
      <label for="student-id">Student ID</label><br />
      <input
        type="text"
        name="student-id"
        id="student-id"
        placeholder="Student ID"
        pattern="[0-9]{4}[a-z,A-Z]{1}[0-9]{5}|03[0-9]{5}"
        required
      />
      <!-- Use https://www.regexpal.com to craft regular expressions -->
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="status">Status</label><br />
      <select name="status" id="status">
        <option disabled selected>Please select status</option>
        <option value="active">Active</option>
        <option value="deferred">Deferred</option>
        <option value="graduated">Graduated</option>
        <option value="terminated">Terminated</option>
      </select>
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- section.row -->
</fieldset>

Row 3: Address

Continuing on, we create yet another section.row element, just to contain the Address textfield.

Personal Particulars Fieldset
<fieldset class="container" id="personal-particulars">
  <legend>
    <h2>Personal Particulars</h2>
  </legend>

  <section class="row">
    <section class="column-50">
      <label for="first-name">First Name</label><br />
      <input
        type="text"
        name="first-name"
        id="first-name"
        placeholder="First Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="last-name">Last Name</label><br />
      <input
        type="text"
        name="last-name"
        id="last-name"
        placeholder="Last Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- /section.row -->

  <section class="row">
    <section class="column-50">
      <label for="student-id">Student ID</label><br />
      <input
        type="text"
        name="student-id"
        id="student-id"
        placeholder="Student ID"
        pattern="[0-9]{4}[a-z,A-Z]{1}[0-9]{5}|03[0-9]{5}"
        required
      />
      <!-- Use https://www.regexpal.com to craft regular expressions -->
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="status">Status</label><br />
      <select name="status" id="status">
        <option disabled selected>Please select status</option>
        <option value="active">Active</option>
        <option value="deferred">Deferred</option>
        <option value="graduated">Graduated</option>
        <option value="terminated">Terminated</option>
      </select>
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- section.row -->

  <section class="row">
    <label for="address">Home Address</label><br />
    <input type="text" name="address" id="address" placeholder="Address" />
  </section>
  <!-- section.row -->
</fieldset>

Row 4: Contact Number and Email

One more section.row element, now for Contact Number and Email textfields. Note that we also have an email input type value, instead of needing to craft a new regex for that. You could do it this way, though, supposing you only allow specific emails to be entered in, for instance.

Personal Particulars Fieldset
<fieldset class="container" id="personal-particulars">
  <legend>
    <h2>Personal Particulars</h2>
  </legend>

  <section class="row">
    <section class="column-50">
      <label for="first-name">First Name</label><br />
      <input
        type="text"
        name="first-name"
        id="first-name"
        placeholder="First Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="last-name">Last Name</label><br />
      <input
        type="text"
        name="last-name"
        id="last-name"
        placeholder="Last Name"
        required
        autofocus
      />
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- /section.row -->

  <section class="row">
    <section class="column-50">
      <label for="student-id">Student ID</label><br />
      <input
        type="text"
        name="student-id"
        id="student-id"
        placeholder="Student ID"
        pattern="[0-9]{4}[a-z,A-Z]{1}[0-9]{5}|03[0-9]{5}"
        required
      />
      <!-- Use https://www.regexpal.com to craft regular expressions -->
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="status">Status</label><br />
      <select name="status" id="status">
        <option disabled selected>Please select status</option>
        <option value="active">Active</option>
        <option value="deferred">Deferred</option>
        <option value="graduated">Graduated</option>
        <option value="terminated">Terminated</option>
      </select>
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- section.row -->

  <section class="row">
    <label for="address">Home Address</label><br />
    <input type="text" name="address" id="address" placeholder="Address" />
  </section>
  <!-- section.row -->

  <section class="row">
    <section class="column-50">
      <label for="contact-no">Contact Number</label><br />
      <input
        type="text"
        name="contact-no"
        id="contact-no"
        placeholder="Contact Number"
      />
    </section>
    <!-- /section.column-50 -->

    <section class="column-50">
      <label for="email">E-mail</label><br />
      <input type="email" name="email" id="email" placeholder="E-mail" />
    </section>
    <!-- /section.column-50 -->
  </section>
  <!-- section.row -->
</fieldset>

Good job, we just completed our first fieldset! Now, moving forward to the next fieldset...

Academic Record

In the same fashion, we will craft out the fieldset.container#academic-record element like as follows first:

Academic Record Fieldset
1
2
3
4
5
<fieldset class="container" id="academic-record">
  <legend>
    <h2>Academic Record</h2>
  </legend>
</fieldset>

There are at least three different inputs in here: Enrolled Program, Semester Intake, and a table containing a CGPA value.

  • The Enrolled Program input is yet another <select> element: select.programme#programme
  • Semester Intake is selected from one of several options arranged as radio buttons: section.radiogroup#intake
  • CGPA is calculated using several textfields arranged in a table structure: table.cgpa-table

With radio inputs, it is critical that the name of all the related radio buttons are the same; otherwise, it will be possible to select multiple radio button options at once. Additionally, this will cause incorrect collection of data on the PHP side when the form is submitted. In our case, we will give the name value of "intake".

With input.cgpa#cgpa, we give the type value of number, denote a value range of \([0,4]\), and a default value of 0.00. Additionally, we make this readonly; the value can dynamically change with some JavaScript code embedded into it.

Academic Record Fieldset
<fieldset class="container" id="academic-record">
  <legend>
    <h2>Academic Record</h2>
  </legend>

  <label for="program">Enrolled Program</label><br />
  <select name="programme" id="programme">
    <option disabled selected>Please select a program</option>
    <option value="FIC">Foundation in Computing (FIC)</option>
    <option value="DIT">Diploma in Information Technology</option>
  </select>
  <br />

  <label for="intake">Semester Intake</label>
  <section class="radiogroup" id="intake">
    <input type="radio" name="intake" id="intake-jan22" value="jan22" />
    <label for="intake-jan22">January 2022</label>

    <input type="radio" name="intake" id="intake-apr22" value="apr22" />
    <label for="intake-apr22">April 2022</label>

    <input type="radio" name="intake" id="intake-aug22" value="aug22" />
    <label for="intake-aug22">August 2022</label>
  </section>
  <!-- /section#intake -->

  <table id="cgpa-table">
    <thead>
      <tr>
        <th colspan="2">
          <h3>Cumulative Grade Point Average (CGPA)</h3>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th>Semester 1</th>
        <td><input type="number" name="sem1" id="sem1" min="0" max="4" /></td>
      </tr>
      <tr>
        <th>Semester 2</th>
        <td><input type="number" name="sem2" id="sem2" min="0" max="4" /></td>
      </tr>
      <tr>
        <th>Semester 3</th>
        <td><input type="number" name="sem3" id="sem3" min="0" max="4" /></td>
      </tr>
    </tbody>
    <tfoot>
      <tr>
        <th>Cumulative Grade Point Average (CGPA)</th>
        <td>
          <input
            type="number"
            name="cgpa"
            id="cgpa"
            min="0"
            max="4"
            value="0.00"
            readonly
          />
        </td>
      </tr>
    </tfoot>
  </table>
</fieldset>
<!-- /fieldset#academic-record -->

Academic Progression

As like with the previous two fieldsets, we will craft out the fieldset.container#academic-progression element like as follows first:

Academic Progression Fieldset
1
2
3
4
5
<fieldset class="container" id="academic-progression">
  <legend>
    <h2>Academic Progression</h2>
  </legend>
</fieldset>

Inside it are going to be a series of checkbox inputs denoting "Prospective Degree Options", and a textarea for "Remarks". Unlike radio button inputs, you may choose to give each checkbox name a different value. Additionally, with <textarea> inputs, you may specify the cols and rows attribute values to automatically resize them to a specific set of dimensions when the page is loaded. If anything, we can leave it be and allow users to resize it if needed (to disable this, set the resize property of this <textarea> element to false).

Academic Progression Fieldset
<fieldset class="container" id="academic-progression">
  <legend>
    <h2>Academic Progression</h2>
  </legend>

  <label for="progression-degree">Prospective Degree Options</label>
  <section class="checkboxgroup">
    <input type="checkbox" name="bcs" id="bcs" value="bcs" />
    <label for="bcs">Bachelor of Computer Science (Hons)</label><br />
    <input type="checkbox" name="bit" id="bit" value="bit" />
    <label for="bit">Bachelor of Information Technology (Hons)</label><br />
    <input type="checkbox" name="bse" id="bse" value="bse" />
    <label for="bse">Bachelor of Software Engineering (Hons)</label><br />
    <input type="checkbox" name="brdd" id="brdd" value="brdd" />
    <label for="brdd">BSc (Hons) Robotic Design and Development</label><br />
    <br />
  </section>
  <!-- section.checkboxgroup -->

  <label for="remarks">Remarks</label><br />
  <textarea name="remarks" id="remarks" cols="50" rows="10"></textarea>
</fieldset>

Submit and Reset Buttons

Create a section.center.container#actions element after all the <fieldset> elements. Include the submit and reset inputs (indicate the correct type values resectively) inside them. This section should be automatically centered since we are including the .center class in it.

Actions Section Element
1
2
3
4
5
<section class="center container" id="actions">
  <input type="submit" value="Submit" />
  <input type="reset" value="Reset" />
</section>
<!-- section#actions -->

The Rest of the CSS Styles

At this point, we have finished structuring our HTML webpage. Now to polish it up properly with some CSS styles. As you go along, provided your machine's screen resolution is big enough, I encourage you to have your code editor on one side and the browser on the other so that you can view the changes each time you save progress on your stylesheet.

Global Custom CSS Properties

To start off, we are going to declare some global custom properties to use throughout the stylesheet. These property values are arbitrarily chosen when I crafted this form, but you may choose to modify them as you see fit to produce your own variation of the web form. We will keep this in :root.

1
2
3
4
5
6
7
8
:root {
  --normal-text-size: 20px;
  --h1-size: 48px;
  --h2-size: 28px;
  --input-size: 24px;
  --theme-color: red;
  --accent-color: maroon;
}

<body> Element and The Background Image

Now, we get to implement styles on the elements itself before targeting the element id and name values. Let's start with the body element - this is we get to implement the background image.

  • background-image: specify the image to use as the webpage's background, typically using url()
  • background-size: used here to ensure the background image covers all visible area within the browser window
  • background-position: used here to center the background image
  • background-repeat: set to no-repeat to ensure no repeated instances of the background (though since it's covering the whole browser window, this may not be necessary)

Additionally, I have included in a border value to produce a maroon border around the webpage, and a margin value of 0 to remove any default margin introduced. By default, the visible content's height is strictly relative to how much is contained in the webpage - this means that on a ridiculously large screen resolution (let's say something like 5K or more), there's a high chance you'll see an empty white (or black?) area at the bottom of the browser window. To mitigate this and ensure the background image definitely does cover the whole browser window, we set the min-height value to 100vh (vh stands for visible height).

1
2
3
4
5
6
7
8
9
body {
  background-image: url("../images/taylors-bg.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border: 1rem solid var(--theme-color);
  margin: 0;
  min-height: 100vh;
}
Slow Image Loading and The WEBP Image Format

If you find that the background image (and/or the logo on top) loads slowly, it could be any or all of these factors: the size of the image and the speed of your internet connection. Whilst we can't dictate how fast everyone's internet connection is supposed to be, we can definitely reduce this tendency of slow-loading images by using WEBP images instead. These are image file types that are more well-suited for use on a website due to their relatively smaller size.

PNG files tend to be much larger but have a higher image quality to them, whilst JPG/JPEG files can be small too but not of the same high quality. WEBP files are in the same boat as JPG/JPEG files too, as I have also frequently noticed a drop in image quality when converting them. If you'd like to use the same Terminal WEBP image converter I currently use (i.e., cwebp from Google), you can learn more about it from here.

<form> Element

You may notice that the form's text is not as visible anymore with the strong colors of the background image. Let's now modify the form element to mitigate that while styling it.

  • We place a background color overlay on the background image by specifying a background color for the form element. rgb(255, 255, 255) is the same as a white background, but what's special about using rgba() is that we get to specify the opacity of the color as a 4th argument. This effectively means that rgba(255, 255, 255, 0.8) produces a translucent white color with 80% opacity. There are also other ways to introduce transparency to the background, but for our intents and purposes, this is a much simpler solution than some of those other solutions you can find from online.

  • We also add in a top and bottom padding of 2rem to ensure there is a cushion of space on top and at the bottom of the form. We leave the left and right paddings at 0.

1
2
3
4
form {
  background-color: rgba(255, 255, 255, 0.8);
  padding: 2rem 0;
}

The Rest of The Elements

For the rest of the elements, these are the styles I implemented:

h1 {
  font-size: var(--h1-size);
}

h2 {
  font-size: var(--h2-size);
}

h3,
p {
  font-size: var(--input-size);
}

table {
  border-collapse: collapse;
  width: 100%;
}

tr,
th,
td {
  border: 1px solid var(--accent-color);
}

Notice that I made use of the custom properties defined earlier in :root. Like regular variables, this will reduce the need to search out for individual values (and possibly missing them, human error) by keeping it to a specific portion of the CSS stylesheet that's easy to find and modify at once. For the table element, I set the border-collapse property to collapse to remove any padding between the table cells, its width to full, and each tr, th and td element to use a solid thin (1px) border of the same color as the one implemented on the body element.

Notice that we did not target the input elements yet - that will come later. For now, let's target the class and id values.

Rows in The First Fieldset

We first set up the .row dynamic with the following:

1
2
3
.row section {
  margin: 0 auto;
}

Radio Buttons

For the radio buttons, we modify their font sizes and top margins:

1
2
3
4
5
.radiogroup,
.checkboxgroup {
  font-size: var(--normal-text-size);
  margin-top: 0.25rem;
}

Letterhead Logo Image

We can set the letterhead logo image size to scale to 40% of the visible width of the browser window (i.e., 40vw, where vw stands for visible width), but subject to a maximum width of 600px.

1
2
3
4
#top-title img {
  width: 40vw;
  max-width: 600px;
}

Action Buttons

Nothing much, we add in a simple top margin here to section#actions.

1
2
3
#actions {
  margin-top: 1.5rem;
}

CGPA Table

Here, we set the table width to 75%, vertical margin (top and bottom) to 1.5rem and position it in the center with horizontal margin (left and right) to auto. Additionally, we set the following styles to its child elements:

  • th: set width to 75%
  • td: align text and inline elements to the center
  • input[type="number"]: set width to 75%, vertical margin to .25rem and horizontal margin to auto
  • tfoot contents: align text and inline elements to the right
#cgpa-table {
  margin: 1.5rem auto;
  width: 75%;
}

#cgpa-table tr th {
  width: 75%;
}

#cgpa-table tr td {
  text-align: center;
}

#cgpa-table tr td input[type="number"] {
  width: 75%;
  margin: 0.25rem auto;
}

#cgpa-table tfoot,
#cgpa-table input {
  text-align: right;
}

Fieldsets

We have now commenced modifying the style of the inputs in this form. Now to target those in the fieldset elements..

fieldset {
  border-radius: 1rem;
  border-color: var(--accent-color);
}

fieldset legend {
  color: var(--accent-color);
}

input,
select {
  font-size: var(--input-size);
  margin-bottom: 0.5rem;
  padding: 0.25rem;
}

input:not(
  [type="submit"],
  [type="reset"],
  [type="radio"],
  [type="checkbox"],
  [type="button"]
),
select,
textarea {
  width: 100%;
}

input[type="submit"],
input[type="reset"],
input[type="button"] {
  font-size: var(--normal-text-size);
  margin: 0.5rem;
  padding: 0.25rem 0.5rem;
}

input:hover,
select:hover {
  border-color: var(--theme-color);
}

input[type="submit"],
input[type="reset"],
input[type="button"] {
  cursor: pointer;
}

option[disabled] {
  color: darkgrey;
}

Responsive Design - Columns

At this point, you should see that all the input fields inside the fieldsets are in full width - this is to be expected on a narrower screen resolution. In a wider screen resolution as one may find with desktops and laptops, for instance, you may want to make better use of the space by implementing columns. This is where we now use media queries to target the .column-50 class elements, among some other elements as well.

Let's set the column arrangement to take into effect for screens that are at least 768px wide.

/* Extra styling for window sizes of larger widths */

@media only screen and (min-width: 768px) {
  .container {
    width: 75%;
    margin: 0 auto;
  }

  .row section.column-50 {
    width: 49%;
  }

  .row .column-50:nth-of-type(odd) {
    float: left;
  }

  .row .column-50:nth-of-type(even) {
    float: right;
  }
}

At the very end, you should now have replicated the webpage as shown earlier in this lab activity.. huzzah!! There's still one more thing to do, though - create an acknowledgment page for when the form is submitted.

"Form Submitted" Acknowledgment Page

This is going to be a sort-of scrappy acknowledgment page... with some styling, at least. We will name this new HTML file form-submitted.html (following where we created our <form> element earlier).

Inside a typical HTML document structure, contain the following in the <body> section:

form-submitted.html
<main>
  <h1>Form Submitted</h1>

  <p>Submit another?</p>
  <input
    type="button"
    value="New Form Submission"
    onclick="window.location.href='.';"
  />
</main>

Include a <link> element in the <head> section to an external CSS stylesheet with the following contents:

form-submitted.css
1
2
3
4
5
6
7
8
9
main {
  background-color: rgba(255, 255, 255, 0.8);
  min-height: 100vh;
}

h1 {
  margin-top: 0;
  padding: 40% 0 2rem;
}

You should now see this as your acknowledgment page:

Complete HTML and CSS Code

I implore you to try this activity as much as you can - the steps should be enough to guide you through completing it. However, you may choose to refer to the complete code if you'd like to check if you did anything wrong (assuming it happens.. don't worry, this is normal!). But if you made it this far either on your own or using the guide/steps given above, give yourself a pat on the back! This wasn't easy, but I sure hope this taught you a lot about creating this kind of form from scratch! 😊

Form HTML and Stylesheet
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Student Record Form</title>

    <link rel="stylesheet" href="css/main.css" />

  </head>

  <body>
    <form action="form-submitted.html" method="post">
      <header class="center" id="top-title">
        <img src="images/logo.png" alt="Taylor's Logo" />
        <h1>Student Record Form</h1>
      </header>
      <!-- /header#top-title -->

      <fieldset class="container" id="personal-particulars">
        <legend>
          <h2>Personal Particulars</h2>
        </legend>

        <section class="row">
          <section class="column-50">
            <label for="first-name">First Name</label><br />
            <input type="text" name="first-name" id="first-name" placeholder="First Name" required autofocus />
          </section>
          <!-- /section.column-50 -->

          <section class="column-50">
            <label for="last-name">Last Name</label><br />
            <input type="text" name="last-name" id="last-name" placeholder="Last Name" required />
          </section>
          <!-- /section.column-50 -->
        </section>
        <!-- section.row -->

        <section class="row">
          <section class="column-50">
            <label for="student-id">Student ID</label><br />
            <input
                type="text"
                name="student-id"
                id="student-id"
                placeholder="Student ID"
                pattern="[0-9]{4}[a-z,A-Z]{1}[0-9]{5}|03[0-9]{5}"
                required
            />
            <!-- Use https://www.regexpal.com to craft regular expressions -->
          </section>
          <!-- /section.column-50 -->

          <section class="column-50">
            <label for="status">Status</label><br />
            <select name="status" id="status">
              <option disabled selected>Please select status</option>
              <option value="active">Active</option>
              <option value="deferred">Deferred</option>
              <option value="graduated">Graduated</option>
              <option value="terminated">Terminated</option>
            </select>
          </section>
          <!-- /section.column-50 -->
        </section>
        <!-- section.row -->

        <section class="row">
          <label for="address">Home Address</label><br />
          <input type="text" name="address" id="address" placeholder="Address" />
        </section>
        <!-- section.row -->

        <section class="row">
          <section class="column-50">
            <label for="contact-no">Contact Number</label><br />
            <input type="text" name="contact-no" id="contact-no" placeholder="Contact Number" />
          </section>
          <!-- /section.column-50 -->

          <section class="column-50">
            <label for="email">E-mail</label><br />
            <input type="email" name="email" id="email" placeholder="E-mail" />
          </section>
          <!-- /section.column-50 -->
        </section>
        <!-- section.row -->
      </fieldset>
      <!-- /fieldset#personal-particulars -->

      <fieldset class="container" id="academic-record">
        <legend>
          <h2>Academic Record</h2>
        </legend>

        <label for="program">Enrolled Program</label><br />
        <select name="programme" id="programme">
          <option disabled selected>Please select a program</option>
          <option value="FIC">Foundation in Computing (FIC)</option>
          <option value="DIT">Diploma in Information Technology</option>
        </select>
        <br />

        <label for="intake">Semester Intake</label>
        <section class="radiogroup" id="intake">
          <input type="radio" name="intake" id="intake-jan22" value="jan22" />
          <label for="intake-jan22">January 2022</label>

          <input type="radio" name="intake" id="intake-apr22" value="apr22" />
          <label for="intake-apr22">April 2022</label>

          <input type="radio" name="intake" id="intake-aug22" value="aug22" />
          <label for="intake-aug22">August 2022</label>
        </section>
        <!-- /section#intake -->

        <table id="cgpa-table">
          <thead>
            <tr>
              <th colspan="2">
                <h3>Cumulative Grade Point Average (CGPA)</h3>
              </th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th>Semester 1</th>
              <td><input type="number" name="sem1" id="sem1" min="0" max="4" /></td>
            </tr>
            <tr>
              <th>Semester 2</th>
              <td><input type="number" name="sem2" id="sem2" min="0" max="4" /></td>
            </tr>
            <tr>
              <th>Semester 3</th>
              <td><input type="number" name="sem3" id="sem3" min="0" max="4" /></td>
            </tr>
          </tbody>
          <tfoot>
            <tr>
              <th>Cumulative Grade Point Average (CGPA)</th>
              <td><input type="number" name="cgpa" id="cgpa" min="0" max="4" value="0.00" readonly /></td>
            </tr>
          </tfoot>
        </table>
      </fieldset>
      <!-- /fieldset#academic-record -->

      <fieldset class="container" id="academic-progression">
        <legend>
          <h2>Academic Progression</h2>
        </legend>

        <label for="progression-degree">Prospective Degree Options</label>
        <section class="checkboxgroup">
          <input type="checkbox" name="bcs" id="bcs" value="bcs" />
          <label for="bcs">Bachelor of Computer Science (Hons)</label><br />
          <input type="checkbox" name="bit" id="bit" value="bit" />
          <label for="bit">Bachelor of Information Technology (Hons)</label><br />
          <input type="checkbox" name="bse" id="bse" value="bse" />
          <label for="bse">Bachelor of Software Engineering (Hons)</label><br />
          <input type="checkbox" name="brdd" id="brdd" value="brdd" />
          <label for="brdd">BSc (Hons) Robotic Design and Development</label><br /><br />
        </section>
        <!-- section.checkboxgroup -->

        <label for="remarks">Remarks</label><br />
        <textarea name="remarks" id="remarks" cols="50" rows="10"></textarea>
      </fieldset>
      <!-- /fieldset#academic-progression -->

      <section class="center container" id="actions">
        <input type="submit" value="Submit" />
        <input type="reset" value="Reset" />
      </section>
      <!-- section#actions -->
    </form>

  </body>
</html>
main.css
@import url('https://fonts.googleapis.com/css2?family=Urbanist:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');

:root {
  --normal-text-size: 20px;
  --h1-size: 48px;
  --h2-size: 28px;
  --input-size: 24px;
  --theme-color: red;
  --accent-color: maroon;
}

* {
  font-family: "Urbanist", Arial, sans-serif;
}

body {
  background-image: url("../images/taylors-bg.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border: 1rem solid var(--theme-color);
  margin: 0;
  min-height: 100vh;
}

form {
  background-color: rgba(255, 255, 255, .8);
  /* min-height: 100vh; */
  padding: 2rem 0;
}

h1 {
  font-size: var(--h1-size);
}

h2 {
  font-size: var(--h2-size);
}

h3, p {
  font-size: var(--input-size);
}

table {
  border-collapse: collapse;
  width: 100%;
}

tr, th, td {
  border: 1px solid var(--accent-color);
}

/* Special division/sections */

.center {
  text-align: center;
}

.container {
  width: 87.5%;
  margin: 0 auto;
  padding: 0 1.5rem 1.5rem;
}

#top-title img {
  width: 40vw;
  max-width: 600px;
}

.row section {
  margin: 0 auto;
}

.radiogroup, .checkboxgroup {
  font-size: var(--normal-text-size);
  margin-top: .25rem;
}

#cgpa-table {
  margin: 1.5rem auto;
  width: 75%;
}

#cgpa-table tr th {
  width: 75%;
}

#cgpa-table tr td {
  text-align: center;
}

#cgpa-table tr td input[type="number"] {
  width: 75%;
  margin: .25rem auto;
}

#cgpa-table tfoot, #cgpa-table input {
  text-align: right;
}

#actions {
  margin-top: 1.5rem;
}

/* Input Elements */

fieldset {
  border-radius: 1rem;
  border-color: var(--accent-color);
}

fieldset legend {
  color: var(--accent-color);
}

input, select {
  font-size: var(--input-size);
  margin-bottom: .5rem;
  padding: .25rem;
}

input:not([type="submit"], [type="reset"], [type="radio"], [type="checkbox"], [type="button"]),
select,
textarea {
  width: 100%;
}

input[type="submit"],
input[type="reset"],
input[type="button"] {
  font-size: var(--normal-text-size);
  margin: .5rem;
  padding: .25rem .5rem;
}

input:hover,
select:hover {
  border-color: var(--theme-color);
}

input[type="submit"],
input[type="reset"],
input[type="button"] {
  cursor: pointer;
}

option[disabled] {
  color: darkgrey;
}

/* Extra styling for window sizes of larger widths */

@media only screen and (min-width: 768px) {
  .container {
    width: 75%;
    margin: 0 auto;
  }

  .row section.column-50 {
    width: 49%;
  }

  .row .column-50:nth-of-type(odd) {
    float: left;
  }

  .row .column-50:nth-of-type(even) {
    float: right;
  }
}
Form Submitted HTML and Stylesheet
form-submitted.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Form Submitted</title>

    <link rel="stylesheet" href="css/main.css" />
    <link rel="stylesheet" href="css/form-submitted.css" />
  </head>
  <body class="center">
    <!-- <form action="."> -->
    <main>
      <h1>Form Submitted</h1>

      <p>Submit another?</p>
      <input type="button" value="New Form Submission" onclick="window.location.href='.';" />
    </main>
    <!-- </form> -->
  </body>
</html>
form-submitted.css
1
2
3
4
5
6
7
8
9
main {
  background-color: rgba(255, 255, 255, 0.8);
  min-height: 100vh;
}

h1 {
  margin-top: 0;
  padding: 40% 0 2rem;
}