Search for:
SITK - Pie Shop 3of5 Featured image

Exciting Web Development Journey – Pie Shop Website 3/7

Overview

Welcome back to Sharing Is The Key. Let’s continue digging deeper into the CSS world to build vital Web Developments’ fundaments to deliver a compelling user interface. As we discussed in the second post of this series, there are many essential concepts about CSS that we miss most of the time, and it causes many issues to the end-users.

Now that you’ve learned how to add styles with Cascading Style Sheets, let’s look at working with them more in-depth on your web pages. You’ll learn about the box model, how to create layouts for your web pages, how to target desktop versus mobile devices, and how to determine browser support for the styles you write.

The Box Model

Every element in your web page has a sense of presence on the page. The way the browser interprets this presence is called the box model. Let’s take a look at the button we did in the previous post, and let’s add display: block, margin: 10px, and height:50px to the existing .button class. Save it and see the changes in the browser.

SITK - Pie Shop - the box model - adding rules

Let’s open up the developer tools and take a look at a utility that better depicts how the browser sees this element within the page. So I’ll right‑click on the button and choose Inspect. As we take a look at the Elements tab, bring your attention to the bottom right corner, where you can see a representation of how the browser sees this element. So for each element, we have margin, border, padding, and then the dimensions.

SITK - Pie Shop - the box model via debug tools

You can see that the values that we added into the style correspond to the diagram above. So the margin value that we created was for 10 pixels. Now the margin is the space between the border itself and everything else around the boundary of that element. As depicted here, the border was set to 1 pixel, so there’s a nice thin border around the element, and padding is the space inside the element, in between the border and the content of the element. And then lastly, we have the height and the width of the element itself.

Something is interesting you need to notice here. While I set the width for this element at 40 pixels, the actual width is 82 pixels. It is 10 pixels for the margin, 1 pixel for the border, and 10 pixels for the padding on both sides, and then 40 pixels for the width of the element inside the box. So as you’re styling elements on the page, you need to know how the margin, border, and padding values affect the dimensions of the elements on your page.

Now that you’re acquainted with the box model, let’s take a look at the type of style rules you’d need to write to create columns on your page.

Columns with Float

One of the fundamental features of creating a layout for a web page is to create columns, and unfortunately, that is a lot easier said than done when it comes to building a web page. So the first thing I’d like to do is show you a common way that people try to achieve a column layout, and I’d like to highlight a few of its problems, so then next I can show you a little more of a robust solution. Let’s add one div with class="columns" with two divs inside right after the Hello button. And we’ll use this class name to add style to the elements inside of it. Let’s try to use Emmet as much as we can to get the hang of it.

So to start, let’s create a class for columns. Let’s give it a width of 100%. And I’ll put a border on there as well so you can see how much space it’s taking up within the browser. So when I press Save, you can see I have the columns container taking up 100% of the width of its parent container, and it’s got that border.

SITK - Pie Shop - columns with float

All right, now let’s see if we can get Column 1 and Column 2 to situate next to each other. For my next style rule, I’ll use a child selector. So what I want to do is target all of the div elements that are children of my columns class selector. When you think about creating columns, essentially, what you’d like to do is take each one of these div elements and make them take up the same amount of space on the page and then situate them next to each other. So I’ll give each one of these divs a width of 50%. Now, just so that we have a better idea of what’s going on, let’s add a red border around these elements.

SITK - Pie Shop - columns with float - child element selector

Now we need to tell Column 2 to float up next to Column 1, and so we’ll use the float rule for that. We’ll say float: left;, and what this rule should do is tell the Column 2 div to show up next to Column 1. Because the box model is at play, and the width and border values are calculated into the overall elements’ width, there’s not enough space to create the columns when each of the divs is set to be 50%. So let make this 49% and save it, now I have two columns floating right next to each other, but there’s still a problem. I have this space left over at the edge of the page. And when you begin designing layouts, small bits of extra space can be frustrating.

SITK - Pie Shop - columns with float - frustating experience

So instead of using the float rule, let’s take a look at how Flexbox can make our life so much easier.

Columns with Flexbox

Starting in the same spot as we did when we first tried to create columns for our layout, we’ll use Flexbox, and we have our columns class and our divs for Column 1 and Column 2 available on the page. Let’s start by getting rid of the width and float rules in our class and class with a child selector. Let’s keep only the border for both of them. It takes up 100% of its parent’s width, so we can start creating some columns.

SITK - Pie Shop - columns with flexbox

Now, I’d like to introduce you to display: flex. By adding this one rule to our page, now when I save the file, you can see we’ve got two columns on the page.

SITK - Pie Shop - columns with flexbox - display flex

It isn’t quite the type of layout that we want, so let’s customize it slightly more. In the child selector .columns > div, we’ll add in the flex rule. Now, by saying flex equals 1, I’m telling the browser to evenly distribute all the space that’s available within the container and allow each one of my divs to take up one portion of that amount of space. So, essentially, since I have two columns, by setting flex equal to 1, I’m telling the browser, allow each div to take up one column’s worth of space within the container.

SITK - Pie Shop - columns with flexbox - flex equals 1

Now, to illustrate this a little more clearly, let’s see what happens when we add a third column into the mix.

SITK - Pie Shop - columns with flexbox - flex equals 1 - adding more colums

By merely adding a new div onto the page, we have three columns that have equal widths, but I have even more control available to me with Flexbox than that.

For our layout, we want Column 1 and Column 3 to be more narrow, and Column 2 takes up a majority of the space within the page.

Well, we can do that by adding in another selector. I’ll start with another child selector based on the columns container. Now I’ll create another child selector, and then I’ll use a particular type of selector called a pseudo‑class. Now the syntax for this is to add a colon, and VS Code will give us many different options available for pseudo‑classes. So I can target the first‑child of the container or the first of a specific type. I want to make Column 2 a little bit wider than Column 1 and Column 3, so I’ll use the nth‑of‑type pseudo‑class. By using nth‑of‑type, I’m telling the browser to look for a div within the container based on its position. So when I add in 2 as an argument, it will skip the first div and select the second div. Now I can add a rule into this block and tell the style I want the flex value to be 2. So, what will happen when I save the file?

SITK - Pie Shop - columns with flexbox - setting size of column 2

That’s right. Column 2 is wider than Column 3 and Column 1. What Flexbox is doing is calculating all of the available space needed for the columns, giving Column 2 a double portion of that space, and Column 1 and Column 3 get a single proportion of the space allotted for the columns. Now there’s so much more that you can do with Flexbox, this scratches the surface, but the rules you see here will get us where we need to build Bethany’s Pie Shop. Next, let’s look at how we can target rules to only apply to desktop or mobile devices.

Responsive Layouts: Viewport

Media queries allow you to target your CSS rules to different devices. It means you can create rules that target the desktop browser versus other rules that apply to mobile devices, so let’s take a look and see how this works.

Here, I have many elements on the page. We want that projects show up on the desktop, the Hello button and the class columns divs show up for mobile devices, and the table shows up only when you print the page. We need to add desktop, mobile and print value to the element’s class attribute to accomplish this task.

SITK - Pie Shop - responsive layouts

Now when you’re designing for the web and creating styles that target different devices, often the best approach is to design for mobile devices first. It is essential because it forces you to make sure that your layout works in the smaller dimensions before it works in the larger ones. Therefore we will use this approach here. Before we start writing CSS rules, there is a specific metadata tag that you need to be aware of that’s essential to make our styles work correctly. The metadata element is named viewport and is required to let the device know how to interpret its width.

SITK - Pie Shop - viewport metadata

This element is telling the browser that the viewport or the way that the page is rendered within the browser will have a width of whatever the device width is. It is important so that the page is rendered at the correct width of the device. An initial scale is a setting for the scaling or the zoom. So by setting an initial scale equal to 1, we’re telling the device to take on the 100% zoom setting, so you’re not zoomed in, and you’re not zoomed out.

Okay, well, with this in place, now we can write some CSS rules that target different devices.

Responsive Layouts: Media Queries

So now, with the viewport defined, I can start working on my styles. Now I want to make sure that I’m doing my styles for my mobile devices first. So the first thing that I’ll do here is to hide the Desktop and Print elements. To do that, I’ll create a list of class selectors and give it a style rule of display: none.

SITK - Pie Shop - mobile first approach

Now when I press Save, you’ll notice that those elements disappear from the page. With display: none in place, it tells the browser that any of these elements no longer take up any physical presence within the layout. By setting display equal to none, I’ve essentially taken those elements out of any rendering on the page. So using display: none is a very common way of hiding elements on the page.

SITK - Pie Shop - mobile first approach - desktop and print elements are gone

Next, I’ll create a media query just for when the page is printed. Now I’m showing you the print media query because other rules we’ll use target the screen only. So we start with the at symbol @ and use the media keyword. Then I tell it that this works for printing only. Within this media query, I want to create the reverse rules for what I initially set up. Here, I want to tell the Mobile and Desktop elements to be hidden and then show the Print element. So this will hide the Mobile and Desktop elements. And by setting display to block for the Print element, that will show that element as we print the page.

SITK - Pie Shop - media query print

So when I press Save, you’ll notice that nothing happened in the browser. As it’s rendered on the screen, it looks just like our mobile stylesheet. However, if I come over to the browser and type Ctrl+P, you can see within the print preview that the only thing that’s rendered on the page to be printed is our Print element.

SITK - Pie Shop - media query print - Ctrl+P

Next, we can target the desktop browser on the screen by using a different media query. So here, I’ll build the rule with the media screen and then add a selector. Now I’m adding the ‘and’ keyword in here to create a selector for the rules to be applied only in certain situations. So, in this case, I only want to apply the rule where the browser’s width is greater than 768 px. So to do that, I’ll use the min‑width property. And so now I can tell the Mobile elements to hide and show the Desktop ones. So, again, any screen that’s 768 px in width or greater will hide the Mobile element and show the Desktop element.

SITK - Pie Shop - media query desktop

So let’s save the page and see what happens. Since I’m showing my screen side by side, and the screen width is less than 768 px, nothing happened. So if I take my browser and expand it out, you’ll notice that it begins to show the Desktop element after it crosses over that threshold.

Now when you’re testing media queries and want to see what they look like in different environments, just changing the size of the browser is not the best way to go about it. And the browser developer tools once again make your life so much easier. So I can open them up by saying Inspect element, and then you’ll notice an icon where you can toggle the device toolbar. When I click on that, it creates a simulation of what this page might look like under different mobile contexts. So here, I can come up here and select from several different preconfigured devices. I can change the orientation and even the zoom level. And so you’ll notice on an iPad Pro, we’ll get the Desktop experience because of its dimensions. But on an iPhone 5, it renders the Mobile experience

Media queries give you a lot of power to target your layouts for different contexts. Next, let’s look at how you can determine browser support for the CSS you write.

Browser Support

Just like when you’re writing HTML, you’ll want to know about the browser support for the different CSS rules you write for your websites. And to find out which rules work in which browsers, we can use the website caniuse.com. So let’s take a look at one of those rules, and we’ll take a look at Flexbox. And so, through this table, you can see that Flexbox enjoys quite a bit of support throughout most browsers available in the world today.

SITK - Pie Shop - Can I Use - Flexbox

And any feature with this type of support you can safely use in just about any production application. Scrolling down the page a little bit, you have the opportunity to read some of the developer notes about the feature, and I find the Known Issues tab to be incredibly enlightening. It is where you can dive into edge cases where certain features may have restrictions under particular circumstances. So that’s a well-supported rule.

SITK - Pie Shop - Can I Use - Flexbox Known Issues

Let’s take a look at something that’s not quite as ubiquitous. Let’s search the hanging‑punctuation rule. It allows some punctuation characters from the start or end of text elements to be placed outside the box to preserve the reading flow. Well, as you can see here, we have a whole lot of red, and this rule is not supported well enough for you to use it in a production application.

SITK - Pie Shop - Can I Use - hanging punctuation

So chances are most of the rules you choose to use for your layouts will be supported well enough for you without worrying about it, but if you have any questions, make your way over to caniuse.com and find out for sure.

Building Content Pages

Introduction

Well, you have come a long way since we first introduced the very basics of HTML. We made our way through style sheets, and now we’re ready to start building the website for Bethany’s Pie Shop. We will set the HTML foundation for the home page and develop the global style sheet and styles specifically for each of the content pages. Let’s start building the home page.

Create the Foundation

So let’s start by returning to the starter project that you downloaded in the first post. Now, let’s create the index file, order file, list of pies, contact file, and the global stylesheet file. Once again, we’ll be using Live Server to watch the changes as we make them here in VS Code.

SITK - Pie Shop - creating HTML and CSS files

Let’s start with the index file, and we’ll use the Emmet shortcut to create the basis of an HTML file. So I can type ht and then come down and select html:5. That will give us an HTML5 stub of a web page. And a lot of this should look familiar to you by now. So we have our doctype. We have our HTML element set with language lang="en" for English. We know this will pass our validation rules. Here we have a meta tag. The character set is UTF‑8, which is the text encoding for this page. We have our viewport. That’s already put in there for us, so they’ll work as expected when we create responsive styles. We’ve got a title and then our body element. So I’ll save this, and then I’ll right‑click on the page and say Open with Live Server.

SITK - Pie Shop - open index with Live Server

That opens the browser for us automatically. And when I come back over to VS Code and hide the explorer. That gives us a bit more space. And now I’ll shrink VS Code so that we can see both windows at the same time. Now, when I type something in the file and save it, we can automatically see that change in the browser.

SITK - Pie Shop - start coding with Live Server on

Now, to serve as a reminder of what we’re building, this is the home page.

SITK - Pie Shop - Home Page

So we’ll start by creating the navigation at the top of the page, add the logo image, generate the markup for the content of the page itself, and then add the markup for the footer. Once the structure is in place for the HTML, we’ll add the styles, and the final result will be this home page here for Bethany’s Pie shop.

SITK - Pie Shop - Home Page described

So here I can add in the structure for the top navigation of the page. And we’ll start, of course, by using an Emmet shortcut again. So inside the body, what I want to build is a header by typing header>. Inside that, the site navigation. The element that we can use here is the nav element header>nav>. Then I want to create an unordered list header>nav>ul>. And inside that list, I want to have three different list items header>nav>ul>li*3>. I want to make an anchor for a link inside each one of the list items header>nav>ul>li*3>a. So now, when I press Tab, all of that HTML will be generated for me.

SITK - Pie Shop - Home Page - Emmet Navigation

If you recall our discussion about semantic markup in the first post of this series, it is telling a search engine that this section of the page is the header of the page. Inside of it, I have navigation, and the nav element is a container for links that apply just to this site. So we wouldn’t put a link to, let’s say, an outside website within the nav element. It is just navigation for our website alone. Then we can create an unordered list and then the list items here.

So we’ll create the first link for the home page. It is a little weird because we’re building the home page right now, but I put it on here just for consistency’s sake as you go through the different pages in the website. Adding the slash value for href tells the browser to go to the very root of the website. In other words, if we had bethanyspieshop.com, that’s where this link will go.

SITK - Piae Shop - Home Page - home link

Next, we want a link to the pies list page, and so we can add pies.html in the second list item, so when you click on it, it’ll go to that page, and then we’ll give it the label of Pies. And lastly, we have a link to the contact page. Now when I press save, you’ll see that the result is pretty unimpressive visually, highlighting the value of stylesheets.

SITK - Pie Shop - Home Page - pies and contact link

And we’ll implement the styles soon, but for now, let’s finish building the rest of the home page’s structure. So next, we’ll add Bethany’s logo to the page.

Add Main and Aside Elements

So now we’ll add the page’s main content. To do that, we’ll use an element called main. The overall structure of the page will give us a header, the main content, and then a footer for the page. It is vital to use the main element for this page because that signals to a search engine that the content within this page inside this element is the primary content. Sure, the header and the footer are essential, but they are most of the time links around the site. We’ll probably have some branding information, maybe some contact information. But when it comes to the primary purpose of this web page, what is in the main element is what we most care about.

SITK - Pie Shop - Home Page - main element

Now inside the main element, I’ll use two different tags. One is the aside, and the other is the article element. Now, if you think of a typical magazine article, the page’s main content flow is the article text, and sometimes you’ll have pull quotes that show up over on the side. Well, that’s the difference between the article element and the aside element, which I’ll use here.

SITK - Pie Shop - Home Page - article and aside elements

The aside element is important and contextually relevant to the content on the page. But it’s not the most critical part. Here I’m using the aside with an image inside of it to show the logo on the page. Let’s use Emmet again, type aside>img:s and hit Tab.

SITK - Pie Shop - Home Page - Emmet aside and img elements

You’ve seen in the past, the source attribute is where we put the path to point to the image, and in this case, it’s images/logo.png. The alt attribute gives a hint to machines about what this image is about. So whether it’s a search engine or a screen reader, the text we add here describes the image. So here I’ll just put in Bethany’s Pie Shop. And so now, when I save the page, the logo shows up on the screen.

SITK - Pie Shop - Home Page - adding logo

Add Article and Footer Elements

Next to the aside element, we’ll add the article element with some different supporting elements. If you recall the finished product, inside the main, we have a banner, a title, and some text with a link to our pies list page. So that’s what we’ll add on the page now.

SITK - Pie Shop - Home Page - what is inside the main

Now, rather than typing everything out character by character, I’ll paste in the markup for this page, and then we’ll discuss it.

So we’ve got the article element, and I’ve got an image element that renders out the banner, the h1 element, that’s the main title for the page. Again, for search engines, they’re going to key in on this h1 element. Then I’ve got a paragraph of text that welcomes people to the page. So it’s a message from Bethany and a link over to the pies list page.

SITK - Pie Shop - Home Page - article with image header1 paragraph and anchor

Now we’ll use Emmet one more time to generate our footer, and then we’ll have everything we need for the home page. Here, we’ll create a footer with a navigation element that includes a list of anchors by typing footer>nav>li. We want three list items, so that’ll be footer>nav>li*3, and inside those list items, we’ll render some anchor tags footer>nav>li*3>a. And again, rather than typing everything out, I’ll copy from the header and paste in the links and save it.

SITK - Pie Shop - Home Page - Footer with nav

We’ve got our top navigation, logo, banner, welcome text, and the footer links on the page. So now we can move on towards adding the global styles for the website.

Global Styles: General and Body Rules

Okay, well, we’re off to a good start. We have the foundation set for the home page. We have all the pieces that we need to start styling it with a global style sheet. I mean by a global style sheet that we’ll create a style sheet that works for every page—all of the base styles that every page needs to make it look like Bethany’s Pie Shop.

Individual pages will have their own set of styles that customize what they need for those pages. But we’ll get started by creating the base required styles for our website.

Now we need to reference our style sheet file. Go to the index.html and make sure that we add a reference to the site.css file so that all the styles we enter into site.css end up getting loaded into the home page.

To do that, we’ll add a new element into the head of the page, and we’ll create a link to site.css. We’re going to have rel="stylesheet". The href will be site.css. And then we need to tell this element that it’s reading CSS, so we’ll add a type attribute, and the value is text/css. Now the type attribute is important because it tells the browser when it loads this file to read it as a CSS file.

SITK - Pie Shop - link index to css via link

The first thing that we want to do is reset the margin on all of the elements on the page. Some elements like title elements have a little bit of margin and maybe some padding built-in as their default styles. To get our layout working correctly, what I’d like to do is reset every single element so that it has no margin at all.

To do that, in the site.css, I’ll use the * selector. It says every single element on the page will get the following rule. So now I can set all margins 0. When I press Save, you can see that all of the margins around these elements are compacted. It is good because now we won’t be fighting with any default values, and so elements will only get the margin that we set.

SITK - Pie Shop - setting margin to 0 for all elements on the page

Next, I want to add rules that will help make sure that it calculates the dimensions of the page correctly. So here I have a selector for HTML and the body. So essentially, this is the entire page within the browser. And here, I’m setting the height to 100%. While this didn’t visually make a change within the browser, it helps other styles to be able to calculate their position on the page correctly.

SITK - Pie Shop - setting html and body to 100% on the site

Now let’s add some styles just for the body itself. These rules will rely on inheritance to make sure all of the other elements on the page have the style rules that we’ll enter here. Here I’ll change the font, and you’ll notice that VS Code gives me some options. So here, we’ll select the Arial, Helvetica, sans‑serif option. And now I want the background colour of the body to be a light gray. I’ll press Save, and we can see the change made to the file.

SITK - Pie Shop - setting body font-family and background colour

Global Styles: P and Header Rules

Now you might be wondering, Why am I setting the background colour to that gray? When we look at the finished product, you’ll notice that the top navigation has its background colour. Within the body of the page, we have an image applied to the background that’s repeated to give us that striped look. And then, when we come down to the bottom of the page, the footer has a gray colour. By adding this rule at this point, the footer can just inherit the colour of the body.

SITK - Pie Shop - Home Page

We want to add a style for all of the paragraphs within our website to have its custom margin.

SITK - Pie Shop - setting margin for all website paragraphs

Now I’ll scroll down on the page, and when I hit Save, you’ll be able to see here within the paragraph how the margins will change.

SITK - Pie Shop - setting margin for all website paragraphs - result

Next, we can add styles for our header so that our navigation begins to look the way we want it. The first rule I’ll add display: block. The second is position: fixed. Now when I hit Save, notice what happens?

SITK - Pie Shop - setting header display and position

The logo shows up underneath the links at the top, but because I have the position as fixed, you’ll notice that the navigation links stay in place when I scroll the page. And that’s exactly what we see on the finished product. As I scroll the page, the top navigation stays fixed into position at the top of the browser.

And so we want to add in that position. So we’ll add top and left dimensions, the top rule telling the browser to fix that position at the very top of the browser window, as well as the very left‑most edge of the window.

SITK - Pie Shop - setting header top and left to 0

Now let’s make it take up 100% of the width of the page, set its background colour, and add a little bit of padding. Here we’ll use the colour code specific to the theme for her website and add in the padding. So now we have a fixed element at the top of the page that includes our links. The links aren’t quite exactly like what we’d expect yet, but that’s just the style for the header.

SITK - Pie Shop - adding width background-color and padding to the header

Next, let’s look at how we can customize the links within the page’s header.

Global Styles: Nav Element

So we have the fixed header set up, now let’s add the rules to make our navigation links look a whole lot better.

First, I’ll start with a selector that styles the links depending on the click state. I want to style the appearance of the links after someone visits them. And the default state for all links underneath the navigation element on the page. So to do that, let’s use the pseudo-class link as a:link. We’ll make the links white, use a rule called text‑decoration, and set that to none. Now text‑decoration: none says that our links won’t have any underlines underneath them.

SITK - Pie Shop - changing link appearance and state under nav element

So now, when I save the file, you can see that the links turn white, and they’ll stay white whether or not we’ve clicked on them before or not, and, of course, the underlining has been taken away from the text.

SITK - Pie Shop - changing link appearance and state under nav element - result

Next, let’s deal with how this list renders on the page. So we’ll look at the nav element and target the unordered list within that element nav > ul. Now we’ll tell the browser to display this list inline and zero out all the padding around the list.

SITK - Pie Shop - changing display and padding of ul elements

When I save the page, you can see that the bullets have disappeared from our list, and there’s no extra padding around the links.

SITK - Pie Shop - changing display and padding of ul elements - result

For our final style for the list, we can add some rules that target the individual list items within that unordered list nav > ul > li. For these, we want them to display as inline‑block, set the list‑style to none, and set the left and right margin. So the first value is for the top, so we’ll fix it to 0, then we have the right, the bottom, and the left value. So what display: inline‑block tells the browser to do is to display our element inline, so that means it stacks the elements right next to each other, but we put it within a particular mode of inline‑block, saying that you can still have control over things like width, margin, padding, where you don’t usually have control over those aspects when you have a typical inline element.

SITK - Pie Shop - changing display list-style and margin for nav li emelemtns

Setting list‑style: none; tells the browser not even to interpret this item as a list item, and then our margin values give a little bit of space between each link. You might be wondering, why using a list element at all when we’re trying to style it to look like a series of links right next to each other? And that goes back to semantic markup. When a search engine looks at our web page, it’ll see that there’s a list of links within a navigation element and has a better job of interpreting the meaning of those links, rather than just having random anchors scattered around on the page.

Congratulations, we’ve got the header and nav elements ready to go. We applied most of the HTML and CSS concepts and fundaments we’ve been learning until now. At this point, things are getting clear, and you are probably having fun! There is more about CSS and HTML in the following posts as well as JavaScript. Let’s make a pause and continue in the next post.

If you need any help or something is going wrong, let me know. It will be my pleasure to help you. If you want to extend some point, we have discussed, contact me so we can cover in the fllowing posts.

We also have pro bono projects just in case you are interested in learning more about them.

Be aware of why we started this project by clicking here.

Learn more about other posts here.

Contact us for any suggestions. And follow us on FacebookInstagram and Twitter.

If you are a good reader like myself, I recommend the following readings:

  • Docker Quick Start Guide: Learn Docker like a boss, and finally own your applications
  • Docker for Developers: Develop and run your application with Docker containers using DevOps tools for continuous delivery
  • Responsive Web Design with HTML5 and CSS: Develop future-proof responsive websites using the latest HTML5 and CSS techniques, 3rd Edition
  • JavaScript: The Definitive Guide: Master the World’s Most-Used Programming Language 7th Edition

See you in the next post!

ToDoList Blog banner

Exciting Web Development Journey – To Do List

Hi there! Let’s continue our Web Development Journey we started in the previous post when we learned HTML, CSS, and JavaScript concepts. We had the opportunity to build a proof-of-concept web page to work with Sharing is The Key Website light and dark themes. I will assume you know some of the conventions, tricks, concepts, and tools we taught in the previous post for better productivity.

SITK To Do List

Scenario

We will make a web app for a to-do list. We’ll be able to use this app to track whatever we want: cool programming tricks that you want to learn, places to go, songs to listen to or learn to play, or something as basic as things to pick up at the stores. It will be possible to add and remove to-do items from the list and save them so they reload for you later.

Learning goals

  1. Getting to know more HTML elements such as Form and input text fields
  2. Styling using global variables, Flexbox module, and many other CSS resources
  3. Creating your own JavaScript functions
  4. Listening for different user actions on a web page
  5. Using functions together to write code more professionally.
  6. Saving user information between visits to your web page

What you will need

  1. VS Code, the cross-platform code editor. Or one of your preference.
  2. Docker Desktop latest stable version. You can see how to set it up here.
  3. Familiarity with at least one programming language. You don’t need to be an expert.
  4. A computer running one of the following:
    • Windows: Windows 10 Home or Professional
    • Mac: macOS 10.9 or later
    • Linux: Ubuntu, Debian, Red Hat, Fedora, or SUSE

Project structure

Let’s clone the previous post project to save some time and learn more about git CLI.

In your terminal, type the following command and hit Enter.

git clone https://github.com/sitknewnormal/SITK-themes.git "SITK-ToDoList"

This command will pull SITK-themes source code from our Git Hub repository and copy it into the SITK-ToDoList new folder.

SITK-TodoList project structure

Move into the SITK-ToDoList project folder, remove git source control, and open the VS Code by running the following commands.

cd .\SITK-ToDoList\; Remove-Item -LiteralPath ".git" -Force -Recurse; code .

opening SITK-ToDoList in VS code

It will open SITK-ToDoList in VS Code. If you remember from the previous post, it will ask you to reopen the project into a Dev Container, but for now, let’s not do this because I want to introduce you to an exciting VS Code extension.

SITK-ToDoList in VS Code

Let’s open the devcontainer.json file, make some changes and save them:

  • In the extensions values, replace "tht13.html-preview-vscode" by "ritwickdey.liveserver" (Live Server). Live Server extension launches a local development server with live reload feature for static and dynamic pages;
  • Change the name to “SITK – ToDo List.”
making changes to dev container config file

Now that we have everything in place, close VS Code and reopen it, but at this time, choose to reopen the project into the Docker Dev Container when asked to do so.

Let’s code HTML

When the Dev Container is up and running, and the project is ready to be edited, let’s go to the index.html and make some changes.

First, click on Go Live in the status bar to start our Live Server.

opening Live Server

It will open the web page in your default browser. Let’s put the VS Code and the browser windows side-by-side to see the reflection of what we are coding in the browser as soon as we save the changes, and let’s close the VS Code Explorer to get more room to code.

VS Code and browser side by side

Let’s get rid of everything between the opening <body> and closing </body> body element except for the theme switcher button element and save it.

SITK-ToDoList clearing out everything in the body

Let’s give our app an important header To-do List using <h1> element at the beginning of the body and save it.

SITK-ToDoList adding H1

We will need a paragraph <p> right after the header to inform the user to mark an item as completed by double-clicking on it. Please save it to see it in the browser.

SITK-ToDoList adding a paragraph with some instruction

To add items to our To-do List, we will need a Form with an input text element and a button. An HTML Form is used to collect user input. The user input is most often sent to a server for processing, but this is not our case for this post. Therefore copy the code below to a new line right after the paragraph we’ve just added.

        <form name="todo-adder">
            <input type="text" id="todo-entry-box" />
        </form>
        <button id="add-btn" class="pretty-button">Add</button>

Notice that we  named our Form name="todo-adder", we’ve given an identification id="todo-entry-box" to our input text, we did it to the button id="add-btn" as well, and we also created a class class="pretty-button" for future CSS styling. It is essential to keep in mind that naming, giving identification to HTML elements is always a good practice and will help you style them uniquely. Classes are often used to style a group of elements. Furthermore, the naming convention for CSS attributes such as name, id, and class suggests using lowercase and the hyphen for composed names.

SITK-ToDoList adding a form input text and a button

Now let’s break a line to separate the Form from the items, and let’s create an ordered list container so the user can see the item they will add to the list. Please copy the code below to a new line after the Add button.


        <br />
        <ol id="todo-list">
        </ol>

We gave an ID id="todo-list" to the To-do List for future CSS styling.

SITK-ToDoList adding ordered list

Next, we will create three buttons and wrap them in a div element. When it comes to productivity, VS Code is one of the best editors. The Emmet feature can help you with repetitive and boring coding tasks, and no extension is needed. Take a look at the video below to have a taste of VS Code editor’s power.

Let’s give them some IDs and texts accordingly to the chunk of code below.


    <div id="control-wrapper">
        <button id="clear-completed-btn" class="pretty-button">Clear Completed</button>
        <button id="empty-btn" class="pretty-button">Empty List</button>
        <button id="save-btn" class="pretty-button">Save List</button>
    </div>
SITK-ToDoList adding three buttons

Let’s do one more cool thing! To make our To-do List look better, we will wrap the elements from line 12 (Header 1) to 25 (three buttons div) in a div to style it. We will select lines 12 to 25, type the shortcut Ctrl+Shift+P to access the command palette, type Emmet: Wrap with Abbreviation, when it opens to enter the abbreviation, type div.todo-wrapper and hit Enter.

The final HTML code should look like this.

SITK-ToDoList final HTML code

As we could notice, we didn’t touch the head section where we still can see the style sheet linked, and we didn’t change the script tag where we still keep our JavaScript also linked.

Styling HTML with CSS

We already have our CSS from the previous post set up, which already supports light and dark themes, and we will keep and extend it. By the way, spending some time styling an application is very important and allows a better user experience.

Let’s do some cleaning before we style the new HTML elements we added.

First, let’s get rid of li, ul and .list selectors since we don’t have them anymore in the HTML file. Plus, let’s add three more colour variables in the root element. Please copy the code below at the end of the root element and save it.


    --laser1-light: #e5d9b6;
    --light-gray: #3a3a3a;
    --completed: #666666
SITK-ToDoList adding variables to the root element

We will use --laser1-light and --light-gray to style the to-do wrapper div’s background colour when we switch between light and dark themes, respectively. Place each variable inside light and dark themes selectors.

SITK-ToDoList placing new variables in dark and light themes

Let’s change the theme switcher button absolute position to the web page’s right top corner by changing the top key to 0px, replacing left by right key and set it also to 0px, in the .btn selector.

SITK-ToDoList setting theme switcher button to top right corner

Next, we will style the to-do wrapper div setting the background colour, border-radius, top, left and right margin and padding. Please copy the code below to the end of the CSS file. Notice that we are already using the --todo-wrapper-bg variable so the background will assume --laser1-light or --light-gray for the light and dark themes, respectively.


.todo-wrapper {
    margin-top: 60px;
    background-color: var(--todo-wrapper-bg);
    border-radius: 30px;
    margin-left: auto;
    margin-right: auto;
    padding: 30px;
}

Let’s check our work so far, but first, create four items in the ordered list using Emmet, remember? Inside the <ol> element, start typing li*4 and hit Enter.

SITK-ToDoList styling ToDo wrapper div

Now let’s style the only paragraph inside the to-do wrapper using the --completed variable we defined previously to set the colour; let’s set it up to italic and define margins. Please copy the code below to the end of the CSS file.


.todo-wrapper p {
    font-style: italic;
    color: var(--completed);
    margin: 5px 0;
}

The variable --completed will also be used to style the finished tasks’ font and colour.

Next, we will style the ordered list and its items, setting margin and some padding to the items to allow a little bit of space between them. Please copy the code below to the end of the CSS file.


.todo-wrapper ol {
    margin: 20px 0;
}

.todo-wrapper ol li {
    margin: 5px 0;
    padding: 3px;
}

Now let’s highlight the even items in our list for easy reading. Please copy the code below to the end of the CSS file.


.todo-wrapper ol li:nth-child(even) {
    background: #999999;
}

Let’s check our work so far.

SITK-ToDoList styling list items in the ordered list

Next, we will style the completed list items. First, let’s go to the HTML file and set the two first items as completed using class="completed" attribute.

SITK-ToDoList setting completed list items in the HTML file

Now, we will style those completed list items. Please copy the code below to the end of the CSS file.


.todo-wrapper .completed {
    text-decoration: line-through;
    color: var(--completed)
}
SITK-ToDoList styling completed list items

Time to style all buttons inside to-do wrapper div to look pretty. Remember that we used class="pretty-button" all buttons except the theme switcher? We are now changing their margin, padding, border-radius, background colour, border, text alignment, and more at once. Please copy the code below to the end of the CSS file.


.todo-wrapper .pretty-button {
    margin: 10px 2px;
    padding: 5px 20px;
    border-radius: 15px;
    background-color: var(--bg);
    border: none;
    color: var(--fontColor);
    text-align: center;
    display: inline-block;
    outline-style: none;
}
SITK-ToDoList styling all buttons inside To-do wrapper div

If you hover the mouse over the buttons, you will see no indication they are clickable. Let’s fix it by changing the cursor to a pointer and add a little bit of opacity as we hover over them. Please copy the code below to the end of the CSS file.


.todo-wrapper .pretty-button:hover {
    cursor: pointer;
    opacity: 0.75;
}

If we type in the text input field in the Form, we will notice the text look tight inside the text field. Let’s fix it by adding some padding. Please copy the code below to the end of the CSS file.


.todo-wrapper input {
    padding: 6px 6px;
}
SITK-ToDoList styling input text field

Next, we will fix the Add button, placing it on the input text field’s right side, which looks better.

SITK-ToDoList styling form children display

Display using inline-block makes the element generate a block box that’s laid out as if it were an inline box. According to QuirksMode: An inline-block is placed inline (i.e. on the same line as adjacent content), but it behaves as a block.

We will now align the buttons in the control-wrapper div using the display flexible box module, a relatively new and easy way to arrange elements on the page.  There is rich content here, so you can dig deep and learn more. For now, let’s say that the setup below finds a way to arrange the buttons at the center of the div and provides even spaces between them and the margins, which fits in most of the scenarios. Please copy the code below to the end of the CSS file.

#control-wrapper {
    text-align: center;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
}

For the matter of responsiveness, the following code uses media query CSS resource to resize the .to-do wrapper width and .to-do wrapper input width. For devices with screen resolutions of at least 1400 pixels, the .to-do wrapper width will be set to 75%, and the .to-do wrapper input width will be 600 pixels. For devices with screen resolutions between 750 pixels and 1399 pixels, the .to-do wrapper width will be set to 50%, and the .to-do wrapper input width will be 400 pixels. Please copy the code below to the end of the CSS file.

@media only screen and (min-width: 1400px) {
    .todo-wrapper {
        width: 50%;
    }

    .todo-wrapper input {
        width: 600px;
    }
    
}

@media only screen and (max-width: 1399px) and (min-width: 750px) {
    .todo-wrapper {
        width: 75%;
    }

    .todo-wrapper input {
        width: 400px;
    }
}
SITK-ToDoList adding responsiveness

We can better see the responsiveness explained before in the following video where the .to-do wrapper width and .to-do wrapper input width resizes as soon as they reach the resolution limits defined in the media queries.

It is crucial to think of the behaviour you want your application to have in different devices and resolutions to catch and keep the user’s attention.

Let’s see the viewport metadata behaviour and how the elements arrange themselves in desktop, tablets, smartphones when properly styled using Flexbox, media queries, display inline-block and so on. Go back to the browser and click on the Toggle device toolbar button and play with the options.

Now that we have an awesome To-do List app well structured and styled, we will give it some action with JavaScript.

JavaScript

If you look at the page, you’ll see it has four buttons:

  • An Add button for adding new to-do items
  • A Clear Completed button for clearing items that you’ve marked as finished
  • An Empty List button for completely emptying the to-do list
  • A Save List button for saving what’s on the list

Of course, since you haven’t written any code yet, right now, none of them do anything!

Let’s add some code to our JavaScript file.

Add button

It is essential to tell JavaScript which parts of the HTML page are relevant and how user interactions with these parts should react. In this case, you want to tell it about the Add button and tell it to react when the user clicks this button.

Getting the Add button

Start by creating a button variable and telling JavaScript to get the id="add-btn" button element from the HTML document. Please type or copy the following code to the end of our JavaScript file and save it.

const addBtn = document.getElementById("add-btn");

Listening for the click

Now connect your button to an event handler so that JavaScript listens to a particular type of event and then runs a function when it hears it. The event is a click in our case. Do this with the function addEventListener. Please type or copy the following code to the end of our JavaScript file and save it.

addBtn.addEventListener("click", addToDoItem);

This listener will wait for the addBtn click, and when the click is heard, it will respond by running the addToDoItem function. Of course, because you haven’t written the addToDoItem function yet, it just won’t work yet!

Creating the function

Later in this post,  you will be writing code for your functions to add to-do items, clear the list, save it, etc. But for now, you want to check that you’ve connected your event listeners properly.

Create the addToDoItem function so that it will pop up an alert message informing the user which button they have clicked. Please type or copy the following code to the end of our JavaScript file and save it.


function addToDoItem() {
    alert("Add button clicked!");
}

Let’s check our work so far. Put the VS Code and the browser side by side again, and click on the Add button.

SITK-ToDoList checking Add button alert message

Write code for the remaining buttons.

Try it on your own, following the Add button steps to make sure you got the idea.

Connect the Clear Completed button, which has the Id clear-completed-btn, to an alerting function called emptyList.

Connect the Empty List button, which has the Id empty-btn, to an alerting function called clearCompletedToDoItems.

Connect the Save List button, which has the Id save-btn, to an alerting function called saveList.

Let’s see if you got it right! Check the code below and make some adjustments if needed or copy the following code to the end of our JavaScript file and save it.

let clearCompletedBtn = document.getElementById("clear-completed-btn");
clearCompletedBtn.addEventListener("click", clearCompletedToDoItems);
function clearCompletedToDoItems() {
    alert("Clear completed button clicked!");
}

let emptyBtn = document.getElementById("empty-btn");
emptyBtn.addEventListener("click", emptyList);
function emptyList() {
    alert("Empty button clicked!");
}
let saveBtn = document.getElementById("save-btn");
saveBtn.addEventListener("click", saveList);
function saveList() {
    alert("Save List button clicked!");
}

Don’t forget to save it! So far, the code should look like this.

SITK-ToDoList remaining buttons code so far

Click on all buttons to make sure they are working.

Add to-do items

Time to make the first of those buttons work correctly! This step will show you how to add a to-do item to the list.

First, go to the HTML file and delete all four list items <li> inside the ordered list <ol> and save it.

SITK-ToDoList clearing all list items from the ordered list

We are going to use a tiny bit of HTML in this step. Therefore you need to write some JavaScript to add <li> elements for each new to-do item. The user should enter text and then click the Add button to see it appear on the list as a numbered item.

First, just like you did with the buttons, create variables to select the text box and the ordered list. They already have the Ids todo-entry-box and todo-list. Please type or copy the following code to the end of our JavaScript file and save it.

let toDoEntryBox = document.getElementById("todo-entry-box");
let toDoList = document.getElementById("todo-list");

Now the text box and the ordered list can be easily reached from within your JavaScript.

Let’s create a function called newToDoItem to add an item to the list. This function will need to have two inputs:

  • The text of the item
  • The item completed or not

Of course, no new to-do item will ever be complete, but we are preparing ahead of time here: we will use the same function again when we load a saved list with some finished items. Please type or copy the following code to the end of our JavaScript file and save it.


function newToDoItem(itemText, completed) {
    let toDoItem = document.createElement("li");
    let toDoText = document.createTextNode(itemText);
    toDoItem.appendChild(toDoText);

    if (completed) {
        toDoItem.classList.add("completed");
    }

    toDoList.appendChild(toDoItem);
    toDoItem.addEventListener("dblclick", toggleToDoItemState);
}

This newToDoItem  does a few things.

let toDoItem = document.createElement("li");

Creates an li element to use as your new list item.

let toDoText = document.createTextNode(itemText);

Creates a text node, a special container for a text that we want to put inside an HTML element using JavaScript, and fills it with the contents of the itemText variable that is passed into the function.

toDoItem.appendChild(toDoText);

The function appendChild takes the element, or text node, that you pass to it (in this case toDoText), and puts it inside toDoItem. If there are already elements inside that one, the one we are adding now will be last.

if (completed) { toDoItem.classList.add("completed"); }

Checks if the value for the completed variable that was passed to newToDoItem is true. If it is true, it will add the class completed to the li element, changing how it looks on the page. In our CSS file, there are special styling rules text-decoration: line-through; for li elements.

toDoList.appendChild(toDoItem);

The function appendChild puts toDoItem, the <li> element inside of toDoList, the <ol> element.

toDoItem.addEventListener("dblclick", toggleToDoItemState);

Attaches an event listener for double-click to the toDoItem And tells it to call a function named toggleToDoItemState in response.

Next, connect to the function to the Add button. Change your existing addToDoItem function to get the text from the box and pass it to the function newToDoItem we’ve just created.


function addToDoItem() {
    let itemText = toDoEntryBox.value;
    newToDoItem(itemText, false);
}

Since a new to-do item is never finished, you can always pass false to the completed parameter of the newToDoItem function.

Let’s test it to see if it works!

SITK-ToDoList testing Add button

Completing items

When you can’t mark items as done, there’s not much point to a to-do list! It’s time to add that feature.

For a double-click on a to-do item, we have already set up the listener. All we need to do now is write a function that, when that double-click occurs, will toggle the item between complete and not complete.

Note that to mark items as complete, we are using the completed class. Not having that class implies that they aren’t complete. All our function needs to do is add or remove the class from the item’s class list, either add it if it is not yet on the list or delete it.

The this keyword

The trick is to know which item the class can turn on. You’ll need to use a new JavaScript keyword to describe the object that was clicked: this.

It’s a little bit complicated how exactly the this keyword works, but all we need to know here is that when used with a function called by an event listener, it means ‘the element to which the listener was bound.’ But you can use this to find the particular list item <li> we clicked on.

Add the toggleToDoItemState function to the end of our JavaScript like so:

function toggleToDoItemState() {
    this.classList.contains("completed") ? this.classList.remove("completed") : this.classList.add("completed");
}

Let’s test it to see if it works!

SITK-ToDoList marking items as completed

Remove items

If we have marked the items as complete, we will want to delete all of the completed items. Also, we may want to clear off everything on it if we come back to your list after a long time or if we just want to focus on something entirely different. To do this, we just need to update two functions that have already been connected to the buttons: clearCompletedToDoItems and emptyList.

Clearing completed items

Just as you can select all the elements in an HTML document, you can select the elements within any other element. The children of that element are called the elements inside another element. Likewise, just as you can select the Id elements, you can also select them by class.

Let’s update the existing clearCompletedToDoItems function with code to select the toDoList children who have the completed class to clear the completed items. Then loop over the selected items to remove one by one.

function clearCompletedToDoItems() {
    let completedItems = toDoList.getElementsByClassName("completed");

    while (completedItems.length > 0) {
        completedItems.item(0).remove();
    }
}

You will see that the code will always delete the item at position 0 of the list, the first item on the list. To do this, you need to use 0 since JavaScript starts counting at 0 and not 1. You delete this item to replace the first item every time the loop runs, so the list gets shorter and shorter. In this way, the loop will finally delete them all, no matter how many incomplete items are listed.

Let’s test it to see if it works!

SITK-ToDoList clearing items completed step1
SITK-ToDoList clearing items completed step2

Clearing everything

Let’s focus on the existing function emptyList. To delete all from the list, do the same thing as above, but pick all the children from the toDoList.


function emptyList() {
    let toDoItems = toDoList.children;
    while (toDoItems.length > 0) {
        toDoItems.item(0).remove();
    }
}

 It is always recommended to check your work as soon as you advance on it.

Save the list

You can save the to-do list to a local storage location on the user’s computer to make it even more useful. Then, as long as they open it in the same browser next time, it will remember their to-do list.

There are two important steps for this task: saving the list and loading it again when the page is reloaded if the list is there.

This gets a little tricky: HTML can’t be saved in the local storage, so we need to take the HTML code and convert it to pure JavaScript. To do that, you will need an array.

An array is a variable of a special kind, which is a list of variables. You can build one with square brackets and use the push method to add objects to it. You can remind yourself what a specific array item is, using alert and the item’s position in the array. Remember that JavaScript starts counting at 0. Take a look at the code below to understand it better.

const myArray = [];
myArray.push("array item 1");
myArray.push("array item 2");
alert(myArray[0]);
//This will alert "array item 1"

Next, we need to loop over the list toDoList and add each item to the array. Remember that we need to store the task and whether or not it has been completed. The best way to do this is to use JavaScript objects.

JavaScript objects

A JavaScript object is a set of properties and values. You create one like this:

const toDoInfo = {
    "task": "Learn HTML",
    "completed": false
};

You just need to save all the to-do items to local storage once you have converted them into objects. Local Storage can only store strings, but fortunately, JavaScript turns arrays into strings for you when you use the stringify function.

Saving in a Local Storage – Step 1

Enough said, let’s put it all together!

Let’s update the existing saveList function to:

  • Make an array
  • Use a for loop to put every item in toDoList into the array as an object
  • Stringify the array and store it in local storage with the key toDos

Here is the code for the saveList function.

function saveList() {
    const toDos = [];
    for (let i = 0; i < toDoList.children.length; i++) {
        let toDo = toDoList.children.item(i);
        let toDoInfo = {
            "task": toDo.innerText,
            "completed": toDo.classList.contains("completed")
        };
        toDos.push(toDoInfo);
    }
    localStorage.setItem("toDos", JSON.stringify(toDos));
}

Load the saved list – Step 2

We need to reverse everything we have done to save it, to load the list. But first, we need to check if anything needs to be loaded. You do this by checking whether there is no null value on the key you used to store the list. ‘Null’ is yet another ’empty’ word or ‘nothing’ word.

Let’s create a loadList function to:

  • Check if the toDos key exists in local storage
  • If it does, load it into a variable as an array
  • Loop over the array, and use newToDoItem to create new to-do items for everything in it

Add the code below to the end of our JavaScript file.

function loadList() {
    if (localStorage.getItem("toDos") != null) {
        let toDos = JSON.parse(localStorage.getItem("toDos"));

        for (let i = 0; i < toDos.length; i++) {
            let toDo = toDos[i];
            newToDoItem(toDo.task, toDo.completed);
        }
    }
}

Let’s call the loadList function after we have created it. Add the code below to the end of our JavaScript file and save it.

loadList();

To close it with a golden key, let’s save it to the local storage every time we add a new item, mark an item as completed, clear completed items, and empty the list.  All we need to do is adding the code below at the very end of addToDoItem, clearCompletedToDoItems, toggleToDoItemState and emptyList functions.

saveList();
SITK-ToDoList adding saveList to addToDoItem
SITK-ToDoList adding saveList to clearCompletedToDoItems
SITK-ToDoList adding saveList to toggleToDoItemState
SITK-ToDoList adding saveList to emptyList

Let’s test it to see if it works!

Congratulations, we have done a great job! I know it is a lot to take in, but you will get used to it with time and practice.

Let’s use Git to commit our work. We taught how to do it in our previous post; check it out here.

If you don’t know what Git is, take a look here and find out. The SITK-ToDo List source code can be found on our GitHub account.

We’ve got more of the basics of front-end web development. Certainly, there is much more to learn about HTML, CSS and JavaScript, and there are some free and excellent references for this: w3schools.com and MDN Web Docs.

If you need any help or something is going wrong, let me know. It will be my pleasure to help you. If you want to extend some point, we have discussed, contact me so we can cover in the next posts.

We also have pro bono projects just in case you are interested in learning more about them.

Be aware of why we started this project by clicking here.

Learn more about other posts here.

Contact us for any suggestions. And follow us on FacebookInstagram and Twitter.

If you are a good reader like myself, I recommend the following readings:

  • Docker Quick Start Guide: Learn Docker like a boss, and finally own your applications
  • Docker for Developers: Develop and run your application with Docker containers using DevOps tools for continuous delivery
  • Responsive Web Design with HTML5 and CSS: Develop future-proof responsive websites using the latest HTML5 and CSS techniques, 3rd Edition
  • JavaScript: The Definitive Guide: Master the World’s Most-Used Programming Language 7th Edition

See you in the next post!

%d bloggers like this: