Web Programming Foundations
Schedule Notes Resources Graded Work MyApps Instructions Vercel Guide Code examplesIn HTML5 we don’t include markup related to how our page should look; instead we focus on its structure, layout, and organization. We put all this information in style sheets: text files that define CSS selectors and rules for how to style our HTML elements.
CSS allows us to specify styles, layout, positioning, and other “style” properties for HTML elements. CSS makes it possible for a page’s style information to be separated from its structure and content.
NOTE: Before we proceed to discuss CSS and it’s syntax, it’s important to note that these notes have been divided into two parts, since the content is longer than usual. If the entire topic cannot be covered during a lecture period, the 2nd half (Part 2 - “Box Model”) will be given during the lab period
CSS syntax is made up of rules, which are broken into two parts:
{...}
bracesh1 {
color: blue;
font-size: 12px;
}
In this example, the selector is h1
, which indicates that we want the following
rules to be applied to level-1 heading elements (i.e., all <h1></h1>
elements in the document).
Next comes a list of two definitions, each ending with a ;
. These declarations
follow the usual key/value syntax, with a property name coming before the :
, and a value
coming after:
color: blue;
says we want to use the colour (note the spelling) bluefont-size: 12px;
says we want the font to be 12px.Here’s another example:
p {
color: red;
text-align: center;
text-decoration: underline;
}
This indicates we want all <p></p>
elements in the document to have red, centered, underlined text.
CSS can come from a number of sources in an HTML page:
Browsers apply styles to elements using a priority order that matches the list above. If more than one style rule is specified for an element, the browser will prefer whatever is defined in Inline styles over Internal Embedded, Internal Embedded over External files, etc.
CSS rules can be placed directly on an element via the style
attribute:
<div style="background-color: green">...</div>
If we want to apply the same CSS rules to more than one element, it makes more sense to
not duplicate them on every element’s style
attribute. One solution is to use an internal embedded
<style>
element in the <head>
or <body>
, similar to how embedded <script>
elements work:
<style>
p { color: red; }
div {
background-color: blue;
text-align: center;
}
</style>
Putting large amounts of CSS in <style>
elements makes our HTML harder to read and maintain
(CSS is about separating style from structure), and also causes our page to perform worse
in terms of load times (i.e., the styles can’t be cached by the browser). To overcome this,
we often include external .css
files via the <link>
element within the document’s <head>
:
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="styles.css" type="text/css">
</head>
We can include many stylesheets in this way (i.e., everything doesn’t have to go in one file),
and we can include .css
files on the same origin, or a remote origin:
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="styles.css" type="text/css">
</head>
In the example above, the page uses the popular Bootstrap CSS styles
along with some locally (i.e., local to the web server) styles in styles.css
.
A .css
file included in this way can also @import
to have even more .css
files get loaded at runtime:
/* Import Font Awesome */
@import url(https://use.fontawesome.com/releases/v5.4.2/css/all.css);
In this example, the popular Font Awesome CSS library for font icons
has been imported via a .css
file.
The name of an HTML element can be used to specify the styles associated with all
elements of the given type. For example, to indent all <p>
text in our document, we could do this:
p {
text-indent: 20px;
}
Often we want to apply styles to some but not all elements of a certain kind. Perhaps
we only want some of our page’s <p>
elements to have a particular look. To achieve this,
we define a class, and then put that class on the elements that require it:
<style>
.demo {
text-decoration: underline red;
}
</style>
<p>This is a paragraph that won't get the styles below applied to it (doesn't include the class)</p>
<p class="demo">This paragraph will get the styling applied.</p>
<p class="demo">And so will this one.</p>
A class can be applied to elements that aren’t of the same type:
<style>
.invisible {
display: none;
}
</style>
<h1 class="invisible">Title</p>
<p class="invisible">This is a paragraph.</p>
I this example, both the <h1>
element, and the <p>
element will have the display: none
style applied,
hiding them so they don’t appear in the page.
If we want to be more specific, and only apply styles to elements of a given type which also have a given class, we can do this:
<style>
p.note {
font-weight: bold;
}
</style>
<p class="note">This is a paragraph that also uses the note class.</p>
<div class="note">This div uses the note class too, but because we said p.note, no styles are used.</div>
An element can also have multiple classes applied, each one adding different styling:
<style>
.invisible {
display: none;
}
.example {
color: green;
background-color: red;
}
</style>
<p class="invisible example">This is a paragraph that uses two classes at once.</p>
In many cases, we have only a single element that should use styles. Using a type
or class selector would be overly broad, and so we tend to use an id
instead.
Recall that only one HTML element in a document can have a given id
attribute:
it must be unique.
<style>
#summary {
background-color: skyblue;
}
</style>
<div id="summary"></div>
When we use the id
as a selector, we prefix it with the #
symbol. Notice that
the HTML does not use the #
symbol though.
Another common way to write selectors is to use the position (context) of elements. The context selector indicates the context, or placement/nesting (i.e., determined by the parent node) of the element.
For example, if we want to apply styles to <p>
elements that are children of <div>
elements, we could do this:
<style>
div p {
font-size: 16px;
}
</style>
<p>This paragraph will not receive the styling</p>
<div>
<p>This paragraph will receive the styling.</p>
<p>This paragraph will receive the styling also.</p>
</div>
As our CSS grows, it’s common that we’ll notice that we’re repeating the same things multiple times. Instead of doing this, we can group a number of selectors together into a comma-separated list:
html, body {
height: 100%
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: Serif;
color: blue;
}
Here we’ve used grouping twice to cut-down on the number of times we have to repeat things.
In the first case, we defined a height of 100%
(full height of the window) for the <html>
and <body>
elements (they don’t have a height by default, and will only be as tall as
the content within them). We’ve also declared some font and color information for all the
headings we want to use.
We’ve discussed <div>
and <span>
in the past, but their purpose may not have been clear.
Why bother wrapping other elements in <div>...</div>
or <span>...</span>
when they don’t
display any different?
With CSS we can now start to take advantage of what they provide. If we think of them as containers which can be used to group styling, their purpose will become more clear.
A <div>
is a block level element, and <span>
an inline element. Depending on how we want
to group and apply styling, we can use one or both. Consider the following:
<style>
.info-box {
border: solid green;
}
.info-box p {
font-family: Serif;
}
.info-box span {
font-weight: bold;
}
.info-box img {
width: 75px;
height: 75px;
}
</style>
<p>This paragraph won't have any special style applied. Neither will this <span>span</span>.</p>
<div class="info-box">
<p><span>Name:</span> Thomas Lee</p>
<p><span>Age:</span> 23</p>
<img src="tlee.jpg">
</div>
Many CSS values require units to be specified, for example, font sizes, widths, heights, etc. At first you might think that we should specify things in pixels; however, browsers need to work on such a wide variety of hardware and render to so many different displays (watches to billboards), we need more options. It’s also important to be able to specify sizes using relative units vs. fixed, for layouts that need to adapt to changing conditions and still retain the correct proportions.
There is one exception, and that is for 0
(i.e., zero), which never needs a unit (i.e., 0px
is the
same as 0%
, etc).
The most common units we use in CSS are:
1em = 12pt = 16px = 100%
Let’s look at each of these in turn:
em
(the width of the capital letter M
) - a scalable unit that is used in web media, and is equal to the current font-size
. If the font-size
is 12pt
, 1em
is the same as 12pt
. If the font-size
is changed, 1em
changes to match. We can also use multiples: 2em
is twice the font-size
, and .5em
is half. Using em
for sizes is popular on the web, since things have to scale on mobile vs. desktop (i.e., fixed unit sizes don’t work as the screen shrinks/expands).pt
- a fixed-size Point unit that comes from print media, where 1pt
equals 1/72
of an inch.px
- pixels are fixed size units for web media (screens), and 1px
is equal to one dot on a computer display. We use px
on the web when we need “pixel perfect” sizing (e.g., image sizes).%
- the percent unit is similar to em
in that it scales with the size of the display. 100%
is the same as the current font-size
.vw
, vh
- the viewport width and height units are percentages of the visible space in the viewport (the part of the page you can see, the window’s width and height). 1vw
is the same as 1%
of the width of the viewport, and 80vh
is the same as 80%
of the visible height.You will also sometimes encounter other ways of measurement that use full words: xx-small, x-small, small, medium, large, x-large, xx-large, smaller, larger, thin, medium, thick
Here’s an example that uses a number of the units mentioned above:
<style>
html, body {
height: 100vh;
}
.box {
margin: 10px;
font-size: 2em;
height: 150px;
border: medium solid black;
}
</style>
<div class="box"></div>
color
)CSS allows us to define colour values for many declarations. We do so by specifying a colour using one of the following notations:
#
sign. Each of the 3 pairs represents a value between 0 and 255 for Red, Green, and Blue: #000000
is pure Black and #ffffff
is pure White, and #ffd700
is Gold.#ffffff
is the same as rgb(255, 255, 255)
and #ffd700
is the same as rgb(255, 215, 0)
. If we want to define how see-through the colour is (by default you can’t see through a colour), we add an alpha value: rgba(0, 191, 0, 0.5)
means that the colour will be 50% see through.white
, black
, green
, red
, but also chocolate
, darkorange
, peru
, etc.The easiest way to understand this is using a Colour Picker tool, which lets you visually see the difference in changing values.
A property is assigned to a selector in order to manipulate its style. The CSS properties are defined as part of the CSS standard. When you want to know how one of them works, or which values you can assign, you can look at the documentation on MDN. For example:
There are hundreds of properties we can tweak as web developers, and it’s a good idea to explore what’s available, and to look at how other web sites use them via the developer tools.
A property can have one or more values. A the possible values a property can have also comes from the standard. For example:
p {
text-decoration: underline;
}
.spelling-error {
text-decoration: red wavy underline;
}
The text-decoration
property is defined
to take one of a number of values, each of which is also defined in the standard.
By far the best way to learn about CSS is to look at how other sites use it. When you find something on the web that you think looks interesting, open your browser’s dev tools and inspect the CSS Styles:
You can look at the specific properties specified for an element, or see all the computed styles (i.e., everything, including all default values). You can also try toggling these on and off, or double-click the values to enter your own.
text
PropertiesThere are dozens of properties that affect how text is rendered. These include things like the color, spacing, margins, font characteristics, etc.
h2 {
color: red;
text-align: center;
text-decoration: underline;
text-transform: uppercase;
}
p {
color: #0000ff;
text-indent: 100px;
}
font
PropertiesWe can use the font-family
property to specify a font, or list of fonts, for the
browser to apply to an element. The font must be available on the user’s computer,
otherwise the next font in the list will be tried until one is found that is installed,
or a default font will be used.
In general it is safe to assume that the following fonts are available:
Helvetica, Arial, Verdana, sans-serif
- sans-serif fonts"Courier New", Courier, monospace
- monospace fontsGeorgia, "Times New Roman", Times, serif
- serif fontsYou can see a list of the fonts, and OS support here.
h3 {
font-family: Arial;
}
h4 {
font-family: "Times New Roman", Times, serif;
}
h5 {
font-size: 18pt;
font-style: italic;
font-weight: 500
}
@font-face
Modern browsers also allow custom fonts to be included as external files, and downloaded as needed by the web site. This is often the preferred method for designers, who don’t want to be limited to the set of fonts available on all operating systems.
A font is a file that describes the curves and lines needed to generate characters at
different scales. There are various formats, from OTF
(OpenType Format) to
TTF
(TrueType Format) to WOFF
(Web Open Font Format), etc. In order for
the browser to use a new font, it has to be downloadable via one or more URLs.
We then tell the browser which font files to download in our CSS via the
@font-face
property:
@font-face {
font-family: "FontName"
src: url(font.woff2) format('woff2'),
url(font.ttf) format('truetype');
}
body {
font-family: "FontName";
}
Many fonts have to be purchased, but there are some good sources of high quality, freely available fonts for your sites:
For example, we can use the popular "Lobster"
font
from Google by doing the following in our CSS:
@import url(https://fonts.googleapis.com/css?family=Lobster);
p {
font-family: "Lobster";
}
font-size
propertyUsing the font-size
property, font sizes
can be given in fixed or relative units, depending on how we want our text to scale on different devices:
h1 {
font-size: 250% /* scaled to 250% of regular font size */
}
p {
font-size: 20pt /* size in points -- 20/72 of an inch */
}
.quote {
font-size: smaller; /* smaller than normal size */
}
.bigger {
font-size: 1.5em; /* 1.5 times larger than the 'M' in normal font size */
}
There are numerous effects that can be added to text (or any element), many beyond the scope of this initial exploration of CSS. Here are a few simple examples to give you an idea
text-shadow
allows a
shadow to be added to text, giving it a 3-D style appearance. The value includes a colour,
x
and y
offsets that determine the distance of the shadow from the text. Finally, we
can also add a blur-radius
, indicating how much to blur the shadow.
.shadow-text {
text-shadow: 1px 1px 2px pink;
}
text-overflow
can be used
to determine what the browser should do when the amount of text exceeds the available space
in a container (e.g. in a <div>
or <p>
that isn’t wide enough). For example, we can specify
that we want to clip
the contents and not show any more, or we can automatically display ...
,
the ellipsis
.
<style>
.movie-title {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>
<p class="movie-title">Pirates of the Caribbean: The Curse of the Black Perl</p>
background
PropertiesEvery element has a background that we can modify. We might, for example, want to
specify that the background be a certain colour; or we might want to use an image,
or even tile an image multiple times (like wallpaper to create a pattern); or we
might want to create a gradient, from one colour to another. All of these options
and more are possible using the background
property.
div.error {
background: red;
}
div.wallpaper {
background: url("pattern.jpg") repeat;
}
We can control the way that links (i.e., <a>
) appear in our document. By default
they will have a solid blue underline, and when visited, a purple solid underline.
If you want to remove the underline, or change it’s colour to match the theme of a page,
we can do that using CSS pseudo-classes
.
With pseudo-classes we can specify certain states for the elements in our selector, for example:
a:link
- a normal, unvisited link (normally blue underline)a:visited
- a link the user has visited previously (normally purple underline)a:hover
- a link when hovered with the mouse (NOTE: can also be used on other elements)a:active
- a link when it is clicked (i.e., while the mouse button is pressed)NOTE: pseudo-classes can be used with any element, but we mention them here in relation to styling links, since we often need them to deal with different states for a link.
Let’s alter our links so that they use blue text, with no underline. However, when hovered, add back the underline:
a:link, a:visited {
text-decoration: none;
}
a:hover, a:active {
text-decoration: underline;
}
We’ve been focused on the mechanics of writing CSS ourselves, and this is an important skill. In addition, it’s a good idea to know how to use third-party CSS libraries created by other developers. There are many pre-existing CSS libraries and frameworks we can use to help us create the web pages and apps we desire.
There is a general pattern to using any CSS library in your web page.
.css
files, and maybe .js
,fonts, etc. You will likely need to use <link>
and <script>
elementsHere’s a list of some popular CSS libraries and frameworks to get you started.
First, a few examples of simple “drop in” style libraries, where you simply include the CSS file, and everything “Just Works”:
Next, there are lots of stylesheets you can use to improve the readability of your text:
In addition to changing how our text looks, a lot of CSS libraries add interesting and playful animations and effects to spice up our HTML:
Another common problem CSS can solve is what to do while we wait for things to finish loading:
Many CSS libraries have grown into more complex suites of layout, component, typography, navigation, and other solutions. We often refer to these as “frameworks” to indicate the expanded scope. There are many to choose from, including:
All elements can be considered to be a box. The Box Model is a specification for how all the various attributes of an element’s sizing relate to each other. A “box” is made up of four distinct parts:
The easiest way to visual this is using your browser’s dev tools, which have tools for viewing and altering each of these parts.
The sizes of each of these can be controlled through CSS properties:
Each of these is a shorthand property that lets you specify multiple CSS properties at the same time. For example, the following are equivalent:
/* Use separate properties for all aspects */
.example1 {
border-width: 1px;
border-style: solid;
border-color: #000;
margin-top: 5px;
margin-right: 10px;
margin-bottom: 15px;
margin-left: 20px;
}
/* Use shorthand properties to do everything at once */
.example2 {
border: 1px solid #000;
margin: 5px 10px 15px 20px;
}
In the code above for margin
, notice how the the different portions of the
margin
get translated into a single line. The order we use follows the same
order as a clockface, the numbers begin at the top
and go clockwise around:
.example2 {
/* top right bottom left */
margin: 5px 10px 15px 20px;
}
We often shorten our lists when multiple properties share the same values:
.example3 {
/* Everything is different, specify them all */
margin: 10px 5px 15px 20px;
}
.example4 {
/* Top and bottom are both 10px, right and left are both 5px */
margin: 10px 5px;
}
.example5 {
/* Top, bottom, left, and right are all 5px */
margin: 5px;
}
When two elements that specify a margin
at the top and bottom are stacked, the
browser will collapse (i.e., combine) the two into a single margin, whose size is
the largest of the two. Consider the following CSS:
<style>
h1 {
margin-bottom: 25px;
}
p {
margin-top: 20px;
}
</style>
<h1>Heading</h1>
<p>Paragraph</p>
Here the stylesheet calls for a <p>
element to have 20px
of whitespace above it.
However, since the <h1>
has 25px
of whitespace below it, when the two are placed
one after the other, the distance between them will be 25px
vs. 45px
(i.e., the browser won’t apply both margins, but just make sure that both margins are
honoured).
display
PropertyCSS lets us control how an element gets displayed. This is a large topic, and we’ll give an overview of some of the most common display types. Further study is required to fully appreciate the subtleties of each layout method.
Perhaps the easiest way to get started understanding display types is to look at
what display: none;
does:
<style>
.hidden {
display: none
}
.error-msg {
/* styles for error message UI */
}
</style>
<div class="hidden error-msg">
<h1>Error!</h1>
<p>There was an error completing your request.</p>
</div>
When an element uses a display type of none
, nothing will be painted to the screen.
This includes the element itself, but also any of its children.
If elements don’t have a display type of none
, they get included in the render
tree and eventually painted to the screen. If we don’t specify a display type, the default is inline
for inline elements (like <a>
and <span>
) and block
for block-level elements (like <p>
and <div>
).
With inline
, boxes are laid out horizontally (typically left to right, unless
we are doing rtl), starting
at the top corner of the parent.
We can also specify that an element should be display: block;
, which will layout
blocks in a vertical way, using margin
to determine the space between them. To
understand the difference, try this using this snippet of code an HTML page, and
change the display
from block
to inline
:
<style>
h1 {
display: block; /* try changing to `inline` */
}
</style>
<h1>One</h1>
<h1>Two</h1>
<h1>Three3</h1>
We can also control the way that elements are laid out within an element (i.e., its children). Some of the display types for inside layout options include:
table
- make elements behave as though they were part of a <table>
flex
- lays out the contents according to the flexbox modelgrid
- lays out the contents according to the grid modelA great way to learn a bit about the latter two is to work through the following online CSS learning games:
p { text-align: center; }
.center {
width: 400px; /* set a fixed width */
margin: 0 auto; /* allow the browser to split the margin evenly */
}
.vertical-center {
display: table-cell; /* make the element work like a cell in a table */
vertical-align: middle; /* align to the centre vertically */
text-align: center; /* align to centre horizontally */
}
position
PropertyMany web interface designs require more sophisticated element positioning than simply allowing everything to flow. Sometimes we need very precise control over where things end up, and how the page reacts to scrolling or movement.
To accomplish this kind of positioning we can
use the CSS position
property
to override the defaults provided by the browser.
static
- the default, where elements are positioned according to the normal flow of the documentrelative
- elements are positioned according to the normal flow, but with extra offsets (top, bottom, left, right
), allowing content to overlapabsolute
- elements are positioned separate from normal flow, in their own “layer” relative to their ancestor element, and don’t affect other elements. Useful for things like popups, dialog boxes, etc.fixed
- elements are positioned separate from normal flow, and get positioned relative to the viewport.sticky
- a hybrid of relative
and fixed
, allowing an element to be positioned relatively, but then “stick” when scrolling or resizing the viewport. This is often used for headings, which can be scrolled up, but then stay in place as you continue down into the document.z-index
PropertyIn addition to controlling how elements are positioned in the X and Y planes,
we can also stack elements on top of each other in different layers. We achieve
this through the use of the z-index
property.
The z-index
is a value positive or negative integer, indicting which stack
level the element should be placed within. The default stack level is 0
, so
using a z-index
higher than 0
will place the content on top of anything below it.
The z-index
is often used with position
to place content in arbitrary positions
overtop of other content. For example, a lightbox that appears over a site’s content to show an image.
overflow
PropertyWhen the contents on an element are too large to be displayed, we have options
as to how the browser will display the overflowing content. To do this, we
work with the overflow
, overflow-x
, overflow-y
properties
visible
- default. No scroll bars provided, content is not clipped.scroll
- always include scroll bars, content is clipped and and scroll if requiredauto
- only include scroll bars when necessary, content is clipped and and scroll if requiredhidden
- content is clipped, no scroll bars provided.If you recall from last week, we introduced an online validator to check your HTML code for errors. There are similar tools for CSS, for example:
The above allows you to enter a URL to an existing web page, or enter CSS directly in a text field. It will then attempt to parse your CSS and report back on any errors or warnings.