Skip to main content

4. Semantic HTML & CSS Selectors

Display types

There are 3 major types of HTML elements: block-level, inline, and inline-block.

Block-level elements

Block-level elements are generally the bigger structural components of your web page.

As the name tells us, block-level elements are like blocks. They are rectangles that stack on top of each other. They automatically start on a new line. And most will take up the entire width of the page, or the entire width of its parent element, by default:

block-level element
another block-level element

Exception: Tables are considered block-level elements, but only take up the width required for the content inside. We'll discuss tables in a future lesson.

Examples of block-level elements:

Block-level elements may contain text content, inline elements, and inline-block elements (We'll discuss those here in a little bit).

Most block-level elements may contain other block-level elements. Paragraph elements are an exception to this.

Paragraphs and nesting

<p> elements are block-level elements. However, you should not nest other block-level elements inside of paragraphs.

Paragraphs should only contain text, inline elements, and inline-block elements. You shouldn't put a ul, ol, div, blockquote, or other block-level element inside a paragraph.

If you need to include block-level elements within your text, end the paragraph before the block-level element, and start a new paragraph after it.

<p>A paragraph of text.</p>

<!-- ul is a block-level element. So, it can't be inside of a paragraph (p) element. -->

<ul>
<li>item 1</li>
<li>item 2</li>
</ul>

<p>Another paragraph after the block-level element.</p>

Inline elements

Inline elements flow side-by-side with no defined width, just like text:

inline elementanother inline element

Inline elements are not affected by the width property or margin-top or margin-bottom.

You can only add margin on the right and left sides of inline elements.

Padding will work for all 4 sides. However, padding-top and padding-bottom will not create space between the inline element and other elements on the page. When using padding on the top and bottom of inline elements, it may cause the element to overlap other elements.

Examples of inline elements:

Inline elements will usually only contain text content, other inline elements, and inline-block elements. However, there is an exception to this rule also.

The <a> element is an inline element. Generally, you would not put block-level elements inside of an inline element. But it is fine to nest block-level elements within the <a> element. This will make the block-level element a clickable link:

<a href="https://40px.org">
<div class="click-block">
A clickable block-level element!
</div>
</a>

Inline-block elements

Inline-block elements are a hybrid. A little bit inline. A little bit block.

They will stay on the same line side-by-side like inline elements. But unlike inline elements, they can have a defined width and height:

inline-block elementanother inline-block element

Padding and margin will work on all sides of an inline-block element.

The img element is an inline-block element.

CSS display property

You can change how any element "behaves" using the display property.

For example, you could take an element that is inline by default and turn it into a block-level element:

.my-span-class {
display: block;
width: 300px;
height: 400px;
}

Using the display property like this is required in order to center an img element.

This is how you center an img element:

.my-img-class {
display: block;
margin-right: auto;
margin-left: auto;
}

We will discuss images in more detail in the next lesson.

CSS box model

We will discuss the CSS box model in the layout lesson. The basic idea is that HTML elements are like boxes.

The actual height and width of these boxes are determined by the space required for the content, in addition to the margin, border, and padding.

Margin
Border
Padding
Content

Margin and padding

Margin and padding allow you to create space.

Margin is applied to the outside of the element. It creates space between the element and other elements on the page.

Padding is applied to the inside of the element. It creates space between the content and the border.

Margin and padding can be declared using a CSS unit of measurement, such as pixel (px), em, or percentage.

The div element

The div element, short for "division", has been a popular block-level element among web designers for many years. A div can be used to section off portions of your web page for structure and styling.

We used to use it for creating the layout structure for the entire page. Some of us even developed a not-so-rare condition called divitis due to our impossible love for this element.

Overuse of divs can make your code confusing and more difficult to manage. It's best practice to try to accomplish your goals with the least amount of code possible. If you can do it without adding an extra div, choose that option.

With the introduction of HTML5 and its new semantic elements, the div element isn't needed quite as much as it once was. But it still comes in handy as a general-purpose element for grouping things together.

In this simple example, I have enclosed a couple of paragraphs within a div:

<div class="giraffe">

<p>Some text that is within the nonsensically named "giraffe" div.</p>
<p>Some more text in this same div.</p>

</div> <!--/giraffe div -->

First, notice that I have added an HTML comment to show where my "giraffe" div ends. This can be really important if there are several divs nested within other divs. It helps you easily determine which particular div is ending at that point.

And my class name "giraffe" is completely nonsensical. That's fine in lesson examples and when first learning this stuff. But we'll discuss the importance of using meaningful class and ID names further along in this lesson.

I added some CSS code in my external stylesheet to style this div:

.giraffe {
background: #ccc;
border: 1px solid #555;
padding: 15px;
margin: 10px;
}

And here's how the output looks on the page:

Some text that is within the nonsensically named "giraffe" div.

Some more text in this same div.

The span element

The span element is the inline equivalent of the div. It is most commonly used for sectioning off portions of text within a block-level element. Since a span is an inline element, it cannot contain block-level elements.

HTML:

<p>I am building a <span class="highlight">giant</span> statue of Kelly Clarkson in my yard.</p>

CSS:

.highlight {
background-color: #ffe280;
}

Output:

I am building a giant statue of Kelly Clarkson in my yard.

Semantic coding

If the page looks fine when viewed in a web browser, why would a few little errors in the code matter? Who cares if everything isn't done using best practice techniques?

It's important to realize that you are not just creating web pages for humans. Computer programs will also need to "read" the content on your website.

How your website looks on the screen is not important to computer programs. They are only "looking" at the code.

People with visual impairments use software that reads information about the web page to them. This software needs to be able to "understand" how the page and website is structured. It needs to be able to understand the meaning and purpose of each piece of content so it can extract meaning and present that to the user.

Search engines have automated "crawlers" that travel around the web and index web pages. These crawlers also need your help. Your code needs to communicate.

Take for example the heading tags <h1>, <h2>, <h3>, etc. These HTML tags attach meaning to the content between the opening and ending tags, as well as the content that appears beneath the headings.

Here's the example I used in a previous lesson:

<h1>An article about the United States</h1>

<h2>California</h2>
<p>Content under the California heading is here.</p>

<h3>Sacramento</h3>
<p>Content under the Sacramento heading is here (A subheading in the California section).</p>

<h2>Ohio</h2>
<p>Content under the Ohio heading is here.</p>

<h3>Toledo</h3>
<p>Content under the Toledo heading is here (A subheading in the Ohio section).</p>

h1 is used for the most important heading on the page. It represents the "aboutness" for the website or page.

h2 elements are used for the major headings within the content of the page.

And h3 would be used for any subheadings beneath an h2. And so on.

You shouldn't choose a particular heading tag because it makes the font a certain size. That can be changed with CSS.

You choose to use a particular HTML element because it provides meaning for the content. HTML is for structure and meaning. CSS is for controlling how it looks.

Proper usage of heading elements creates an outline of your page that communicates how each section of the content fits within the article as a whole.

When writing your code, you should try to use the element that provides the most meaning for the content.

HTML5 semantic elements

HTML5 took semantic coding to a greater level with elements that provide more meaning. For example, there is an <article> element for enclosing the content of an entire article.

But why does this matter?

Computers are not as perceptive as we are. The goal is to make your code and content "machine-readable".

If you saw a div in the code with this ID, what would you think is within that div?

<div id="the-article">

It's pretty obvious to us humans. It contains the text of an article.

But how do you tell a computer that? Maybe create some programming code that searches for the word "article" in ID or class names?

How do you explain to a computer how to find the div element here that contains an article?

<div id="not-an-article">
<div id="particle">
<div id="toparticle">

Or maybe the web designer is crazy and uses totally nonsensical ID and class names:

<div id="qwerty">

In this case, it would be very difficult to "teach" a computer to "understand" the code.

One solution is to standardize how certain elements are named. If every web designer puts the text of the article within an element named <article>, there is no confusion.

And we could go even further and provide a ridiculous amount of semantic meaning within the article using additional HTML elements and microdata.

<article itemscope itemtype="http://schema.org/Article">

<header>
<h1>Wonderful title of my article</h1>
<p>Published on <time datetime="2045-03-12" itemprop="datePublished">March 12th, 2045</time> by <span itemprop="author">Raymond Dean</span></p>
</header>

<div class="content" itemprop="articleBody">
<p>The wonderful text of this wonderful article that I have not yet written. I hope I live long enough to write it.</p>
</div>

</article>

It's not necessary to get this complex right now. But it is definitely something you should be aware of.

This idea of a semantic web is still a bit of an idealistic hope for the future. But a lot of people think it would be really cool to make the web into a giant database of information that could be easily parsed by any person or program.

We will discuss additional semantically delicious elements in future lessons.

Semantic class and ID names

Take a look at the example code for the span element:

<p>I am building a <span class="highlight">giant</span> statue of Kelly Clarkson in my yard.</p>

Notice that I chose to use "highlight" as the name of the class instead of "yellowish-color"or something else that merely describes how the styling will make it look.

It's best to choose a class or ID name with meaning rather than words that describe how it will look. It should describe the purpose for the class or ID. Or it should provide meaning for the content.

If you use a class name that describes how something looksand you later decide to change how it looksthat class name would no longer make sense. If you choose a class name that describes the purpose for the class, you can avoid this.

I have been known to use meaningless class and ID names in my code examples. Often, I am doing this to demonstrate that you can name it whatever you would like.

And it's fine if your class names aren't super semantic while learning. But it's something that you should definitely be aware of.

HTML comments

In addition to providing meaning for computers in your HTML code, you should also use HTML comments to provide meaning to designers and developers. It can benefit both yourself and anyone else who may work on your website.

Here's is an example of using an HTML comment as a placeholder for content we want to add later:

<p>Some wonderful text here.</p>

<!-- we'll add the images here when we get them -->

<p>Some more wonderful text.</p>

An HTML comment begins with <!-- and ends with -->

HTML comments can be seen in the source code but are not visible on the web page.

CSS comments

Just like in HTML, you can create comments in your CSS code. This is often helpful for organizing your code. For example, if you have a contact form on your website, you might want to put all of the CSS code for that together. That will make it easier to find later.

CSS Comments begin with /* and end with */

/* Form CSS */

.contact-form label {
color: #000;
font-weight: bold;
}

.submit-button {
padding: 4px;
color: #555;
background-color: #e3e3e3;
}

/* Something Else */

.something {
display: none;
}

Document Object Model (DOM)

The HTML in your page is all connected. It's part of a code family, so to speak. Each element in the page has relationships and a place within the hierarchy of the HTML document.

We have talked about the relationship between parent and child elements. An element that is nested inside of another is considered to be the child element. The element that contains the child element is known as its parent. Take a look at the structure of this HTML code:

<html>
<body>

<div id="something">
<p>Text</p>
</div>

<div id="something_else">
<ul>
<li>list item</li>
</ul>
</div>

</body>
</html>

This structure that makes up your HTML document forms a tree. This is a visual representation of the "DOM tree":

Document Object Model (DOM)

It's all about "what is inside of what"

The DOM is the method for accessing different parts of an HTML page based upon its structure. Using the relationships in this structure, we can access these different parts and manipulate them, such as styling them with CSS or doing something else with them with the JavaScript programming language.

CSS selectors

As we know, a selector is used to select elements for styling. Let's discuss a few different types of CSS selectors.

Descendant selectors

When we discussed nesting in lesson 2, you were introduced to the concept of parent and child elements.

The outer element is the parent.

The element inside is the child.

Child elements are also referred to as descendants of the parent.

We can use this relationship to identify elements for styling in our CSS code.

For example, here is some HTML code with a parent element and its children:

<div class="house">

<p class="person">This is some tremendously remarkable and excellent text in a paragraph.</p>

<p>This is the text of another paragraph.</p>

</div> <!-- end of house -->

The div is the parent and the two paragraphs are the children.

In our CSS code, we could select the paragraph elements within .house and apply styling:

.house p {
color: #898989;
}

Each <p> element inside that div would display in the color specified above.

Or I could specifically target the paragraph with the class "person" like this:

.house .person {
color: #898989;
}

Now, let's add a child element to the .person paragraph:

<div class="house">

<p class="person">This is some tremendously remarkable and excellent <span class="pie">text</span> in a paragraph.</p>

<p>This is the text of another paragraph.</p>

</div> <!-- end of house -->

Now, we have a .house, with a .person inside.

And .pie inside the .person

To style .pie, which is inside of .person, we could use a selector with a third level depth:

.house .person .pie {
color: #ffe5b4;
}

When you use spaces between the selectors, you are using the DOM. You are saying that .pie is inside of .person. And .person is inside of .house. From left to right, you are moving "deeper" into the structure of the HTML.

And note that you don't have to include every element in this "path" to the element in a descendant selector. In the example above, you could omit .person and use .house .pie and it might work just the same. The latter would just be less specific.*

*We will discuss this concept of CSS "specificity" further along in this lesson.

Group selectors

You can create group selectors by placing commas between each selector.

.tacos, .pizza, .beans {
color: #ff0000;
border: 1px solid green;
}

Every element with the classes "tacos, "pizza", and "beans" would be styled with that color and border.

If you are applying the same properties and values to more than one element, you can use a group selector.

It's a good idea to use as little code as possible to accomplish your goals. Using group selectors can reduce the amount of CSS code you need to type.

Pseudo-elements

Pseudo-elements are used to select things that aren't actually elements. For example, you can use them to select a portion of an element.

::first-letter

The ::first-letter pseudo-element allows you to select the first letter of text within an element.

For example:

p::first-letter {
font-size: 200%;
}

This would increase the font-size of the first letter of every paragraph.

::before and ::after

These pseudo-elements allow you to insert content within an element.

::before makes the content appear as the first child of the element. It will appear before any other content within the element:

div::before {
content: "This text will appear before any other content in the div element!";
}

::after makes the content appear as the last child of the element. It will appear after any other content within the element:

div::after {
content: "This text will appear last within the div element!";
}

Pseudo-classes

Pseudo-classes allow you to select elements for styling in all kinds of fancy ways.

I'll use this unordered list to demonstrate using these next few pseudo-class selectors:

<ul class="list-example">
<li>first</li>
<li>second</li>
<li>third</li>
</ul>

:first-child

:first-child could be used to select the first list item:

.list-example li:first-child {
color: red;
}

Notice that I'm using both a descendant selector and a pseudo-class selector. The list item elements (li) are inside the ul element with the class list-example.

:nth-child()

In order to select the second list item, we could use :nth-child() with a "2" in the parentheses:

.list-example li:nth-child(2) {
color: blue;
}

You can also use odd and even to style every other one a certain way.

This would make the first and third red and the second blue:

.list-example li:nth-child(odd) {
color: red;
}

.list-example li:nth-child(even) {
color: blue;
}

:last-child

And we could use the :last-child pseudo-class to make the third purple:

.list-example li:last-child {
color: purple;
}

You can style links based upon the current state of the link.

a:link can be used as the selector to style links that haven't yet been visited and are not currently being clicked or hovered.

a:link {
color: blue;
}

:visited

a:visited is used to style links that have been visited by the user. In other words, this means that the URL is in their browser history.

a:visited {
color: black;
}

:hover

a:hover can be used to style links when the user is hovering (or pointing at) the link with their mouse/pointer.

a:hover {
color: purple;
}

The :hover pseudo-class can be used to provide styling for more than just <a> elements on hover. For example, to add a background-color to list items when hovered:

li:hover {
background-color: #ebebeb;
}

:active

a:active applies to links right at the moment that they are clicked.

a:active {
color: red;
}
caution

The link selectors need to be in this order in your CSS to work properly:

  1. a:link
  2. a:visited
  3. a:hover
  4. a:active

That's L-V-H-A.

Some people remember it with LoVe HAte.

For some odd reason, I remember it with Las Vegas HA!

CSS precedence

So, why do the link selectors need to appear in the order shown above?

It's all about CSS precedence. CSS stands for "Cascading Style Sheets". The "cascade" is the order in which styles are applied and what takes precedence.

Here's a rule of CSS precedence that is relevant to these link selectors:

If all else is equal and more than one selector applies to the same element, the styling that is declared last takes precedence.

For example, let's say you had this CSS in your stylesheet for styling paragraphs:

p {
color: white;
}

p {
color: black;
}

There would be no reason to use the above in your stylesheet since they contradict each other. But if you did have that in your stylesheet, the paragraphs would be black. Since all else is equal, the last rule wins.

So, back to the link selectors. Let's say you had your link selectors in this incorrect order:

a:active {
color: red;
}

a:hover {
color: purple;
}

a:visited {
color: black;
}

a:link {
color: blue;
}

If the link hasn't been visited yet by the user and is in the active state, what color would it be? Red?

Nope. It would be blue. This is because a:link is the last selector in the stylesheet that applies. a:link applies to links that have not yet been visited (Not yet in your browser history).

What if the link has been visited and the user hovers over it? Would it be purple?

No, again. It would stay in the visited black color because that appears last and also applies to this link.

So, put them in this order and all of the precedence stuff works:

  1. a:link
  2. a:visited
  3. a:hover
  4. a:active

CSS specificity

So, I just explained this rule of CSS precedence:

If all else is equal and more than one selector applies to the same element, the styling that is declared last takes precedence.

But what does the "if all else is equal" part mean?

That's where CSS specificity comes into play.

When two rules both apply to the same element, the most specific selector will be used by the browser. For example, let's say you had both of these selectors with their declarations in your CSS stylesheet:

.person {
color: #000000;
}

p {
color: #898989;
}

Both of these apply to paragraphs since the element with the class "person" is also a paragraph. The first selector would take precedence because a class is more specific than a generic element selector. It tells you which specific paragraph(s) you are referring to. This will override any others that are less specific.

But there is no reason to be super specific with your selectors unless you need to. You only need to be more specific if you want your selector to target specific elements without affecting other elements.

CSS precedence and specificity is the reason that many designers no longer use IDs. An ID selector is powerfully specific. Styling that uses an ID selector will take precedence over most other selectors and their declarations. This can sometimes cause problems because it may require the coder to create long and cumbersome descendant selectors to be specific enough to override certain things.

There's a bit more to CSS specificity than that. So, check out this article for more information about CSS specificity.

CSS inheritance

We have at least one thing in common with HTML elements. We can both inherit traits from our ancestors :)

All of the elements within the body element are descendants of the body. And they may all inherit certain property values that you declare for the body.

For example, if you use this in your CSS...

body {
color: red;
}

...almost every element within the body will inherit that value. All text on the page will be red, with the exception of links. The <a> element will not inherit the color property.

You could override the inherited value by providing a different color for specific elements.

If you used this in your CSS...

body {
color: red;
}

p {
color: blue;
}

...all paragraphs would be blue. All other text in the page (except for links) would be red, unless you specify otherwise.

Now, not all properties are inherited. If that was the case, things would get pretty crazy.

If the property controls the size or placement of the element, it is not inherited. Things like padding, margin, width, height, position, and float are not inherited. Borders and backgrounds are also not inherited.

Most of the properties that are inherited involve styling text. Properties such as color, font-family, font-size, font-weight, and text-align are inherited.

In the CSS property reference on W3Schools, it will state whether or not the property is inherited.