Remove all child elements of a DOM node in JavaScript

JavascriptDom

Javascript Problem Overview


How would I go about removing all of the child elements of a DOM node in JavaScript?

Say I have the following (ugly) HTML:

<p id="foo">
    <span>hello</span>
    <div>world</div>
</p>

And I grab the node I want like so:

var myNode = document.getElementById("foo");

How could I remove the children of foo so that just <p id="foo"></p> is left?

Could I just do:

myNode.childNodes = new Array();

or should I be using some combination of removeElement?

I'd like the answer to be straight up DOM; though extra points if you also provide an answer in jQuery along with the DOM-only answer.

Javascript Solutions


Solution 1 - Javascript

Option 1 A: Clearing innerHTML.

  • This approach is simple, but might not be suitable for high-performance applications because it invokes the browser's HTML parser (though browsers may optimize for the case where the value is an empty string).

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.innerHTML = '';
}

<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via innerHTML</button>

Option 1 B: Clearing textContent

  • As above, but use .textContent. According to MDN this will be faster than innerHTML as browsers won't invoke their HTML parsers and will instead immediately replace all children of the element with a single #text node.

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.textContent = '';
}

<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via textContent</button>

Option 2 A: Looping to remove every lastChild:

  • An earlier edit to this answer used firstChild, but this is updated to use lastChild as in computer-science, in general, it's significantly faster to remove the last element of a collection than it is to remove the first element (depending on how the collection is implemented).
  • The loop continues to check for firstChild just in case it's faster to check for firstChild than lastChild (e.g. if the element list is implemented as a directed linked-list by the UA).

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  while (myNode.firstChild) {
    myNode.removeChild(myNode.lastChild);
  }
}

<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via lastChild-loop</button>

Option 2 B: Looping to remove every lastElementChild:

  • This approach preserves all non-Element (namely #text nodes and <!-- comments --> ) children of the parent (but not their descendants) - and this may be desirable in your application (e.g. some templating systems that use inline HTML comments to store template instructions).
  • This approach wasn't used until recent years as Internet Explorer only added support for lastElementChild in IE9.

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  while (myNode.lastElementChild) {
    myNode.removeChild(myNode.lastElementChild);
  }
}

<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <!-- This comment won't be removed -->
  <span>Hello <!-- This comment WILL be removed --></span>
  <!-- But this one won't. -->
</div>
<button id='doFoo'>Remove via lastElementChild-loop</button>

Bonus: Element.clearChildren monkey-patch:

  • We can add a new method-property to the Element prototype in JavaScript to simplify invoking it to just el.clearChildren() (where el is any HTML element object).
  • (Strictly speaking this is a monkey-patch, not a polyfill, as this is not a standard DOM feature or missing feature. Note that monkey-patching is rightfully discouraged in many situations.)

if( typeof Element.prototype.clearChildren === 'undefined' ) {
    Object.defineProperty(Element.prototype, 'clearChildren', {
      configurable: true,
      enumerable: false,
      value: function() {
        while(this.firstChild) this.removeChild(this.lastChild);
      }
    });
}

<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello <!-- This comment WILL be removed --></span>
</div>
<button onclick="this.previousElementSibling.clearChildren()">Remove via monkey-patch</button>

Solution 2 - Javascript

2020 Update - use the replaceChildren() API!

Replacing all children can now be done with the (cross-browser supported) replaceChildren API:

container.replaceChildren(...arrayOfNewChildren);

This will do both:

  • remove all existing children, and
  • append all of the given new children, in one operation.

You can also use this same API to just remove existing children, without replacing them:

container.replaceChildren();

This is fully supported in Chrome/Edge 86+, Firefox 78+, and Safari 14+. It is fully specified behavior. This is likely to be faster than any other proposed method here, since the removal of old children and addition of new children is done without requiring innerHTML, and in one step instead of multiple.

Solution 3 - Javascript

Use modern Javascript, with remove!

const parent = document.getElementById("foo")
while (parent.firstChild) {
    parent.firstChild.remove()
}

This is a newer way to write node removal in ES5. It is vanilla JS and reads much nicer than relying on parent.

All modern browsers are supported.

Browser Support - 97% Jun '21

Solution 4 - Javascript

The currently accepted answer is wrong about innerHTML being slower (at least in IE and Chrome), as m93a correctly mentioned.

Chrome and FF are dramatically faster using this method (which will destroy attached jquery data):

var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode, node);

in a distant second for FF and Chrome, and fastest in IE:

node.innerHTML = '';

InnerHTML won't destroy your event handlers or break jquery references, it's also recommended as a solution here: https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML.

The fastest DOM manipulation method (still slower than the previous two) is the Range removal, but ranges aren't supported until IE9.

var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();

The other methods mentioned seem to be comparable, but a lot slower than innerHTML, except for the outlier, jquery (1.1.1 and 3.1.1), which is considerably slower than anything else:

$(node).empty();

Evidence here:

http://jsperf.com/innerhtml-vs-removechild/167</strike> http://jsperf.com/innerhtml-vs-removechild/300</strike> https://jsperf.com/remove-all-child-elements-of-a-dom-node-in-javascript (New url for jsperf reboot because editing the old url isn't working)

Jsperf's "per-test-loop" often gets understood as "per-iteration", and only the first iteration has nodes to remove so the results are meaningless, at time of posting there were tests in this thread set up incorrectly.

Solution 5 - Javascript

var myNode = document.getElementById("foo");
var fc = myNode.firstChild;

while( fc ) {
    myNode.removeChild( fc );
    fc = myNode.firstChild;
}

If there's any chance that you have jQuery affected descendants, then you must use some method that will clean up jQuery data.

$('#foo').empty();

The jQuery .empty() method will ensure that any data that jQuery associated with elements being removed will be cleaned up.

If you simply use DOM methods of removing the children, that data will remain.

Solution 6 - Javascript

If you use jQuery:

$('#foo').empty();

If you don't:

var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);

Solution 7 - Javascript

The fastest...

var removeChilds = function (node) {
    var last;
    while (last = node.lastChild) node.removeChild(last);
};

Thanks to Andrey Lushnikov for his link to jsperf.com (cool site!).

EDIT: to be clear, there is no performance difference in Chrome between firstChild and lastChild. The top answer shows a good solution for performance.

Solution 8 - Javascript

Use elm.replaceChildren().

It’s experimental without wide support, but when executed with no params will do what you’re asking for, and it’s more efficient than looping through each child and removing it. As mentioned already, replacing innerHTML with an empty string will require HTML parsing on the browser’s part.

MDN Documentation.

Update It's widely supported now

Solution 9 - Javascript

If you only want to have the node without its children you could also make a copy of it like this:

var dupNode = document.getElementById("foo").cloneNode(false);

Depends on what you're trying to achieve.

Solution 10 - Javascript

Here's another approach:

function removeAllChildren(theParent){
	
    // Create the Range object
    var rangeObj = new Range();
    
    // Select all of theParent's children
    rangeObj.selectNodeContents(theParent);
    
    // Delete everything that is selected
    rangeObj.deleteContents();
}

Solution 11 - Javascript

element.textContent = '';

It's like innerText, except standard. It's a bit slower than removeChild(), but it's easier to use and won't make much of a performance difference if you don't have too much stuff to delete.

Solution 12 - Javascript

Here is what I usually do :

HTMLElement.prototype.empty = function() {
    while (this.firstChild) {
        this.removeChild(this.firstChild);
    }
}

And voila, later on you can empty any dom element with :

anyDom.empty()

Solution 13 - Javascript

Ecma6 makes it easy and compact

myNode.querySelectorAll('*').forEach( n => n.remove() );

This answers the question, and removes “all child nodes”.

If there are text nodes belonging to myNode they can’t be selected with CSS selectors, in this case we’ve to apply (also):

myNode.textContent = '';

Actually the last one could be the fastest and more effective/efficient solution.

.textContent is more efficient than .innerText and .innerHTML, see: MDN

Solution 14 - Javascript

In response to DanMan, Maarten and Matt. Cloning a node, to set the text is indeed a viable way in my results.

// @param {node} node
// @return {node} empty node
function removeAllChildrenFromNode (node) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = removeAllChildrenFromNode( myNode );

Also this works for nodes not in the dom which return null when trying to access the parentNode. In addition, if you need to be safe a node is empty before adding content this is really helpful. Consider the use case underneath.

// @param {node} node
// @param {string|html} content
// @return {node} node with content only
function refreshContent (node, content) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);
  
  // use innerHTML or you preffered method
  // depending on what you need
  shell.innerHTML( content );

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = refreshContent( myNode );

I find this method very useful when replacing a string inside an element, if you are not sure what the node will contain, instead of worrying how to clean up the mess, start out fresh.

Solution 15 - Javascript

Using a range loop feels the most natural to me:

for (var child of node.childNodes) {
    child.remove();
}

According to my measurements in Chrome and Firefox, it is about 1.3x slower. In normal circumstances, this will perhaps not matter.

Solution 16 - Javascript

var empty_element = function (element) {

    var node = element;
    
    while (element.hasChildNodes()) {              // selected elem has children

        if (node.hasChildNodes()) {                // current node has children
            node = node.lastChild;                 // set current node to child
        }
        else {                                     // last child found
            console.log(node.nodeName);
            node = node.parentNode;                // set node to parent
            node.removeChild(node.lastChild);      // remove last node
        }
    }
}

This will remove all nodes within the element.

Solution 17 - Javascript

There are couple of options to achieve that:

The fastest ():

while (node.lastChild) {
  node.removeChild(node.lastChild);
}

Alternatives (slower):

while (node.firstChild) {
  node.removeChild(node.firstChild);
}

while (node.hasChildNodes()) {
  node.removeChild(node.lastChild);
}

Benchmark with the suggested options

Solution 18 - Javascript

innerText is the winner! http://jsperf.com/innerhtml-vs-removechild/133. At all previous tests inner dom of parent node were deleted at first iteration and then innerHTML or removeChild where applied to empty div.

Solution 19 - Javascript

Simplest way of removing the child nodes of a node via Javascript

var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
   myNode.removeChild(myNode.lastChild);
}

Solution 20 - Javascript

 let el = document.querySelector('#el');
 if (el.hasChildNodes()) {
      el.childNodes.forEach(child => el.removeChild(child));
 }

Solution 21 - Javascript

i saw people doing:

while (el.firstNode) {
    el.removeChild(el.firstNode);
}

then someone said using el.lastNode is faster

however I would think that this is the fastest:

var children = el.childNodes;
for (var i=children.length - 1; i>-1; i--) {
    el.removeNode(children[i]);
}

what do you think?

ps: this topic was a life saver for me. my firefox addon got rejected cuz i used innerHTML. Its been a habit for a long time. then i foudn this. and i actually noticed a speed difference. on load the innerhtml took awhile to update, however going by addElement its instant!

Solution 22 - Javascript

Why aren't we following the simplest method here "remove" looped inside while.

const foo = document.querySelector(".foo");
while (foo.firstChild) {
  foo.firstChild.remove();     
}
  • Selecting the parent div
  • Using "remove" Method inside a While loop for eliminating First child element , until there is none left.

Solution 23 - Javascript

Generally, JavaScript uses arrays to reference lists of DOM nodes. So, this will work nicely if you have an interest in doing it through the HTMLElements array. Also, worth noting, because I am using an array reference instead of JavaScript proto's this should work in any browser, including IE.

while(nodeArray.length !== 0) {
  nodeArray[0].parentNode.removeChild(nodeArray[0]);
}

Solution 24 - Javascript

Just saw someone mention this question in another and thought I would add a method I didn't see yet:

function clear(el) {
    el.parentNode.replaceChild(el.cloneNode(false), el);
}

var myNode = document.getElementById("foo");
clear(myNode);

The clear function is taking the element and using the parent node to replace itself with a copy without it's children. Not much performance gain if the element is sparse but when the element has a bunch of nodes the performance gains are realized.

Solution 25 - Javascript

Functional only approach:

const domChildren = (el) => Array.from(el.childNodes)
const domRemove = (el) => el.parentNode.removeChild(el)
const domEmpty = (el) => domChildren(el).map(domRemove)

"childNodes" in domChildren will give a nodeList of the immediate children elements, which is empty when none are found. In order to map over the nodeList, domChildren converts it to array. domEmpty maps a function domRemove over all elements which removes it.

Example usage:

domEmpty(document.body)

removes all children from the body element.

Solution 26 - Javascript

element.innerHTML = "" (or .textContent) is by far the fastest solution

Most of the answers here are based on flawed tests

For example: https://jsperf.com/innerhtml-vs-removechild/15
This test does not add new children to the element between each iteration. The first iteration will remove the element's contents, and every other iteration will then do nothing. In this case, while (box.lastChild) box.removeChild(box.lastChild) was faster because box.lastChild was null 99% of the time

Here is a proper test: https://jsperf.com/innerhtml-conspiracy

Finally, do not use node.parentNode.replaceChild(node.cloneNode(false), node). This will replace the node with a copy of itself without its children. However, this does not preserve event listeners and breaks any other references to the node.

Solution 27 - Javascript

Best Removal Method for ES6+ Browser (major browsers released after year 2016):

Perhaps there are lots of way to do it, such as Element.replaceChildren(). I would like to show you an effective solution with only one redraw & reflow supporting all ES6+ browsers.

function removeChildren(cssSelector, parentNode){
    var elements = parentNode.querySelectorAll(cssSelector);
    let fragment = document.createDocumentFragment(); 
    fragment.textContent=' ';
    fragment.firstChild.replaceWith(...elements);
}

Usage: removeChildren('.foo',document.body);: remove all elements with className foo in <body>

Solution 28 - Javascript

You can remove all child elements from a container like below:

function emptyDom(selector){
 const elem = document.querySelector(selector);
 if(elem) elem.innerHTML = "";
}

Now you can call the function and pass the selector like below: > If element has id = foo

emptyDom('#foo');

> If element has class = foo

emptyDom('.foo');

> if element has tag = <div>

emptyDom('div')

Solution 29 - Javascript

If you want to empty entire parent DOM then it's very simple...

Just use .empty()

function removeAll() {
  $('#parent').empty();
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onclick="removeAll()">Remove all the element of parent</button>
<div id="parent">
  <h3>Title</h3>
  <p>Child 1</p>
  <p>Child 2</p>
  <p>Child 3</p>
</div>

Solution 30 - Javascript

I did it like this

data = {
    "messages": [
        [0, "userName", "message test"],
        [1, "userName1", "message test1"]
    ]
}
for (let i = 0; i < data.messages.length; i++) {
    var messageData = document.createElement('span')
    messageData.className = 'messageClass'
    messageData.innerHTML = `${data.messages[i][2]} ${'<br />'}`
    $(".messages").append(messageData)
}

$('#removeMessages').on('click', () => {
    node = $('.messages').get(0)
    while (node.firstChild) {
        node.firstChild.remove()
    }
    $('#removeMessages').toggle(500)
    $('#addMessages').toggle(500)
})

$('#addMessages').on('click', () => {
    for (let i = 0; i < data.messages.length; i++) {
        var messageData = document.createElement('span')
        messageData.className = 'messageClass'
        messageData.innerHTML = `${data.messages[i][2]} ${'<br />'}`
        $(".messages").append(messageData)
    }
    $('#addMessages').toggle(500)
    $('#removeMessages').toggle(500)
})

#addMessages{
  display:none;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="messages"></div>
<button type='button' id="removeMessages">Remove</button>
<button type='button' id="addMessages">Add MEssages</button>

Solution 31 - Javascript

simply only IE:

parentElement.removeNode(true);

true - means to do deep removal - which means that all child are also removed

Solution 32 - Javascript

Other ways in jQuery

var foo = $("#foo");
foo.children().remove();
//or
$("*", foo ).remove();
//or
foo.html("");
//or
foo.empty();

Solution 33 - Javascript

The easiest way:

let container = document.getElementById("containerId");
container.innerHTML = "";

Solution 34 - Javascript

simple and fast using for loop!!

var myNode = document.getElementById("foo");

    for(var i = myNode.childNodes.length - 1; i >= 0; --i) {
      myNode.removeChild(myNode.childNodes[i]);
    }

this will not work in <span> tag!

Solution 35 - Javascript

If you want to put something back into that div, the innerHTML is probably better.

My example:

<ul><div id="result"></div></ul>

<script>
  function displayHTML(result){
    var movieLink = document.createElement("li");
    var t = document.createTextNode(result.Title);
    movieLink.appendChild(t);
    outputDiv.appendChild(movieLink);
  }
</script>

If I use the .firstChild or .lastChild method the displayHTML() function doesnt work afterwards, but no problem with the .innerHTML method.

Solution 36 - Javascript

This is a pure javascript i am not using jQuery but works in all browser even IE and it is verry simple to understand

   <div id="my_div">
    <p>Paragraph one</p>
    <p>Paragraph two</p>
    <p>Paragraph three</p>
   </div>
   <button id ="my_button>Remove nodes ?</button>

   document.getElementById("my_button").addEventListener("click",function(){

  let parent_node =document.getElemetById("my_div"); //Div which contains paagraphs

  //Let find numbers of child inside the div then remove all
  for(var i =0; i < parent_node.childNodes.length; i++) {
     //To avoid a problem which may happen if there is no childNodes[i] 
     try{
       if(parent_node.childNodes[i]){
         parent_node.removeChild(parent_node.childNodes[i]);
       }
     }catch(e){
     }
  }

})

or you may simpli do this which is a quick way to do

document.getElementById("my_button").addEventListener("click",function(){

 let parent_node =document.getElemetById("my_div");
 parent_node.innerHTML ="";

})

Solution 37 - Javascript

with jQuery :

$("#foo").find("*").remove();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPolaris878View Question on Stackoverflow
Solution 1 - JavascriptGabriel McAdamsView Answer on Stackoverflow
Solution 2 - JavascriptMason FreedView Answer on Stackoverflow
Solution 3 - JavascriptGiboltView Answer on Stackoverflow
Solution 4 - JavascriptnpjohnsView Answer on Stackoverflow
Solution 5 - Javascriptuser113716View Answer on Stackoverflow
Solution 6 - JavascriptPleaseStandView Answer on Stackoverflow
Solution 7 - JavascriptGabe HalsmerView Answer on Stackoverflow
Solution 8 - JavascriptMarc M.View Answer on Stackoverflow
Solution 9 - JavascriptDanManView Answer on Stackoverflow
Solution 10 - JavascriptNathan KView Answer on Stackoverflow
Solution 11 - Javascriptbjb568View Answer on Stackoverflow
Solution 12 - JavascriptAdo RenView Answer on Stackoverflow
Solution 13 - JavascriptMarco BalestraView Answer on Stackoverflow
Solution 14 - JavascriptjeroenView Answer on Stackoverflow
Solution 15 - JavascriptemuView Answer on Stackoverflow
Solution 16 - JavascriptHenrikView Answer on Stackoverflow
Solution 17 - JavascriptmagiccrafterView Answer on Stackoverflow
Solution 18 - JavascriptAlexeyView Answer on Stackoverflow
Solution 19 - JavascriptChaitanya BapatView Answer on Stackoverflow
Solution 20 - JavascriptThomasView Answer on Stackoverflow
Solution 21 - JavascriptNoitidartView Answer on Stackoverflow
Solution 22 - JavascriptNeelansh VermaView Answer on Stackoverflow
Solution 23 - Javascriptr00t hkrView Answer on Stackoverflow
Solution 24 - JavascriptHarry ChilinguerianView Answer on Stackoverflow
Solution 25 - JavascriptDolph RogerView Answer on Stackoverflow
Solution 26 - Javascript12Me21View Answer on Stackoverflow
Solution 27 - JavascriptChester FungView Answer on Stackoverflow
Solution 28 - Javascriptharish kumarView Answer on Stackoverflow
Solution 29 - JavascriptRohit TagadiyaView Answer on Stackoverflow
Solution 30 - JavascriptAllanRibasView Answer on Stackoverflow
Solution 31 - Javascriptuser2656596View Answer on Stackoverflow
Solution 32 - JavascriptAnoopView Answer on Stackoverflow
Solution 33 - JavascriptmiloszView Answer on Stackoverflow
Solution 34 - JavascriptMohit KarkarView Answer on Stackoverflow
Solution 35 - JavascriptBjathrView Answer on Stackoverflow
Solution 36 - JavascriptIr CalifView Answer on Stackoverflow
Solution 37 - JavascriptArnaud F.View Answer on Stackoverflow