How to insert an element after another element in JavaScript without using a library?
Solution 1
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
Where referenceNode
is the node you want to put newNode
after. If referenceNode
is the last child within its parent element, that's fine, because referenceNode.nextSibling
will be null
and insertBefore
handles that case by adding to the end of the list.
So:
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
You can test it using the following snippet:
function insertAfter(referenceNode, newNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
var el = document.createElement("span");
el.innerHTML = "test";
var div = document.getElementById("foo");
insertAfter(div, el);
<div id="foo">Hello</div>
Solution 2
Straightforward JavaScript Would Be the Following:
Append Before:
element.parentNode.insertBefore(newElement, element);
Append After:
element.parentNode.insertBefore(newElement, element.nextSibling);
But, Toss Some Prototypes In There For Ease of Use
By building the following prototypes, you will be able to call these function directly from newly created elements.
newElement.appendBefore(element);
newElement.appendAfter(element);
.appendBefore(element) Prototype
Element.prototype.appendBefore = function (element) {
element.parentNode.insertBefore(this, element);
},false;
.appendAfter(element) Prototype
Element.prototype.appendAfter = function (element) {
element.parentNode.insertBefore(this, element.nextSibling);
},false;
And, To See It All In Action, Run the Following Code Snippet
/* Adds Element BEFORE NeighborElement */
Element.prototype.appendBefore = function(element) {
element.parentNode.insertBefore(this, element);
}, false;
/* Adds Element AFTER NeighborElement */
Element.prototype.appendAfter = function(element) {
element.parentNode.insertBefore(this, element.nextSibling);
}, false;
/* Typical Creation and Setup A New Orphaned Element Object */
var NewElement = document.createElement('div');
NewElement.innerHTML = 'New Element';
NewElement.id = 'NewElement';
/* Add NewElement BEFORE -OR- AFTER Using the Aforementioned Prototypes */
NewElement.appendAfter(document.getElementById('Neighbor2'));
div {
text-align: center;
}
#Neighborhood {
color: brown;
}
#NewElement {
color: green;
}
<div id="Neighborhood">
<div id="Neighbor1">Neighbor 1</div>
<div id="Neighbor2">Neighbor 2</div>
<div id="Neighbor3">Neighbor 3</div>
</div>
Solution 3
Though insertBefore() is great and referenced by most answers here. For added flexibility, and to be a little more explicit, you can use:
The insertAdjacentElement() as refElem.insertAdjacentElement(position, newElem)
lets you reference any element, and insert the to-be moved element exactly where you want (position can be one of: 'beforebegin'
, 'afterbegin'
, 'beforeend'
, 'afterend'
) as shown below:
// refElem.insertAdjacentElement('beforebegin', myElem);
<p id="refElem">
// refElem.insertAdjacentElement('afterbegin', myElem);
... content ...
// refElem.insertAdjacentElement('beforeend', myElem);
</p>
// refElem.insertAdjacentElement('afterend', myElem);
Others to consider for similar use cases: insertAdjacentHTML()
and insertAdjacentText()
References:
https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentText
Solution 4
insertAdjacentHTML
+ outerHTML
elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)
Upsides:
- DRYer: you don't have to store the before node in a variable and use it twice. If you rename the variable, on less occurrence to modify.
- golfs better than the
insertBefore
(break even if the existing node variable name is 3 chars long)
Downsides:
- lower browser support since newer: https://caniuse.com/#feat=insert-adjacent
- will lose properties of the element such as events because
outerHTML
converts the element to a string. We need it becauseinsertAdjacentHTML
adds content from strings rather than elements.
Solution 5
2018 Solution (Bad Practice, go to 2020)
I know this question is Ancient, but for any future users, heres a modified prototype. This is just a polyfill for the .insertAfter function that doesnt exist. This prototype directly adds the function HTMLElement.insertAfter(element);
to the HTMLElement Prototype:
// Parent
const el = document.body;
// New Element
const newEl = document.createElement("div");
// Custom Method
Element.prototype.insertAfter = function(new) {
this.parentNode.insertBefore(new, this.nextSibling);
}
// Insert Before Element
el.insertBefore(newEl)
// Insert After Element
el.insertAfter(newEl);
// Just remember you cant use .insertAfter() or .insertBefore()
// after either is already called.
// You cant place one element in two places at once.
2019 Solution (Ugly / Outdated, go to 2020)
Don't use prototypes (Like the 2018 Solution). Overwriting the prototype is both dangerous, and low quality. If you want a new method, use Function Overrides Instead.
If you want a safe function for commercial projects, just use a default function. its not as pretty but it works:
// Parent
const el = document.body;
// New Element
const newEl = document.createElement("div");
// Function You Need
function insertAfter(el0, el1) {
el0.parentNode.insertBefore(el1, el0.nextSibling);
}
// Insert Before Element
el.insertBefore(newEl);
// Insert After Element
insertAfter(el, newEl);
// Just remember you cant use insertAfter() or .insertBefore()
// after either is already called.
// You cant place one element in two places at once.
2020 Solution - ChildNode
Current Web Standards for ChildNode: MDN Docs - ChildNode
Its currently in the Living Standards and is safe to use.
For unsupported browsers (Such as IE), use this Polyfill: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js
I realize the polyfill uses Proto Overrides, when I said they were bad practice. They are, especially when they are used blindly, like with my first solution. However, the polyfill on the MDN Documentation uses a form of initialization and execution that is much more reliable and safe compared to just overwriting a prototype.
How to use ChildNode:
// Parent
const el = document.body;
// New Element
const newEl = document.createElement("div");
// Insert Before Element
el.before(newEl);
// Insert After Element
el.after(newEl);
// Just remember you cant use .after() or .before()
// after either is already called.
// You cant place one element in two places at once.
// Another feature of ChildNode is the .remove() method,
// which deletes the element from the DOM
el.remove();
newEl.remove();
Xah Lee
Effete functional hotshot, armature mathematician. I write programing tutorials as hobby. Please see • JavaScript in Depth • Practical Emacs Lisp • math. Visual Dictionary of Special Plane Curves
Updated on July 15, 2022Comments
-
Xah Lee almost 2 years
There's
insertBefore()
in JavaScript, but how can I insert an element after another element without using jQuery or another library? -
James Long over 10 yearsFor anyone who stumbles upon this script, I don't recommend using it. It attempts to solve problems that @karim79's native solution already solves. His script is faster and more efficient - I'd strongly recommend using that script instead of this one.
-
GijsjanB over 10 yearsThanks for a great answer, but isn't it confusing to flip referenceNode and newNode in the arguments list? Why not comply with the insertBefore syntax?
-
Brad Vogel over 9 yearsThis code snippet doesn't handle if the referenceNode is the last child, in which it should appendChild.
-
Pancho over 9 years@BradVogel I think he explains that the case you mention is handled by insertBefore?
-
dvdchr over 9 yearsWhy? It's just a couple more lines, with added conditional for last child edge case handling. Everything else is perfectly the same.
-
electroCutie over 9 yearsAccording to MDN if the element is last (and so nextSibling is null) the newNode will be appended as expected
-
James Long over 9 yearsAs a general-rule-of-thumb in JavaScript, the browser can do a task faster than anything you can write. Although the two solutions are functionally the same, my JavaScript solution needs to be read an understood by the browser before it can be used and requires an additional check each time it's executed. The solution offered by karim79 will do all this internally, saving those steps. The difference will be trivial at best, but his solution is the better one.
-
1j01 about 9 yearsIn other words, it's attempting to solve a problem that doesn't exist. There's nothing inherently wrong about the extra check, but I suppose it's not propagating the best understanding of these methods
-
James Long about 9 yearsPretty much. I'm leaving the script here because it's the kind of thing I used to write, but the accepted answer is the better one, shows a better understanding of the methods and is faster. There's no reason use this answer instead - I'm not even sure why it still gets upvotes
-
Ben J about 8 yearsI wouldn't have thought of that approach. I'd prefer to use @karim79's more direct answer, but good to keep in mind.
-
Bhumi Singhal over 7 yearsreferenceNode.nextElementSibling is a better option to be used
-
Rolf over 7 yearsIf targetElement is the last element amongst it's siblings, then
targetElement.nextSibling
will returnnull
. Whennode.insertBefore
is called withnull
as it's second argument, then it will add the node at the end of the collection. In other words theif(parent.lastchild == targetElement) {
branch is superfluous, becauseparent.insertBefore(newElement, targetElement.nextSibling);
will deal properly with all cases, even though it may appear otherwise at first. Many have already pointed that out in other comments. -
James Long over 7 years@Rolf - yeah, that's why I don't recommend using this script and say it's better to use the accepted answer
-
ρяσѕρєя K over 7 yearsAdd some explanation with answer for how this answer help OP in fixing current issue
-
Admin over 7 yearsRun the code above,then you can insert a newNode after the specified referenceNode.
-
7vujy0f0hy about 7 years@BhumiSinghal: Wrong.
insertBefore()
works with text nodes. Why do you wantinsertAfter()
to be different? You should create a separate pair of functions namedinsertBeforeElement()
andinsertAfterElement()
for that. -
Donatas Navidonskis about 7 yearsthis function are great, but also and bad (not finished). reference node does not have any next siblings elements (example is the last child), function will not add the element, because reference does not have any more next siblings.
-
stomtech almost 7 yearsThe extension function names are misleading. It think it should rather be called appendMeBefore and appendMeAfter. I thought it was used like the appendChild() Method, e.g.
existingElement.appendAfter(newElement);
. See what I mean at this updated jsfiddle. -
do0g about 6 years@DonatasNavidonskis: this concern has already been addressed by doublebackslash.
-
Berkyjay about 6 yearsIf you already have the element constructed, you can use
.insertAdjacentElement()
-
madannes almost 6 yearsAs of 2018, browser support looks pretty solid: caniuse.com/#feat=insert-adjacent
-
mindplay.dk almost 6 yearsUnlike
insertBefore
, this function does not accept a nullreferenceNode
- I went ahead and posted a function that does, and has the opposite behavior ofinsertBefore
stackoverflow.com/a/51437118/283851 -
EugenSunic over 5 yearsThe fiddle doesn't work for me, here is the stackblitz for the code instead stackblitz.com/edit/js-rshtm2?file=index.js
-
Mukyuu about 5 yearsSimply add random stuff to workaround
"html is not defined"
@DGRFDSGN e.g:const html='';
-
Stefan Steiger over 4 yearsAppend After works, because if element.nextSibling does not have a next sibling, nextSibling is NULL, and then it will append at the end.
-
serraosays over 4 yearsShould really give this answer some love, it's the modern approach for the 2020s that are quickly approaching.
-
Mister SirCode over 4 yearsThis takes a bit of manual work to implement as a functioning insertAfter though, so unfortunately I dont think this would work correctly.
-
Mehregan Rahmani over 4 yearsThis solution doesn't work for 2 p tags.. you cannot add a p tag after another p tag with this function ..
-
Mehregan Rahmani over 4 yearsThis was a nice solution, i suggest eveyone read this xahlee.info/js/js_insert_after.html
-
flen about 4 yearsThis answer seems outdated,
insertAdjacentElement
looks like a better candidate nowadays. Could you maybe update your post to reflect this? This answer seems to be the most up-to-date: stackoverflow.com/a/50066247/4621141 -
Qwerty almost 4 yearsHow come this answer is burried so deep? I shall reward it some points to bring more attention.
-
Martin James almost 4 yearsNot really. This appends to the end or beginning, NOT after another element.
-
Lajos Mészáros over 3 yearsA little side note, that it's not working for document fragments.
-
flash over 3 years@MartinJames It actually DOES APPEND AFTER another element. There are four possible insertPositions: beforebegin - Inserts element BEFORE the current node beforeend - Appends element to the end of current node. So element becomes the last child of current node afterbegin - Prepends element to the beginning of current node. So element becomes first child of current node afterend - Inserts element AFTER current node. So element becomes the nextSibling of current node
-
caston over 3 yearsI get warnings in jslint: Expected ';' and instead saw ','. }, false;
-
izogfif over 3 yearsAbout "2020 solution":
before
andafter
are both marked as "experimental" on MDN page:Experimental. Expect behavior to change in the future.
-
Mister SirCode over 3 years@izogfif Well, Considering its just got into the living standards, that's expected. I highly doubt they will significantly change the behavior of the method to fit a new standard. If they do, I will edit the answer. The only reason that's on the MDN docs is most likely because it was recently added to the Living Standard, so its still "experimental" even though its stable and on the current release
-
Mircea about 3 yearsIt is working perfectly. Full support except IE.
-
Mister SirCode about 3 years@Mircea If you want it to work on IE, use the polyfill suggested in my answer. (Though lets be honest here, I doubt anyone really cares for IE anymore, I personally dont support it anymore)
-
Waruyama over 2 yearsI would no recomment this, but +1 for creativity.
-
Optimae about 2 years
before
andafter
are no longer marked as "experimental" on the MDN page: developer.mozilla.org/en-US/docs/Web/API/Element/before developer.mozilla.org/en-US/docs/Web/API/Element/after