jQuery / Method / .replaceWith() - Replace Entire Elements
jQuery’s .replaceWith(newContent) replaces the selected elements themselves. Its return value is the jQuery object for the removed original elements, not the newly inserted ones. To work on new elements afterward, retain a separate reference or select them again from the document.
Whole elements versus inner content
.replaceWith() removes existing nodes and their children from the Document Object Model (DOM), putting new content in their place. $(".entry").replaceWith("<section>New</section>") replaces the outer tag, classes and children of .entry. The new section does not inherit .entry unless you specify that class.
Use .html() to retain the outer element and change its contents. replaceWith accepts an HTML string, DOM element, array of elements, jQuery object or a function returning replacement content. In the function, read each original element through this and explicitly transfer needed values to the new node.
Complete example with edited values and events
Save all code as UTF-8 in replace-demo.html and open it in a browser. Internet is required for the official jQuery file 4.0.0 from its content delivery network (CDN); no installation is needed. Replacement, inputs, events, reset and Console snippets below were executed with 3.7.1 and 4.0.0.
Two div.entry elements become section.entry. Names move through .text() and current input values through .val(). Each original button has a directly bound handler; a separate handler is delegated from #board, which is retained.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Replace whole elements</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
button, input { font: inherit; margin: 4px; max-width: 100%; box-sizing: border-box; }
.entry { padding: 12px; border: 1px solid #aab; margin: 10px 0; }
section.entry { border: 2px solid teal; background: #edf9f6; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<h1>Replace the outer element</h1>
<button type="button" id="replace">Replace both entries</button>
<button type="button" id="reset">Reset</button>
<div id="board">
<div class="entry"><strong class="name">Alpha</strong><input aria-label="Alpha note" value="First note"><button type="button" class="inspect">Inspect</button></div>
<div class="entry"><strong class="name">Beta</strong><input aria-label="Beta note" value="Second note"><button type="button" class="inspect">Inspect</button></div>
</div>
<pre id="result" aria-live="polite"></pre>
<script>
$(function () {
const initial = $("#board").html();
let $old, $returned = null, direct = 0, delegated = 0;
function report() {
const tags = $("#board > .entry").map(function () { return this.tagName.toLowerCase(); }).get();
const connected = $old.filter(function () { return this.isConnected; }).length;
$("#result").text(`live tags=${tags.join(",")}\noriginal connected=${connected}\nreturned original=${$returned ? $returned === $old : "(not run)"}\nold data=${$old.first().data("lesson")}\ndirect=${direct}; delegated=${delegated}`);
}
function initialize() {
$old = $("#board > .entry").data("lesson", "original");
$old.find(".inspect").on("click.directExample", function () { direct++; });
$returned = null; direct = 0; delegated = 0;
$("#replace").prop("disabled", false);
report();
}
$("#board").on("click.replaceLesson", ".inspect", function () { delegated++; report(); });
$("#replace").on("click", function () {
$returned = $old.replaceWith(function () {
const name = $(this).find(".name").text();
const note = $(this).find("input").val();
return $("<section>", { "class": "entry" }).append(
$("<strong>", { "class": "name" }).text(name),
$("<input>", { "aria-label": name + " note" }).val(note),
$("<button>", { type: "button", "class": "inspect" }).text("Inspect")
);
});
$returned.addClass("old-only");
$(this).prop("disabled", true);
report();
});
$("#reset").on("click", function () { $("#board").html(initial); initialize(); });
initialize();
});
</script>
</body>
</html>
Initial output follows. original connected counts original elements still connected to the document; old data is jQuery data stored on those elements.
live tags=div,div
original connected=2
returned original=(not run)
old data=original
direct=0; delegated=0
- Press Inspect once before replacement: direct=1; delegated=1. Both handlers run.
- Edit Alpha’s input and press Replace both entries. live tags becomes section,section; original connected becomes 0; returned original is true; old data is undefined. The edited value remains because the code explicitly copies it to the new input.
- Press Inspect afterward: only delegated increases. The new button is a different node and does not inherit the direct handler.
- $returned.addClass("old-only") adds a class to removed nodes. New sections in the document do not receive it. Inspect this in developer tools to see the return target.
- Replacement disables its button after one use. Reset restores HTML, input values and counters and binds direct handlers again. Delegation is registered once on the outer #board, so repeated resets do not duplicate it.
Do not assume inputs, data or focus transfer automatically. This example explicitly copies current value and does not restore focus. If users must continue entering data, retain the new control and design the necessary focus movement separately.
Return values and moving an existing node
Retain a newly created jQuery object as $new before passing it to replaceWith. Run the following in the same page’s developer tools Console. Temporary containers are created and removed without modifying the two main cards. .replaceAll() writes the operation from new content toward targets and returns the inserted set, as shown.
const $holder = $('<div><p class="slot">A</p><p class="slot">B</p></div>').appendTo("body");
const $new = $("<section>").text("New");
const $removed = $holder.find(".slot").first().replaceWith($new);
console.log(`removed=${$removed.get(0).tagName.toLowerCase()}; new=${$new.get(0).tagName.toLowerCase()}`);
const $inserted = $("<section>").text("Another").replaceAll($holder.find(".slot"));
console.log(`replaceAll inserted=${$inserted.get(0).tagName.toLowerCase()}; live sections=${$holder.children("section").length}`);
$holder.remove();
removed=p; new=section
replaceAll inserted=section; live sections=2
Passing an existing document node as replacement for one target moves it from its old location. It does not leave a new copy behind. The next snippet compares node identity and confirms that replacement has no effect on a detached node without a parent.
const $holder = $('<div><p class="slot">Placeholder</p><button type="button" class="source">Existing button</button></div>').appendTo("body");
const $source = $holder.find(".source");
const node = $source.get(0);
$holder.find(".slot").replaceWith($source);
console.log(`children=${$holder.children().length}; same node=${$holder.children().get(0) === node}`);
const $orphan = $("<p>Detached without parent</p>");
$orphan.replaceWith("<section>Replacement</section>");
console.log(`orphan tag=${$orphan.get(0).tagName.toLowerCase()}; connected=${$orphan.get(0).isConnected}`);
$holder.remove();
children=1; same node=true
orphan tag=p; connected=false
Repeating an HTML string with the same id for several targets creates duplicate IDs. Use classes for shared formatting and unique IDs where needed. Do not generalize the single-target move result to all cloning/moving behavior with multiple targets. When every target needs a new node, create each separately inside a function to make that intent explicit.
Missing handlers and changes that are not visible
replaceWith cleans jQuery data and event handlers from removed nodes and their descendants. It does not copy their .on() handlers to new nodes. For recurring behavior on replaced children, use delegated .on() events on a retained ancestor, or initialize new nodes explicitly. This cleanup is not a promise that all external state or native addEventListener listeners are cleaned up.
Chaining .css() or .addClass() to the cached original selection may change nodes outside the document. Use the new reference or a fresh scoped selection. Also check for an empty selection or a node without a parent; the return value alone does not prove the document changed.
Do not concatenate user input directly into HTML accepted by these methods. The example creates fixed developer-defined tags, passes names with .text() and input contents with .val(), so strings such as <em> are not interpreted as tags. This addresses plain text and input-value contexts here, not sanitization of arbitrary HTML.




