DEV Community

hungle00
hungle00

Posted on

Vanilla JS Effect Methods

In the past, I worked quite a lot with jQuery and the thing I love about jQuery is that it provides many useful methods with simple and lightweight syntax. One of the most used jQuery methods is effects methods - which are used for creating animation effects for website.

For example:

  • hide() / show()
  • toggle()
  • fadeIn()
  • fadeOut()
  • ...

W3schools listed all JQuery effect methods here

But now with the growth of tons of JS libraries, jQuery seems to be out of date, and in some projects, developers must replace jQuery code with pure JS.

It's effortless to create the function act the same as hide() / show(), just edit the display style

element.style.display = 'block' // or none
Enter fullscreen mode Exit fullscreen mode

but with more complex effects like fadeIn()/fadeOut(), we need to write more code.

Another problem with the writing effect method in vanilla JS is verbose syntax. You can see that with the jQuery method:

$(".myClass").slideDown();
Enter fullscreen mode Exit fullscreen mode

It is very readable and intuitive, you find the element with jQuery selector, and then call the slideDown method as the method of the element.
The code implements the same feature in vanilla JS if you define slideToggle method before:

const element = document.querySelector(".myClass");
slideToggle(element);
Enter fullscreen mode Exit fullscreen mode

You query the element and then pass it to the slideToggle() function, it seems less native and less readable than the sample with jQuery.

The trick here is to use HTMLElement.prototype to add a method to the HTML element and you can use the effect function as a method of the HTML element. For simplicity, let's define the hide() method:

HTMLElement.prototype.hide = function() {
  this.style.display = 'none'
}

document.querySelector(".myClass").hide()
Enter fullscreen mode Exit fullscreen mode

For reuse purposes, I created some vanilla JS methods for effects here. Just put it somewhere on your codebase and use it as the native method of HTML element.

Top comments (4)

Collapse
 
edlinkiii profile image
Ed Link III

Not bad. 👍🏻

Very similar to a project I posted about five years ago.
dev.to/edlinkiii/recovering-from-j...

Mine was more focused on DOM manipulation.

Collapse
 
horaceshmorace profile image
Horace Nelson • Edited

There are several libraries that handle UI transitions and animations. Of course, unless you're using them extensively, then you should do what you're detailing here and create purpose-built functions. A few notes however:

1) It's considered an anti-pattern to add to or otherwise manipulate the prototype of native types (that is, any type built into the browser's JavaScript runtime, like Window or String or HTMLElement). In your examples in particular, adding to the prototype of all HTMLElements is not the best idea, as it adds methods to the prototypes of elements that will not need them. In the abstract, all change introduces entropy, and in practice, change only what's needed. Also, as a hard rule, don't try to directly extend the language or runtime; build libraries on top of the language or runtime. A better pattern is to maintain a wrapper object that composes the specific instance of an HTMLElement, and add the methods that object, not the element. This is, in fact, the basis for frontend component libraries like React or Vue. For instance, to add transitions to any number of HTML elements, but only HTML elements:

(note that I wrote all of this code blindly on my phone, without testing it)

async function createComponent (element) {
  this.element = element
  this.fadeIn = () => { /*add a `transition` style rule to `this.element`*/ }
  this.fadeOut = () => { /*add a `transition` style rule to `this.element`*/ }
  return this
}

const h1Element = document.querySelector('h1')
const H1Component = createComponent(h1Element)

H1Component.fadeIn()
H1Component.fadeOut()
Enter fullscreen mode Exit fullscreen mode

2) You should observe a "separation of concerns" and use CSS classes rather than creating all of your styles in JavaScript. It'll keep your JS focused on logic and not muddled with styling.

transitions.css

.fadeIn {
  /* style rules here */
}

.fadeOut {
  /* style rules here */
}

Enter fullscreen mode Exit fullscreen mode

constants.js

const CSS_CLASS_FADE_IN = 'fadeIn'
const CSS_CLASS_FADE_OUT = 'fadeOut'
Enter fullscreen mode Exit fullscreen mode

createComponent.js

/** Not a production-ready example, as you'd want to
  * add the class to any existing `.className` value,
  * ensuring that it's only added once, and probably
  * remove certain other classes you've added.
  */

async function createComponent (element) {
  this.element = element
  this.fadeIn = () => { this.element.className = CSS_CLASS_FADE_IN }
  this.fadeOut = () => { this.element.className = CSS_CLASS_FADE_OUT }
  return this
}

const h1Element = document.querySelector('h1')
const H1Component = createComponent(h1Element)

H1Component.fadeIn()
H1Component.fadeOut()
Enter fullscreen mode Exit fullscreen mode

And note that you don't need to use requestAnimation frame as CSS has built-in and much more performant support for transitions and animation.

Collapse
 
hungle00 profile image
hungle00

thanks for your comments, it's truly better than my code. I will try to rewrite code based on your suggestion

Collapse
 
horaceshmorace profile image
Horace Nelson

Feel free to DM if you have any questions or run into any problems.