4 things in web development I've learned in 2020, so far
Tags: css, javascript, beginners, tutorial
Published: 2020-08-10 13:15:31

---
title: 4 things in web development I've learned in 2020, so far
published: true
description: The new tricks I learned and implemented this year!
tags: css, javascript, beginners, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/hj7ws53r88m2b9ov9kdp.png
---

The thing I like most about web development is that you never stop learning new properties and tricks. These past few months have been weird; working from home, having the company I've worked at for three years stop, and starting as a freelancer. It's been a while since writing my last post, for all those reasons and more, but today I decided to pick it up again and write about all the small triumphs I've had this year learning new things!

## Fill available
In the Safari iOS browser 100vh is calculated on the viewport height regardless of the visibility of the bottom navigation bar. While this is fine most of the time, and is probably preferable to the other option, in which element heights are recalculated when you scroll slightly up, it can be a very weird bug on fixed scrollable containers (like the popups in the following example).
![Safari browser shown with and without visible nav bars](https://dev-to-uploads.s3.amazonaws.com/i/7xiviqb85ml8fdqxj46t.gif)
This is a bug many [developers](https://github.com/FrDH/mmenu-js/issues/837) have been pulling their hair out to [fix](https://forum.webflow.com/t/bottom-navbar-solution/47150) for [many](https://apple.stackexchange.com/questions/130822/safari-ios-menu-bar-conflicts-with-buttons-in-lower-10-of-the-screen) [many](https://stackoverflow.com/questions/33644584/how-might-one-force-show-the-mobile-safari-bottom-nav-bar-to-show-programmatical) years.
Then in April Matt Smith tweeted this and it *almost* made up for being socially isolated for a month by that point.

{% twitter 1254151507412496384 %}

The best way to implement this in my opinion is like Matt does, with a backup for browsers that don't yet understand this property, for example;
```css
.container {
  height: 100vh;
  height: -webkit-fill-available;
  height: fill-available;
}
```

## Interaction based media queries
I think I'm a bit late to the party, but this might be my favourite CSS discovery this year. It's [supported by all modern browsers](https://caniuse.com/#feat=css-media-interaction) and allows you to style based on a user's primary input mechanism.  The great thing about media queries like these is that you don't have to rely on using screen size media queries which don't always correspond with modern devices (looking at you iPad Pro). 

Possible options are `pointer`, `any-pointer`, `hover`, and `any-hover`, the beautiful thing about `pointer` is that it accepts `coarse`, `fine` or `none` taking in account the specificity of the pointer device's input. This would allow you to create slightly larger CTA's, inputs or checkboxes for devices that have a coarse pointer input to create a more accessible experience ✨. I believe the fine pointer value is implemented when a user is using a stylus, but I'm not sure.
I have used the `hover` property a handful of times, mostly to create custom cursors, which obviously do not have to show on touch devices.

Example:
```css
@media (pointer: coarse) {
  input[type="checkbox"] {
    width: 1.5rem;
    height: 1.5rem;
  }
}
```

## Intersection Observer API
This is one of the best ways to create scroll position based animations and I could write an article solely on this. I've learned a lot about it from reading this [Mozilla article](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). 
It's supported in all modern browsers and allows you to call functions when elements come in to view (or are intersecting) in your viewport.

```js
const header = document.querySelector('.header');
const inView = (entries) => {
  for (const entry of entries) {
    // try logging entry to view all the possible values
    if (entry.boundingClientRect.y < -32) {
      header.classList.add('background--dark'); // for example change the background of the header when the page has scrolled 32 px.
    } else {
      header.classList.remove('background--dark'); 
    }
  }
};
// threshold is just one of the options you can pass in the InteractionObserver
// It determines the amount of triggers while scrolling, it allows an array of numbers between 0 and 1
let threshold = []; 
for (let i = 0; i <= 100; i++) {
  threshold.push(i / 100);
}

const observePageHeader = new IntersectionObserver(inView, { threshold });

// observing the element that has .header as a class
observePageHeader.observe(header);
```
{% codepen https://codepen.io/Sidstumple/pen/WNwvYZR %}

It can be used to [create lazy loading images](https://codepen.io/rpsthecoder/pen/pByZjR) or [play videos only when they're in view](https://codepen.io/rpsthecoder/pen/ZZLyaG). Or add styles and animations to elements at certain scroll positions.
I was also pleasantly surprised it still worked while using the Locomotive scroll library!

## Perspective
Apparently, when you set the css `perspective` property and create a horizontally scrollable container it creates a sort of out of the box scroll animation? Weird stuff!
{% codepen https://codepen.io/Sidstumple/pen/rNxymbe %}

Found this unexpected feature while working on a way to create a sort of scrollable timeline:

{% codepen https://codepen.io/Sidstumple/pen/wvMazzM %}

### Bonus: learn from my mistakes
I've spent waaaay too many hours trying to fix a 'bug' where a container wouldn't scroll on mobile iOS but would on desktop. It appears using `pointer-events: none` on a parent element can really screw up the ability to scroll inside a scrollable container on iOS.


## Want to work with me?
[Check out my portfolio](https://cydstumpel.nl/)