Gijs Gijs - 9 months ago 159
CSS Question

contenteditable single-line input

For an application we're developing at the company where I work, we need an input that supports inserting emoticons inside our JS-based web app. We're currently using an input with the emoticon shortcodes (ie ':-)') and would like to switch to inserting actual, graphical images.

Our original plan was to use a

. We're using listeners for the paste event as well as the different key/mouse interactions to ensure no unwanted markup enters the contenteditable (we strip text out of its container tags and leave only image tags that we inserted ourselves).

However, the problem right now is that the div resizes if you put in enough content (ie its height increases). We don't want this to happen, nor is it acceptable for the text to just be hidden (ie plain
overflow: hidden
). So:

Is there a way to make the contenteditable div behave like a single-line input?

I'd like it best if there is a relatively simple attribute/css property that I've missed that will do what I want, but if necessary CSS+JS suggestions will also be appreciated.

Answer Source

So, for posterity: the simplest solution is to get your product manager to change the requirements so you can do multiline editing. This is what ended up happening in our case.

However, before that happened, I ended up going quite a way in creating a manually moving single-line richtext editor. I wrapped it up in a jQuery plugin in the end. I don't have time to finish it up (there are probably bugs in IE, Firefox works best and Chrome works pretty well - comments are sparse and sometimes not very clear). It uses parts of the Rangy library (extracted because I didn't want to rely on the complete library) to get screen positions of selections in order to test for mouse position vs. selection (so you can drag selections and move the box).

Roughly, it works by using 3 elements. An outer div (the thing you call the plugin on), which gets overflow: hidden, and then 2 levels of nesting inside it. The first level is absolutely positioned, the second level is the actual contenteditable. This separation is necessary because otherwise some browsers will give the contenteditable absolutely positioned element grippies, to let the user move it around...

In any case, then there is a whole bunch of code to move the absolutely positioned element around inside the top element, thus moving the actual contenteditable. The contenteditable itself has white-space nowrap, etc. etc. to force it to stay a single line.

There is also code in the plugin that strips out anything that isn't an image (like br, tables, etc. etc.) from any text that's pasted / dragged into the box. You need some parts of this (like the brs, stripping/normalizing paragraphs, etc.) but maybe you would normally want to keep links, em, strong and/or some other formatting.