BWC Bootcamp Recap: Week 3
Tags: css, html, webdev, freecodecamp
Published: 2023-08-24 06:05:34

Hello friends and learners! Can you believe we’re more than halfway through the [Bad Website Club web dev bootcamp](https://badwebsite.club/webdev-bootcamp-2023.html) already? Don’t worry if you’re not that far along yet yourself though—there are no deadlines here and you’re free to complete the work at your own pace.

There was a lot of material this week, but fortunately, many of the topics appeared in more than one lesson. This time the post is organized by topics addressed instead of by freeCodeCamp lesson. I hope this helps you make more connections between what you did in the different lessons and see more of the big picture of what you’re capable of now!

### Accessibility

- The `role` attribute is used to tell assistive technology what the *purpose* of an element is. It’s particularly important on elements that don’t already have semantic meaning built in. This is part of the system called ARIA (Accessible Rich Internet Applications).
- When you assign the `role` as `region`, you can use the `aria-labelledby` attribute to indicate which text acts as a name for the region.
- Navigation is a key aspect of accessibility! Using semantic HTML elements to structure the page create accessible navigation. These elements include header, nav, main, section, article, and footer.
- Visual accessibility: Choose a typeface that remains legible even at low resolutions. Also, there needs to be enough color contrast between text and its background. You can use a [color contrast checker](https://webaim.org/resources/contrastchecker/) to help.
- Inputs should have a `label` element connected to their `id`, as we learned in the lesson on forms.
- Sometimes we want certain text to be read by a screen reader but not visible on the page. In those cases we can create a “screen reader only” class, often called `sr-only`, and give it a certain set of properties that make it invisible. You can learn more about this method at [WebAIM](https://webaim.org/techniques/css/invisiblecontent/).
- Conversely, to make an element hidden from assistive technology, put the attribute `aria-hidden="true"` in the opening tag. Of course, it’s important to keep the visual content and the screen reader content in harmony, so you should generally only use this on text if it’s repeated nearby in a screen-reader-only element.
- `scroll-behavior` is a property that can be used to change what happens when you click on links to different sections within the same page, and make the page appear to scroll smoothly instead of jumping instantly to the new section. However, visual movement like this can cause problems for certain users. We should put this behavior inside a media query with the rule `prefers-reduced-motion: no-preference` so that the effect doesn’t apply for users who have not requested low motion in their browser settings.  (See below for more on media queries!)

### Tables

Tables are a way to display *tabular data*, or in other words, information that can be logically arranged into rows and columns. The [Bad Website Club schedule page](https://badwebsite.club/webdev-bootcamp-2023.html) uses tables to organize the information, because that information consists of a series of items that all share the same categories. In that example, each day’s class makes up a *table row*, and each category of information such as date or URL makes up a *table column*.

- Start by making a `<table>` element.
- The first element inside a table should be a `<caption>` element, which describes what the table is about.
- Next, inside the table after the caption, add one `<thead>` (table header) and one `<tbody>` (table body). `thead` will have the headings for the columns, and `tbody` will contain the main data of the table.
- The data of an HTML table is grouped by rows. The children of both `thead` and `tbody` will be **table rows**, or `<tr>` elements.
- Then, within each row, the content gets split into cells. For the header, these should be **table heading** `<th>` elements. Regular non-heading cells are **table data** `<td>` elements. Both the `td` and the `th` elements get nested inside the `<tr>`'s.
- Tables have some very particular default styles—they’re one of the few elements that get borders by default. But if you don’t like the look, don’t worry, you can still customize their appearance as much as every other element! There are also a few properties useful for tables that you might not use elsewhere, such as `border-collapse` and `vertical-align`.

### Pseudo-selectors

Pseudo-selectors are extra keywords that get added on to the end of a CSS selector, and they let us get more specific about what we’re selecting. Some of them select an element based on its *context* instead of just what it is, while other ones give us access to things that can’t be targeted by normal selectors.

The term pseudo-selector refers both to *pseudo-elements* like `::before` and `::after`, and *pseudo-classes* like `:first-of-type`. Pseudo-classes are written with one colon (`:`) and pseudo-elements are written with two colons (`::`). 

Pseudo-classes

- The selector `h2:first-of-type` targets only the first `h2` element on the page. Likewise, add the  `:last-of-type` pseudo-selector on to the end of a type selector to target only the last instance of that element. Or `:nth-of-type()` with a number between the parentheses to target only the 5th or 20th or whatever element of that type.
- Note that we mean “first” and “last” based on what order the tags are written in the HTML file, not where they visually display on the page—if you put some elements inside a flexbox set to reverse order, it does *not* reverse what order they’re counted in.
- It’s not just for h2s of course! Selectors like `:first-of-type` can be added to pretty much any type selector.
- The advantage of using these selectors instead of an ID selector (with the ID of the first h2, for instance) is that, if you edit the HTML later and rearrange the order of h2s, you won’t need to update the CSS to make it still keep selecting whichever one comes first.
- `:not()` is a special pseudo-selector that selects the *inverse* of another selector that you write between the parentheses. In the balance sheet, we used the selector `span:not(.sr-only)` to target every span *except* the ones with class `sr-only`. Notice how we still use the `.` syntax for the class selector inside the parentheses.
- Remember using `a:hover` or `a:visited` in past lessons to change how links look when the user hovers over them or after they’ve been clicked? These were pseudo-classes all along! you can add the `:hover` pseudo-class to many other elements too, not just links.

Pseudo-Elements

- There weren’t any pseudo-elements in the balance sheet lesson, but we actually saw `::before` in the accessibility lesson and `::after` way back in the flexbox lesson. These are called pseudo-element selectors because they create a “fake” child element at either the start or end of the targeted element. They’re often used with the `content` property. For example, in the quiz, we programmatically added the word “question” before each question number by writing this CSS rule:

```css
p::before {
  content: "Question #";
}
```

- Instead of using these pseudo-elements to add text content, we can also use them to draw shapes, similar to how we’ve used divs. The piano lesson used this method with the `::after` pseudo-element to draw the black keys onto the piano as a “pseudo child” of certain white keys. When you use it this way, just remember to include `content: ""`, or else the pseudo-element won’t display at all.

There are many, many more pseudo-selectors that we haven’t seen yet! To learn more, check out [MDN’s pseudo-selector overview](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements) or, to find out what all the possibilities are, the full [pseudo-classes documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) and [pseudo-elements documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements).

### Position

In the Picasso lesson, we used the `position` property to help us arrange elements at very specific distances relative to one another. It’s especially useful for doing CSS art like that, but it can also be applied in creating regular page layouts.

- `position: absolute` removes an element from the *normal document flow*, or in other words, takes it out of the place where it would normally sit in the page and doesn’t reserve space for it. Instead, it positions the element a certain distance away from a container, ignoring the size of the other content around it and letting it layer on top of the “normal” elements.
- In some cases, absolute position won’t work until you also specify a value for at least one of the `top`, `bottom`, `left`, or `right` properties. These tell the absolute item how far away to be from whichever side you pick.
- That “container” that these distances are calculated in relation to will be the nearest ancestor (parent, or parent of a parent, etc) that has `position: absolute` or `position: relative`. If none is assigned, then the container will be the body element. In the balance sheet, we gave the `table` elements `position: relative` so that it would act as a positioning container for the `caption` element that we wanted to absolutely position 0.5rem in from its left edge.
- We also used `position: fixed` in the quiz lesson to make the header remain fixed to the top of the page, so that it remained visible even when scrolling down. We did almost the same thing in the balance sheet, setting the years heading to stay at the top of the page when you scroll down past it, but in that one we used `position: sticky` instead. The difference is that `sticky` reserves space for the element in the normal document flow, whereas `fixed` completely removes it into its own layer. In my personal opinion, `sticky` is usually better for stuff like headers, because it doesn’t leave a gap in the document flow.

Position can be pretty confusing, and it definitely makes more sense with visuals, so check out these two short YouTube videos:  a [video from the great Kevin Powell explaining absolute position](https://www.youtube.com/watch?v=P6UgYq3J3Qs) that helped me in the past, and a [video from Slaying the Dragon that goes over all five position types](https://www.youtube.com/watch?v=P6UgYq3J3Qs0).

### Z-index

The `z-index` property determines how elements layer on top of each other. Elements with higher values of `z-index` are drawn on top of (or closer to the front than) ones with a lower z-index. 

In the Picasso lesson, we used a negative z-index to put the back wall behind everything else, and then we used different positive values to arrange parts of the scene on top of each other, like making the table go in front of the characters.

- Elements where we don’t set the `z-index` property are equivalent to z-index of 0.
- As we saw in the Picasso lesson, changing the Z-index is most often used in combination with absolute positioning.
- Z-index doesn’t work on elements that have the default `position` type of `static`. If you want to use z-index but otherwise don’t need to change the element’s position, give it a position of `relative`.

### Media queries (responsiveness)

Media queries were properly introduced in the piano lesson, but we actually saw them once or twice beforehand as well. The basic idea is that they allow your CSS to *respond differently* when your website is viewed in different contexts (AKA on different media), which is why we call this *responsive design*. The topic is actually much broader than freeCodeCamp has shown us, so you may want to [read more about them on MDN](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Media_queries) if you’re curious.

- Media queries use a slightly different syntax than anything else we’ve seen in CSS so far. It’s a type of *at-rule*, meaning that it uses a keyword with an at symbol `@` in front. They look like this:

```css
@media (max-width: 800px) {
  p {
    margin: 1rem;
  }

  body {
    width: 100%;
  }
}
```

- Notice how there’s more than one selector and rule set nested inside the media query! You can think of it almost like an entire mini CSS file wrapped inside of the query. You can write as many different rule sets for different selectors as you want, all within the same media query, and you can use all the same selectors as usual.
- The statement inside the parentheses in the first line is the condition for when this entire set of styles should be applied. In this example, when the viewport is 800px wide or smaller, then this set of rules will be applied. When the viewport is larger than the rule’s max width, then these styles will be ignored.
- It’s possible to combine more than one condition. For example, to make an intermediate size for the piano, we used the media query `@media (max-width: 1199px) and (min-width: 769px)`.
- If you’re using a media query to override styles that you declared elsewhere in the file, then make sure that you put the media query *after* them! When you’re using a min or max screen size rule to make a responsive layout (as you often will), it’s a good habit to always put this media query at the very bottom of your file.

### Odds and ends

- `aspect-ratio` is a property that sets the ratio of the width and height. It’s useful when we want to make sure an image doesn’t get distorted when it gets resized.
- `max()` and `min()` are two CSS functions that can take two measurements and choose whichever one is larger or smaller. This is most useful when one of the measurements is in relative units, where its actual size might vary. For example, `font-size: min(5vw, 1.2em);` will set the font size to be whichever of `5vw` and `1.2em` is smaller—and which one is smaller will change depending on the viewport size.
- `calc()` is a CSS function that lets you do some math and calculate a value dynamically. For example, `width: calc(100% - 20px);` will make the width 20px less than whatever the parent’s width is, and it will update and recalculate any time the parent’s width changes. You can also use it for static values like `calc(350px - 78px)` if you just don’t want to do the math yourself! But it really comes in most handy when you’re trying to do math between two different units.
- You can use the `!important` keyword to protect a rule from being overwritten by any others. Just add the word to the end of the declaration right before the semicolon, as in `border: 0 !important;`. However, it’s best to avoid relying on this keyword because it makes the code harder to read and understand later. Often, you can prevent clashes just by making your selectors more precise instead.

---

That was a lot (I think these posts might be getting longer each week, whoops), but I hope it’s starting to sink in bit by bit! It’s okay if things still feel confusing right now. We’re learning so much and I’m so proud of everyone who’s participating in this bootcamp! I love all the work I’ve seen so far from those of you who have shared your projects, too! I would be thrilled to see more of you share your work on the [Bad Website Club Discord](https://discord.gg/pySW9YZfYY) or the [forum](https://forum.freecodecamp.org/c/2023-webdev-bootcamp/586)—or, if you’re feeling stuck with your project, use those places to reach out and talk about what you’re struggling with.

As always, you’re more than welcome to leave any questions in the comments below, as well as asking on Discord and the forum. Take care until next time!

Cover art by [Kiri](https://ecasticx.com/)!