In the previous articles, we took a look at HTML5 and CSS, and we toyed around with a few different ways we could change text fonts and decorations. In this article, we will build an entire web page, while digging a bit into the conceptual model of CSS.
We will look at the following:
Creating a site is much like creating a piece of art. There are a few rules, but nothing really holding you back from making whatever you want. The browser page is your canvas, your brushes HTML5, and your pigments CSS.
But, even the best artists need to have some idea of what to create in their heads. And many more create rough sketches, build prototypes, and keep a lot of materials on hand. The idea behind the sketches and all is "planning". Here is how we will start the process:
- Create a Vision
- Make a Sketch
- Experiment and Save the Good Stuff
The first two of these steps were mentioned in the previous article, and the third will be the step that you will most likely repeat over and over until you are satisfied.
Create a Vision
The vision can be anything, from an informative white paper on monomers to a complex interactive game, for example. In this article, we will create a vanity page. Yes, this page will be all about you, the stuff you like, and so forth.
Hey, if you don't like the vanity page idea, you are welcome to formulate your own. The takeaway from web page design should be your satisfaction. This article will provide the framework.
Make a Sketch
For this site, the article will demonstrate the creation of a web page with easily-recognizable sections and functions. Over the years, people have come to expect certain things, and that is what we will keep in mind with our design.
We will create a page for a PC-based browser and not a smartphone. Remember, we are just getting our feet wet. Here is a sketch of what we would like to create:
Yes, it really is just a hand-drawn sketch. We can use CAD tools and so forth, but it's not really necessary when all we are doing is roughing out our design.
Note that there are three areas: header, nav, and content. The header is along the top of the page, the navigation runs down the left side, and the content takes up the rest of the space. A sketch of the details of the contents will come later.
Experiment and Save the Good Stuff
From here on out, we will code, test, evaluate, and repeat. Welcome to the world of programming.
To begin, we must create the very outermost shell of an HTML5 web page, so open up your editor and key in the following code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>My First Web Page</title>
<style type="text/css">
</style>
</head>
<body>
<!--
</body>
</html>
Feel free to remove the comments in the body and style elements. They are only placeholders. The page title can also be anything else you would like.
We haven't yet decided on how many pages we will need, so we will hold off on any decisions until we get a mock-up of the page.
Header, Nav, and Content
The majority of the web pages on the net consist of a header, a navigation area, and the content. The header does not necessarily need to be on the top or span the whole page, nor does the navigation necessarily need to be on the left. This is a very conventional design
HTML5 provides semantic elements for these parts of the web page:
<header></header>
<nav></nav>
Let's put these two elements in our web page and see what it looks like.
<body>
<header></header>
<nav></nav>
</body>
Well, that was a whole lot of nothing. The page was blank! So, what did we learn from this? We found out that semantic elements may not display anything, by default. But, we have CSS. So, we should enter some CSS definitions that will help.
In the style element, enter the following:
header {
border: 1px solid blue;
background-color: lightgray;
}
nav {
border: 1px solid red;
background-color: lightblue;
}
Now we have defined borders and background colors for the two elements. Re-load the web page in your browser, and we can see where these elements are. Later in our work, we can get rid of the borders and colors if necessary.
Unfortunately, what you see are two lines across the top of the page. In order to fill out the sections, we need content. To quickly expand the elements, enter some text in the header and nav content areas.
<body>
<header>Header</header>
<nav>Navigation</nav>
</body>
Now when you re-load the web page, you will see the word Header in side the header element and the word Navigation in side the nav element.
Success!
But the nav element just sits under the header element, taking up the full width of the browser window. We need to make the nav element much narrower. Enter this into your style for the nav element:
width: 120px;
Re-load the page, and you will see the navigation element now only 120 pixels wide. But, you ask, what about the height? Well, we can add this to the nav selector in our style element:
height: 100%;
What this will do is make sure the nav section grows to fit the contents of the web page, not the window. Still, it is a good thing to add in right now, so go ahead and type it in.
Header
Now let's do something with the header. In the sketch, we have a picture on the left, words in the middle, and a smaller area in the lower-right corner of the header reserved for a page title. Now, the page title section is meant to show us where we are in a multi-page site. We will put something in place, just in case we will need it, with the knowledge that we can just remove it if we want.
So, we have three sections. Hmm. How can we divide the header space up like that?
First, let's try dropping some inline element into the header element. We know inline elements will stack left-to-right, so we should be okay. Erase the word "Header" from the header section and enter this:
<header>
<img id="siteimage" src="somepicture.png" />
<span id="sitename">My Vanity Page</span>
<span id="sitepagetitle">Page Title</span>
</header>
Use this picture for somepicture.png if you need one:
Well, it really isn't what we want, so we are going to have to do something else.
Upon closer examination of the sketch, you should notice that the image is on the left, the site title is in the middle, and the page title is on the right. What we really need to do is space these things so that the picture hugs the left, the page title hugs the right, and the site title floats in the middle.
The picture already hugs the left side, but something must be done with the other two bits.
We will need to think a bit. :-( We obviously need CSS to formulate this kind of arrangement, so let's take a look at how CSS works, and then we can determine what we need to do from that.
Before we go into an examination of properties and models, we should first look at two default values that can be assigned to any CSS property:
The "cascading" action of Cascading Style Sheets begins with the browser. When the browser displays a web page, it will use a set of default values, sometimes known as the definition table, for font, font size, color, and so forth. All properties have a default value, and the defaults will be used if the document has no additional styling information.
We saw the action of using initial settings above when we created the header and nav elements. We saw nothing, because these elements by default have no borders and no background colors.
When this, however, is the desired effect, the defaults can be set in a CSS document by the value "initial":
<p style="color: red;">Initial settings are built into the browser, but
they <em style="color: initial;">can be changed</em> with style sheets.</p>
In the example above, the color property is set to red for the entire paragraph. However, the em element specifies its color to be "initial", thereby pulling the value from the browser's definition table.
Some element properties are set to the values of those properties in the element's parent. This is called inheritance, and it is how cascading works. Elements inherit many properties from their parents, which inherit from their parents, and so on, until we reach the initial settings in the browser.
Referring to the above example, if the em element did not declare the color as "initial", then it would have inherited the color (red in this example) from its parent, the paragraph.
But, some properties are not inherited. CSS does not specify that all properties should be inherited, so it has provided a standard property value which can be used to force inheritance: the value "inherit".
And with this information under our belts, let's take a look at the CSS model, which the W3C calls the "box model".
CSS formulates placement and display based upon a 'box model' by defining the layout for margins, borders, padding, and content. This figure demonstrates the model:
The content is at the very center of the box. Around the content, we see three layers. Padding is whitespace that surrounds the content. The border exists just outside the padding. And the margin is the outermost layer, containing the whitespace that surrounds everything else. The outline is not a true layer, but it can be rendered like the border just outside of the border.
Each of these layers is represented in CSS via properties. Each layer can also be divided into four sections: top, right, bottom, left. That gives us a top border, a right margin, a left padding and so forth. The defaults for these layers are all basically zero, which means there is no padding, margin, or border for the elements, unless otherwise specified.
True Width
The CSS properties width and height describe the width and height of only the content, not everything else around it. The true size of the element includes the padding, border width, and margin values. So, when an element has a CSS definition like this:
width: 200px;
height: 100px;
border: 1px solid brown;
padding: 8px 8px 8px 8px;
margin: 3px 3px 3px 3px;
The width of the element on the browser page is actually 224px. Here is a formula you can use:
True width =
element width property +
left padding + right padding +
left border width + right border width +
left margin + right margin
Plug in the numbers, and you get:
224px =
200px +
8px + 8px +
1px + 1px +
3px + 3px
We don't include the outline in this calculation because the outline is not included in any dimensional calculation. It can be displayed, but the browser ignores it when determining dimensions and placements.
The elements in an HTML5 document are displayed in the order they are defined in the the document. By default they will order themselves left to right, top to bottom. Block elements separate themselves from the previous element with a line break. Inline elements will stack horizontally, moving below the first element on the line when it wraps.
Because block elements stack vertically, they will, by default, span the entire width of the web page. They also size themselves vertically according to their content.
We saw this happen in our web page, but let's see what we can do to change this.
Dimension
The dimension of a CSS element is defined by its width and height, which correspond to the CSS properties called "width" and "height". The values of these properties define the width and height of the content inside the padding (referring to the box model).
nav {
width: 120px;
height: 100%;
}
We can say that a value specified as a percentage is a relative value, and a value with a specific notation (like px or em) is a static value. Or nav element has a static width of 120 pixels and a relative height of 100%.
Positioning
Positioning an element can also be relative or static using either a keyword value for the position property or values that define the position of the top, bottom, right, or left sides of the element.
Here are the values for the position property:
- relative
- absolute
- static
- fixed
Relative positioning places elements relative to its normal position. Adding a property like "top: 25px;" will move the element down 25 pixels from where it would normally be. If the properties top, left, right, and bottom are not defined, the element is positioned as if the position property were set to "static".
Absolute positioning places elements in an exact spot on the page according to the values for the properties left, top, right, and bottom. This position is relative to the elements' first non-static positioned ancestor.
Static positioning is the default. This property value tells the element to display in the order it was defined in the document.
Fixed positioning tells the browser to place the element at a location relative to the browser. This means, for example, scrolling has no effect upon the element.
So, what about our header section?
Without a specification, the header contents were positioned as static elements. Perhaps we could position them absolutely. That would certainly make sense, but where exactly is the absolute position of the middle and right when we have no idea how wide the browser window will be?
Obviously, absolute positioning is not the answer.
Floating and Alignment
One way to alter the flow order is to set a value for the float property. Telling an element to float makes the other elements flow around it, where the float value specifies how the element will be anchored.
For example, when I specify "float: left", this means the element will align to the left and the elements defined after it in the document will float around the right side of the element.
Well, the picture is already aligned to the left, so let's try floating the page title to the right:
#sitepagetitle {
float: right;
}
This is better, but we will need to fix a few things. First, let's get that site title centered. Now, how should we do this?
We could tell the header to align its text to the center with the text-align property. Let's try:
<header>
text-align: center;
...
</header>
Hmm. This is definitely not what we want. Specifying the text to align to center also affects the img element as well because it is an inline element. And so it follows that we cannot give it an absolute position like we could a block element. If we float it to the left, however:
#siteimage {
float: left;
}
Well, that's a total bust. Somehow, we need to get the image to sit on the left and keep the header sized properly. It looks like we either find a way to center the site name text differently, or we change the img element into a block element. What a mess. Maybe if we just size the header...
header {
text-align: center;
height: 60px;
...
}
Nice. We've forced the header height to match the height of the image, but the page title needs to move to the bottom of the header, and the font for the site title should be bigger and nicer looking.
In order to move the page title text to the bottom, we can change the span tags into div tags and proceed from there. Inline elements are limited in how they can be positioned and aligned. Because the div is a block element, it will be much easier to move things around.
Then, because we want to change the position of that div, we need to change the position property value for the header to "relative". This is necessary, because child elements of the header will not position themselves correctly unless the header's position property is "relative"".
Once that is done, we can set the position property on the page title div to "absolute" and then pin it down in the lower right corner. So, let's get these things done:
<head>
...
* {
font-family: Segoe UI, Arial, sans;
}
header {
...
position: relative;
}
...
#sitepagetitle {
float: right;
position: absolute;
bottom: 0;
right: 2px;
font-size: small;
}
...
#sitename {
font-size: 24px;
font-weight: bold;
}
...
<header>
...
<div id="sitepagetitle">Page Title</div>
</header>
This is good, and almost exactly what we've sketched out. Once you have this up in your browser, go ahead and change the size of the window. No matter how wide the window is, the page title text will always stay on the bottom right, the img will always hang to the left, and the site title text will always hang around somewhere in the middle.
Well, it's not really the middle of the window. Because the img element floats on the left, the calculation for the center alignment of text falls between the right edge of the image (plus any margins) and the right edge of the window (minus any padding).
One way to absolutely center the text is to put it--and only that text--into a block element and make that block element span the width of the header. Here is a way to do this:
<style type="text/css">
...
#sitename {
...
width: 100%;
position: absolute;
}
</style>
<header>
...
<div id="sitename">My Vanity Page</div>
...
</header>
Now the text is most definitely centered. If we made the borders of the sitename div visible, you would see them stretch the entire width of the header element.
Perhaps the next thing we can do is mock-up a navigation menu. The easiest way to do this when the nav bar is a vertical element is to create a ul element:
<nav>
<ul>
<li>My Story</li>
<li>Links</li>
<li>Music</li>
<li>Video</li>
</ul>
</nav>
Yeah, this looks...ok. After looking at this layout on the screen, it seems that a better solution for the navigation links would be to have them flow horizontally under the header. A lot of sites do this as well, so it's not like we're going to do something weird.
First, let's get rid of the width limitation on the nav element. We can just erase that definition for the width. While we're at it, we should also remove the specification on the height as well. And...please be patient...drop the border definition. The nav selector in the CSS definitions should now look like this:
nav {
background-color: lightblue;
}
And a refresh of the browser should look like this:
Display
Ok, so without sketching anything, we can easily imagine a row of menu items starting with 'My Story', followed by 'Links', and so on. We have a list, but it happens to be ordered vertically. It looks like we might need something new, like maybe a row of buttons.
Well, we can keep the ul element and still have a row of buttons too. All we need to do is tell the browser how to display the list with some crafty CSS properties. The first property we will use is "display".
The display property tells the browser what kind of box it need to use when displaying an element. Block elements have a default value in display of "block". Inline elements have a default value in display of "inline". We can, however, change all that with the display property.
These are the most common values you will probably use:
- none
- inline
- block
- inline-block
There are several others, but these four should encompass all that you will need.
The none value completely removes the element and its descendants from the displayed web page. It acts like "visibility: hidden;", but unlike the visibility property, all children will be removed, regardless of their display or visibility settings.
Setting the display to inline tells the browser to show the element as if it were an inline element, and not a block element. The contents of the element are placed inline with the element preceding it, and not the entire box structure.
The ul element we have entered for our navigation will normally display each li element as a block item. That is, the content for each li element renders on a separate line.
But, we can change this behavior by adding a new definition to our CSS document that makes them line up in a row:
<style type="text/css">
...
nav ul > li {
display: inline;
}
...
</style>
Wait a minute. Something looks odd.
Selectors and Specificity
When you define CSS properties, you assign them to elements by the use of a selector. The selector is the text in front of the left bracket ('{') which matches elements. Up to this point, you have seen a way to match elements by name, id value, or class value.
CSS can target certain elements based on other factors as well. Here are a few of them:
li { display: inline; }
ul > li { display: inline; }
nav ul > li { display: inline; }
li,em { color: blue; }
The reason we have so many ways to target elements in CSS is that we sometimes need to be more specific in what we are targeting. If all of the CSS selectors in the above example were used, there will only be one that the browser uses to set the display property. The one the browser uses is determined by the selector's specificity.
Generally, the more specific you get, the better chance the browser will pick the rule you want. Furthermore, you may not want all li elements on the page to display as inline elements, just the ones in the nav element.
Now, we could have set the class attribute to all the li items in the nav element to a certain value and then used that as a class selector, but using "nav ul > li" is much more compact and a whole lot cooler.
So, with the new CSS definition in the file, the nav element looks like this:
This looks better, but everything is clumped together. I cannot tell if I should have a link for "My Story" or "My Story Links". We need to set these apart from each other visually. Let's put some space between them and make them a different color from the background. While we are at it, we should also make sure they are each the same width:
nav ul {
margin: 0;
padding: 0;
}
nav ul > li {
display: inline;
background-color: #9DC8C6;
padding: 4px;
text-align: center;
width: 80px;
}
Well, this almost looks right. We set a width for the li elements, removed the padding and margins from the ul so that there wouldn't be a space between the header and the nav contents, we centered the text, and we still have something wrong.
The li elements are all different widths and the light blue background is not tall enough. So, we will try one other thing to the display of the li elements. We will change the display property to "inline-block".
...
nav ul > li {
display: inline-block;
...
The difference between inline and inline-block is that "inline" renders the element as an inline element and "inline-block" renders the element as a block. The similarity is that elements are displayed as an inline element with either "inline" or "inline-block" set. The rendering action constructs the object and the displaying action puts it in a certain place.
Now it really looks cool. All we need is content and a footer. The content will come later, but we can set up a standard footer with ease.
<footer>My Vanity Page Copyright 2014, Me [9999 hits]</footer>
Ok, that looks dumb. What we need is a way to format the information in the footer and make it simple.
Tables are a simple and useful way to tabulate data and format items into columns when you don't really care much for exact measurements.
Now don't get the wrong idea. We can institute exactness very well with CSS, but if you want to slap something down quickly, a table is a great way to get an easy format.
<footer>
<table>
<tr>
<td>My Vanity Page</td>
<td>Copyright 2014, Me</td>
<td>[9999 hits]</td>
</tr>
</table>
</footer>
Well, it still looks cruddy, but we can fix it up real quick with some CSS:
footer table {
margin-top: 2em;
width: 100%;
}
The table element will evenly spread out the cells throughout its width. It also inherits the text alignment from its container, which in this case is just the default of "left". What we would really like to do is get the left cell text to snap left, the right cell text to snap right, and the center text to sit in the center.
We are not going to need this except in one place--the footer--and each of the three cells needs something different. What we will do here is assign a unique id value to each cell and fix things up in CSS:
#footleft {
width: 25%;
text-align: left;
}
#footcenter {
text-align: center;
}
#footright {
width: 25%;
text-align: right;
}
...
<tr>
<td id="footleft">My Vanity Page</td>
<td id="footcenter">Copyright 2014, Me</td>
<td id="footright">[9999 hits]</td>
</tr>
...
We used id values of "footleft", "footright", and "footcenter". Now it looks great. It re-sizes well, too:
I suggest that you now save this file as "vanity_template.html". We can use this as a template file for several pages. We need some tweaking with the navigation and that goofy hit counter thing in the footer, but it is mostly there.
You have created your first HTML5 web page with a bunch of CSS. In case you haven't followed the article, the code in its entirety can be copied from here:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>My First Web Page</title>
<style type="text/css">
* {
font-family: Segoe UI, Arial, sans;
}
header {
background-color: lightgray;
text-align: center;
height: 60px;
position: relative;
}
nav {
background-color: lightblue;
}
nav ul {
margin: 0;
padding: 0;
}
nav ul > li {
display: inline-block;
background-color: #9DC8C6;
padding: 4px;
text-align: center;
width: 80px;
}
#sitepagetitle {
float: right;
position: absolute;
bottom: 0;
right: 2px;
font-size: small;
}
#siteimage {
float: left;
}
#sitename {
font-size: 24px;
font-weight: bold;
width: 100%;
position: absolute;
}
footer table {
margin-top: 2em;
width: 100%;
}
#footleft {
width: 25%;
text-align: left;
}
#footcenter {
text-align: center;
}
#footright {
width: 25%;
text-align: right;
}
</style>
</head>
<body>
<header>
<img id="siteimage" src="somepicture.png" />
<div id="sitename">My Vanity Page</div>
<div id="sitepagetitle">Page Title</div>
</header>
<nav>
<ul>
<li>My Story</li>
<li>Links</li>
<li>Music</li>
<li>Video</li>
</ul>
</nav>
<footer>
<table>
<tr>
<td id="footleft">My Vanity Page</td>
<td id="footcenter">Copyright 2014, Me</td>
<td id="footright">[9999 hits]</td>
</tr>
</table>
</footer>
</body>
</html>
Summary
In this chapter, we took a good look at creating a real web page. We went through the motions of designing, testing, refining, and repeating until we hammered out a decent-looking document. The resulting code is quite short and the HTML5 parts are very succinct. In the next article, we will be looking at adding some audio and video to the document, as well as some cool CSS effects.
Other articles in this series:
History
2014-04-09: First posting.