Lesson 8 - CSS Crash Course for Beginners #fullstackroadmap
Tags: codenewbie, webdev, css
Published: 2021-03-01 15:58:13

## Prerequisites

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

- [A basic understanding of HTML](https://www.zachgollwitzer.com/posts/2021/fullstack-developer-series/7-html-crash-course/)
- Required for solving the code challenges: [lessons 1-7 in this series](https://www.zachgollwitzer.com/posts/2021/fullstack-developer-series/fullstack-roadmap-toc).

## The goal for this lesson

See this crash course on YouTube:

- [Part 1 - CSS Basics](https://youtu.be/hAD58ej0E4o)
- [Part 2 - Box Model](https://youtu.be/gGjJDEEXFv0)
- [Part 3 - Must Know CSS Properties](https://youtu.be/dqaNvIJ4Fyk)
- [Part 4 - Pricing Grid Code Challenge](https://youtu.be/zwBoEwUD__0)

By the end of this lesson, you will have built this from scratch ([Frontend mentor link](https://www.frontendmentor.io/challenges/single-price-grid-component-5ce41129d0ff452fec5abbbc/hub/single-price-grid-component-7wZJ4lx_U)).

![desktop card preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jt75eqwhamskgms8mxpi.jpg)

And after a few short lessons on responsive design, CSS Grid, and Flexbox, we will build this ([Frontend mentor link](https://www.frontendmentor.io/challenges/testimonials-grid-section-Nnw6J7Un7/hub/testimonials-grid-section-QuSSjaTVM)).

![css grid challenge preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jf4m88b110sdelr7e6yz.jpg)

And finally, we'll bring everything we've learned in this course together to build this ([Frontend mentor link](https://www.frontendmentor.io/challenges/crowdfunding-product-page-7uvcZe7ZR/hub/crowdfunding-product-page-7OC236vqP)).  No, this is not the final project, but will be pretty exciting to build with our new skills!

![product landing page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q98uueynkpknnxtxj3a0.jpg)

### 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](https://www.frontendmentor.io/challenges) 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](https://www.zachgollwitzer.com/posts/2021/fullstack-developer-series/introduction/) to get an overview of what this series is all about.

- [Series Table of Contents](https://www.zachgollwitzer.com/posts/2021/fullstack-developer-series/fullstack-roadmap-toc)
- [Github Repository](https://github.com/zachgoll/fullstack-roadmap-series) - where you'll find all the code we write in this series
- [YouTube Playlist](https://www.youtube.com/watch?v=ZZJT5uskuvI&list=PLYQSCk-qyTW37zDPzcAyzCsnypFQrhUcq)
- [Series Overview](https://www.zachgollwitzer.com/posts/2021/fullstack-developer-series/introduction/)
- [100 Days of Code Challenge](https://www.100daysofcode.com/) - I highly recommend you take this on while reading this series!

Please tag me on Twitter [@zg_dev](https://twitter.com/zg_dev) and share this series with [#100DaysOfCode](https://twitter.com/search?q=%23100DaysOfCode&src=typed_query)!

## 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:

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

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

```css
.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**](https://codepen.io/zg_dev/pen/RwoWRaX), 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](https://youtu.be/hAD58ej0E4o)

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.

<iframe height="363" style="width: 100%;" scrolling="no" title="CSS Layout and Style Example" src="https://codepen.io/zg_dev/embed/dyORWWm?height=363&theme-id=dark&default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/dyORWWm'>CSS Layout and Style Example</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/dyORWWm %}

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

![CSS Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1llhiepeqduc6mwhsmt.png)

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.

```html
<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?

```js
// Select by tag
document.querySelector('p');

// Select by class
document.querySelector('.main-text');

// Select by ID
document.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.

```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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mhcp8za2sdnqmkr33dl9.jpg)

### 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?

![dom tree visual](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zk54v4v7u88g9m7hsslm.jpg)

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
<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?

```css
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
<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:

```css
/* 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.

```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>
```

```css
#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.

<iframe height="387" style="width: 100%;" scrolling="no" title="Selecting Descendants in CSS" src="https://codepen.io/zg_dev/embed/OJbyKVp?height=387&theme-id=dark&default-tab=html,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/OJbyKVp'>Selecting Descendants in CSS</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/OJbyKVp %}

#### 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.

```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`.

```css
#main > p {
  color: blue;
}
```

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

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="html,result" data-user="zg_dev" data-slug-hash="yLVYmNE" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Selecting Children in CSS">
  <span>See the Pen <a href="https://codepen.io/zg_dev/pen/yLVYmNE">
  Selecting Children in CSS</a> by Zach  (<a href="https://codepen.io/zg_dev">@zg_dev</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#### 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](https://twitter.com/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.

```html
<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.

```css
ul + p {
  color: red;
}
```

<iframe height="462" style="width: 100%;" scrolling="no" title="Selecting Siblings in CSS" src="https://codepen.io/zg_dev/embed/oNYjKjg?height=462&theme-id=dark&default-tab=html,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/oNYjKjg'>Selecting Siblings in CSS</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/oNYjKjg %}

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:

```css
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:

```html
<p class="regular-text">some text here</p>
<div class="regular-text">some text here</div>
```

```css
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.

```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:

```css
.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.

```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.

<iframe height="226" style="width: 100%;" scrolling="no" title="Multiple Selectors at once with CSS" src="https://codepen.io/zg_dev/embed/gOLxYJJ?height=226&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/gOLxYJJ'>Multiple Selectors at once with CSS</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/gOLxYJJ %}

### 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.

<iframe height="353" style="width: 100%;" scrolling="no" title="Multiple Classes on HTML" src="https://codepen.io/zg_dev/embed/yLVoqYa?height=353&theme-id=dark&default-tab=html,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/yLVoqYa'>Multiple Classes on HTML</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/yLVoqYa %}

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.

```html
<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:

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

And then use our individual classes for unique styles.

```css
.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.

```html
<button>Hover me</button>
```

```css
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](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements#user-action_pseudo_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!

<iframe height="265" style="width: 100%;" scrolling="no" title="MWbvWym" src="https://codepen.io/zg_dev/embed/MWbvWym?height=265&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/MWbvWym'>MWbvWym</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/MWbvWym %}

### Multiple Selectors vs. Nested Selectors

In the previous example, we saw this.

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

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

```css
.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.

```html
<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**.

```css
/* 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.

```html
<p>Some text</p>
```

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

```css
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.

```html
<p class="my-text">Some text</p>
```

```css
.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":

![CSS selector importance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvpwbx389in5mlsdkj87.png)

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".

```css
#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:

```html
<div>
  <p class="my-text">paragraph text</p>
</div>
```

```css
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**.

<iframe height="234" style="width: 100%;" scrolling="no" title="Which style takes precedence?" src="https://codepen.io/zg_dev/embed/XWNmNGe?height=234&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/XWNmNGe'>Which style takes precedence?</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/XWNmNGe %}

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.

```css
/* 
  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.

```html
<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.

```css
/* 
  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!

<iframe height="265" style="width: 100%;" scrolling="no" title="Which style takes precedence? v2" src="https://codepen.io/zg_dev/embed/MWbapYP?height=265&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/MWbapYP'>Which style takes precedence? v2</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/MWbapYP %}

### Inline HTML Styles

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

```html
<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](https://codepen.io/zg_dev/pen/rNWGazo) 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.

```html
<p id="my-text">Some text</p>
```

```css
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:

```css
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:

```html
<div>
  <h2>Some Text</h2>
</div>
```

The CSS is the tricky part.

```CSS
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.

<iframe height="327" style="width: 100%;" scrolling="no" title="CSS properties example" src="https://codepen.io/zg_dev/embed/qBqjerE?height=327&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/qBqjerE'>CSS properties example</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/qBqjerE %}

### 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](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference#index) if you forget what something does.

## What is the Box Model in CSS?

[Here is the video version of this section](https://youtu.be/gGjJDEEXFv0)

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 calculations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0ta549fm7xk6bb2qqqz.JPG)

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.

- [Width](https://developer.mozilla.org/en-US/docs/Web/CSS/width)
- [Height](https://developer.mozilla.org/en-US/docs/Web/CSS/height)
- [Padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding)
- [Border](https://developer.mozilla.org/en-US/docs/Web/CSS/border)
- [Margin](https://developer.mozilla.org/en-US/docs/Web/CSS/margin)

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.**

<iframe height="674" style="width: 100%;" scrolling="no" title="Building the Box Model 1" src="https://codepen.io/zg_dev/embed/zYodJYM?height=674&theme-id=dark&default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/zYodJYM'>Building the Box Model 1</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/zYodJYM %}

### 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](https://www.w3schools.com/html/html_blocks.asp).
- `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 calculations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0ta549fm7xk6bb2qqqz.JPG)

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.

<iframe height="747" style="width: 100%;" scrolling="no" title="Content vs. Border Box" src="https://codepen.io/zg_dev/embed/dyOzqvo?height=747&theme-id=dark&default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/dyOzqvo'>Content vs. Border Box</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/dyOzqvo %}

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

```css
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

### Position

There are five possible values for the `position` property [as shown in its documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/position).

- `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.

<iframe height="625" style="width: 100%;" scrolling="no" title="Position Property CSS" src="https://codepen.io/zg_dev/embed/zYodwKq?height=625&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/zYodwKq'>Position Property CSS</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/zYodwKq %}

### Display

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:

```css
.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:

```css
.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](https://youtu.be/dqaNvIJ4Fyk)

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

#### Pixels 

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).

<iframe height="265" style="width: 100%;" scrolling="no" title="Using pixels" src="https://codepen.io/zg_dev/embed/BaQdLmm?height=265&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/BaQdLmm'>Using pixels</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/BaQdLmm %}

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.

![pixel units dev tools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s6t5retodpwa4u7ltnr3.JPG)

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?

```js
window.innerHeight; // The webpage height in pixels
window.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.

```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.

#### Percentages

Take a look at this brainteaser.

<iframe height="265" style="width: 100%;" scrolling="no" title="Using CSS percentages" src="https://codepen.io/zg_dev/embed/ExNvgMj?height=265&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/ExNvgMj'>Using CSS percentages</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/ExNvgMj %}

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;

But...

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.

```css
body {
  font-size: 16px; /* 16px is a "standard" value for normal text on most webpages */
}
```

```css
body {
  font-size: 1em; /* 100% of the parent element's font size */
}
```

```css
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
<html>
  <head></head>
  <body>
    <p>Paragraph #1</p>
    <p class="smaller-text">Paragraph #2</p>
  </body>
</html>
```

```css
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](https://stackoverflow.com/a/4986517/7437737).
- `#00ff00` - The "hex" or ["hexadecimal" version of the color](https://stackoverflow.com/a/22239907/7437737).  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](https://www.google.com/search?q=color+picker) you can use to do this.

And one more thing while we're here–check out [Adobe Color](https://color.adobe.com/create) 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:

```css
p {
  color: #16A6F5;
}
```

Or this...

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

Or this...

```css
/* 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`.

```css
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](https://www.w3.org/Style/Examples/007/fonts.en.html).

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](https://fonts.google.com/specimen/Roboto?preview.text_type=custom&sidebar.open=true&selection.family=Roboto:wght@400;900) and copy that `link` tags you see on the right side of the page.  It should look like this.

```html
<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
<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:

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

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

```css
.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.

<iframe height="540" style="width: 100%;" scrolling="no" title="Including Custom Fonts" src="https://codepen.io/zg_dev/embed/RwoZKew?height=540&theme-id=dark&default-tab=html,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/RwoZKew'>Including Custom Fonts</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/RwoZKew %}

### 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!

```html
<div class="container">
<div>
```

```css
.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.

```html
<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.](https://www.thediygolfer.com/wp-content/uploads/2020/12/homepage-background.jpg)

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

```css
/* 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.

<iframe height="339" style="width: 100%;" scrolling="no" title="Background images" src="https://codepen.io/zg_dev/embed/WNoEpKK?height=339&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/WNoEpKK'>Background images</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/WNoEpKK %}

### 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.

```css
.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.

```css
.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.

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

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

```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.

```css
.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](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference#index)!

## 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:

<iframe height="363" style="width: 100%;" scrolling="no" title="CSS Layout and Style Example" src="https://codepen.io/zg_dev/embed/dyORWWm?height=363&theme-id=dark&default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/dyORWWm'>CSS Layout and Style Example</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/dyORWWm %}

### 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:

```html
<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.

```html
<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).

<iframe height="321" style="width: 100%;" scrolling="no" title="Layout only example (html only)" src="https://codepen.io/zg_dev/embed/GRNvRPo?height=321&theme-id=dark&default-tab=html,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/GRNvRPo'>Layout only example (html only)</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/GRNvRPo %}

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:

```css
.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.

```css
.container {
  display: flex;
  flex-direction: row;
}

.box-1, .box-2 {
  flex: 50%;
}
```

Here is our result after adding this CSS.

<iframe height="265" style="width: 100%;" scrolling="no" title="Layout only example" src="https://codepen.io/zg_dev/embed/ZEBJEdj?height=265&theme-id=dark&default-tab=html,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/ZEBJEdj'>Layout only example</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/ZEBJEdj %}

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.

```css
.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.

<iframe height="265" style="width: 100%;" scrolling="no" title="Layout + Style Example" src="https://codepen.io/zg_dev/embed/MWbvYgX?height=265&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/zg_dev/pen/MWbvYgX'>Layout + Style Example</a> by Zach 
  (<a href='https://codepen.io/zg_dev'>@zg_dev</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

{% codepen https://codepen.io/zg_dev/pen/MWbvYgX %}

## 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.

![desktop card preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jt75eqwhamskgms8mxpi.jpg)

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!](https://youtu.be/zwBoEwUD__0)