DEV Community

Cover image for JavaScript Should Be Your Last Resort
Olavi Haapala
Olavi Haapala

Posted on • Originally published at olavihaapala.fi on

JavaScript Should Be Your Last Resort

JS Is Your Hammer

When working on modern frontend web development, using your favorite framework of choice, it can be sometimes tempting to solve all the problems with JavaScript. Sometimes this happens unconsciously as JS is what you mostly use in your day-to-day development work.

This is similar to the situation described by Abraham Maslow in 1966:

I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.

Wikipedia: Law of the instrument

Photo of a hammer about to hit some nails

Photo by Fausto Marqués on Unsplash

Note: In this blog post, I’m only talking about JS even though I’m mostly using TS in my projects – it ends up as JS after compilation anyways.

What to Take into Account When Implementing UI

This mindset of using JS for everything causes unnecessary processing that needs to be run on your end users’ devices as client-side JS. All the JS resources on a website need to be downloaded, parsed and executed by the web browser. This is quite often the cause of slow and unresponsive websites on low-end mobile devices or slow network speeds.

How You Should Be Thinking Instead:

  1. Can this be done in HTML?
  2. If not, can I solve it with HTML + CSS?
  3. And if nothing else works, the solution probably requires a minimal amount of JS in addition to HTML and CSS

This way of thinking is not about what is easiest for you as a developer. You may be a JavaScript focused frontend developer, and solving most of your problems with it feels natural for you. However, you should be thinking about your end users. Client-side JS is the single biggest problem when it comes to web performance. You can read some of my thoughts on web performance from my other blog posts. You can find some links at the bottom of this blog post on my personal blog.

1. Can This Be Done in HTML?

Plan and implement the basic structure and semantics of the feature in plain HTML without any extra styles and using native HTML elements and functionality. If some additional styling or features are needed, go to step 2.

2. Try to Solve It with HTML + CSS

Use CSS to apply the additional styling or animation that is required, still keeping the semantics and accessibility in my mind. If some additional interactivity is required in the particular piece of UI you are building, go to step 3.

3. Use HTML + CSS + JS

Add the minimum amount of JS required to fulfill the requirements. Keep in mind that something that can be solved without JS should probably be solved without JS.

When you’re done, show your code to your colleagues and let them review it. Perhaps there is still something unnecessary parts in your code, that could be solved without having a client-side JS cost for your users.

Simple Example

This problem applies to almost anything in web frontend development, but here is a simple practical example that should help me prove my point.

Imagine you are working on a React project, and you are working on a feature that has some UI parts that should only become visible after a certain delay, let’s say after 2s.

Using React Hooks

If you are used to solving your problems with React and Hooks, your initial solution could look something like this:

const [thingVisible, setThingVisible] = useState(false);

useEffect(() => {
  const timeoutId = setTimeout(() => {
    setThingVisible(true);
  }, 2000);

  return function cleanup() {
    clearTimeout(timeoutId);
  };
}, []);

return thingVisible ? <section>Here's a thing for you!</section> : null;

Enter fullscreen mode Exit fullscreen mode

This is fine and works. Probably you notice no difference in performance either on your hyper powerful developer machine. And probably, there is no real performance issue in this case. But imagine if these pile up and suddenly you would have tens or hundreds of similar unnecessary JS computations to be run on the client-side or some larger and longer executions that are taking place.

Using HTML + CSS Animation

Using CSS, you can animate content to appear on the page with a delay using CSS animations and animation-delay. This is supported by all browsers and could even have a better end user experience as you could fade the content in or use any other ways of making the content appear more smoothly.

The HTML:

<section class="fade-in">Here's a thing for you!</section>

Enter fullscreen mode Exit fullscreen mode

The CSS:

.fade-in {
  opacity: 0;
  animation: fadeIn 2s;
  animation-delay: 2s;
  animation-fill-mode: forwards;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

Enter fullscreen mode Exit fullscreen mode

Don’t Use CSS for What You Can Do with HTML

Similarly, don’t do something with CSS that you could and should be doing in HTML.

An extreme example of this was that we had accidentally been using margins to separate two words from each other, instead of using a space in between the words!

This was obviously not a good idea from at least the following perspectives:

  • It might not follow the font size, letter spacing etc.
  • It is not needed, waste of effort and processing
  • If someone would need to copy the text, there would be no space in between the words

Frontend Development Is Not Easy

Web frontend development is not an easy topic to master. It is something you can get started with quite rapidly, but mastering it requires some level of experience and understanding the whole picture in order to be able to solve the right problems on the right level using the right tools. Solving something on the frontend has many levels and details baked in it.

Additionally, you’ll need to understand when a problem should be solved on the backend instead of the frontend for various reasons such as performance, usability or maintainability among others.

However, keep in mind that sometimes you don’t need to try to reach for a perfect solution and something that works might be good enough to be shipped to production and to be used by your end users.

Latest comments (120)

Collapse
 
jdnichollsc profile image
J.D Nicholls

In some cases, you have more control with JS, example with animations: github.com/proyecto26/animatable-c...
And if you use that as a web component, it's easier to use for Designers and Developers :)

Collapse
 
aarone4 profile image
Aaron Reese

Not mentioned in 115 comments is the cost of reshaping API data in js. Pulling down more records than are practically required, or more fields, or having to nest related items (e.g. customer.order.item) using .map.filter is computational cost better suited to the server or data store layers. GraphQLcan help but it is often worth re-specifying the API response or implementing partial datasets and a fetch-ahead policy to prevent UX delays on progressing down the list.
An example of this is Jobserve.co.uk where they prefetch the next 20 jobs in the list; if you scroll quickly you can catch it out.

Collapse
 
nicozerpa profile image
Nico Zerpa (he/him)

Great article Olavi! Yeah, JavaScript is fantastic, but if you overuse it, it's worse for the end-user, in terms of performance but also accessibility.

If you reimplement in JavaScript or React something that HTML alone already does, you'll probably break something and the element is no longer accessible. Don't reinvent the wheel.

Collapse
 
kylewcode profile image
Kyle Williams

Awesome advice. I'm in the process of learning React so I've been biased towards using React to solve all the problems in the apps I am creating.

Collapse
 
barelyhuman profile image
Reaper

I realised this last year, got into learning other languages that I could randomly switch to.
Got into Go and have been building simple template based websites while avoiding as much JS as I can just for a change.

A recent project was
commitlog-web
source

I did write a bit on a similar topic but that involves a few controvertial statements but if anyone would like to go through it.

reaper.im/blog/06012020-Getting-be...

Collapse
 
tccodez profile image
Tim Carey

JS sucks I am all for using less of it

Collapse
 
eelstork profile image
Tea

Totally agree there is a big world outside your browser.
Okay okay. Joke : )

Collapse
 
andreidascalu profile image
Andrei Dascalu

"This way of thinking is not about what is easiest for you as a developer" - ok, but this is what makes it a losing way.
All other things being equal with respect to the outcome given business requirements, things should go with what's easiest for a developer.
Easiest for a developer (as long as architecture is respected) translates into quicker time to market and lower development costs. Long term costs should be addressed by architecture and other business constraints (such as hiring market, other costs, etc).
Unless there's a significant impact to the end result for that business requirement, I see no reason to go against a developers toolset.

Collapse
 
olpeh profile image
Olavi Haapala

But you should always consider the cost from the end-user point-of-view. Think about accessibility or browser support for example. It's not fun or easy for you as a developer, but it makes it possible for your (possibly paying) users to use your service!

Collapse
 
andreidascalu profile image
Andrei Dascalu

I disagree. You don't. That's a business decision that depends on how the product was defined to target and support. What you (eg: developer / architect) should do is present the options and constraints to business to make a decision.
Doing in this way means a certain time-to-market and development costs but it may leave out or otherwise impact users.
Doing it the other way may come with extra costs in terms of development but may results in other advantages.
Middle way: we could start one way but there may be extra overhead to design it in a way that allows a reasonable time to change later on.
Then the business decides. It's perfectly reasonable to knowingly limit browser support for example if it's cost effective to market earlier. It's not a development decision.

Collapse
 
jmarshall9120 profile image
jmarshall9120 • Edited

"Client-side JS is the single biggest problem when it comes to web performance" - why do you think this?

Collapse
 
olpeh profile image
Olavi Haapala

Hey, thanks for the question! I in fact forgot to mention where I got this idea from. It's from Steve Souders' keynote at performance.now() conf in 2018.

Direct quote actually is:

JavaScript is the biggest problem for web performance today.

You can watch the talk here:
youtube.com/watch?v=RwSlubTBnew

Collapse
 
russellbateman profile image
Russell Bateman

Terve ! Interesting article and, on the surface, I agree with much you have said though I'm a backend (Java) guy--not a frontend guy and deserve no voice here. However, I have been doing HTML and CSS for a couple of decades, I do almost zero JS.

Collapse
 
bvandenbon profile image
Bram Vandenbon • Edited

You can set font and font-size, alignment and borders in HTML, and it's a really bad idea. (not to mention poorly supported ones like blink) So, "don't use CSS for what you can do in HTML" is a really incomplete statement.
HTML should be about structure, CSS about styling. Don't try to style with HTML.

Collapse
 
djpandab profile image
Stephen Smith

Hi. I would a link to your book mentioned in the comments. I follow the author. Thanks.

Collapse
 
raddevus profile image
raddevus

I sent you the link via Chat.

Collapse
 
pozda profile image
Ivan Pozderac

I see what you did there!

Working with SPAs, PWAs and hybrid apps I cannot escape using JS/TS, but you have valid point there. For a static site there are several approaches but the one I like the most is the idea and concept behind 11ty as its output is as 'pure' as it can be.

Never do things with JS if you can do it with CSS - that's both sane decision as well as using technologies the way they are intended to be used.

Also, I would add -> use HTML tags as they should be used, div is okay, but too many apps and pages are suffering from div-itis.

Collapse
 
ojrask profile image
Otto Rask

PWA can be a regular HTML + CSS + req/res looped website with just the service worker thing installing the PWA, no need to go "all in" with JS/TS there either.

Collapse
 
pozda profile image
Ivan Pozderac

I totally agree that you should strip everything you don't need and that mostly depends from project to project. PWAs I was working on were mostly data driven apps and were interactive. Can't have real time graph without at least some JS on client considering there was no SSR mechanism included.

Collapse
 
olpeh profile image
Olavi Haapala

Yeah, totally agree, but can't fit everything in one post. I could write another post about the importance of semantic HTML.

Meanwhile you can read this amazing post by my colleague Eevis: dev.to/eevajonnapanula/ode-to-sema...

Collapse
 
erebos-manannan profile image
Erebos Manannán

The worst thing is how often JavaScript developers reinvent the wheel and break accessibility, common shortcuts such as Ctrl+Clicking or middle-clicking on links to open things in a new tab because the navigation is implemented as onclick handlers instead of <a href="">, or really the worst common issue is making your custom dropdown which does not support the same keyboard selection as a normal dropdown does. Why? So it looks marginally better?

Collapse
 
olpeh profile image
Olavi Haapala

I generally think there's nothing wrong with the browser default styles for input elements. Why can't we often stick with those and avoid wasting time re-inventing the wheel?

Collapse
 
zenwork profile image
Florian Hehlen

Reading the first sentence I thought this was going to be a framework v. vanilla article and was ready to be critical! Having read through I couldn't agree more. But I would go further and say that you don't have to use React if some simple vanilla JS will do.

Collapse
 
olpeh profile image
Olavi Haapala

Thanks! Yeah, I agree. But this was based on my current project(s) where React is used, and that won't change in the near future. It's easier to change how you use the framework instead of rewriting everything. Also, it's good to keep in mind the actual impact on the end users.
There are even solutions that use React on the server, but have no runtime JS – so the end users don't get punished for your choice of framework.

Collapse
 
zenwork profile image
Florian Hehlen

I have had to do a lot of React lately. I think there is also some arguments to be made about how much you use it. For example there is a tendency to break everything down into micro components which gets excessive. I think the functional and stateless dogma leads often to heavy to execute and unreadable code.... which is funny because that is exactly what React wants to solve.

Thread Thread
 
olpeh profile image
Olavi Haapala

I think this is also a problem that is not React specific. This problem will occur in every project that grows large enough.

Thread Thread
 
zenwork profile image
Florian Hehlen

For sure! I have seen this in other languages and with all sorts of frameworks over the years. It is very tempting as a developer to look at any DX improvement as an improvement for the universe.