CSS continued¶
In this reading, we'll learn more CSS. We'll learn about some powerful selection tools, how to handle colors and transparency, and (optionally) how to expand our repertoire of fonts.
Ottergram Example¶
As before, let's start with an example. The following three pages are all Ottergram, and the HTML is mostly unchanged. The appearance of the latter two are subtly different, mostly in fonts and colors. There's also a difference in the HTML and CSS.
I suggest opening the latter two each in a separate window, placing them side by side and scrolling up and down a bit. Also:
- View Source, to see the changes to the HTML
- Inspect an element and see the CSS rule(s) that are applied
Structural Selectors¶
If you view the source, you'll see that the HTML has been simplified,
removing much of the clutter of all those class
attributes that we
added last time in order to style various elements. Instead, we are
using structural selectors, which are built out of combinations of
the basic selectors.
Basic Selectors¶
Recall that we have (so far), three kinds of basic selectors in CSS:
- tag: style every such tag
- classes: style every element with that class.
- id: style the (unique) element with that ID.
Descendant Selectors¶
As you know, HTML defines the structure of the page. In particular, it defines parent/child relationships, which we can generalize to ancestor/descendant relationships.
So, the following snippet of HTML from Ottergram
<ul class="thumbnail-list">
<li class="thumbnail-item">
<a href="imgs/otter1.jpg">
<img src="imgs/otter1.jpg" alt="Barry the Otter">
<span>Barry</span>
</a>
</li>
means that the ul
is a parent of the li
, which is a parent of the
a
, which is the parent of both the img
and the span
. If we look
at the img
element in the Firefox developer tools, we see the
following:
This shows the ancestry of the img
element. In fact, the ancestry is
shown at the bottom of the screenshot, like this:
html > body > main > ul.thumbnail-list > li.thumbnail-item > a > img
We can use the parent/child and ancestor/descendant relationships to select a set of elements.
To select any hyperlink (a
) that is a child of a
.thumbnail-item
, we can use the following selector:
.thumbnail-item > a
For example, to remove the underline on the hyperlinks in every thumbnail-item, we could do:
.thumnail-item > a {
text-decoration: none;
}
This selector is built out of two basic selectors: a class
(.thumbnail-item
) and a tag (a
). It matches elements based on
their structural relationships. In general, the selector is:
parent-selector > child-selector
where both parent and child selectors are drawn from our basic set (tag, classes and ids).
Descendants¶
Descendants are exactly what you'd think they are:
the extension of the parent/child relationship. (Click that link if
you're not sure about the meaning of "descendant"). In the following,
the em
is a descendant of the ul
, though it is not a child of
ul
:
<ul>
<li>harry</li>
<li>ron</li>
<li>hermione</li>
<li>malfoy, who is a <em>pureblood</em></li>
</ul>
Thus, a descendant selector, A B
, is always a superset of a child
selector, A > B
.
Siblings¶
Similarly, an li
is a child of the ol
or ul
that it's a list
item of. But lists also create a bunch of siblings. Here's a list with
three children, all siblings:
<ul>
<li>harry</li>
<li>ron</li>
<li>hermione</li>
</ul>
In the list above, ron and hermione have an earlier sibling (harry is earlier than ron, and ron is earlier than hermione), but harry does not have an earlier sibling.
Note that there are lots of sibling relationships; they can even be
different tags. The h2
, p
and ul
in this div
are all siblings:
<div>
<h2>stuff</h2>
<p>introduction</p>
<ul>
<li>first</li>
<li>second</li>
</ul>
</div>
More Structural Selectors¶
If A and B are both basic selectors, then:
A > B
selects every B that is a child of any AA B
selects every B that is a descendant of any AA + B
selects every B that immediately follows (is the next sibling of) any AA ~ B
selects every B that follows (is a later sibling of) any A. That symbol is a tilde (probably next to the exclamation point on your keyboard)
Notice that it's always the second thing, the B
, that is
selected. So if B
is, say, em
, then everything that is selected
will be an em
element; the only question is what its ancestor
relationship is.
(I'll note that I use child and descendant selectors all the time; the
sibling selectors are relatively rare. We'll use +
in Ottergram, but
we won't use ~
at all.)
Interactive Demonstration¶
You might re-visit the interactive selector display to try some of these structural selectors. First, though, you might refresh your memory about what the HTML looks like:
<h2>this is an h2 header</h2>
<p id="par1">This paragraph has ID <code>par1</code></p>
<h2>this is another h2 header</h2>
<p>this paragraph precedes the list of fruits and veggies</p>
<ol id="list1">
<li class="fruit">apple</li>
<li class="veg">broccoli</li>
<li class="fruit">coconut. this is tough</li>
<li class="fruit">date</li>
<li class="veg">endive</li>
<li class="veg">fennel. this is yucky</li>
<li class="fruit">"g" fruits
<ul>
<li>gooseberry</li>
<li>grape</li>
<li>grapefruit</li>
<li>guava</li>
</ul>
</li>
<li class="veg">horseradish</li>
<li>tomato</li>
</ol>
<p>this paragraph follows the list of fruits and veggies</p>
Notice the parent/child, sibling and ancestor/descendant relationships. Then try the structural selectors below.
Revised Ottergram HTML¶
With this in mind, we can omit a lot of the class attributes in
Ottergram's HTML and plan instead to use descendant selectors. So
instead of putting class="thumbnail-item-a"
on the A
tag that is a
descendant of the li.thumbnail-item
, we can just use
.thumbnail-item a
as the selector.
Here's the body of the revised Ottergram page.
<body>
<header>
<h1 class="logo-text">ottergram</h1>
</header>
<main>
<ul class="thumbnail-list">
<li class="thumbnail-item">
<a href="imgs/otter1.jpg">
<img src="imgs/otter1.jpg" alt="Barry the Otter">
<span>Barry</span>
</a>
</li>
<li class="thumbnail-item">
<a href="imgs/otter2.jpg">
<img src="imgs/otter2.jpg" alt="Robin the Otter">
<span>Robin</span>
</a>
</li>
<li class="thumbnail-item">
<a href="imgs/otter3.jpg">
<img src="imgs/otter3.jpg" alt="Maurice the Otter">
<span>Maurice</span>
</a>
</li>
<li class="thumbnail-item">
<a href="imgs/otter4.jpg">
<img src="imgs/otter4.jpg" alt="Lesley the Otter">
<span>Lesley</span>
</a>
</li>
<li class="thumbnail-item">
<a href="imgs/otter5.jpg">
<img src="imgs/otter5.jpg" alt="Barbara the Otter">
<span>Barbara</span>
</a>
</li>
</ul>
</main>
</body>
That's much simpler and less cluttered! (For comparison, here's the original Ottergram and the previous Ottergram (css1). Do a "view source" to see the source.
Revised Ottergram CSS¶
I won't go through the CSS rules one by one; at this point, I just want you to look at the selectors.
body {
font-size: 62.5%;
background: rgb(149, 194, 215);
}
.logo-text {
background: white;
text-align: center;
text-transform: uppercase;
font-family: lakeshore;
font-size: 3.7em;
}
.thumbnail-list {
padding: 0;
}
.thumbnail-item {
display: inline-block;
border: 2px solid rgb(100%, 100%, 100%);
border: 2px solid rgba(100%, 100%, 100%, 0.8);
}
.thumbnail-item:hover {
border: 2px solid mediumblue;
}
.thumbnail-item + .thumbnail-item {
margin-top: 1em;
}
.thumbnail-item a {
text-decoration: none;
display: block;
border: 1px solid rgb(100%, 100%, 100%);
border: 1px solid rgba(100%, 100%, 100%, 0.8);
}
.thumbnail-item img {
display: block;
width: 100%;
}
.thumbnail-item span {
display: block;
margin: 0;
padding: 0.4em 1em;
background: rgb(96, 125, 139);
color: rgb(202, 238, 255);
font-family: airstreamregular;
font-size: 1.8em;
}
You can compare them with the prior CSS file.
Pseudoclasses¶
You may have noticed a new rule:
.thumbnail-item:hover {
border: 2px solid mediumblue;
}
The :hover
notation is a pseudo-class. In this case, the rule
applies to selected elements that also have the mouse hovering on
them. For example, p:hover
would match the paragraph the mouse is
on.
Of course, :hover
isn't useful on touch devices, since the device
can't tell where your finger is hovering.
Spacing¶
To put some vertical space between the thumbnails, we can add some margin-top to each thumbnail except the first one. (We don't want to add a margin-top to the first one because there's nothing above it that we want separation from.) We can do that by using a sibling selector:
.thumbnail-item + .thumbnail-item {
margin-top: 1em;
}
This rule will apply to all the thumbnail items except the first one, because the first one doesn't have a prior sibling. That's exactly what we want.
Colors¶
You probably noticed some other changes in the rules, namely replacing
color names with an rgb(red, green, blue)
syntax. For example,
body {
font-size: 62.5%;
background: skyblue;
}
became
body {
font-size: 62.5%;
background: rgb(149, 194, 215);
}
So, let's talk about color in CSS. There are many named colors in the CSS language. But with all those named colors, it's only a small fraction of the over 16 million colors that are possible on modern screens. (224 is 16,777,216) If you want a color that's not on the list of names, you have to specify it using the amount of red, green and blue (henceforth, RGB). This isn't the place for a tutorial in RGB color theory; though I've written those in the past, so feel free to ask.
The CSS language allows a variety of ways to specify colors. Just using RGB (there are other color models as well), we have several notations. Consider a shade of chartreuse. You can give it as:
- a name: background-color:chartreuse
- an RGB triple of values from 0-255: background-color:rgb(127,255,0)
- an RGB triple of percentages: background-color:rgb(50%,100%,0%)
- a hex value: background-color:#7fff00
Let's focus on the second option. So, the background color we saw
above for the body
tag, rgb(149, 194, 215)
is 149 units of red (on
a scale from 0 to 255), 194 units of green, and 215 units of blue. I
like to think of these as "knobs" you can turn to adjust the amount of
each primary color.
The result is like this.
If you want to design your own color, you can use this color calculator
But wait, there's more.
Transparency¶
Most browsers also support a four-dimensional system of colors, where the fourth dimension is transparency, also called alpha. So the system is RGBA. Alpha is measured on a scale from 0 (perfectly transparent) to 1 (completely opaque). If you want to use transparency, though, your choices of notation are more limited:
- RGBA percentages:
background-color:rgba(50%,100%,0%,0.5)
- RGBA values:
background-color:rgba(127,255,0,0.5)
Here they are in action. Here are two overlapping squares, one solid
red background-color: rgb(100%,0%,0%)
and the other 50% transparent blue background-color: rgba(0%,0%,100%,0.5)
:
(By mixing solid red with blue at 50% transparency, we get a purplish result because red+blue is purple. Note that the blue at the right looks different from solid blue because the white background of the page is showing through. We'll learn how to have overlapping elements in a future reading.)
Since not all browsers support transparency, it's good to have a backup option. Strangely, we put the backup option first. That's because the second value will override the first value, but if the browser doesn't understand the second value because the second value uses transparency, the browser will use the first value.
Thus, if we want to have a border around our thumbnail items that is white but 80% transparent, with solid white as the backup, we do this:
.thumbnail-item {
display: inline-block;
border: 2px solid rgb(100%, 100%, 100%);
border: 2px solid rgba(100%, 100%, 100%, 0.8);
}
You get white if you turn all the knobs up to 100% (or 255). I could have used the color name "white" on the first one, but I wanted to show the RGB and RGBA notations.
Multiple Selectors¶
If you have a declaration block that you'd like to have apply to more than one set of elements, just list all the selectors before the block, separated by commas:
A, B {
prop1: val1;
prop2: val2;
}
For example, the following turns off padding for both kinds of lists:
OL, UL {
padding: 0
}
Style Inheritance¶
Some CSS declarations (property-value pairs) are inherited, which means they apply to all descendants of the selected elements. This is usually pretty intuitive: font-size and background color are inherited, but border is not.
Fonts¶
Most of the time, we can stick to built-in fonts that browsers provide, though if a user doesn't have that font, they may see something slightly different from what you intended.
Some built-in values for font-family
include:
- verdana; the quick brown fox jumps over the lazy dog
- arial; the quick brown fox jumps over the lazy dog
- Times New Roman; the quick brown fox jumps over the lazy dog
- Georgia; the quick brown fox jumps over the lazy dog
- fantasy; the quick brown fox jumps over the lazy dog
If you'd like to learn more about custom fonts, you can read that at the given link.
I put the font definitions in a second CSS file fonts.css and modified the head of the HTML file to load it:
<link rel="stylesheet" href="stylesheets/fonts.css">
<link rel="stylesheet" href="stylesheets/styles.css">
The fonts are referred to in the styles.css
file, so we load the
fonts.css
file first.
Summary¶
- CSS selectors can be structural
- We learned four kinds:
A > B
which is a child selector, selecting B elements that are children of A elementsA B
which is a descendant selector, selecting B elements that are descendants of A elementsA + B
which is a next sibling selector, selecting B elements that immediately follow A elementsA ~ B
which is a sibling selector, selecting B elements that follow A elements
- We learned about RGB color and the
rgb(val, val, val)
notation - We learned about transparency and the
rgba(val, val, val, val)
notation