Prevent contenteditable adding <div> on ENTER - Chrome

113,501

Solution 1

Try this:

$('div[contenteditable]').keydown(function(e) {
    // trap the return key being pressed
    if (e.keyCode === 13) {
        // insert 2 br tags (if only one br tag is inserted the cursor won't go to the next line)
        document.execCommand('insertHTML', false, '<br/>');
        // prevent the default behaviour of return key pressed
        return false;
    }
});

Click here for demo

Solution 2

Add style display:inline-block; to contenteditable, it will not generate div, p and span automatically in Chrome.

Solution 3

You can do this with just a CSS change:

div{
    background: skyblue;
    padding:10px;
    display: inline-block;
}

pre{
    white-space: pre-wrap;
    background: #EEE;
}

http://jsfiddle.net/ayiem999/HW43Q/

Solution 4

This works in all major browsers (Chrome, Firefox, Safari, Edge)

document.addEventListener('keydown', event => {
  if (event.key === 'Enter') {
    document.execCommand('insertLineBreak')
    event.preventDefault()
  }
})
<div class="element" contenteditable="true">Sample text</div>
<p class="element" contenteditable="true">Sample text</p>

There is one inconvenience. After you finish editing, the elements might contain an ending <br> inside. But you could add code to trim that down if you need to.

Check this answer to remove the trailing <br> https://stackoverflow.com/a/61237737/670839

Solution 5

document.execCommand('defaultParagraphSeparator', false, 'p');

It overrides the default behavior to have paragraph instead.

On chrome the default behavior on enter is:

<div>
    <br>
</div>

With that command it is gonna be

<p>
    <br>
</p>

Now that it's more linear across it's easy to have only <br> would you need to.

Share:
113,501

Related videos on Youtube

iConnor
Author by

iConnor

"There is only one hard thing in programming and that is naming things" “No one has ever become poor by giving.” ― Anne Frank A Project Manager is someone who thinks 9 women can deliver a baby in 1 month.

Updated on October 04, 2021

Comments

  • iConnor
    iConnor over 2 years

    I have a contenteditable element, and whenever I type some stuff and hit ENTER it creates a new <div> and places the new line text in there. I don't like this one little bit.

    Is it possible to prevent this from happening or at least just replace it with a <br>?

    Here is demo http://jsfiddle.net/jDvau/

    Note: This is not an issue in firefox.

    • ViliusL
      ViliusL over 10 years
      firefox adds <br>, chrome - not, but after fixing your styles, extra divs do not break left padding. Question is why you dont like it? Think it is br... jsfiddle.net/jDvau/1 Also you can use DOMSubtreeModified event on catch these divs and remove them.
    • Sirikon
      Sirikon over 10 years
      stackoverflow.com/questions/6024594/… this could help you, good luck!
    • BeNdErR
      BeNdErR over 10 years
    • backdesk
      backdesk over 10 years
    • svassr
      svassr over 10 years
      To me Blake Plumb's solution is the simplest and from far the best down here.
    • sv_in
      sv_in over 10 years
    • iConnor
      iConnor over 10 years
      @svassr that's not the point, it's not you or I that will be using it, It's a client that may not even know what shift is.
    • svassr
      svassr over 10 years
      Indeed it changes everything. That said it's a common behaviour and small help message would'nt arm. "Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime."
    • L.T
      L.T over 8 years
      need add e.preventDefault() before return false
  • Math chiller
    Math chiller over 10 years
    @connorspiracist sorry its document.body.div (you probably will need to put in some other code to point to correct div its just the general idea)
  • iConnor
    iConnor over 10 years
    Good, works :) I'll await more attention before I decide, thanks.
  • Andrew
    Andrew over 10 years
    But I find a little difference here. Put your cursor just on the blank line(on the top of "Type some stuff"), and press enter. The cursor is now just before the "Type", not on the new blank line.
  • iConnor
    iConnor over 10 years
    Just to let you know, jQuery.browser is no longer part of jQuery.
  • iConnor
    iConnor over 10 years
    @Andrew yes that is correct, It would be good if you can fix this Ram
  • Elie
    Elie over 10 years
    You've right, I should mention this and use something like navigator.userAgent.indexOf("msie") > 0 and navigator.userAgent.indexOf("webkit") > 0
  • Ram G Athreya
    Ram G Athreya over 10 years
    I am sorry I can't find an easy fix for this at the moment & I am a little busy with work & all, I will try my best to find a workaround for this issue soon
  • iConnor
    iConnor over 10 years
    +1 Thanks, this is very handy to know, but if you have a client that's writing a book, that'll be a pain in the ***
  • iConnor
    iConnor over 10 years
    This may help some people but I was more concerned about the unessasary markup, as I would be taking the final HTML of the contenteditable and using it elsewhere
  • webprogrammer
    webprogrammer about 10 years
    This doesn't work in IE11 as it does not support insertHTML. See answer below!
  • Imskull
    Imskull about 10 years
    There was a problem when I used inline-block, execute execCommand("insertHTML", xxx) to insert anything, a "<br>" will added at the end of inserted element, tested in Chrome33.
  • daedelus_j
    daedelus_j about 10 years
    In chrome if you try this within a blockquote, it automatically creates a new blockquote as well, not the desired behavior.
  • Chandrew
    Chandrew almost 10 years
    If you put your cursor between characters eg. 'Ty[cursor]pe some stuff' and hit enter, you get 1 line too many.
  • raoulinski
    raoulinski over 9 years
    Answer is not acceptable. Solution would be to have only one <br />
  • ericjbasti
    ericjbasti almost 9 years
    This is a great solution. *[contenteditable="true"]{display: inline-block;}
  • Nishad Up
    Nishad Up over 8 years
    this return both <br> and <div>
  • HADI
    HADI over 8 years
    if there is multiple contentEditable then it will insert extra br. If there is four contentEditable then four break will occur
  • user25794
    user25794 over 8 years
    Love it, simple but effective
  • Ced
    Ced about 8 years
    When you press enter, instead of having div and br you'll have p and br accross browser. Try it.
  • jpaugh
    jpaugh about 8 years
    Thanks! Explanations are always helpful
  • Ced
    Ced about 8 years
    @jpaugh np, I edited my answer further so it explains better.
  • medBouzid
    medBouzid about 8 years
    this doesn't work on firefox (I tested in chrome and firefox only)
  • Sceptic
    Sceptic about 8 years
    Nice find. Sadly this won't work on position: absolute elements or elements that are direct children of a parent with display: flex. You can hack it to work though keeping that in mind. Just make sure it's not a direct child of flex elements. If you need it position: absolute just give it a extra parent with that.
  • Sebastian Sandqvist
    Sebastian Sandqvist about 8 years
    if( ( e.keyCode || e.witch ) == 13 ) { ... } needs to be if (e.keyCode === 13 || e.which === 13) { ... }
  • Betty St
    Betty St about 8 years
    In IE11 this will make an extra <p></p> :(
  • A Gupta
    A Gupta almost 8 years
    doesn't work properly on firefox. it adds one extra line.
  • LarsW
    LarsW almost 8 years
    This makes it so that the input doesn't get triggered when you press enter. A simple solution: add sth like $(this).trigger('input')
  • vsync
    vsync over 7 years
    answers half the question without trying to answer the first part, which is to prevent this from happening
  • vsync
    vsync over 7 years
    but it will create another very annoying Chrome bug (what a shitty browser)
  • Jay Jee
    Jay Jee almost 7 years
    This solved a line break problem I was trying to fix for the last six months! Thank you @le-tung-anh
  • zamber
    zamber almost 7 years
    ericjbasti's CSS snippet is not a great solution performance-wise. Wildcard selectors are costly. Make sure to specify it for elements that actually will use it.
  • kittu
    kittu almost 7 years
    @ReinoutvanKempen Started using flex 3 months ago already. I guess this hack won't work
  • mike rodent
    mike rodent over 6 years
    another prob here is that it takes no account of modifiers... when using keydown you want to do sthg like if ... && ! e.ctrlKey && ! e.shiftKey && ! e.altKey as appropriate...
  • vsync
    vsync over 6 years
    This doesn't help if you're pasting content
  • Mikaël Mayer
    Mikaël Mayer over 6 years
    Does not work anymore with Chrome Version 63.0.3239.84
  • Mikaël Mayer
    Mikaël Mayer over 6 years
    With the answer of @airi, I discovered that the contenteditable should be a <div>. It cannot be a <span> or a <body> for this idea to work
  • blackmamba
    blackmamba about 6 years
    FireFox has been fixed to now respect the defaultParagraphSeparator. IMHO this make this answer the best as it make all browsers now consistent and inline with the spec. If you then don't want a P tag to have a margin 'spacing' from the previous text block in content editable then you can use css to modify that.
  • Jelle De Loecker
    Jelle De Loecker almost 6 years
    The insertHTML command will indeed produce some weird results when you have nested contenteditable elements. Andrew's answer, where you replace the current selection with a new document fragment, is better for this.
  • Jelle De Loecker
    Jelle De Loecker almost 6 years
    The insertHTML solution does some weird things when there are nested contenteditable elements, your solution circumvents that but there are some more issues, I added it as a new possible solution.
  • Ahtisham
    Ahtisham over 5 years
    I does execute twice for the first time.
  • AaronHS
    AaronHS over 5 years
    this is actually not a bad solution
  • defend orca
    defend orca about 5 years
    this is a really really greatest solution, it is extreme clean and clear, nothing will be insert, even include br. and especially this solution without js.
  • cbdeveloper
    cbdeveloper about 5 years
    Wow... this solves Chrome, but makes Firefox begin adding divs on enter, which it doesn't by default.
  • JoJo
    JoJo almost 5 years
    This was the best fix after hours of search. IE11 and modern browsers work with this solution.
  • Bob Stein
    Bob Stein almost 5 years
    Glad this works, but it's dumb that this works. The difference between inline-block and block is supposed to be in the flow outside the element. This solution reveals a distinction Chrome makes inside the element. Chrome should behave the same for display:block.
  • Max
    Max over 4 years
    This is nice but I really wish you could change it to just br and not have the extra p tag at all.
  • Sushil
    Sushil over 4 years
    I want to do this whiling pasting text, is it possible?
  • Jack Lu
    Jack Lu about 4 years
    It does not let the cursor move forward as you type.
  • Jack Lu
    Jack Lu about 4 years
    I find it will not insert <br> when the cursor is before a <br>. Chrome 80. Weird.
  • MrAJ
    MrAJ about 4 years
    That is strange, I just tried in Chrome and IE 11 and it works fine. Reference Could you please tell me which browser you are using? Any more details about the behavior would be helpful for solving the issue
  • Admin
    Admin about 4 years
    This also doesn't work when the element is a grid child. The inline-block will not do anything, and pressing Enter still inserts <div>s.
  • Admin
    Admin about 4 years
    This doesn't work when the element is a grid child. The inline-block will not do anything, and pressing Enter still inserts <div>s.
  • Admin
    Admin about 4 years
    Doesn't work on Chrome. First time when you press enter at the end of the string, it adds a space. The second time it works though.
  • Admin
    Admin about 4 years
    I have added a modern solution (check below), which actually works as expected.
  • Dror Bar
    Dror Bar about 4 years
    A solution with pure javascript is preferred.
  • SO Stinks
    SO Stinks about 4 years
    .execCommand() is now considered obsolete by MDN... See Document.execCommand()
  • user12861
    user12861 almost 4 years
    What the heck? How can the only solution that actually worked for me be this far down the page? Thanks so much.
  • Matt
    Matt almost 4 years
    Doesn't do anything on my end…
  • Alexander Kludt
    Alexander Kludt over 3 years
    You just made my day, this took hours to figure out - thanks!
  • ahsan ayub
    ahsan ayub over 3 years
    execCommand is depricated! This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards.
  • Serkan Sipahi
    Serkan Sipahi about 3 years
    Thanks! This works fine for me. It does not add div or br.
  • stackoverflow
    stackoverflow about 3 years
    this is what I needed!
  • Dee
    Dee about 3 years
    great! simple enough, now it inserts <br> instead of <div>
  • danish
    danish almost 3 years
    I am using a contenteditable with a child div inside and want to enter new line in that div. The code works well but not if I enter at the end of the line. At the end of the line, I have to enter twice for a new line.
  • Obed Parlapiano
    Obed Parlapiano almost 3 years
    This works right now for all major browsers and will likely continue to work as no one ever removes stuff from the web.
  • Osama Abdullah
    Osama Abdullah over 2 years
    Man. Thank you for the code, it saved me!.
  • Airy
    Airy over 2 years
    It is still in very early stage. only 57% browser support as of Dec 2021