How to replace DOM element in place using Javascript?
Asked Answered
O

10

222

I am looking to replace an element in the DOM.
For example, there is an <a> element that I want to replace with a <span> instead.

How would I go and do that?

Odlo answered 9/5, 2009 at 17:14 Comment(4)
target.replaceWith(element); is the modern (ES5+) way to do thisSyrian
@Syrian What does DOM spec have with ES? Moreover, it's not yet a part of the DOM standard, while ES5 was released 9 years ago.Agonized
ES5+ means ES5 OR LATER. Even if ES5 is 9 years old, later versions are NOT that old.Webby
If you still use StackOverflow it's worth picking the new standard answer below.Whole
O
230

by using replaceChild():

<html>
<head>
</head>
<body>
  <div>
    <a id="myAnchor" href="http://www.stackoverflow.com">StackOverflow</a>
  </div>
<script type="text/JavaScript">
  var myAnchor = document.getElementById("myAnchor");
  var mySpan = document.createElement("span");
  mySpan.innerHTML = "replaced anchor!";
  myAnchor.parentNode.replaceChild(mySpan, myAnchor);
</script>
</body>
</html>
Outgrowth answered 9/5, 2009 at 17:15 Comment(4)
this example wouldn't work. You should put the script block at the end of the body to make it work. Furthermore, just for fun: try adding the line [alert(myAnchor.innerHTML)] after the operation.Kickoff
Theres a spelling mistake with StackOverflow in the anchor innerTextPayload
what if it is root html elementShashaban
Thank you @Outgrowth Tipling. I've created a follow up question on how to add an id and a function to the replaced element, here: #15670761Mottled
S
153

A.replaceWith(span) - No parent needed

Generic form:

target.replaceWith(element)

Way better/cleaner than the previous method.

For your use case:

A.replaceWith(span)

Advanced usage

  1. You can pass multiple values (or use spread operator ...).
  2. Any string value will be added as a text element.

Examples:

// Initially [child1, target, child3]

target.replaceWith(span, "foo")     // [child1, span, "foo", child3]

const list = ["bar", span]
target.replaceWith(...list, "fizz")  // [child1, "bar", span, "fizz", child3]

Safely handling null target

If your target has a chance to be null, you can consider using the newish ?. optional chaining operator. Nothing will happen if target doesn't exist. Read more here.

target?.replaceWith?.(element)

Related DOM methods

  1. Read More - child.before and child.after
  2. Read More - parent.prepend and parent.append

Mozilla Docs

Supported Browsers - 97% Nov '22

Syrian answered 5/11, 2016 at 23:18 Comment(12)
Not supported in IE11 or Edge 14 (now: 2016-11-16).Rhamnaceous
Try using Google's Closure or another transpiler to convert to ES5. You shouldn't be writing old code based on browser support, if you have a better, more maintainable optionSyrian
Thus transpiling. You can optimize, minify, and down-convert all in one. Check it out: developers.google.com/closure/compilerSyrian
I think if the choice is between use code that works on all browsers I'm trying to support, or re-tool your whole build process to use Closure, I would pick use code that works on all browsers that I'm trying to support.Lindholm
@Rhamnaceous I kinda agree to support as many browsers as possible, but I refuse to remade my code just because IE or Edge are incomplete or just "want to be different". There are standards, if they don't follow them and a few people support it, that is their problem, that don't have to affect us as web developers.Amplification
@Davdriver: of course, but the current global support is only 69%: caniuse.com/#search=replaceWithRhamnaceous
replaceWith has nothing to do with ES5. It is defined by the WHATWG DOM spec.Jayejaylene
Global support is now at 72%, 80% in U.S. as of Oct 2017Syrian
My gulp process didn't transpile this function into something more browser friendly.Cloakanddagger
It’s super neat, bit of a bummer that as of January 2019 Safari still offers no support of replaceWith. Unless you’re using transpilers/polyfills, I would stick with replaceChild in meantime.Apothecium
Safari and all major modern browsers now support this in Apr 2020.Syrian
It is not my concern that replaceWith is not supported in Internet Explorer I dropped support for it 11 years ago (IE8). Note that I'm still supporting current minus 10 on browsers that auto update can be turned off and this still works fine.Gainsborough
U
68
var a = A.parentNode.replaceChild(document.createElement("span"), A);

a is the replaced A element.

Usn answered 9/5, 2009 at 17:20 Comment(2)
Answer from @Outgrowth Tipling in fact does not work. This is the (correct!) answer for KooiInc, also correct, comment . Now it works! ;-) Tx to both!Precious
surely you could have come up with a variable name other than A lolTopotype
M
8

This question is very old, but I found myself studying for a Microsoft Certification, and in the study book it was suggested to use:

oldElement.replaceNode(newElement)

I looked it up and it seems to only be supported in IE. Doh..

I thought I'd just add it here as a funny side note ;)

Meilen answered 22/5, 2018 at 18:59 Comment(0)
M
4

Best way to do it. No parents need. Just use Element.outerHTML = template;

// Get the current element
var currentNode = document.querySelector('#greeting');

// Replace the element
currentNode.outerHTML =
    '<div id="salutations">' +
        '<h1>Hi, universe!</h1>' +
        '<p>The sun is always shining!</p>' +
    '</div>';
Mutz answered 10/12, 2021 at 8:13 Comment(0)
P
3

I had a similar issue and found this thread. Replace didn't work for me, and going by the parent was difficult for my situation. Inner Html replaced the children, which wasn't what I wanted either. Using outerHTML got the job done. Hope this helps someone else!

currEl = <div>hello</div>
newElem = <span>Goodbye</span>
currEl.outerHTML = newElem
# currEl = <span>Goodbye</span>
Pinnate answered 24/3, 2019 at 7:45 Comment(2)
This is very clever but I don't know if it complies to the standards. Thanks !Youngstown
Probably it is globally used and I vote answer is the best !Youngstown
O
3

You can replace an HTML Element or Node using Node.replaceWith(newNode).

This example should keep all attributes and childs from origin node:

const links = document.querySelectorAll('a')

links.forEach(link => {
  const replacement = document.createElement('span')
  
  // copy attributes
  for (let i = 0; i < link.attributes.length; i++) {
     const attr = link.attributes[i]
     replacement.setAttribute(attr.name, attr.value)
  }
  
  // copy content
  replacement.innerHTML = link.innerHTML
  
  // or you can use appendChild instead
  // link.childNodes.forEach(node => replacement.appendChild(node))

  link.replaceWith(replacement)
})

If you have these elements:

<a href="#link-1">Link 1</a>
<a href="#link-2">Link 2</a>
<a href="#link-3">Link 3</a>
<a href="#link-4">Link 4</a>

After running above codes, you will end up with these elements:

<span href="#link-1">Link 1</span>
<span href="#link-2">Link 2</span>
<span href="#link-3">Link 3</span>
<span href="#link-4">Link 4</span>
Osteopath answered 2/5, 2020 at 0:31 Comment(2)
The answers given assume a static DOM. What if the DOM has been modified, e.g., via an onload script?Yance
just make sure that the document.querySelectorAll('a') is executed after the DOM has been modified or generated.Osteopath
M
2

You can use replaceChild on the parent of the target element after creating your new element (createElement):

const newElement = document.createElement(/*...*/);
const target = document.getElementById("my-table");
target.parentNode.replaceChild(newElement, target);

If your starting point for the new element is HTML, you can use insertAdjacentHTML and then removeChild on the parent (or remove on the element itself, in modern environments):

const target = document.getElementById("my-table");
target.insertAdjacentHTML("afterend", theHTMLForTheNewElement);
target.parentNode.removeChild(target); // Or: `target.remove()`
Magnitogorsk answered 4/3, 2021 at 8:11 Comment(0)
O
-1

Example for replacing LI elements

function (element) {
    let li = element.parentElement;
    let ul = li.parentNode;   
    if (li.nextSibling.nodeName === 'LI') {
        let li_replaced = ul.replaceChild(li, li.nextSibling);
        ul.insertBefore(li_replaced, li);
    }
}
Oyer answered 1/10, 2018 at 6:22 Comment(0)
P
-1

Given the already proposed options the easiest solution without finding a parent:

var parent = document.createElement("div");
var child = parent.appendChild(document.createElement("a"));
var span = document.createElement("span");

// for IE
if("replaceNode" in child)
  child.replaceNode(span);

// for other browsers
if("replaceWith" in child)
  child.replaceWith(span);

console.log(parent.outerHTML);
Parolee answered 26/5, 2019 at 22:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.