How I’d Learn Front End Web Development Now

When I started out with doing web stuff in 1999, things were very different, much simpler in some ways but much harder in others. So, the way I gradually learnt was quite different from how somebody would learn now.

Back in my day…

Don’t yawn, there is a point to this. In 1999 when I started learning this stuff, there was only HTML, CSS and JavaScript. No TypeScript, no Sass, no real frameworks to speak of, no packages, no build tools. You get the picture.

So, there was a lot less to learn but learning was harder. There wasn’t great documentation online, or, at least, not easy to find, so I used books. Cross browser compatibility was hard.

In short, it’s a completely different landscape now. So, I thought it would be interesting to think about how I would learn or advise others to learn if starting out now.

The basics

The basics are still the basics. HTML, CSS and JavaScript are the technologies used by web browsers. That hasn’t changed in all this time and it’s not likely to change any time soon. While trends will come and go a good understanding of these three areas will always be time well spent.

Accessibility

This is a critical area that is often overlooked. The web is a universal platform that should be for everyone, not just for those with good eyesight, expensive devices and fast networks. We need to consider how we deliver content that works for all.

It’s definitely worth learning this from the beginning so things are done in the right way as it’s harder to correct bad habits later. Being able to demonstrate an understanding of accessibility will put you ahead of other candidates who have skipped over it when it comes to job hunting.

Go deep

Going further, I’d say it’s worth exploring these HTML, CSS and JavaScript in some depth before moving on. I think it’s worth skimming through everything on them at pace without worrying about retaining too much. This could be either a course or just working through documentation. Just becoming familiar with what features there are and some terminology will help you understand more conversations and documentation, as well as know what to search for when the time comes to use them. Nobody can remember it all and even experienced developers have to look up syntax. That’s not generally what an employer would expect, it’s more about the broad understanding of how you can use features to solve problems.

Responsive design

It’s rare these days that we can create a web page that will be for a single screen size, so we need to know how to make a user interface that looks good on a big desktop screen and a phone. This is a whole area that is again worth tackling fairly early on. It’s a bit of an art, a collection of techniques and tricks that are not easy to discover. This is an area that would probably benefit from a course.

Source control and package management

Once you’ve got enough of the basics to make something amazing, you’ll naturally want to share it with the world, and then you’ll want to make use of your amazing thing or other people’s in your future projects.

Source control is about publishing code but also collaboration – reviewing each other’s code, branching out and merging it back together. The most commonly used system for this is probably git. Worth reading up on.

Package management is about bundling up your project into a package that can be easily exported and then imported into other projects. The most common platform for front end code is npm.

These two areas usually involve using the command line, a terminal where you type commands to make things happen. It’s not as scary as it looks and makes you look like a proper hacker to those not in the know.

Frameworks

Probably later than some would expect, but I genuinely feel the other things are more important to get good longer term. If you learn a framework too early their way of doing things becomes your normal and then if you change framework you have to start again. If you understand the core technologies then you can see what the framework is giving you and can adjust more easily.

CSS frameworks can be very useful for providing ready-made styling, bringing consistency and the CSS is well structured. It’s a good way of learning how to structure your own CSS for larger projects.

JavaScript frameworks like React, Vue or Angular take some investment to learn but it is paid off in terms of faster development down the line.

There are also UI frameworks and design systems which provide complete components ready to use.

With all of these frameworks, there’s lots of time saving and knowledge to be gained but it’s important to remember that these are just someone’s opinion and one way of doing things. There is no single right way or best way.

Extending the basics with pre-compilation

I’d say that’s probably everything you need but there are a couple of other bits that are cheap to learn so worth throwing in there – more skills to boast about can’t hurt.

Sass is a superset of CSS – it’s CSS with added bells and whistles. You write in .scss files, making use of the fancy additional features and then it gets compiled to normal CSS. The great part is that it’s additional features, not a different language so CSS is valid Sass. You can start out with a .scss file, just write normal CSS and it gets compiled to CSS. It’s a bit pointless but means you can start off with nothing and then gradually learn and use Sass one feature at a time. It’s a nice easy learning curve.

It’s the same idea with TypeScript. This is enhanced JavaScript so you can write in .ts files and get JavaScript, learning the new features as you go.

With both of these, once you get into the new features you’ll never go back.

Then, anything goes

Once you’ve got these skills, it’s really an open playing field. You can learn whatever takes your interest, or maybe whatever your job needs.

Let me know if you’d do things differently.

The Dangers of Logic in CSS

We can do a lot of logic in CSS. I’m thinking specifically of scenarios which take the form “if this, then that”.

There are media queries which will let us control the appearance of elements based on a variety of factors. Probably the most common is screen width, so we get things like “if the width is 1024px or higher, then show an extra element”.

There are pseudo selectors like :empty, :checked, :valid, :disabled which let us control appearance based on state, giving us, for example, “if the parent element has no children (:empty), then change its opacity”.

We can also do logic based on combinations of elements or selectors, like li + li, for example, “if the list item follows another list item, then give it a top border.”

I’m sure there are plenty more ways of applying logic but you get the idea. Each of these is equivalent to writing a conditional statement in a programming language – if this, then that.

The big question is, should we be doing this in CSS, and is there a point at which it becomes too difficult to manage in CSS and we need to defer to another technology, like JavaScript?

My Experience

I started thinking about this when I was designing a UI with a lot of logic going on. We had a busy table where we show some additional columns at wider screen resolutions. At smaller widths the user would be able to toggle between different groups of columns and save a preference. But then these additional columns are only offered if they contain data. So, we had logic around the screen width, user preference and presence of data, which, multiplied out, meant 8 permutations.

I initially tried to do it all with CSS. I set up media queries for the narrower and wider screen widths. Within each of these I then read a class for the user preference and then I used :empty to see if table cells contained any data. I managed it and it worked. Just.

However, I realised that it was really not scalable. Every time I added a new condition it doubled the amount of CSS I was having to write. If we wanted to add more logic in future it would create more and more work and be harder and harder to maintain.

By moving all the logic into JavaScript we can set simpler classes, one for each type of display we need rather than every permutation of logic. So now we just have 3 classes: 1) show the first set of columns, 2) show the second set or 3) show all columns.

We still have lots of branches in our JavaScript but the big difference is that it’s easy to read and follow. It’s also easy to edit or extend if we ever need to.

I think doing some logic with CSS is fine but as soon as you’re starting to layer it on and find yourself multiplying out the selectors you’re writing it’s probably time to move it over to JavaScript.

Clicking Off Things to Close Them

There’s a common design pattern these days where a bit of content is shown over the main screen. It might be a modal window or maybe a fly-in menu or sidebar. It’s also common, especially in native apps, that we can just click or tap in the space not used by these elements to close them. So, how can we do this?

I think there are 2 approaches, one which is pure JavaScript and another which involves an overlay element. Let’s look at both.

JavaScript Document Click Event Method

We can detect that a click is not on the content element using JavaScript. As all click events bubble up or propagate through the DOM tree they eventually reach the top document level. We can listen for a click on the document and then use the event target to check what was clicked. For this example let’s assume our content element has a class of ‘modal’, like <div class=”modal”></div>.

// JavaScript

function handleClick(event) {
  if (!event.target.closest('.modal')) {
    console.log('close');
  }
}

document.addEventListener('click', handleClick);

event.target gets the element that was clicked. This could be the modal element itself, another element inside it or another element outside of it. event.target.closest(‘.modal’) checks if the element clicked is the modal or is an antecedent of the modal element, an element within it. If the element clicked is not (!) in the modal we can close it.

It’s maybe worth noting that .closest() doesn’t work in IE11 if you need to support this but there is a polyfill available.

Using an Overlay Element

The other approach, and the one I tend to use, is to use an overlay element. This means adding an element that covers the whole screen area, slipped in between the modal and the main screen content. The idea is that this overlay will appear and disappear along with the modal and will pick up any click events which are not on the modal. It’s a bit like a safety net that will catch any stray clicks.

The CSS for the overlay would typically look something like this:

/* CSS */

.overlay {
  background-color:#000;
  bottom:0;
  left:0;
  opacity:.5;
  position:fixed;
  right:0;
  top:0;
  z-index:1;
}

.modal {
  /* styling */
  z-index:2;
}

The overlay has fixed display and goes to each edge so it fills the screen.

The overlay has z-index set to 1 so it’s over the main screen content, and the modal has it set to 2 so it’s over the overlay. These can increase as needed but the modal always needs to be higher.

I’ve given the overlay a background colour and 50% (.5) opacity so that it veils the main screen content underneath giving the modal a “lightbox” effect but these are not needed and our overlay can be effectively invisible.

You then just add a click event to the overlay which will close the modal and hide the overlay.

The reason I like this approach is that by covering the main screen we prevent any interactions with it. If the user tries to click on a button under the overlay their first click will just close the modal. We don’t need to worry about any other interactions – while the modal is showing it becomes the sole focus.

Extra tip. If you use a visible overlay it’s nicer not to show and hide it immediately but fade it in and out with a transition on the opacity, taking it between 0 and .5. This feels much smoother and less jerky.

Hiding UI Elements

At the start of March 2019 I ran a poll on Twitter to see how devs hide UI elements. Here’s the tweet and results.

50% CSS "display:none",5% HTML "hidden" attribute,27% JS framework state,18% Something else

Admittedly, not a very scientific sample size but it was enough to confirm my suspicion that very few people use the “hidden” attribute. I should probably call it a property rather than an attribute as it’s a Boolean and acts in a similar way to “disabled” or “required” which we often use on form elements. And, by contrast, the most common method seems to be to use the CSS “display:none”. Probably no great surprise to anyone.

I think it’s interesting to think about what we’re really doing when we hide an element. Is the visibility of the element just for screen users or for all users? Do we still want the element available for non visual media? Or is the content going to be used by another part of the page in some way? Does it need to be in the DOM at all or are we just keeping it there because it’s easier?

If we use JavaScript, either native or a framework, we can insert and remove elements as needed based on logic. If it’s playing no part in our document why not just leave it out altogether? This keeps the DOM light and performant and easier to work with. If you’re working with something like automated testing you can check for an element’s existence rather than trying to figure out if it’s visible or not.

If we use CSS to hide an element and respect the separation of concerns principle then are we saying that hiding this element is a presentational choice rather than a semantic one? Maybe we are hiding it, maybe temporarily, rather than denying its existence?

In the case where we want an element to be hidden in one medium and shown in another, CSS feels like the right choice. Whilst “display:none” and “visibility:hidden” are valid, other techniques like “height:0”, “opacity:0” or “left:9999px” feel very unclear in their intentions and too focused on the visual user.

The HTML “hidden” property is a more semantic choice. It is stating that this element is not to be considered when reading the document, whether that be on screen or via assistive technologies. It is about more than visibility and is probably badly named. Maybe “ignore” would have been more fitting? It is more about the state of the element and closer in meaning to the input[type=hidden] that we used to see in the days before Ajax.

If you take away the JavaScript and CSS – maybe some network issues, maybe the HTML gets copied elsewhere – the element stays hidden. The point is that it’s meant to be hidden, it’s not styling.

The “hidden” property is also easy to work with and change in JavaScript. In fact, it’s easier than using a CSS class as you don’t have to write any CSS and you know it will work regardless.

<p class="disclaimer" hidden>This is a disclaimer</p>

<script>
  const disclaimer = document.querySelector('.disclaimer');
  function showDisclaimer() {
    // with a CSS class
    disclaimer.classList.add('show');
    // with the hidden property
    disclaimer.hidden = false;
  }
</script>

Think about why your content is hidden and how it may be reused and choose the most appropriate method of hiding it (or removing it).

To DOM or Not to DOM?

I’m trying to work out when it’s best to put attributes in the DOM and when it’s best to just leave them in JavaScript objects. This is going to be hard to explain so bear with me.

Let’s suppose we have a list of users on a page. Each user has a number of properties, not things we’d display like name, age and gender but hidden things like permissions, e.g. isAdmin, canComment, isManager, etc. These properties are going to be used in logic to determine how things are displayed on screen – maybe an extra bit of detail or an icon. Just as an example, if canComment is true then a speech bubble icon will appear.

The basic HTML might look something like this:

<ul>
  <li id="001" class="user">John</li>
  <li id="002" class="user">Paul</li>
  <li id="003" class="user">George</li>
</ul>

Behind this is a JavaScript object, like this:

var users = [
  {
    id: '001',
    name: 'John',
    canComment: true
  },
  {
    id: '002',
    name: 'Paul',
    canComment: false
  },
  {
    id: '003',
    name: 'George',
    canComment: false
  }
];

So, user John is allowed to comment and we want to show an icon. There are 2 approaches:

  1. Use the DOM

    We could add the icon inside each <li> and then add a class (class=”user can-edit”) or a data-attribute (data-can-edit) to the <li> and use CSS to display it as appropriate, e.g. .user[data-can-edit] .icon { display: inline-block }.

  2. Use JavaScript

    Or, we could write a JavaScript function to filter the objects to just those with canComment set to true, get their ids, and then loop through the list items adding the icon HTML when the ids match the filtered list.

The first approach puts the property into the DOM, puts the icon into the DOM and then uses CSS to show/hide it. It feels easy. The icon is always sat there waiting, like an unchecked checkbox, only shown when needed (checked). There is still logic but it’s done up front. The DOM is actually human readable and it’s easy to see which users can and can’t edit for debugging purposes. I see this approach used a lot, including the hidden DOM elements, usually because of the way templates or components are used. It’s easier to include it and pass a property to toggle whether or not it displays. It also means that if we want to change the property during the lifecycle of the page, e.g. take away John’s commenting permission, it’s minimal change to the DOM.

The second approach only touches the DOM to insert the icon where needed. It does all the logic in JavaScript and the output in the DOM reflects what the user actually sees on screen. There are no hidden elements. This has advantages when it’s scaled up, in that it keeps the DOM lighter and there’s no waste. The JavaScript is incredibly fast in modern browsers so the functions won’t slow anything down, especially if using .filter(), map(), etc. The trick here is not to loop through and add the icons one at a time but to run through building the whole list and just doing the one insert or replace operation. This makes the DOM less readable as all the canComment data is in JavaScript.

So, is it better to use the DOM for data or keep it in JavaScript?