In frameworks like Angular 2 or React, you'll never manipulate the Document Object Model directly : you'll use their own templating systems, so the framework can manage automatic data binding and optimize performances.
But these templating systems are modeled on native DOM. So it helps to have good basics, to know what you can do and what's going on.
You'll find other guides and a general explanation here. We strongly recommend to read HTML5 CSS3 essentials for JavaScript first, as the DOM is about manipulating HTML and CSS.
DOM selection
Most of the time, you'll just pick one element. It's the most effective way.
let someElement = document.getElementById('some-id');
For multiple or complex selection, you can use CSS selectors you (should) already know. Then you'll need to do a loop on each element.
let someElements = document.querySelectorAll('#nav-list>li');
for (let element of someElements) {}
Sometimes you'll already be somewhere in the DOM, and you'll need to navigate up or down the tree.
Do not use childNodes
, firstChild
and lastChild
, they will lead to troubles.
someElement.parentNode;
someElement.children[0];
DOM content : HTML manipulation
Main thing you'll do is to read or modifiy the content of an element. You can change it like raw text (when possible, it's better for performance and security) or like HTML content.
someElement.textContent; // Read
someElement.textContent = "New content"; // Write
someElement.innerHTML; // Read
someElement.innerHTML = "New content"; // Write
DOM elements are objects, so HTML attributes are just properties in JavaScript and you can access them directly. For example :
someInputElement.value; // Read
someInputElement.value = "New value"; // Write
HTML5 allows you to store data in your own custom attributes. They need to start with
data-
and JavaScript has a special property for them.
Be careful with the difference of naming convention.
<p data-custom-name="Some value"></p>
myParagraphElement.dataset.customName; // Read myParagraphElement.dataset.customName = "New value"; // Write
DOM styles : CSS manipulation
The most direct way to modify CSS is to access the style property. Be careful with the difference of naming convention. It's OK for a functional modification (like moving an element), but never do that for a graphic modification : graphics belong to CSS.
someElement.style.marginLeft = '100px';
For graphics, manipulate classes. Do not use class
(it does not exist, it is a reserved keyword for another feature) or
className
as it would delete potentials other existing classes.
someElement.classList.add('color-main');
someElement.classList.remove('color-main');
someElement.classList.toggle('color-main');
someElement.classList.contains('color-main');
Notice we didn't try to read current styles. It's not relevant,
except for a few special properties : offsetWidth
, offsetHeight
,
offsetTop
, offsetLeft
.
DOM animations
The easy way : CSS3 transitions,
with the transitionend
event to know when it's finished.
Sometimes you'll need to manage some part of animations manually, with timers. Do use the new ES6 arrow function syntax, or it will lead to troubles. Times are always in milliseconds in JavaScript.
let differed = setTimeout(() => {
// Some styles manipulation
}, 2000);
If necessary, you can stop a timer with clearTimeout(differed)
.
Be aware it is asynchronous, as mostly everything in JavaScript. It means JS does not wait 2 seconds to continue the script. So be careful to where your next action should be placed.
DOM events
Do not you use the old properties like onclick
,
onmouseover
and so on, as you can only manage one listener with them.
And with vanilla JavaScript, never do inline events in HTML,
they can be forbidden by a new security option in HTML5 called
Content Security Policy
(frameworks will allow that but only because it's part
of their templating system, which is then transformed).
someElement.addEventListener('click', (event) => {
// Some action
});
Main events are : click
, mouseenter
,
mouseleave
, input
, keyup
,
submit
, focus
, blur
.
You do not need touch events for normal situations, as a touch on a link fires a
click
event too.
Be aware all DOM manipulations are only possible if the elements are loaded. So you should always
wait the DOM is ready. Do not use the load
event as it waits for full
ressources loading which is really too late. Be careful with the naming syntax.
document.addEventListener('DOMContentLoaded', (event) => {
// Launch all your features
});
You'll receive an event
object as parameter, with information dependent on
what's going on (mouse position, key pressed...). You'll always know from what element
the event started with :
someElement.addEventListener('click', (event) => {
event.target;
});
Last but not least, you can cancel the default behavior of the event. For example, prevent a click on a link to redirect to the target page. It's very important for 2 reasons : on normal websites, main features (navigation...) should keep default behaviors which don't need JavaScript for many situations (SEO, accessibility, slow network, overloaded server, unforeseen error...) and in an app, the page must never change.
someElement.addEventListener('click', (event) => {
event.preventDefault();
});