382

imagine what we have something like this:

<div id="xxx"><p>Hello World</p></div>

if we call .html function in this way:

$("#xxx").html();

we will get:

<p>Hello World</p>

But i need to get:

<div id="xxx"><p>Hello World</p></div>

So, what i need to do? I think to add another wrapper around #xxx, but this is not a good idea.

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
vorobey
  • 4,401
  • 3
  • 18
  • 20

4 Answers4

1324

Just use standard DOM functionality:

$('#xxx')[0].outerHTML

Or a bit simpler with .prop():

$('#xxx').prop('outerHTML')

outerHTML is well supported - verify at Mozilla or caniuse.

KARASZI István
  • 30,900
  • 8
  • 101
  • 128
Andy
  • 29,707
  • 9
  • 41
  • 58
  • 308
    another option: $('#xxx').prop('outerHTML') – Aaron Mar 15 '13 at 20:51
  • The most elegant solution by far. My only (small) gripe is that you have to address the first element. I wish jquery had $el.outerHTML(); – Dylan Pierce Nov 11 '14 at 14:02
  • 1
    I prefer this more: $('#xxx').get(0).outerHTML; – Jain Jan 01 '15 at 17:27
  • 12
    Keep in mind that as of April 2015, SVG elements still don't have an outerHTML property in all browsers, see: http://stackoverflow.com/a/20559830/656010 – Tom Wayson Apr 30 '15 at 15:42
  • 4
    Keep in mind that this approach doesn't execute javascript in the html while jQuery method that accepts an HTML string can execute code. – Gqqnbig Aug 10 '15 at 18:28
  • 12
    Update: since the addition of `prop()` to the jQuery source, the above can now be made more succinct: `$('#xxx').prop('outerHTML');` – Rory McCrossan Sep 25 '15 at 14:48
  • @RoryMcCrossan wins, as it's the only one (afaict) that degrades gracefully when `$("#xxx")[0]` is null. – ruffin Mar 09 '18 at 00:41
  • 3
    Keep in mind that this approach gives `outerHTML` of only **first** element, e.g. `$('ab')[0].outerHTML` will return `a`, not `ab`. – izogfif Mar 15 '18 at 09:19
  • 1
    I don't agree with this approach since it only works for the first element (as @izogfif stated) and excludes the rest. This is not what the output of outerHTML is supposed to be. One day your code might give unexpected results if the targeted element contains more than one element. – biko Jun 01 '18 at 01:07
  • .prop("outerHTML") – Pavel Nazarov Aug 22 '18 at 10:36
  • maybe emphasize CAPITOL H T M L. Just spent an hour trying to get outerHtml to work. My fault of course for not reading carefully. – rocketsarefast Sep 21 '18 at 20:02
  • 1
    If you need it to work with multiple elements you can use var html = ''; $('#xxx').each(function () { html += this.outerHTML; }); @izogfif – Tofandel Jan 28 '19 at 21:56
217

Create a temporary element, then clone() and append():

$('<div>').append($('#xxx').clone()).html();
David Tang
  • 92,262
  • 30
  • 167
  • 149
  • 1
    Does one actually need to clone it? e.g. does appending an element to a detached element remove it from the DOM? – Jamie Treworgy Apr 21 '11 at 12:44
  • 6
    @jamietre, yes because `.append()` will always *move* the element. – David Tang Apr 21 '11 at 12:45
  • @jamietre why isn't ezmilhouse's response universally correct? I think it would be faster to wrap then clone. Unless you don't want the wrapping to be applied to the DOM; but if you're working on a temp object, it won't be visible anyhow. – vol7ron Jan 13 '13 at 17:32
  • @vol7ron at the time I made this comment the answers looked a lot different than they do now. However, looking at his "universal solution" that is still problematic. `wrapAll` alters the DOM. If you look at his fiddle example, you can see the extra div added to the output vs. the input. I don't see why one would go to so much trouble just to avoid `clone()` which works fine and is non-destructive! – Jamie Treworgy Jan 14 '13 at 12:47
  • @jamietre: I haven't done any testing, but my assumption is that creating the wrapper and attaching an already created DOM element to it is less resource intensive attaching a deep copy of what could be complex object. Additionally, clone will create multiple elements with the same `id`, which can be a bad thing. Furthermore, given the above, for them to be the same I think you want to pass `true` to `clone` (eg `.clone(true)`) – vol7ron Jan 14 '13 at 14:00
  • A clone is not attached to the DOM, until you add it, making the ID concern irrelevant. We never add it to the DOM. We're just getting the HTML. Nor would you have any interest in bound events for the purpose of simply getting the HTML, so no need to use `true`. While you're probably correct about resource use, this is not a place where it would ever matter. You can run video games in web browsers these days. This is client code, so it will only be run in a single thread by a single user. This is small, small potatoes. There is no reason to be concerned about performance in this situation. – Jamie Treworgy Jan 14 '13 at 14:21
  • .. btw you should also check the duplicate question that this one is linked to when it was closed; the answer is the same. This technique seems to be widely accepted. – Jamie Treworgy Jan 14 '13 at 14:29
  • 1
    @JamieTreworgy: nice commenting ;) You're right, if you're only after HTML, then events and bindings aren't relative - it's been 3/4 a year and I don't know what I was thinking, maybe I was incorrectly thinking about `data-*` attributes, but they should work -- who knows – vol7ron Aug 14 '13 at 15:41
  • 80
    I down voted because this is a terribly circuitous method of solving a simple problem. See the docs for VanillaJS: https://developer.mozilla.org/en-US/docs/Web/API/element.outerHTML – just_wes Aug 29 '13 at 18:52
  • 48
    This is a great example of having "jQuery blinders" on, because the plain JS solution (see Andy's solution below) is so much simpler. – Ryan Burney Nov 22 '13 at 18:35
  • 5
    This seems like an overlycomplicatedheavyweight solution. I prefer just using the simple dom outerHTML property. – Brain2000 Jan 24 '14 at 19:17
  • 3
    This solution is better because outerHTML property can be missing in some special cases. – Andrej Mar 18 '16 at 15:06
  • clone() is broken with data() so this does not work if you want to change the cloned elements data() – Phillipp Jul 02 '16 at 16:49
  • It's a tricky way but totally unnecessary. – Duc Filan Jan 17 '17 at 07:21
  • 1
    Downvote because this should not be the correct answer, this is a hack for what should be a very easy solution $('#xxx')[0].outerHTML – newms87 Mar 29 '17 at 03:32
83

No siblings solution:

var x = $('#xxx').parent().html();
alert(x);

Universal solution:

// no cloning necessary    
var x = $('#xxx').wrapAll('<div>').parent().html(); 
alert(x);

Fiddle here: http://jsfiddle.net/ezmilhouse/Mv76a/

Sevin7
  • 6,296
  • 4
  • 23
  • 31
ezmilhouse
  • 8,933
  • 7
  • 29
  • 38
-10

If you don't want to add a wrapper, you could just add the code manually, since you know the ID you are targeting:

var myID = "xxx";

var newCode = "<div id='"+myID+"'>"+$("#"+myID).html()+"</div>";
Steve Kelly
  • 371
  • 3
  • 17