Anki Forums

Where in source to replace newline <div> behaviour


First off, kudos to all of you that put in so much time and effort into Anki and doing a great job!

I have understood from searching a bit that the reason Anki uses div’s instead of br’s for newlines is an underlying Qt-issue of br’s causing instability?

Unfortunately the div’s break my notes as I put a lot of related questions on a single note using Cloze (Hide all) which means the divs can get broken up between the clozes.

My python skills are zero, do you have any pointers on where to make an ugly hack to replace the div insertion with br’s in the source? I know that you can use shift+enter to insert br’s instead but I have 10 more terms of med school so it seems reasonable to make life easier.

I understand there are no guarantees as to the instability.


Hi, you could use find&replace for that matter. Replacing <div> for <span> and </div> for </span><br>

I explain myself badly, I want to stop Anki from inserting <div> tags and insert <br> tags always for newlines, not manually address it for every edit I do.

The issue is that you end up with this situation all too often when using cloze (Hide All)

<div>Microscopic features of the duodenum: {{c1:Some summary statement</div>
<div>Innervation of the duodenum: {{c2:Some summary statement</div>}}
<li>SNS: {{c2::blabla}}</li>
<li>PSNS: {{c2::blabla}}</li>

The above situation breaks the layout as the ending </div> is hidden when the cloze is collapsed, if <br>'s are used everything works splendidly.

I am not concerned with the stability as my current card deck uses <br> exclusively. Currently to achieve this I am using the extended editor for field (for tables, search&replace, …) to open tinyMCE which can be configured to use <br> instead of <div> and it works great. However it adds steps to the note generation that I would like to avoid (having to the open external editor for every change as well as the inconvenience of having to close tinyMCE to paste images and then reopen it again.


I see, if you paste stripping the HTML you shouldn’t get the div tags. If that is not the case, I guess you would have to rely on add-ons or JavaScript in the template.

It’s the Anki editor that inserts the <div> tags when you hit return, it is the way it handles linebreaks (rather than using <br/>), it has nothing to do with pasting.

My whole idea is to stop Anki from inserting the <divs> and insert <br/> instead. Since pressing shift+return in the editor will insert a <br/> rather than a <div> I am looking for a way to modify the source and build Anki so that just return inserts a <br/> , for instance swapping the two. I have set up a build environment so that is not an issue, I just can’t find where in the code the insertion happens. Unfortunately I don’t know enough python to know where in the code to make, say a key-press hook for the editor and invert the shift state before passing the event on which would a simple (but somewhat ugly) quick fix for example. On the Anki-level it looks like it uses <br> so I am guessing the swap is happening inside the Qt-libraries, where do I capture and mod the keypress event before before passing it on to the Qt widget?


You can use “Shift+Enter” to create a <br> instead.

Ok, after some (a lot) of head scratching. The <div>'s are inserted by the Gecko engine or similar used to render dialog, so neither in Anki nor in Qt code. For anyone interested here is what I did and seems to be working on a Windows machine at least:

  1. In editor.css contenteditable elements are modified to display: block-inline, this will make the webkit insert <br>'s, but require a width hack as that display setting will collapse the width to the content:
    *[contenteditable=“true”] {
    display: inline-block;
    width: calc(100% - 15px);

Unfortunately the “break out” command is somewhat flawed for my purposes (Gecko calls it’s internal api “break out” function when enter is pressed on an empty list item, execCommand). The logic applied leads to insertion of <div>'s once you “return out” of a list. To this end a small hack was necessary, implementing my own handling of this specific case. As the onKey event handler in editor.js didn’t seem to fire I put the hack in webview.js where the keypress event handler does fire:

document.addEventListener("keydown", function (evt) {
    if (evt.keyCode == 13 && evt.shiftKey == evt.ctrltKey ==
   		evt.altKey == evt.metaKey == false) {
          var pe = window.getSelection().anchorNode.parentElement;
          if((pe instanceof HTMLUListElement) || (pe instanceof HTMLOListElement)) {
            pe.insertAdjacentHTML("afterend", "<br/>");
            window.getSelection().modify("move", "forward", "character");

    if (evt.keyCode !== 8) {
    }..... etc etc.

And that’s it, so far it seems to be working as expected, we’ll see what breaks after some usage.


I know, but for the amount of lines I am going to need to type during my remaining 5 years of med school that’s not really optimal.

Fully agree. In fact, I already made an inquiry / suggested a change to address this issue. So with some luck, you don’t need that hack anymore in Anki 2.1.39.