30 things I learned from Javascript 30

Wes Bos has made an awesome course called Javascript 30 that he gives away for free. If you have the time or the inclination to complete the course, do it!

By Connor Leech - Mar 30, 2018

Wes Bos has made an awesome course called Javascript 30 that he gives away for free. If you have the time or the inclination to complete the course, do it! This post serves as some notes for myself and I hope that anyone else reading can gain some insights about Javascript and CSS programming. Here's the tl;dr:

All code for the course and referenced in this post is available fo’ free. It’s on GitHub.

Day 1

To start the course off we built a drumkit so that when you press a button the browser makes a sound. It’s a very neat use of the <audio> HTML5 element. My biggest takeaway for the first day was learning the CSS transform property (transform — CSS | MDN). In the code we added a listener for every keydown event and passed in a function that plays the appropriate noise associated with that key. We first went through all of the elements that have a “key” class on them and attached an event listener for the “transitionend” event (transitionend — Event reference | MDN). The transitionend fires when a CSS transition ends, go figure! When the user clicks a button we add a “playing” class that begins the transform. Once the “transitionend” fires for an element we remove the “playing” class. The result is that there’s a real nice yellow glow around the button when we press the corresponding key!

Result: https://01-js30-drumkit--connor11528.repl.co/

Relevant code:

/* transform CSS styling */
.playing {
  transform: scale(1.1);
  border-color: #ffc600;
  box-shadow: 0 0 1rem #ffc600;
window.addEventListener('keydown', playSound);
/* take in the event and play the appropriate sound file */
function playSound(e){
  // ...
// add listener to every key for when css transitions end
keys.forEach(key => {
  key.addEventListener('transitionend', removeTransform);
function removeTransform(e){
    if(e.propertyName !== 'transform') return; // only listen for transform changes

Day 2

In day two we built a clock with a moving second hand. The neat bits were about the transform and transition (transition — CSS | MDN) CSS properties. Specifically, we used the transition-timing-function (transition-timing-function CSS | MDN) so that the second hand will bounce over and back like a real mechanical second hand. In the wise words of the Mozilla Developer Network:

This [transition-timing-function], in essence, lets you establish an acceleration curve so that the speed of the transition can vary over its duration.

We made a Javascript function that gets the datetime for right now, performs degree calculations and adjusts the CSS transform properties accordingly. Wes uses ES6 in the Javascript, which isn’t too hard to pick up if you’re familiar with regular ES5 code.

Result: https://repl.it/@connor11528/02-JS30-Clock

Relevant code:

/* CSS for the hand effects and having rotation occur from center of the clock */
.hand {      
  position: absolute;      
  transform-origin: 100%;      
  transition: all 0.05s;      
  transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1)    
/* Javascript */
const setDate = () => {      
  const now = new Date();      
  const seconds = now.getSeconds();      
  const minutes = now.getMinutes();      
  const hours = now.getHours();      
  /* degree calculations go here... */
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`;       
  minuteHand.style.transform = `rotate(${minutesDegrees}deg)`;      
  hourHand.style.transform = `rotate(${hoursDegrees}deg)`;    
setInterval(setDate, 1000);

Day 3

Today we covered CSS variables which are now available natively in CSS. In the code we set up and instantiate CSS variables at the highest level within CSS. Then we apply event listeners for the input fields so that we trigger a function anytime the input is scrolled or changed. The syntax is all new so be prepared! Within the Javascript function bound to the input events we grab values from the HTML input element using this.dataset (HTMLElement.dataset — Web | MDN) which is available through our use of custom data attributes in HTML (the data-KEY=”VALUE” syntax). The input for changing the variable are bound by the name of the input and the variable name. From there we set the value of the variable to a custom value using Javascript. This one is pretty funky and would be next to impossible for me to figure out on my own, but Wes explains it easily with easy to read and follow code. Relevant snippets are below!

Result: https://03-js30-css-variables--connor11528.repl.co/

Relevant code:

/* HTML for the funky sliders */
<div class="controls">
    <label for="spacing">Spacing:</label>
    <input id="spacing" type="range" name="spacing" min="10" max="200" value="10" data-sizing="px">
    <label for="blur">Blur:</label>
    <input id="blur" type="range" name="blur" min="0" max="25" value="10" data-sizing="px">
    <label for="base">Base Color</label>
    <input id="base" type="color" name="base" value="#ffc600">
/* CSS to set variables for the document and set them to the img */
:root {
    --base: salmon;
    --spacing: 10px;
    --blur: 10px;
img {
    padding: var(--spacing);
    background: var(--base);
    filter: blur(var(--blur));
/* Javascript to update value for CSS variables */
function handleUpdate(){
  const suffix = this.dataset.sizing || ''; // comes from data- html attributes
  document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);

Day 4

Today is array cardio day and we went through filter, map, sort and reduce array methods in Javascript. Wes referred to these methods as the gateway drugs to functional programming!

Result: https://repl.it/@connor11528/04-JS30-Array-Cardio-One

Relevant code:

// 1. Filter the list of inventors for those who were born in the 1500's
const fifteenhundreds = inventors.filter(function(inventor){
  return (inventor.year > 1499 && inventor.year < 1600);
// 2. Give us an array of the inventors' first and last names
const names = inventors.map(function(inventor){
  return `${inventor.first} ${inventor.last}`;
// Sum up the instances of each of these
    const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck', 'pogostick'];
const transportation = data.reduce(function(obj, item) {
   if (!obj[item]) {
      obj[item] = 0;
   return obj;
}, {});

Day 5

This one was a lot of CSS and a bit over my head. We made an image gallery with CSS Flexbox.

Day 6

Ajax type ahead. We’re using a new JS feature, the fetch method. In the lesson Wes also takes advantage of regular expressions and uses the filter method to build a real thing. I always think of regular expressions as scary and avoid them like the plague, but in this video the code is pretty easy!

Day 7

Array cardio day 2. console.table whaaat, pretty awesome. some, every, find, findIndex. Also we use splice in this episode which is a super helpful function. It’s also not to be confused with slice. At the end Wes mentions the spread ... operator. Array methods come in very handy when you’re “massaging” your data, which is a metaphor I like a lot.

Day 8

Fun with HTML5 canvas. hsl is good for manipulating colors. canvas has a lot of properties that you can manipulate. flags with events. use event information to draw on the canvas context.

Day 9

Dev tools and console tricks. Style console messages, console.table.

Day 10

Nifty feature where you can select multiple checkboxes by holding down Shift. First we need to add event listeners to the whole list of checkboxes, listening for when they get checked. When any of the checkboxes get clicked we run a function called handleCheck which will modify a global variable called lastChecked. We check if they’re holding down the shift key by checking the click event to see if e.shiftKey is true. We also need to make sure the checkbox is being checked by checking for this.checked. We want to make sure the box is being checked, not unchecked. Check?

Before the if statement, we set a local variable for the function called inBetween that’s set to false. Once in the if statement we loop through all the checkboxes and toggle the value of inBetween if we’re in between the two checkboxes that are checked.

Result: https://10-JS30-hold-shift-checkbox-checker--connor11528.repl.co

Relevant code:

let lastChecked;
function handleCheck(e) {
  // Check if they had the shift key down
  // AND check that they are checking it
  let inBetween = false;
  if (e.shiftKey && this.checked) {
    // go ahead and do what we please
    // loop over every single checkbox
    checkboxes.forEach(checkbox => {
      if (checkbox === this || checkbox === lastChecked) {
        inBetween = !inBetween;
        console.log('Starting to check them inbetween!');
if (inBetween) {
        checkbox.checked = true;
lastChecked = this;

Day 11

Custom HTML5 video player. I didn’t know the video element was so configurable. You can also listen in to Javascript events. All we need to do is select the html element and we can invoke methods on it like play and pause, as well as style the buttons and sliders of the video player.

The video is hosted by Vimeo.

Day 12

Today we built a helpful feature for detecting key input sequences. The use case is having the user type anywhere on the page but similar logic can be applied for listening to user input and taking appropriate action.

Day 13

Slide in on scroll: https://slideinonscroll--connor11528.repl.co/

Really digging the CSS magic for the course! The Javascript here determines the image positioning based on the user scroll and where we want the image. The moving the image comes from some nifty Cascading Style Sheets.

.align-left.slide-in {
  transform:translateX(-30%) scale(0.95);
.align-right.slide-in {
  transform:translateX(30%) scale(0.95);
.slide-in.active {
  transform:translateX(0%) scale(1);

Day 14

Copy objects and arrays. You can use the ES6 spread operator to clone arrays without modifying the original.

let ogArray = ['thing1', 'thing2'];
let poserArray = [...ogArray]; 

Day 15

Great learn here, use the noun project for pimp icons: https://thenounproject.com/search/

Otherwise, localStorage.setItem(key, JSON.stringify(value)) and JSON.parse(localStorage.getItem(key)) are your friends. Yes, that is the way to do it. #JavascriptFTW

Day 16


Day 17

This is a pretty nifty one. If you ever need to sort something on a webpage but you want to filter by the main word things start with, like having “The Rock” with the Rs but “The Terminator” with the Ts you can strip out articles:

const bands = ['The Rock', 'The Terminator', 'No Country For Old Men', 'An Inconvenient Truth', 'Anaconda'];
function strip(bandName) {  
  return bandName.replace(/^(a |the |an )/i, '').trim();
const sortedBands = bands.sort((a, b) => strip(a) > strip(b) ? 1 : -1);

Result: https://SortWithoutArticles--connor11528.repl.co

Day 18

Tbh I didn’t watch the video. The Javascript reduce function is pretty cool though and the map reduce pattern is super powerful so, check. it. out!

const timeNodes = Array.from(document.querySelectorAll('[data-time]'));
  const seconds = timeNodes
    .map(node => node.dataset.time)
    .map(timeCode => {
      const [mins, secs] = timeCode.split(':').map(parseFloat);
      return (mins * 60) + secs;
    .reduce((total, vidSeconds) => total + vidSeconds);

Day 19

You can ask the user permission to use their video by calling methods from the navigator object:

navigator.mediaDevices.getUserMedia({ video: true })

Funky, amiright?

Day 20

Wtf web browsers have speech recognition built in?

Using the Web Speech API

Day 21

More good icons.

navigator.geolocation.watchPosition((data) => {       
  speed.textContent = data.coords.speed;      
  arrow.style.transform = `rotate(${data.coords.heading}deg)`;    
}, (err) => {      

Function is called each time the position of a device changes.

Day 22

This will create a highlight that moves around with your mouse and attaches itself to the nearest link.

Day 24

Sticky nav! This is awesome. I’m pretty stoked about this one cause you see it with custom wordpress themes and custom sites and it always seems like it’d be such a pain in the ass to implement. Never fear, Wes Bos is here…

Demo: https://stickynav--connor11528.repl.co/

Don’t be suprised if I change all my websites to look like this one…but with more Bootstrap 3, you know, to keep it classy.

Day 26

Neat bubbling effect for hover and dropdown navigation section: https://legitdropdownnav--connor11528.repl.co/


So much cool stuff! I didn’t watch all the videos or read through every single line of code but from what I could grasp there is some pimp stuff in here. I learned way more than 30 things and am for sure going to use some of these examples for implementations in current and future projects.


Thank you Wes Bos for making an awesome course and giving it away for free.

Mozilla for the Mozilla Developer Network for the docssss 🔥 (Boring I know, but w/e that shit is super helpful)

Repl.it for hosting websites and having in browser editor where anyone can host a site. They’re dope.