By Xah Lee


2011-01-25 12:39:36 8 Comments

There's insertBefore() in JavaScript, but how can I insert an element after another element without using jQuery or another library?

17 comments

@golopot 2016-10-27 07:55:24

node1.after(node2) produces <node1/><node2/>,

where node1 and node2 are DOM nodes.

.after() is not supported on older browsers [1], so you might need to apply a polyfill.

@bit-less 2018-04-27 16:01:22

Though insertBefore() (see MDN) is great and referenced by most answers here. For added flexibility, and to be a little more explicit, you can use:

insertAdjacentElement() (see MDN) This lets you reference any element, and insert the to-be moved element exactly where you want:

<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
    <!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
    ... content ...
    <!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->
</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->

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

@mindplay.dk 2018-07-20 07:17:39

I know this question has far too many answers already, but none of them met my exact requirements.

I wanted a function that has the exact opposite behavior of parentNode.insertBefore - that is, it must accept a null referenceNode (which the accepted answer does not) and where insertBefore would insert at the end of the children this one must insert at the start, since otherwise there'd be no way to insert at the start location with this function at all; the same reason insertBefore inserts at the end.

Since a null referenceNode requires you to locate the parent, we need to know the parent - insertBefore is a method of the parentNode, so it has access to the parent that way; our function doesn't, so we'll need to pass the parent as a parameter.

The resulting function looks like this:

function insertAfter(parentNode, newNode, referenceNode) {
  parentNode.insertBefore(
    newNode,
    referenceNode ? referenceNode.nextSibling : parentNode.firstChild
  );
}

Or (if you must, I don't recommend it) you can of course enhance the Node prototype:

if (! Node.prototype.insertAfter) {
  Node.prototype.insertAfter = function(newNode, referenceNode) {
    this.insertBefore(
      newNode,
      referenceNode ? referenceNode.nextSibling : this.firstChild
    );
  };
}

@yavuzkavus 2018-06-13 14:06:23

if( !Element.prototype.insertAfter ) {
    Element.prototype.insertAfter = function(item, reference) {
        if( reference.nextSibling )
            reference.parentNode.insertBefore(item, reference.nextSibling);
        else
            reference.parentNode.appendChild(item);
    };
}

@Ciro Santilli 新疆改造中心996ICU六四事件 2014-05-11 05:56:20

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 because insertAdjacentHTML adds content from strings rather than elements.

@GetFree 2018-03-13 17:05:01

If you already have the element constructed, you can use .insertAdjacentElement()

@madannes 2018-05-30 14:26:29

As of 2018, browser support looks pretty solid: caniuse.com/#feat=insert-adjacent

@Sami 2018-04-11 10:13:48

Lets handle all the scenarios

 function insertAfter(newNode, referenceNode) {
        if(referenceNode && referenceNode.nextSibling && referenceNode.nextSibling.nodeName == '#text')
            referenceNode = referenceNode.nextSibling;

        if(!referenceNode)
            document.body.appendChild(newNode);
        else if(!referenceNode.nextSibling)
            document.body.appendChild(newNode);
        else            
            referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);            
    }

@Darlesson 2017-01-13 22:51:08

Ideally insertAfter should work similar to insertBefore. The code below will perform the following:

  • If there are no children, the new Node is appended
  • If there is no reference Node, the new Node is appended
  • If there is no Node after the reference Node, the new Node is appended
  • If there the reference Node has a sibling after, then the new Node is inserted before that sibling
  • Returns the new Node

Extending Node

Node.prototype.insertAfter = function(node, referenceNode) {

    if (node)
        this.insertBefore(node, referenceNode && referenceNode.nextSibling);

    return node;
};

One common example

node.parentNode.insertAfter(newNode, node);

See the code running

// First extend
Node.prototype.insertAfter = function(node, referenceNode) {
    
    if (node)
        this.insertBefore(node, referenceNode && referenceNode.nextSibling);

    return node;
};

var referenceNode,
    newNode;

newNode = document.createElement('li')
newNode.innerText = 'First new item';
newNode.style.color = '#FF0000';

document.getElementById('no-children').insertAfter(newNode);

newNode = document.createElement('li');
newNode.innerText = 'Second new item';
newNode.style.color = '#FF0000';

document.getElementById('no-reference-node').insertAfter(newNode);

referenceNode = document.getElementById('no-sibling-after');
newNode = document.createElement('li');
newNode.innerText = 'Third new item';
newNode.style.color = '#FF0000';

referenceNode.parentNode.insertAfter(newNode, referenceNode);

referenceNode = document.getElementById('sibling-after');
newNode = document.createElement('li');
newNode.innerText = 'Fourth new item';
newNode.style.color = '#FF0000';

referenceNode.parentNode.insertAfter(newNode, referenceNode);
<h5>No children</h5>
<ul id="no-children"></ul>

<h5>No reference node</h5>
<ul id="no-reference-node">
  <li>First item</li>
</ul>

<h5>No sibling after</h5>
<ul>
  <li id="no-sibling-after">First item</li>
</ul>

<h5>Sibling after</h5>
<ul>
  <li id="sibling-after">First item</li>
  <li>Third item</li>
</ul>

@jszhou 2017-01-15 03:58:18

a robust implementation of insertAfter.

// source: https://github.com/jserz/domPlus/blob/master/src/insertAfter()/insertAfter.js
Node.prototype.insertAfter = Node.prototype.insertAfter || function (newNode, referenceNode) {
  function isNode(node) {
    return node instanceof Node;
  }

  if(arguments.length < 2){
    throw(new TypeError("Failed to execute 'insertAfter' on 'Node': 2 arguments required, but only "+ arguments.length +" present."));
  }

  if(isNode(newNode)){
    if(referenceNode === null || referenceNode === undefined){
      return this.insertBefore(newNode, referenceNode);
    }

    if(isNode(referenceNode)){
      return this.insertBefore(newNode, referenceNode.nextSibling);
    }

    throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 2 is not of type 'Node'."));
  }

  throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 1 is not of type 'Node'."));

};

@ρяσѕρєя K 2017-01-15 04:27:43

Add some explanation with answer for how this answer help OP in fixing current issue

@jszhou 2017-01-15 05:04:35

Run the code above,then you can insert a newNode after the specified referenceNode.

@James Long 2011-01-25 12:43:00

A quick Google search reveals this script

// create function, it expects 2 values.
function insertAfter(newElement,targetElement) {
    // target is what you want it to go after. Look for this elements parent.
    var parent = targetElement.parentNode;

    // if the parents lastchild is the targetElement...
    if (parent.lastChild == targetElement) {
        // add the newElement after the target element.
        parent.appendChild(newElement);
    } else {
        // else the target has siblings, insert the new element between the target and it's next sibling.
        parent.insertBefore(newElement, targetElement.nextSibling);
    }
}

@James Long 2013-11-11 11:40:27

For 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.

@dvdchr 2014-11-18 11:32:05

Why? It's just a couple more lines, with added conditional for last child edge case handling. Everything else is perfectly the same.

@James Long 2014-11-26 17:10:06

As 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 2015-03-23 02:43:07

In 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 2015-03-23 11:58:16

Pretty 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

@Rolf 2016-11-07 11:12:01

If targetElement is the last element amongst it's siblings, then targetElement.nextSibling will return null. When node.insertBefore is called with null as it's second argument, then it will add the node at the end of the collection. In other words the if(parent.lastchild == targetElement) { branch is superfluous, because parent.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 2016-11-08 09:18:53

@Rolf - yeah, that's why I don't recommend using this script and say it's better to use the accepted answer

@Doug LN 2016-12-14 12:12:37

You can use appendChild function to insert after an element.

Reference: http://www.w3schools.com/jsref/met_node_appendchild.asp

@Malik Khalil 2016-12-03 20:14:37

Step 1. Prepare Elements :

var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;

Step 2. Append after :

elementParent.insertBefore(newElement, element.nextSibling);

@Kunal Awasthi 2016-10-14 09:27:56

 <!DOCTYPE html>
 <html lang="ca">
 <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script>
        function createDiv(){
            var newDiv = document.createElement("div");
            var txt = document.createTextNode("I'm the second div");
            newDiv.appendChild(txt);
            var x = document.getElementsByTagName("BODY")[0];
            x.insertBefore(newDiv, third);
        }
    </script>
</head>
<body>
    <div class="first">
        <p>
            I'm the first div
        </p>
    </div>
    <div id="third">
        <p>
            I'm the third div
        </p>
    </div>
    <button type= " button " name= " button " onclick = " createDiv() " >
        Create the second Div
    </button>
</body>
</html>

@Kunal Awasthi 2016-10-14 09:29:11

here is my Answer for @davidMM Question.

@olvlvl 2015-05-28 09:05:42

Or you can simply do:

referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )

@Ben J 2016-03-24 08:29:37

I wouldn't have thought of that approach. I'd prefer to use @karim79's more direct answer, but good to keep in mind.

@Armando 2015-08-21 08:05:13

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>

Run it on JSFiddle

@stomtech 2017-05-25 09:43:22

The 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.

@Chetabahana 2015-04-09 03:12:32

This code is work to insert a link item right after the last existing child to inlining a small css file

var raf, cb=function(){
    //create newnode
    var link=document.createElement('link');
    link.rel='stylesheet';link.type='text/css';link.href='css/style.css';

    //insert after the lastnode
    var nodes=document.getElementsByTagName('link'); //existing nodes
    var lastnode=document.getElementsByTagName('link')[nodes.length-1]; 
    lastnode.parentNode.insertBefore(link, lastnode.nextSibling);
};

//check before insert
try {
    raf=requestAnimationFrame||
        mozRequestAnimationFrame||
        webkitRequestAnimationFrame||
        msRequestAnimationFrame;
}
catch(err){
    raf=false;
}

if (raf)raf(cb); else window.addEventListener('load',cb);

@Dmytro Dzyubak 2015-04-07 10:06:56

insertBefore() method is used like parentNode.insertBefore(). So to imitate this and make a method parentNode.insertAfter() we can write the following code.

JavaScript

Node.prototype.insertAfter = function(newNode, referenceNode) {
    return referenceNode.parentNode.insertBefore(
        newNode, referenceNode.nextSibling); // based on karim79's solution
};

// getting required handles
var refElem = document.getElementById("pTwo");
var parent = refElem.parentNode;

// creating <p>paragraph three</p>
var txt = document.createTextNode("paragraph three");
var paragraph = document.createElement("p");
paragraph.appendChild(txt);

// now we can call it the same way as insertBefore()
parent.insertAfter(paragraph, refElem);

HTML

<div id="divOne">
    <p id="pOne">paragraph one</p>
    <p id="pTwo">paragraph two</p>
</div>

Note, that extending the DOM might not be the right solution for You as stated in this article.

Hovewer, this article was written in 2010 and things might be different now. So decide on Your own.

JavaScript DOM insertAfter() method @ jsfiddle.net

@karim79 2011-01-25 12:42:32

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);
}

Try it here.

@GijsjanB 2013-11-14 16:09:24

Thanks 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 2014-10-08 06:04:22

This code snippet doesn't handle if the referenceNode is the last child, in which it should appendChild.

@Pancho 2014-11-13 14:05:36

@BradVogel I think he explains that the case you mention is handled by insertBefore?

@electroCutie 2014-11-25 16:07:05

According to MDN if the element is last (and so nextSibling is null) the newNode will be appended as expected

@user310291 2016-03-02 21:53:02

@KARIM79 It doesn't work in my case do you see why ? stackoverflow.com/questions/35758841/…

@Bhumi Singhal 2016-08-08 07:30:28

referenceNode.nextElementSibling is a better option to be used

@7vujy0f0hy 2017-03-19 13:58:10

@BhumiSinghal: Wrong. insertBefore() works with text nodes. Why do you want insertAfter() to be different? You should create a separate pair of functions named insertBeforeElement() and insertAfterElement() for that.

@Donatas Navidonskis 2017-04-14 06:58:48

this 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.

@do0g 2018-02-11 15:21:33

@DonatasNavidonskis: this concern has already been addressed by doublebackslash.

@Faris Rayhan 2018-02-26 04:15:05

Bohoo. Awesome my freind.

@mindplay.dk 2018-07-20 07:20:08

Unlike insertBefore, this function does not accept a null referenceNode - I went ahead and posted a function that does, and has the opposite behavior of insertBefore stackoverflow.com/a/51437118/283851

@eugen sunic 2018-10-09 14:28:47

The fiddle doesn't work for me, here is the stackblitz for the code instead stackblitz.com/edit/js-rshtm2?file=index.js

@DGRFDSGN 2018-12-12 08:55:52

@eugen-sunic also broken :)

@Mukyuu 2019-03-27 08:08:34

Simply add random stuff to workaround "html is not defined" @DGRFDSGN e.g: const html='';

@kiki 2019-06-25 21:33:36

I can't apply it to my case for some reason, it's getting too funny already)) can someone assist here please? stackoverflow.com/questions/56750237/…

Related Questions

Sponsored Content

15 Answered Questions

[SOLVED] How to insert an item into an array at a specific index (JavaScript)?

55 Answered Questions

[SOLVED] How do I check if an element is hidden in jQuery?

83 Answered Questions

[SOLVED] How to validate an email address in JavaScript

57 Answered Questions

[SOLVED] How do I include a JavaScript file in another JavaScript file?

3 Answered Questions

38 Answered Questions

[SOLVED] How do you get a timestamp in JavaScript?

58 Answered Questions

[SOLVED] How do I redirect to another webpage?

79 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5841558 View
  • 7285 Score
  • 79 Answer
  • Tags:   javascript arrays

86 Answered Questions

[SOLVED] How do JavaScript closures work?

28 Answered Questions

[SOLVED] How to change an element's class with JavaScript?

  • 2008-10-12 20:06:43
  • Nathan Smith
  • 2385027 View
  • 2560 Score
  • 28 Answer
  • Tags:   javascript html dom

Sponsored Content