Ace: Wrong cursor position

Created on 15 Jun 2015  ·  34Comments  ·  Source: ajaxorg/ace

I've used ace library for formatting json.
I know that we must use monospaced fonts. I use "Consolas", but I've another bug, cusrsor is margined right from last letter
See screen
bug

Do you know how to fix this?

Most helpful comment

I had got similar issue, and this css addition has fixed it. Might help...

.ace_editor, .ace_editor div{
    font-family:monospace
}

(Reason : As @nightwing has told. This addition of css would insure you are using monospace.)

All 34 comments

Try running

fm = editor.renderer.$textLayer.$fontMetrics;
"xiXbm".split("").map(fm.$measureCharWidth, fm)

if this prints different numbers then font used in the editor is not monospace.

Also note that adding a rule consolas !important is a bad idea since it will break on linux and mac.

I had got similar issue, and this css addition has fixed it. Might help...

.ace_editor, .ace_editor div{
    font-family:monospace
}

(Reason : As @nightwing has told. This addition of css would insure you are using monospace.)

I have users seeing this problem on Windows 10 / Chrome 41.0.2272.76.

@nightwing When I ran that piece of code this was the output.

screen shot 2015-09-14 at 12 05 26 pm

This only seems to happen on Windows. Previously I found that cursor position was _always_ wrong on Windows 8+ until I adjusted letter-spacing: https://github.com/ajaxorg/ace-builds/issues/58

However, my users are still seeing this occasionally. See screenshots here:
https://github.com/Crunch/Crunch-2/issues/39

Does Ace use _all_ CSS properties of the displayed line when measuring? Such as letter-spacing, text-shadow, text-rendering, -webkit-text-size-adjust, and -webkit-font-smoothing? (That is, does it use the computed style of the current font, as applied to the visible editor?) Or only certain ones?

@matthew-dean it requires all this properties to be customized on the editor root element, so stiles inherited by ace lines are inherited by the measure div too.
text-rendering:optimizeLegibility is not supported

@nightwing text-rendering: optimizeLegibility might indeed be the culprit. It's the only thing I could think of that would offset a monospace differently, which has apparently been a problem, specifically in Chrome, _specifically Chrome for Windows_ since Windows 7. See: https://github.com/zurb/foundation/issues/1827 (and other various bugs filed).

I'll try removing that setting, at least for the editor, to see if that changes. @vdzundza Since this is intermittent, I'd be interested to know if that works for you (and if you had that prop / value applied).

I've changed that setting to text-rendering: geometricPrecision, which should be even more accurate at text character rendering. However, on Windows, it's still drawing the cursor position inaccurately. See more screenshots @ https://github.com/Crunch/Crunch-2/issues/39

Could you give me demo page reproducing this issue, or maybe crunch-2 so that i can debug it?

@nightwing You can get a copy of Crunch 2 here: https://github.com/Crunch/Crunch-2/releases

Then message me on Twitter: https://twitter.com/matthewdeaners. On NWJS, you can get to the Chrome developer tools, but there are a few steps involved for Crunch.

@nightwing Any ideas? We're still having issues on Windows 10.

I couldn't reproduce this on windows 10, could you send me an image showing the issue?

@nightwing There are several images, some animated to show what's happening, in this thread: https://github.com/Crunch/Crunch-2/issues/39

@nightwing I think now that this is the Hasklig font (https://github.com/i-tu/Hasklig) + Chromium 41 + text-rendering with either optimizeLegibility or geometricPrecision. Any setting that enables ligatures ends up rendering with inconsistent character widths. I tested it with long lines of ligatures, and by toggling text-rendering on / off, and the lines changed length. So, in my case, it's probably not an Ace issue, since Hasklig does not appear to technically be a monospace font in that environment. Sorry for the wild goose chase; I didn't realize the font was rendering non-monospace.

Errrr... I may have spoken too soon. I'm having problems with cursor position with Source Code Pro as well, and text-rendering: optimizeLegibility is turned off. However, setting / unsetting text-rendering seems to "reset" cursor measuring, so sometimes you can't reproduce after the first time.

Okay. So, I don't know exactly the cause, but I have a fix working for me. I am setting text-indent: 0.1px and then text-indent: 0.1px after a short timeout. This triggers layout / paint / composite as noted here: http://csstriggers.com/

@nightwing One reason you haven't encountered this might be because setting an ace theme probably causes a layout / paint / composite in most cases, if any of the "inherent" font settings of the browser don't match the font settings of the theme, which seems likely. Chrome's first paint of a text line might be inaccurate, meaning Ace's measurements would be too, but as long as someone sets even one CSS property that triggers re-layout, no one would ever notice.

So, if you want to reproduce, you could test with some font settings set only in the CSS, and not in a theme, but I'm not sure what the magic combination might be to get the bug reproduced. It's also possible Ace might be able to detect this bug by measuring a particular line of text with particular CSS and comparing it against a known constant (what the result should be), and then if it doesn't match, triggering a repaint in the same manner. (But of course that would mean reproducing the bug in the first place.)

One other thing you could do is have Ace always set a (late) CSS property regardless that would always trigger layout / repaint. (I tried to figure out something that wouldn't be visibly seen, but I'm not sure what that might be.) As far as I can tell, there's no noticeable performance hit from doing this once, which is all you should need.

I've encountered the exact problem and managed to fix it (for my case).

I was running a function on the output from Ace to extract YAML front matter. Said function runs on Ace's onChange event. When my function threw errors, the cursor started to desynchronize. Contrary to another similar problem in which the cursors go out of sync permanently, this one 'recovers', because if I select-all and delete everything, and start writing without the function throwing any errors, the cursor is positioned correctly.

Not sure if I'm being clear enough, or if it helps in any way, but I suspect that any kind of interruption to the code flow surrounding Ace causes the cursor position to not get updated correctly (ergo the cursor position is updated _after_ certain things are executed, and if those fail, cursor positioning fails?).

@kenlimmj throwing error from event listeners will break the editor, since other listeners won't be called.
editor.on("input", might be a better event for what you are doing.

Same problem.

Screenshot:
image

@AviralGarg1993 you need to use monospace font.

For anyone else having this problem, this might help:

If you have a font-size set in rem (like in Bootstrap 4), your cursor would be wacky.
Setting a font size of 12px solved my problem:

.ace_editor .ace_content {
  font-size: 12px !important;
}

Basically Ace can display only 'monospace' fonts, you might change the font somehow or you were assign font namein css.
if you are working in firefox there's a default font will change your monospace font. so be aware of that.

@wislem's advice didn't work for me but put me on the right track.

I suspect using this in a global stylesheet would fix all problems regardless of framework. The base problem of using font-size in rem was the same core problem though.

.ace_editor div, .ace_editor span { font-size: 12px !important; }

Ace editor seems to be working with monospace font only. As stated by @skbly7 solution can be applying font-family:monospace but adding !important will prevent overriden by other css applied after words on elements.

.ace_editor, .ace_text-input, .ace_editor div{
    font-family : monospace !important;
}

I'm building a new site using Ace for Less.js and this is still an issue, with nothing else on the page except for 2 editors. Going to try my old text-indent: 0.1px hack.

This time these were the default styles in a Vue project that were the culprit:

html {
  word-spacing: 1px;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
}

The Ace default styles should probably reset those settings.

This seems to be an old problem with Ace editor, especially obvious when you paste some text in non-english

My assumption is that some crazy code here is causing it
https://github.com/ajaxorg/ace/blob/902d1a02864479cfa7c47f46972ff53fb56924fc/lib/ace/virtual_renderer.js#L1221

try with
Встре́ча с медве́дем мо́жет быть о́чень опа́сна. Ру́сские лю́ди лю́бят ходи́ть в лес и собира́ть грибы́ и я́годы. Они́ де́лают э́то с осторо́жностью, так как медве́ди то́же о́чень лю́бят я́годы и мо́гут напа́сть на челове́ка. Медве́дь ест всё: я́годы, ры́бу, мя́со и да́же насеко́мых. Осо́бенно он лю́бит мёд.

instead of picking weird fonts, dont you want to fix the cause instead? This is not an issue in monaco editor

You havent fixed the cursor issue yet. It's very much still in there and I don't think the problem is the css. It's the crazy cursor logic

https://github.com/ajaxorg/ace/blob/902d1a02864479cfa7c47f46972ff53fb56924fc/lib/ace/virtual_renderer.js#L1309

and especially
https://github.com/ajaxorg/ace/blob/902d1a02864479cfa7c47f46972ff53fb56924fc/lib/ace/virtual_renderer.js#L1482
https://github.com/ajaxorg/ace/blob/902d1a02864479cfa7c47f46972ff53fb56924fc/lib/ace/virtual_renderer.js#L1509
the X coordinate is off!
this affects the gutters too. font width is not taken into consideration at all

or maybe
https://github.com/ajaxorg/ace/blob/7285dad33867771a688a96bbf2309f4e995a5b7d/lib/ace/layer/cursor.js#L174

I am kind of on the verge of refactoring my app to use monaco instead, but also wondering if this can be fixed

even when I set to monospaced font in russian, the issue is still there

One temporary solution for this monospace font hell is to include a monospace font with ace editor that covers all languages, not just russian

I think there is another problem with the pasting of formatted text into ace editor messing up the cursor position. Ace is not sanitising it

@blurymind I think the long and short is the algorithm for estimating cursor position is terribly naive about how fonts are rendered in a browser engine. So rather than measure how characters are actually drawn, it seem to estimate what they "should be" based on some basic CSS settings and maybe the size of a single character, and assumes the metrics should hold for the rest of the text? I'm not sure what assumptions are being made but they seem to be inherently flawed.

You can't really know where the end of a rendered text block is without getting its actual metrics. I'm not sure what the correct algorithm is, but it seems that because this is so easy to break, however they're reasoning about cursor position and text width is fundamentally flawed.

In my case it only happened after typing "ff" or "fi"...For me turning off ligatures worked.
So just add
.ace_editor, .ace_editor div { font-variant-ligatures: none !important; }
to the css.

Hope it helps ;)

Hi,
weird situation here but I can confirm that the font is not the single issue.
On my project I have a component using Ace editor to input JSON. It always forces font to be "monospace".
Anyway, it works smoothly on Storybook when isolated.
When the component inherits from CSS (when used in the app, not in storybook), I sill have the same issue of malfunctioning cursor.
There are a lot of inherited styles, but the font is monospace.

@Copainbig other css rules may interfere as well, e.g. setting font-size for all div elements

I'm using mediawiki + chrome and encountered the same error.

Problem solved by using

.ace_editor, .ace_editor * { font-family: "Monaco", "Menlo", "Ubuntu Mono", "Droid Sans Mono", "Consolas", monospace !important; font-size: 12px !important; font-weight: 400 !important; letter-spacing: 0 !important; }

in Mediawiki:Common.css

@skbly7 I was facing this problem, looks like in the previous version of Ace Editor, your solution worked however for me it didn't.

Here's the solution you were looking for,

.ace_editor * {
    font-family: monospace !important;
}

All you need to know

So apparently you cannot really use some other font when using an ace editor. It's going to mess up a lot of UX for your code editor or whatsoever you might be working on where you're probably trying to implement ace editor. So in case you face this problem in the future, you can use the above stated code in order to get rid of this shitty problem because it's a bitch to solve. And no it wasn't a javascript error it was just a css error/bug due to which it wasn't working the way it was supposed to.

.ace_editor, .ace_editor * { font-family: "Monaco", "Menlo", "Ubuntu Mono", "Droid Sans Mono", "Consolas", monospace !important; font-size: 12px !important; font-weight: 400 !important; letter-spacing: 0 !important; }

works just fine for me, on windows10 using the react ace package

Was this page helpful?
0 / 5 - 0 ratings