This tutorial is for the complete beginner. Here are the required skills:

The goal for this lesson

See this crash course on YouTube:

By the end of this lesson, you will have built this from scratch (Frontend mentor link).

lesson challenge

And after a few short lessons on responsive design, CSS Grid, and Flexbox, we will build this (Frontend mentor link).

future lesson challenge

What we are covering in this lesson

  • What is CSS (cascading style sheets)?
  • The basics of CSS

    • What is a “selector”?
    • What is a CSS “property”?
  • The “Box Model”

    • Block vs. Inline Elements
    • Box Sizing
    • Layouts in CSS
  • CSS Units of Measure
  • Common CSS Properties

    • Font styling
    • Background styling
    • Color Codes
    • “Shorthand” CSS
  • A four-step system for writing great CSS and HTML
  • Code Challenges!

Supplemental Lessons

While these are not part of the core CSS crash course, these are extremely important topics to know. While building out our designs pictured above, we will be using all three of these and I highly recommend that you watch my tutorials on each of them before attempting the challenges.

  • Media Queries and Responsive Web Design (coming soon)
  • CSS Flexbox (coming soon)
  • CSS Grid (coming soon)

What we are NOT covering

Finally, we will NOT be covering...

  • Graphic design and wireframing - These are huge parts of building a web product, but our focus is learning web development skills; not graphic design or user experience design principles. Designing a visually pleasing and easy to navigate user interface is critical to building a successful app, but you have the rest of your career to learn these. Furthermore, if you're a mediocre graphic designer like myself, I recommend leveraging designs of the pros (legally of course). Frontend Mentor removes the design step from the equation and allows us to focus on coding the design. Don't try to mix design with coding. You'll take 10x as long on your projects. Design, then code.
  • CSS Pre-processors (Sass, LESS, PostCSS) - These can be useful for large projects and codebases but usually overkill for smaller projects like the ones in this course.
  • CSS Frameworks (Bootstrap, Materialize, Tailwind, etc.) - CSS frameworks and UI libraries can be extremely helpful, but you need to learn the fundamentals first. I don't want to lock you into a framework that is popular today but dead tomorrow. When I was learning, Bootstrap was huge. Now, Tailwind is popular. You can always learn these on the fly, so I'm going to teach you the fundamentals and let you educate yourself based on what is required for your future projects.

Useful series links

This is part of my fullstack developer series, where you'll go from never having written a line of code to deploying your first fullstack web application to the internet. Click this link to get an overview of what this series is all about.

Please tag me on Twitter @zg_dev and share this series with #100DaysOfCode!

What is CSS (Cascading Style Sheets)?

We've already learned the basic concept of CSS. In the previous lesson, I introduced the "house" analogy, which describes the following:

When building a house...

  • HTML is the structure (i.e. wood, bricks, concrete, foundation)
  • CSS is the style (i.e. paint, landscaping)
  • JavaScript is the function (i.e. electric, plumbing, heating, water)

The first question we have to answer is, what does "cascading" mean?

When working with CSS, it is possible to define more than one style for a single HTML element. Because of this, the CSS needs to know which rule to actually apply to it. When we say "cascading", we are referring to this fact.

Let's say I had the following HTML snippet:

<div class="main-container">  <p>Some text</p></div>

Now, let's add three CSS rules (I'll explain how these work later):

.main-container {  color: red;}.main-container p {  color: green;}p {  color: blue;}

The question is–what color will "Some text" be?

The answer is green, but right now, we don't know enough about CSS to make this determination. Let's jump in.

Basic CSS Syntax

Here is the video version of this section

So... What is the purpose of CSS? The purpose of CSS is to "select" an HTML element and apply some type of style to that HTML element. Here are the two things that CSS can do for you:

  1. Change the layout of HTML elements on the page (rows, columns, sections, sizes)
  2. Change the style of HTML elements on the page (fonts, colors)

In the Codepen below, I've demonstrated both layout and style. To achieve this result, I have used CSS properties that we will be looking at over the next several lessons.

The diagram below shows the relationship between HTML and CSS in addition to the basic structure of both.


As you can see above, we are using the HTML element's class property to "select" it, and then applying the color style to that element. We have given the color property a value of #211E1E, which is a dark grey color. In effect, we are turning the text dark grey.

In this example, .some-class is the "CSS selector", color is the CSS property, and #211E1E is the CSS property value (a hex code, which we'll cover later).

At this point, it is not clear why I'm using these selectors and properties. For example, why do I have a . before the class name? How did I know to use color to change the text color? To answer these questions, let's explore a few of the basic ways to "select" an HTML element with CSS. Don't worry about all the possible properties yet–we'll get there eventually. For now, I'll try and stick with the color property, which changes the color of the text of the selected element.

The 3 Main CSS Selector Types

There are three primary ways you can "select" an HTML element in order to style it.

  1. By tag
  2. By class
  3. By ID

Since we learned about HTML in the prior lesson, these should sound familiar. Let's take a minute to review anyways.

<p class="main-text" id="first-paragraph">First paragraph of document</p>

Can you spot the tag, class, and id here? Of course! The tag is p, the class is main-text, and the ID is first-paragraph. If you remember from the previous lesson, we were able to use these values to "select" HTML elements using JavaScript. Remember this?

// Select by tagdocument.querySelector('p');// Select by classdocument.querySelector('.main-text');// Select by IDdocument.querySelector('#first-paragraph');

The code above selects this HTML element in three different ways using JavaScript. We use the same type of syntax to select this HTML element with CSS.

/* Oh hey, I'm a CSS comment.  I'm slightly different than HTML and JS comments *//* Select by tag */p {  color: red;}/* Select by class */.main-text {  color: red;}/* Select by ID */#first-paragraph {  color: red;}

These are all valid ways to select the HTML element from above using CSS.

For now, I'm going to be using the color property and value as a placeholder to explain CSS selectors and "cascading" concepts. This changes the text color of the HTML element. We will be walking through all the different CSS properties later in the lesson, but we're not quite ready.

Here is a useful little cheat sheet that I created to help you remember these three most common CSS selector types. The property color: green is not important here. This could be any CSS property.

css selector types

CSS Combinators

The three methods that I wrote above are the "textbook" ways to select and style an HTML element. But we are on lesson 8 of our series and by now, you have probably caught on to the fact that in web development, there are ALWAYS more ways to do things. The same holds true in this scenario.

With CSS, there are "combinators" that allow us to "combine" our selectors to identify an HTML element. Many times, these can be avoided by placing an ID or class attribute on an element, but you should still be familiar with them. Here's what we're dealing with:

  • Descendant selectors
  • Child selectors
  • Sibling selectors

Hmmm... This sounds familiar, doesn't it...

Do you remember this image from the prior lesson on HTML?

html tree

Do you remember how we talked about an HTML document being structured like a big happy family of grandparents, parents, children, and siblings? Well lucky for us, we can leverage that concept once again here.

Let's see how we can combine some CSS selectors to identify various elements in this HTML document. Here it is again in case you can't see it from the photo:

<html>  <head>    <title>Site Title</title>  </head>  <body>    <div class="main-body">      <h1>Article Heading</h1>      <p>Some text in the article</p>      <p>Some more text</p>      <ul>        <li>List item 1</li>        <li>List item 2</li>        <li>List item 3</li>      </ul>    </div>    <div class="footer">      <p>Site created by Zach</p>    </div>  </body></html>

Selecting descendants

Let's say that we wanted to put a CSS style on every li element that exists in the <div class="main-body"> element. How would we do this?

Why not something like this?

li {  color: green;}

Congrats! All your li elements will have green text. Time to call it a day and have a beer.

Not so fast...

What happens if we put another list inside the <div class="footer"> container?

<html>  <head>    <title>Site Title</title>  </head>  <body>    <div class="main-body">      <h1>Article Heading</h1>      <p>Some text in the article</p>      <p>Some more text</p>      <ul>        <li>List item 1</li>        <li>List item 2</li>        <li>List item 3</li>      </ul>    </div>    <div class="footer">      <p>Site created by Zach</p>      <ul>        <li><a href="#">Footer link 1</a></li>        <li><a href="#">Footer link 2</a></li>        <li><a href="#">Footer link 3</a></li>      </ul>    </div>  </body></html>

In reality, it is very common to see lists appear in a footer like this, but they are often styled differently than lists in the main body of the HTML. If we used the selector from above, even our footer list items will have green text, which we probably don't want!

Let's come up with a better solution:

/* Select all li elements that exist inside the element with a class of .main-body */.main-body li {  color: green;}

With CSS, we can combine selectors separated by spaces to identify descendants of elements. No matter how many additional HTML elements we add to the .main-body div, they will all inherit this style. To drill this point home further, let's look at some different HTML.

<div id="main">  <div>    <div>      <ul>        <li>List item 1</li>        <li>List item 2</li>        <li>List item 3</li>      </ul>    </div>      <ul>        <li>List item 1</li>        <li>List item 2</li>        <li>List item 3</li>      </ul>  </div></div>
#main li {  color: green;}

By using the "descendant selector" above, we can target all the li tags at multiple levels, so long as they exist below the level of our "pre-selector". In this case, the first selector, #main is the "pre-selector" and the second selector, li is the actual element(s) you are targeting for that style.

Selecting Children

Sometimes, you only need to target the children of a specific HTML element for styles. Let's say you had the following HTML.

<div id="main">  <p>first paragraph</p>  <p>second paragraph</p>  <p>third paragraph</p>  <div>    <p>fourth paragraph</p>  </div></div>

If we used the CSS selector #main p, we would be able to style all of the p elements in this HTML. But we can use the following syntax to select only the direct children of #main.

#main > p {  color: blue;}

The first, second, and third paragraphs will have blue text while the fourth will have the default text color.

See the Pen Selecting Children in CSS by Zach (@zg_dev) on CodePen.

Selecting Siblings

The last type of combinator you can use is a sibling selector, but I think it is important to disclose–I NEVER use these. Others may feel differently about this, but in the five years I've been writing CSS, I have never come across a compelling case for using these selectors. Drop a comment or hit me up on Twitter @zg_dev if you come up with a good reason to use these.

But of course, I can't just make a bold statement like that and expect that you trust me. Let me show you what I mean here.

Let's say you had this HTML document.

<div id="main">  <ul>    <li>List item 1</li>    <li>List item 2</li>    <li>List item 3</li>  </ul>  <p>first paragraph</p>  <p>second paragraph</p>  <p>third paragraph</p>  <ul>    <li>List item 1</li>    <li>List item 2</li>    <li>List item 3</li>  </ul>  <p>fourth paragraph</p>  <p>fifth paragraph</p>  <p>sixth paragraph</p></div>

And for some odd reason, you only want to style the paragraph elements immediately following the lists (first and fourth paragraphs). Here's how you could do that with a sibling selector.

ul + p {  color: red;}

This will look through the entire HTML document and look for all p elements that immediately follow a ul element (aka "adjacent sibling"). And if you wanted to target all of the siblings to ul elements, you just change your CSS to this:

ul ~ p {  color: red;}

In my opinion, the ~ and + combinators aren't necessary. If you find yourself in this situation, do the following.

  1. Find the HTML element you want to target
  2. Add a class or ID to that element
  3. Style using a class or ID selector

Sure, it's some extra lines of code, but it is easier to follow (and your future self will thank you for writing easy-to-read code).

Other ways to select HTML elements with CSS?

There are other ways to select an HTML element with CSS. For example:

<p class="regular-text">some text here</p><div class="regular-text">some text here</div>
p[class="regular-text"] {  color: blue;}

If you just used .regular-text to select the elements, you would be styling both the p and div elements. You can specify that you only want the p elements with a class of .regular-text.

The likelihood of a situation like this coming up? Very low. Therefore, I won't be spending time explaining all these nuanced ways of using CSS selectors. You can look them up as you need them.

Remember, this crash course and full-stack developer series is about getting you acquainted with the most important concepts. And 95% of the time, you'll never need anything more than what we've talked about so far. Feel free to dig through some advanced CSS tutorials on your own, but at this stage of your journey, I believe it is a waste of your time to do so.

Selecting multiple HTML elements with CSS

To this point, we've only selected one HTML "group" at a time (one selector can target multiple elements). In certain cases, you might want to apply a few "common" styles to several elements and then add additional styles individually. Let's say you had the following HTML.

<div class="box-1">  <p>Box 1</p></div><div class="box-2">  <p>Box 2</p></div>

We haven't talked about CSS properties yet (so don't worry about how these work now), but let's say that we wanted to make both of these boxes the same width and height, but style their borders and text colors separately. Here is the inefficient way to do it:

.box-1 {  width: 200px;  height: 200px;  border: 1px solid green;  color: green;}.box-2 {  width: 200px;  height: 200px;  border: 1px solid blue;  color: blue;}

Wouldn't it be nice if we could assign the width and height properties one time rather than writing for each element? Good news, we can! Here's how I would write this CSS.

.box-1, .box-2 {  width: 200px;  height: 200px;}.box-1 {  border: 1px solid green;  color: green;}.box-2 {  border: 1px solid blue;  color: blue;}

By separating each selector using a comma, we can select multiple HTML "groups" at the same time. In the example above, we are applying the width and height properties to both selectors and then individually applying border and color (text color) styles to each.

We haven't talked a lot about software engineering "best practices", but what we did here was "refactor" our previous code to adhere to "DRY" (don't repeat yourself) principles.

Here's the Codepen for this.

Using Multiple Classes on a Single HTML Element

In the example we just looked at, we have two classes and are defining "shared styles" for them. We could achieve this same result another way! Take a look.

The change that I made is subtle. All I did was add another class to the HTML–make sure you add a space between classes in the class HTML attribute.

<div class="box-1 box">  <p>Box 1</p></div><div class="box-2 box">  <p>Box 2</p></div>

Instead of having two classes, box-1 and box-2, we now have three. We can use the box class to define our shared styles:

.box {  width: 200px;  height: 50px;}

And then use our individual classes for unique styles.

.box-1 {  border: 1px solid green;  color: green;}.box-2 {  border: 1px solid blue;  color: blue;}

Two methods, same solution.

Pseudo Classes/Elements

In addition to being able to select multiple CSS groups at once, we can also use something called a "pseudo" class/element. We will NOT be talking in detail about this, but you need to know it exists for when you do come across it in the future.

Here is the one of the most common occurrences of this concept.

<button>Hover me</button>
button:hover {  color: red;  cursor: pointer;}

By adding :hover directly after the button selector, we are saying, "when the mouse hovers over this button, I want to apply the following CSS styles to it".

Like I said, we will not be covering this in detail here. Here is some documentation on pseudo elements and classes that you can read if you are curious.

Here is the example above in action. Hover your mouse over the button to see it work!

Multiple Selectors vs. Nested Selectors

In the previous example, we saw this.

.box-1, .box-2 {  width: 200px;  height: 200px;}

In the section prior to that, we saw things like this:

.box-1 p {  color: green;}

They look awfully similar don't they? As you read and write CSS, be conscious of this difference. In the first case, you're saying "I want to apply these styles to all HTML elements that have a class of box-1 OR box-2". In the second case, you're saying "I want to apply these styles to all p elements that exist inside elements with a class of box-1".

The difference is subtle, but important. Speaking of this difference...

Let's Talk about CSS Specificity

The "cascading" concept in CSS (aka "specificity") is super important for a beginner to understand.

Being able to select HTML elements is part one of the battle. The second part is figuring out which styles apply to the given element. This is not hard when there is only one CSS style per HTML element, but oftentimes, there are several styles competing against each other in a CSS battle. To demonstrate, let's look at some HTML that has many ways to select each element.

<div class="main-container">  <p class="main-text" id="first-paragraph">First paragraph of document</p></div>

Let's say our goal was to change the text color of our p element. We could do that in several different ways.

/* Hey, I'm a CSS comment again. *//* Everything below does the SAME THING */p {  color: red;}.main-text {  color: red;}#first-paragraph {  color: red;}div p {  color: red;}div .main-text {  color: red;}div #first-paragraph {  color: red;}.main-container p {  color: red;}.main-container .main-text {  color: red;}.main-container #first-paragraph {  color: red;}div > p {  color: red;}.main-container > p {  color: red;}.main-container > #first-paragraph {  color: red;}.main-container > .main-text {  color: red;}


Yep, I know. Not what you wanted to see. And it gets worse...

If you were to write all of these lines of CSS in the same file, they would all be competing with each other.

"But why would you ever put multiple styles in the same CSS file?"

If you are the only developer writing the styles for your HTML, then you probably wouldn't. But in many cases, a website or web app will have multiple stylesheets, and some of those will be externally generated. In other words, you may want to take a pre-existing website theme and apply your own custom styles to it. In this case, you will be writing competing styles to the ones that were already defined.

And in this case, you need to know which style declarations take precedence over one another.

There are two dimensions we must think about here.

  1. Location of the CSS selector in the file
  2. Specificity of the CSS selector

Location of the CSS Selector in the File

Let's start easy. Say we had the following HTML.

<p>Some text</p>

If we had the following CSS file, what color will the text be?

p {  color: red;}p {  color: green;}

If you have been following along with this series, you might be thinking, "That's not valid CSS! You've already declared p, you can't do it again!".

Good logic, but it is indeed valid CSS. Unlike JavaScript, you can declare the same CSS rule twice in the same file. Knowing this fact, which style takes precedence here?

The text will be green because that is the last rule in the file. CSS will always give the final rule precedence assuming the selectors have the same level of "specificity".

Specificity of the CSS Selector

Let's modify the example from above.

<p class="my-text">Some text</p>
.my-text {  color: red;}p {  color: green;}

What color will the text be? The answer is red. In this case, even though our color: green style came last in the file, it doesn't matter because selecting an HTML element by its class is "more specific" than selecting by its tag.

Here is the continuum of CSS selector "importance":

selector importance

In other words, if given the choice of the following three selectors, the text color will be set to green no matter which order you place the rules in because it is the "most specific".

#first-paragraph {  color: green;}p {  color: red;}.main-text {  color: red;}

Easy enough, but this "specificity" business gets a little confusing when we start talking about something like this:

<div>  <p class="my-text">paragraph text</p></div>
div .my-text {  color: red;}.my-text {  color: green;}

What color will the text be? The answer is red.

When we look at a selector like div .my-text, it is basically saying, "find me all elements with a class name my-text that are descendants to div elements". Then we have to ask ourselves... Does the first paragraph have a class of my-text AND a div ancestor (could be parent, grandparent, great-grandparent, etc.)? The answer is yes, so the paragraph text will be red.

In summary, even though the second CSS rule above is at the end of the file, that doesn't mean it will apply to all elements.

After reading the last couple of paragraphs, you might be thinking that this is awfully complicated. To help us out, let's look at two ways that you can always use to determine which CSS rule applies to each HTML element. Here they are:

  1. Test it out (my favorite method)
  2. Calculate it

The easiest way to figure it out is to put together an example in Codepen and see which one takes precedence (as we did above).

The second way is to actually calculate the "specificity" of a CSS rule. Here's how you do that.

  1. Count the number of ID selectors in the rule
  2. Count the number of class selectors in the rule
  3. Count the number of tag selectors in the rule

Combine the count from steps 1-3 in order, and you've got your "specificity" value.

Let's do that for our two rules from above. See the comments for the calculation.

/*   Number of ID selectors - 0  Number of class selectors - 1  Number of tag selectors - 1  Total "Specificity" - 011*/div .my-text {  color: red;}/*   Number of ID selectors - 0  Number of class selectors - 1  Number of tag selectors - 0  Total "Specificity" - 010*/.my-text {  color: green;}

As you can see, the first selector is more specific than the second, and therefore will always take precedence (unless it simply does not apply to the HTML element like we saw in the second paragraph from our example above).

Let's look at one last example to really nail this concept. Here's the HTML and CSS with the specificity calculation.

<div class="my-container" id="container-id">  <p class="my-text" id="text-id">Some text</p></div>

All of the rules below select the same p element above.

/*   Number of ID selectors - 0  Number of class selectors - 2  Number of tag selectors - 0  Total "Specificity" - 020*/.my-container .my-text {  color: red;}/*   Number of ID selectors - 2  Number of class selectors - 0  Number of tag selectors - 0  Total "Specificity" - 200*/#container-id #text-id {  color: orange;}/*   Number of ID selectors - 1  Number of class selectors - 0  Number of tag selectors - 1  Total "Specificity" - 101*/div #text-id {  color: green;}/*   Number of ID selectors - 1  Number of class selectors - 0  Number of tag selectors - 0  Total "Specificity" - 100*/#text-id {  color: blue;}/*   Number of ID selectors - 0  Number of class selectors - 0  Number of tag selectors - 1  Total "Specificity" - 001*/p {  color: purple;}

The text color will be orange because the total specificity of that selector is the greatest. Once again, you can always just test it out like I did below!

Inline HTML Styles

The last thing we have to talk about are inline styles. They look like this.

<p style="color: red; padding: 1px;">Some text</p>

If you apply an inline style, it will take precedence over all other styles, but it is usually not recommended because too many of these will really clutter up your HTML! Some CSS frameworks implement inline styles like this, but that is a debate and topic for another day. For now, just keep these to a minimum.

Here is a Codepen example that shows how an inline style can override a style applied with an ID selector.

The !important keyword

What if I told you that by writing a single word, you can override all the CSS "specificity rules" (including inline styles)?

If you write !important at the end of a CSS property, it will take precedence over every other rule. Here's an example.

<p id="my-text">Some text</p>
p {  color: red !important;}#my-text {  color: blue;}

While the second selector has more specificity, the text will be red because we have added !important to the end of the property value. This can be done on a property-by-property basis. For example:

p {  color: red !important;  font-size: 18px;}#my-text {  color: blue;  font-size: 16px;}

In this case, the color will be red but the font size will be 16px.

Now let's have a little chat about this !important keyword. While it does provide you with an easy way to get a CSS style working without having to think much, it is usually a bad practice. There is no definitive guideline as to when this is acceptable to use, but here is a good rule of thumb.

Use !important if doing so is the ONLY viable method for styling an element

This could occur if you are trying to override styles applied from an external stylesheet (CSS frameworks, UI libraries, etc.).

What is a CSS Property?

As I introduced at the beginning of this lesson, CSS allows us to achieve two primary objectives:

  • Styling HTML elements
  • Positioning HTML elements (layout)

What if I wanted to create an HTML element that has a blue background, is a perfect square, has a black border, and has some large white text centered in the middle? I can do this with basic CSS properties.

The HTML for this is simple:

<div>  <h2>Some Text</h2></div>

The CSS is the tricky part.

div {  width: 200px;  height: 200px;  border: 5px solid black;  background-color: navy;  color: white;  text-align: center;  line-height: 200px;}h2 {  margin: 0;}

As you can see, I've used a variety of properties to achieve this result. From width, height, and border to background-color, color, and text-align, combining these CSS properties together helps us achieve the intended result.

Here is the live version of this example.

How do I know what CSS properties to use?

Great question.

I don't have a great answer.

The truth is, knowing what properties to use is largely a matter of time combined with lots of experience. Studying all the properties at once won't help you. Making flash-cards might help a little, but I wouldn't recommend it.

As we dive into the Box Model and some common CSS properties, try to focus on concepts; not memorization. After all, you've always got the CSS documentation if you forget what something does.

What is the Box Model in CSS?

Here is the video version of this section

Similar to the Document Object Model (DOM) that we explored in the prior lesson, the Box Model can be explained simply, or we can get into tons of nuance.

It is best described visually via the Firefox Developer Tools (we talked a lot about these in prior lessons).

box model

This is saying that our p element has content dimensions of 667 pixels x 18 pixels, has 20 pixels of padding on all four sides, has a 5 pixel border, and has 20 pixels of margin on all four sides.

The Box Model attempts to describe how much "space" an element takes up on the page. The following properties influence that "space" that the element occupies. I suggest skimming through their documentation.

But these are not the only properties that come into play when we talk about the Box Model. It is often difficult to introduce this model to beginners because there are several combinations of properties that will completely change the "rules of the game".

To better explain these "rules", I have created an interactive Codepen that we will be using to better understand the Box Model and all of its nuances. Keep this open in another tab while you read the following sections so that you can see in real-time what I am talking about.

Element Display Types

The display CSS property is arguably the most diverse CSS property there is.

Here are the possible values you can set for it.

  • display: none - Hides the element from the page
  • display: block - The default display type for most HTML elements
  • display: inline - The default display type for a, span, img, button, input, and several other HTML elements.
  • display: inline-block - A mix between block and inline (more on this in a minute)
  • display: flex - Enables the Flexbox framework (out of scope for this tutorial)
  • display: grid - Enables CSS Grid framework (also out of scope)

The display: none value is easy to grasp. Open up the Codepen from above and change the "Display Type" dropdown to "none". The orange box will disappear.

The block, inline, and inline-block properties require a bit of an explanation. Let's jump in.

Block vs. Inline Elements

Most elements will have display: block as their default state. Open up the Codepen example from above and reset all the values.

By default, it has a "block" display type. This means:

  • The orange paragraph element will occupy 100% width of its container because we have not explicitly set a height or width (they are both set to auto)
  • The orange paragraph is on its own line

Now, set the "Content Width" to 400px and "Content Height" to 200px using the dropdowns. The orange paragraph element should change sizes.

Reset all properties.

Now change "Display Type" to "inline". You should see the orange paragraph element jump up to the same line as the green text that was formerly above it. With an "inline" element, the following behavior happens:

  • The element will only occupy the height and width of the content within it. In this case, that content is the text, "Some Content".
  • The element will not break on a new line

Now, change the height and width properties using the dropdown again. Nothing should happen. That is because when an element is "inline", it does not respect its width and height properties.

Without resetting anything, change the display type to "inline-block". What happens?

The display property inline-block is the same as inline except that it respects its width and height properties.

Box Model Variations

Another property that will change the "rules of the game" is the box-type CSS property. It does not affect the flow of the elements on the page like display does, but it affects the calculation of how much space an element occupies. Here are the two values.

  • box-type: content-box - this is the default value
  • box-type: border-box - as you will see, this is easier to grasp and often preferred among developers

To see this in action, open up the Codepen from above again, reset everything, and then select the following options.

  1. Set the content width to 400px
  2. Set the content height to 200px

Now, toggle between the two "Box Type" dropdown options. Notice how the size of the orange paragraph element changes by a small amount?

To make this more noticeable, change the "Padding" option to 20px. Now, toggle the box type again. Now, you should see large changes in size. This is because when you are using the value border-box, the total size of the element will be equal to its height and width. When using a value of content-box (the default), the size of your element is the summation of its dimensions, padding, and border.

Let's look at that screenshot from earlier.

box model

In this example, we have the following "specs".

  • Element width of 667 pixels
  • Element height of 18 pixels
  • Padding of 20 pixels (all sides)
  • A 5 pixel border on all sides
  • Margin of 20 pixels (all sides)

With box-type: content-box, the total height of this element is 18 + 20 + 20 + 5 + 5 pixels, or 68 pixels. Here, we add the element height, bottom padding, top padding, bottom border, and top border. Notice that we did NOT include the margin. Margin surrounds the element, but is not part of the element. We could also calculate the width as 667 (width) + 20 (left padding) + 20 (right padding) + 5 (left border) + 5 (right border), to get 717 pixels.

With box-type: border-box, the calculation is much easier. The total "space" occupied by the element is its width and height. If you add padding or a border, the size of them will reduce the content area of the element, but not the total space occupied by the element.

The border-box type is a bit simpler to understand and makes your job quite a bit easier when trying to fit elements inside parent containers. In the demo below, look out for the following things.

  • The orange background with "Parent Container" text is an image and is there to help you visualize the dimensions of the parent container.
  • The child container has no background color, but has a 5px black border
  • Notice how in the first example (content-box), the child is breaking out of the parent container despite being the same exact dimensions. This is because it has a 5px border, which adds space to it. In the second example, this 5px border doesn't cause any problems because it simply reduces the total inner content dimensions, not the outer dimensions.
  • When you toggle the padding for both, you'll notice that in the first case, it further expands the size of the child element; breaking it even further out of its parent container. In the second example, once again, the child is contained within the parent container. Padding is added, but it doesn't change the total dimensions.

Because this property makes our lives so much easier, in many CSS stylesheets, you may see the following code.

html {  box-sizing: border-box;}*, *:before, *:after {  box-sizing: inherit;}

This is a portion of what we call a "CSS reset". The goal of this is to make every element on your webpage have border-box box sizing. The * selectors target all elements.

Box Model Review

One could argue that the Box Model encompasses everything we do in CSS. The main takeaways that I want you to have are these.

  • The Box Model describes how much "space" an HTML element occupies on a webpage
  • This "space" is heavily influenced by the box-sizing property
  • The "space" and layout is heavily influenced by the display property
  • The most important components of the Box Model are height, width, padding, border, and margin
  • All other CSS properties are supplementary to this Box Model concept

Layout Properties

This section deserves an entire lesson on its own. Positioning HTML elements skillfully on a webpage is not a straightforward topic because there are so many different ways to approach it. You can use margins, floats, and display properties to position elements. You can use Flexbox. You can use CSS Grid. And finally, you can use a CSS framework to help you with this.

Rather than trying to cram a large topic into an impossibly small section, I want to draw your attention to three CSS properties that you will spend a lot of time with.

  • position
  • display
  • float - with the introduction of Flexbox and CSS Grid, you probably won't ever have to use this, but you may see it in someone's code and therefore we need to cover it


There are five possible values for the position property as shown in its documentation.

  • static - the default value (most common)
  • absolute - Removes an element from the content flow and positions it "absolutely" relative to the nearest parent element with a position of relative. If an "absolute" element has no parent with a "relative" position, it will be positioned relative to the viewport (same as the "fixed" position below).
  • relative - Activates the z-index property. Allows content to be positioned in relation to itself, and is often used in conjunction with the absolute property value above.
  • fixed - Removes an element from the content flow and occupies no "space" (often used for navigation bars). The element will now be positioned relative to the viewport.
  • sticky - similar to fixed, and is not fully supported yet

Since static is the default and sticky isn't commonly used yet, we'll focus in on absolute, relative, and fixed. I will not be explaining these in detail, but here is an example I created that showcases how they work.


We talked pretty extensively about this one already in our discussion about the Box Model, but I want to hit it at a different angle here.

As we move forward in this series and as you progress in your career, you're going to learn that this display property might be the most powerful CSS property of them all. For example, what happens when we do this:

.some-element {  display: flex;}

By specifying the flex value of this display property, we have opened up an entirely new world. All the elements within this one are now going to be arranged and positioned based on the Flexbox specification, which is an entire tutorial on its own. Likewise, we could do this:

.some-element {  display: grid;}

By specifying this value, we once again have opened up an entirely new world of "CSS Grid".

Both Flexbox and CSS Grid are extremely powerful components of CSS (and they are both relatively new). They are so powerful that with them, we no longer need a CSS framework to make our development effective.

We will come back to these in future lessons.

Must Know CSS Properties

Here is the video version of this section

Through our discussion on the Box Model and Layout, I believe we have touched on some of the more important CSS properties, but there are hundreds more. In this section, I want to share some of the most common by category.

Don't worry if you can't remember all these; we will be using them heavily in our code challenges.

  • CSS Units of measure (pixels, rem, percentages, etc.)
  • Color codes and CSS properties
  • Font Properties
  • Background Properties
  • Writing "shorthand" CSS

CSS Units of Measure

CSS doesn't require complex math, but it does require math.

While there are many units of measure, we're going to focus on:

  • Pixels (and viewport units)
  • Percentages
  • rem and em units


Let's start with pixels, which are by far the easiest to grasp. Your computer screen is made of pixels, and a webpage is displayed on your computer screen, thus your HTML elements are always defined in terms of pixels.

We can use pixels to define font sizes, padding and margin amounts (remember, Box Model!), element heights and widths, and more. For example, here are a few common properties we are about to talk about in action (using pixels).

When using Firefox (or any browser) developer tools, the numbers that you see when you hover over HTML elements are expressed in pixels regardless of how you originally defined them.

defined in pixels

While we are talking about pixels, I want to revisit something we talked about in the prior lesson on the DOM. Remember when we talked about these built-in properties?

window.innerHeight; // The webpage height in pixelswindow.innerWidth; // The webpage width in pixels

As of right now, we only know how to find these numbers using JavaScript, but they are also available to us with CSS! To use these in CSS, we can write the following lines of CSS.

.some-element {  width: 100vw;  height: 100vh;}

By using vw ("viewport width") and vh ("viewport height"), we can assign elements to have dimensions equal to the entire width or height of the visible webpage. By putting 100 in front, we are saying, "Make this element 100% of the current viewport height/width".

You won't have to use this often, but it will come in handy.


Take a look at this brainteaser.

Read through the HTML and CSS and then ask yourself–if we have assigned a width of 100% to the .progress-bar div, then why is it not equal to the width of the main container?

The reason is because when defining dimensions using percentages, these percentages are relative to the parent element.

In this case, .inner-container has a width of 150px, while .container has a width of 200px. Since .progress-bar is the child of .inner-container, it will have a width equal to 100% * 150px, NOT 100% * 200px;


If the parent container does not have a width defined, then the percentage will be relative to the first parent that does have a dimension defined. If we remove the width property from .inner-container, then our progress bar will be equal in width to the main container.

This seems complicated, but percentages are used heavily when we want to make our web applications responsive on all devices. We won't talk much about responsive web design here in this tutorial, but consider what would happen if you defined an HTML element to have a width of 900px. Mobile devices are usually between 400-500 pixels, which means the element that you have defined will overflow out of the visible screen (the "viewport") when your user sees it on a mobile device. If we instead defined the width of this element as something like 90%, we no longer have this problem. We will talk more about this concept later, but let's keep moving for now.

rem and em Units

These measurements are specific to font sizes. We will soon cover font properties, but first let's understand how we measure the size of them. Here are three ways that we can define the size of a font.

body {  font-size: 16px; /* 16px is a "standard" value for normal text on most webpages */}
body {  font-size: 1em; /* 100% of the parent element's font size */}
body {  font-size: 1rem; /* 100% of the root element's font size */}

The first case is simple, and oftentimes, you'll see it used on the root element, html. The subsequent two methods define the font size based on either the parent element or the root element. Let's say we had the following HTML and CSS.

<html>  <head></head>  <body>    <p>Paragraph #1</p>    <p class="smaller-text">Paragraph #2</p>  </body></html>
html {  font-size: 16px;}/* Since the root font size is 16px, 1rem equals 16px */body {  font-size: 1rem;}/* Since this element's parent, `body` has a font size of 16px, this will have a font-size of 0.8 * 16 = 12.8px */.smaller-text {  font-size: 0.8em;}

This example, although contrived, is a common way of defining font sizes. We define the root element a hardcoded pixel value (usually 16 pixels), and then define elements within the html font sizes relative to that root font size.

Color Codes and CSS Properties

I'm not going to get too detailed here; just give the basic overview.

Here are the most common color-related CSS properties.

  • color - defines the text color of the container or element
  • background-color - defines the background color of the element
  • border-color - defines the border color

And here are four valid ways to define a color.

  • green - a built in value
  • rgb(0, 255, 0) - RGB stands for "red", "green", "blue". Valid values are from 0-255, which is equal to one byte.
  • #00ff00 - The "hex" or "hexadecimal" version of the color. The first two characters represent red, the second two green, and the third blue.
  • rgba(0, 255, 0, 0.8) - Same thing as RGB, but the last number represents the transparency value. In this case, we are defining 80% transparency.

While the built in colors like "green" or "blue" are just part of CSS, we can easily convert back and forth between RGB and Hex. It is simply a matter of converting binary to hexadecimal and vice-versa. There are plenty of online converters you can use to do this.

And one more thing while we're here–check out Adobe Color as a tool for building color themes and working with these color codes.

As a quick review, if we wanted to make all paragraph elements a sky blue color, we could do this:

p {  color: #16A6F5;}

Or this...

p {  color: rgb(22, 166, 245);}

Or this...

/* Here is a list of color keywords - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#color_keywords */p {  color: lightblue;}

Font Properties

While we have already covered the font-size property, there are a couple other important font properties to be aware of.

  • font-family - defines the font that your webpage will use
  • font-size - defines the size of the font
  • font-weight - defines the thickness of the font (i.e. regular, bold, etc.)
  • line-height - defines the spacing between lines of text

In most cases, you'll see the font-family and font-size defined at the root element, html.

html {  font-family: "Georgia", serif;  font-size: 16px;}

The first part of the font-family property represents the actual family (i.e. "Georgia") while the second part represents the generic family (i.e. "serif"), which acts as a fallback value in case the main family is not able to load correctly in the webpage (usually due to unsupported fonts on certain browsers).

For a list of font families and fallbacks, this W3 page is a good reference.

But what if you're not happy with the built-in browser fonts? Adding a custom font can be done in a few different ways, but the most straightforward and common way is by adding a link tag in the head of your HTML document; just like you would a stylesheet.

Let's say we wanted to add the Roboto font family to our webpage. Head over to Google Fonts and copy that link tags you see on the right side of the page. It should look like this.

<link rel="preconnect" href="https://fonts.gstatic.com"><link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;900&display=swap" rel="stylesheet">

Before we wire these up to our HTML document, I want to point out one important thing. You can see in the href attribute, we have font weights of 400 and 900 selected. In other words, we can use the font-weight property with values of 400 and 900 to change the thickness of our text. Let's go ahead and wire it up now.

<html>  <head>    <title>My Webpage</title>    <link rel="preconnect" href="https://fonts.gstatic.com">    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;900&display=swap" rel="stylesheet">    <link href="./path-to-stylesheet.css" rel="stylesheet">  </head>  <body>    <p>Paragraph #1</p>    <p class="bold-text">Paragraph #2</p>  </body></html>

Now, all we have to do in our stylesheet is this:

html {  font-family: 'Roboto', sans-serif;  font-size: 16px;}

And if we wanted to make one of those paragraphs bold, we could do this:

.bold-text {  font-weight: 900;}

Here is a Codepen showing this in action. Please note that the process of adding a custom font family in Codepen is slightly different because the HTML code editor represents the body and not the html document. Just go to Settings->HTML and paste the link tags into the "Stuff for head" section.

Background Properties

Whether we are talking about background colors, background images, or how these backgrounds are positioned, the following CSS properties are really helpful to keep in the back pocket.

Each of these properties will affect the content area of the Box Model (including padding, but excluding border and margin).

  • background-color - changes the color of an HTML element
  • background-image - uses an image as a background
  • background-position - if using a background image, positions the image
  • background-repeat - determines whether a background image is repeated
  • background-size - changes the size of the background image

Changing the background color is pretty straightforward, but make sure that the element you are styling has a width and a height either explicitly or implicitly. After all, an element that has no dimensions cannot have a background!

<div class="container"><div>
.container {  width: 500px;  height: 500px;  background-color: #46D5F2;}

Adding a background image is a bit trickier. If you are adding a background image, you most likely will be working with a picture, and therefore, you want that picture to fill the entire visible screen (the "viewport"). I have no intention in this massive post to walk you through all the possible combinations, so let's look at an extremely common example that you will see and use.

<div class="container">  <div class="text-container">    <h2>Some Centered Large Text</h2>  </div></div>

First, we need to get a high-resolution image (at least 1920x1080, but larger is preferable) for our background. Low-res images will NOT look good on large screens! Here is one from my golf site.

All we need is the image link and we should be set!

/* This is a basic CSS reset.  By default, the body will have   margin and padding that will prevent our background image from   taking up the entire screen */body {  margin: 0;  padding: 0;}/* Sets the background image */.container {  position: fixed;  width: 100vw;  height: 100vh;  background-image: url('https://www.thediygolfer.com/wp-content/uploads/2020/12/homepage-background.jpg');  background-position: right center;  background-size: cover;  background-repeat: no-repeat;  text-align: center;}/* Centers the text container on the page */.text-container {  background-color: white;  width: 200px;  margin: 200px auto;  padding: 20px;  border: 1px solid black;}

There is a lot going on here, I know. What I want you to focus on are the following things.

  • I have set the .container to have a 100vh and 100vw. This ensures that the HTML element with the background occupies the entire visible webpage, or the "viewport"
  • I have set the margin and padding to 0 for the body element to remove browser default styles that will prevent our background from occupying the entire page. Go ahead and remove this block of code in the Codepen and see what happens.
  • Each of the background properties have a set of possible values. These are good defaults. The only property that might be worth changing is the background-position property depending on what parts of your image you want to be shown.
  • Everything else that I didn't comment on will become part of your "CSS vocabulary" with practice (and I will likely cover them in the code challenge for this lesson).

Here is the end result. I highly suggest clicking through this and removing CSS properties one at a time to see what they do to the overall webpage.

Writing Shorthand CSS

And finally, the last thing I want to cover here is something that might be confusing to you like it was me when I was starting out. Many of the CSS properties that we have covered have "shorthand" ways of writing them. When talking about the Box Model, we can define a border around an element.

.some-element {  border: 1px dashed black;}

This creates a 1 pixel, dashed black line as a border. But...

We could have written this across three separate properties.

.some-element {  border-width: 1px;  border-style: dashed;  border-color: black;}

In other words, the first way was the "shorthand" way of writing this CSS rule. We can also do this with other properties like margin. Here's the long way to define margin for an element.

.some-element {  margin-top: 10px;  margin-right: 5px;  margin-bottom: 2px;  margin-left: 15px; }

Here's a shorter way to write the same CSS.

.some-element {  margin: 10px 5px 2px 15px;}

And if you want the same margin value on all sides, this is all you have to do.

.some-element {  margin: 20px;}

As you write CSS, you will pick up on these "shorthand" ways of writing it. I know it is confusing now and tough to remember what to use and when, but if you are ever lost, remember, you've got the documentation available to you!

A Systematic Way to Write CSS Effectively

In my experience, the real key to using CSS effectively is to ask the following four questions in order, every time you style a webpage. These will become second nature eventually.

  1. How do I want to arrange these HTML elements on the page?
  2. How does this arrangement look in the form of HTML?
  3. How can I use CSS to achieve the layout I have imagined?
  4. How should each element be styled?

Talking about CSS in isolation isn't helpful. We have to consider the HTML part too.

I'm going to walk you through these four questions using an example similar to the one below. Take a look at the webpage we looked at earlier:

Step 1: How do I want to arrange the elements?

In the example above, my goal is to have two boxes, horizontally arranged side-by-side with text in them.

Step 2: How does this arrangement look in HTML?

Since I have two boxes, I probably need two div elements. These div elements are perfect "containers" for things like this. I also need a "main" container, so I'll wrap everything in another div.

Furthermore, I need a heading and some paragraph text in each box. The most basic representation of this layout in HTML would be:

<div>  <div>    <h2></h2>    <p></p>  </div>  <div>    <h2></h2>    <p></p>  </div></div>

Of course, I need to put some text in the h2 and p elements and add a few classes to the elements (so that I can select them easily with CSS), but this represents the "skeleton" that I'm trying to imagine in this step.

Step 3: How can I use CSS to achieve the layout I have imagined?

In this step, we're focusing on getting those HTML elements arranged in the correct spots on the webpage. We are NOT worried about how pretty they look yet.

Unfortunately, this step is where experience using CSS comes in handy. There are several "layout" CSS properties to use here, and we can actually achieve the same result in a couple different ways. Since I will be walking through these properties later, I'm going to just give them to you now.

But the first thing we need to do is modify our HTML so that we have the necessary selectors ready to use! Here's how I would modify it.

<div class="container">  <div class="box-1">    <h2>Box 1</h2>    <p>some text</p>  </div>  <div class="box-2">    <h2>Box 2</h2>    <p>some text</p>  </div></div>

Sure, I could have used ID attributes instead of classes, but in this example, it doesn't matter. We just need something that will make writing our CSS easier. Here is how our HTML looks without CSS layout properties (I added borders so you can visualize it better).

By default, these will be stacked on top of each other vertically (we'll talk about why later). Since we want them to be arranged horizontally, we need to add some CSS. Here's one way to do it:

.box-1 {  float: left;  width: 50%;}

The float property will break the first box out of its "natural" layout and the width will make it take up 50% of the page. This is the easiest way to achieve our desired result, but as you start writing more and more CSS, you'll realize that using the float property for layouts is very cumbersome and produces some unexpected results. In the next lesson, we will learn about Flexbox, which is how I would prefer to achieve this layout. Don't worry about how this works yet.

.container {  display: flex;  flex-direction: row;}.box-1, .box-2 {  flex: 50%;}

Here is our result after adding this CSS.

At this point, we have successfully arranged the items in the right place on the page.

Step 4: How should each element be styled?

The last step is in my opinion, the easiest. All we have to do now is take our elements that we have arranged on the page and give them nice colors, borders, spacing, etc. Let's add the following CSS to our existing webpage.

.box-1, .box-2 {  flex: 50%;  text-align: center;  margin: 20px;  padding: 20px;}.box-1 {  border: 2px solid green;  color: green;}.box-2 {  border: 2px solid blue;  color: blue;}

Starting from the top, we have added a text-align property which will center all the text elements inside our div containers. We also added margin and padding (will talk about this in a minute), which just spaces things out nicely. We then add a green border and color (font color) to the box-1 class and the same properties in blue for box-2.

Here's our final result.

A Project to Learn CSS

Like most things in web development, the only true way to digest this stuff is to build something. Instead of giving you a boring overview of all the possible CSS properties, we're going to use what we've learned in this lesson and start building something real.

The challenge that we are doing is from a site called Frontend Mentor, which provides really nice UI designs (that I could not design myself) and presents them as HTML/CSS/JS challenges.

Here is the challenge that we will be completing.

lesson challenge

Since we know how to write JavaScript, HTML, and now CSS, we should be able to complete this entire challenge! I will be releasing some supplemental CSS videos on responsive web design, Flexbox, and CSS grid, so I suggest supplementing this challenge with those videos and trying parts of it on your own. I would not expect you to be able to build this on your own, but there will be many opportunities throughout to pause the video and try it for yourself.

Best of luck, here is the video solution!