Nano ASP.NET SaaS Boilerplate
Admin credentials (all tenants): admin@email.com / Password123!
Sample data resets every hour
Nano ASP.NET SaaS Boilerplate
General
Front-End Development
Front-End Development

Web App Part 1: HTML & CSS

Now that we have some knowledge of the front-end web technologies, HTML, CSS, and JavaScript, let’s build a user interface. The application we will create is a simple product inventory app. It will contain an input area where the user can add new products. The products will be saved in an array and dynamically rendered as a list when we add JavaScript code later. This is what we will build:

final fron-end web app

Begin by creating a new folder called ProductInventory and open it with Visual Studio Code using File then Open Folder. When working with projects, its more common to open folders with VS Code instead of individual files. In the explorer window create a new html document called index.html.

<!DOCTYPE html>
<html>
  <head>
    <title>My Website</title>
    <link rel="stylesheet" href="./style.css" />
    <script src="./script.js"></script>
  </head>
  <body>
    <h1 class="app-title">Product Inventory</h1>
    <div class="input-container">
        <div class="input-container__field">
            <label for="userInput">New Product</label>
            <input type="text" id="userInput" />
        </div>
        <div class="input-container__button">
            <button type="button" id="addProductButton" >Add</button>
        </div>
    </div>
    <div class="output-area" id="outputArea">
    </div>
  </body>
</html>

Since this is an HTML document, we start off with a <!DOCTYPE html> tag to ensure consistent rendering across all browsers. This is followed by an <html> tag which wraps all of the document content.

Next is the <head> section, where we define meta information not visible on the page like the page title and links to external resources. The CSS <link> tag points to a style.css file which we need to create in the same directory. Create a new style.css file from the explorer window. We will add CSS rules later.

The JavaScript <script> tag is similar to the CSS <link> tag in that it links to an external resource. The src (source) attribute points to a script.js file which we also need to create in the same directory. Create a new script.js file from the explorer window. We will add JavaScript code later.

The <body> tag wraps all the content which will be visible on the page. The page content consists of three main parts:

  • An <h1> title with class app-title
  • A <div> section with class input-container. This section contains nested sections for the input field and button. The input field and button elements contain IDs so they can be easily selected with JavaScript. The for attribute on the label should contain the ID of the input it labels. This will make it so that when a user clicks the label, focus will be set on the input field.
  • A <div> section with class output-area. This section is blank but will later receive dynamically generated content from our JavaScript code. This div also contains an ID.

You may have noticed certain naming conventions when defining classes and IDs. There are a few common conventions for naming things in programming:

  • PascalCase – commonly used for files and folders
  • camelCase – commonly used for IDs
  • kebab-case – commonly used for CSS classes

You don’t have to follow any of these conventions but they do make life easier!

Another convention specific to CSS class naming is called BEM which stands for Block Element Modifier. This is a great way to stay organized and you can see this in our HTML structure already. It’s simply the base element followed by the child element separated with double underscore. The element names are either one word or they are connected with a single dash (like kebab-case). This is especially useful when working with SCSS, a superset of CSS which grants new abilities like variables and nesting. You can read all about the BEM methodology here.

Now that our HTML structure is in place, we can add CSS styling to make it look like an app instead of a mixed bag of HTML elements. Here is the full CSS code, which we’ll examine next:

*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}

html {
  font-family: Arial, Helvetica, sans-serif;
  display: flex;
  justify-content: center;
}

label {
  margin-bottom: 10px;
  font-weight: 600;
}

input {
  padding: 10px;
  border-radius: 5px;
  border: none;
  margin-bottom: 20px;
}

button {
  border: none;
  border-radius: 10px;
  background-color: rgb(212, 0, 148);
  padding: 20px 30px;
  cursor: pointer;
  font-weight: 700;
  transition: all 0.3s;
}
button:hover {
  background-color: rgb(234, 255, 141);
}

.app-title {
  margin: 20px 0;
}

.input-container {
  width: 600px;
  background-color: rgb(17, 134, 243);
  border-radius: 10px;
  padding: 30px;
  display: flex;
  justify-content: space-between;
  color: white;
}

.input-container__field {
  display: flex;
  flex-direction: column;
}

.input-container__button {
  display: flex;
  align-items: center;
}

The first rule group is called a CSS reset rule and it probably looks quite confusing! As we learned before, all HTML elements have some default properties – some elements are inline, some are block, some have default padding like paragraphs, etc. These defaults have existed since the early days of the internet, like pre-2000 early days, so some of these default properties can be annoying when trying to make something look modern today. One of these annoying properties is called box-sizing.

There are two options for box-sizing: border-box and content-box. The difference is how an element’s height and width are calculated. Content-box does not include padding, border-box does include padding. Some elements are content-box by default and others are border-box by default and this can make content layout confusing. Since 9 out of 10 developers agree that using border-box is more intuitive, the solution is to just make everything border-box. To do so, we use the asterisk selector which selects everything and select all pseudo elements with ::before and ::after. You can target multiple elements with the same rule separating them with commas. The other rule with the asterisk by itself removes the default 10px margin that is applied to the whole page.

*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}

Don’t worry if this doesn’t make a ton of sense right now with pseudo elements and multiple selectors because that is more advanced CSS. Just know that this CSS reset rule is often found at the start of any CSS document end sets things up for consistency.

The next rule targets the whole html document, changing the default font-family to Arial. It also centers all the content with a combination of the display: flex and justify-content: center properties.

html {
  font-family: Arial, Helvetica, sans-serif;
  display: flex;
  justify-content: center;
}

The display property is one of the most important ones to understand in CSS. As we mentioned before, elements are by default either block or inline for their display. A div tag for example is by default a block display element, meaning it will take up the whole horizontal space, while a span, link, or button will be inline and place itself next to other inline elements if space allows. The problem with block and inline display properties is that they don’t give us much control as to how we position their child elements within them.

That’s when two other display properties, flex and grid, come to the rescue. By setting the element to flex, we can use the justify-content property to horizontally control the position of child elements, and use the align-items property to control vertical position. You can read more about flex and grid to gain a better understanding of how they work.

Here we have set the display property to flex and justify-content property to center. This will arrange all elements within the document to the center of the page.

It’s quite funny if you think there should be an easy way to center something within a div like an ‘align: center’ property – but it’s not so simple! CSS has a few peculiarities that you must get used to first. There are several memes about this.

Moving on, the label, input, and button styles would apply to all matching elements. Most of these properties are self-explanatory.

label {
  margin-bottom: 10px;
  font-weight: 600;
}

input {
  padding: 10px;
  border-radius: 5px;
  border: none;
  margin-bottom: 20px;
}

button {
  border: none;
  border-radius: 10px;
  background-color: rgb(212, 0, 148);
  padding: 20px 30px;
  cursor: pointer;
  font-weight: 700;
  transition: all 0.3s;
}
button:hover {
  background-color: rgb(234, 255, 141);
}

Margin and Padding as you may have noticed, are frequently used properties. Margin is space added to the outside of an element and padding is space added to the interior. Margin and padding can be set explicitly for top, bottom, left, right, or to all sides.

The unit of measure for properties like margin, padding, height, width, can be set in pixels (px) or percentage (%). There are other measures that exist like root element (rem) but those are more advanced CSS.

The CSS rule applying to label elements has a bottom margin, while the input rule applies padding to all sides. When two values are provided for margin or padding, the first value affects the top and bottom, the second controls the left and right. Four values can be given to the padding or margin properties which are applied starting from the top and going in clockwise direction.

The color or background-color properties take either a hex, RGB value or named color as a value. Notice that the button has an extra selection rule for the :hover state, which has a different background-color for when the user hovers over the element. With the transition property, we can make the change gradual over a specified amount of time, in this case .3 seconds.

The remaining rules target CSS classes that are defined in the elements on the page.

.input-container {
  width: 600px;
  background-color: rgb(17, 134, 243);
  border-radius: 10px;
  padding: 30px;
  display: flex;
  justify-content: space-between;
  color: white;
}

.input-container__field {
  display: flex;
  flex-direction: column;
}

.input-container__button {
  display: flex;
  align-items: center;
}

The app-title has a top and bottom margin of 20 pixels. The input-container has blue background-color with white as the foreground color. The color property applies to the text within the div. The input container uses flex for display with justify-content set to space-between, which means that the child elements, the button and the input field, will be positioned with as much space as possible between them.

The child element, input-container__field contains two elements, a label and a text input. Since labels and inputs are inline elements, they will naturally position themselves on the same line. If we want the label to be positioned above the input field, we can use flex once again and use the flex-direction property set to column to have elements align vertically instead of horizontally.

Aligning the text input and label vertically expands the height of the input-container. The button will position itself at the top of its parent container, which looks off and we’ll need to center it vertically. We can do that by setting input-container__button to display: flex and align-content: center. For now the output area won’t have any styling.

That was a lot of CSS information covered in a very short amount of time. But now with these CSS rules in place, our document is starting to resemble a user interface!

If you enjoy this course, check out the Nano ASP.NET Boilerplate, a project template that can serve as an excellent learning resource for learning advanced application design once you level up through this course material.

The next step will be to add functionality with JavaScript. Before we do that though, we need to learn about let and const in JavaScript which we didn’t cover in the fundamentals tutorial.