10 ms·
Why ContentEditable Is Terrible, Or: How the Medium Editor Works (2014)
- meric 11y agoI've always wondered how web non-contenteditable editors implement WYSIWYG. This is a good guide.
- Tiquor 11y agoThe ability tof have your storage format be your own is also an advantage that non Web editors have.
- KaoruAoiShiho 11y agoSo what's a good editor that works this way? I know that quilljs is coming out soon but it's still not released yet. Trix has a ton of bugs and the 1.0 version is still in development. Is there a stable one.
- Rezo 11y agohttps://prosemirror.net https://prosemirror.net is nice to use and seems quite mature. Made by the guy who also did the popular CodeMirror.
- ohfunkyeah 11y agoThe API and internal code is still expected to change. He very recently finished a large breaking refactor, so it is not mature. Having said that it is a nice editor with a lot of promise.
- javan 11y agoWhat ton of bugs? Trix is used by thousands of people daily in Basecamp 3. I'd like to think it's pretty stable.
- mymmaster 11y agoI assume you've seen this: https://github.com/yabwe/medium-editor https://github.com/yabwe/medium-editor It uses ContentEditable. Wonder what your thoughts are?
- travjones 11y agoThe medium-editor project is pretty good. It's not a "true" clone of the medium editor, but it gets development up and going pretty quickly with a contentEditable editor. We used medium-editor for http://www.doctant.com http://www.doctant.com. As others have noted, it's really tough to compete with text editing/rich text applications (e.g., Sublime, Vim, Word, etc.) on the web. So far, the real Medium is the only app that I've used that isn't a pain to write in even though it's contentEditable. Another promising project is draftjs from Facebook. Check it out: https://facebook.github.io/draft-js/ https://facebook.github.io/draft-js/.
- andy_ppp 11y agoI've used it before - about a year ago and found it to be quite buggy in actual use.
- feiss 11y agoI've used it about 3 months ago and it didn't feel so buggy. Quite stable and nice, BUT not totally stable, I'm afraid :(
- morgante 11y agoI made an extensive prototype with it and definitely do not recommend it. It's really just a UI clone of the Medium editor. It doesn't work at all the same way under the hood and instead tries to use ContentEditable as the store of a document. Any approach which works that way is doomed to failure. ContentEditable works fine as an input but you need to have a pure mapping from all inputs to an internal structure which only your editor controls.
- manigandham 11y agoHere's a list of HTML content editors that I put together back when basecamp released Trix: https://news.ycombinator.com/item?id=10413549 https://news.ycombinator.com/item?id=10413549
- Jaruzel 11y agoOn the basis that browser based WYSIWYG editors have become de-rigour in almost all big online publishing platforms, it surprises me that the browsers themselves are not being updated to provide a standard input field (standardised via w3c of course) whose 'value' attribute outputs basic HTML mark-up. Something along the lines of: <input type="editor" supports="bold;italic;images;headings" ... > This would remove the massive amount of work that UI developers still have to do to hand crank something as simple as a good editor that GUI OSs have enjoyed for decades.
- intrasight 11y agoWow, that would be sweet!
- Rezo 11y agoIf the browsers incorporate complex editors, they're likely to be subtly or even wildly different from each other in behavior. What's the "correct" behavior after hinting enter in an unordered item list, create a new bullet or start a new line for the current one? Is there a popup to create links when you highlight text? Can a heading be split over multiple lines? Some of the answers depend on the constraints of your underlying storage format like Markdown vs HTML. On the other hand, if I pick ProseMirror or Draft.js, I can be reasonably secure in that the behavior is consistent for my users. If a capability can be implemented outside of the core browser, I think it's a good idea to do so. It's sort of like putting something into the Linux kernel vs doing it in a userspace module. The kernel/browser should provide the low-level hooks for userspace to innovate, not try to incorporate userspace components. An external project can iterate more rapidly, and there's also a lower barrier for people to contribute code and fixes. Duplicate projects "waste" resources, but they're also competing with each other and that improves quality in the long run.
- esailija 11y agoAka Extensible Web https://extensiblewebmanifesto.org/ https://extensiblewebmanifesto.org/
- KwanEsq 11y ago
- afiedler 11y agoFacebook's draft.js[1] tries to solve a lot of these problems and uses React under the hood to maintain a mapping between the model of the document that you are editing and the DOM. I have only played with it, not used it in production, but if you are using React it could be a good solution. The one limitation I've seen is that is doesn't really support documents that need a hierarchical model (an example of this would be tables, but also things like "I want a code block within a blockquote"). If you want to see draft.js's document model, I made a tool to do that, too[2]. [1]: https://facebook.github.io/draft-js/ https://facebook.github.io/draft-js/ [2]: http://afiedler.github.io/draft-js-dm-demo/ http://afiedler.github.io/draft-js-dm-demo/
- dminor 11y agoOne big problem with draft.js is it doesn't play well with tools like grammarly that reach into the dom and modify it. Medium's editor side steps this by just rerendering after each input.
- underwater 11y agoDraft.js does (or did at some point) have some affordances for this so that it could handle mobile devices. Keyboards on Android Chrome used to emit keycode 0 for every character that was inserted and then mutate the DOM directly. And spelling corrections just mutated he DOM without firing events.
- BasDirks 11y agoThere are a bunch of bugs immediately apparent. Try typing while making a selection with mouse. Is that expected behaviour? nah.
- spicyj 11y agoWhat? This should work properly. If it doesn't, please file a detailed bug with info about your browser.
- teleclimber 11y ago
- twlng 11y agoFor http://www.TwLng.com http://www.TwLng.com we're using http://quilljs.com http://quilljs.com
- georgestephanis 11y agoYup. Wysiwygs are hard. But just saying "You can edit paragraphs, that's all you get" is worse. Clients need to be able to do more advanced things in an editor, and coding a hard limit on never being able to do them feels like pure folly. Is TinyMCE perfect? Far from it. But it's stable and reliable across browsers, with a well-defined API, and it gets the job done. I know a lot of folks here would just as soon just use Markdown for all content writing. I like Markdown. Clients hate it. It feels like an obscure language, when they just want something "like Microsoft Word". And CMS's can hardly say "Yeah, we know we used to support these greater markup sets, but now we're just not going to, so don't open up your old posts, or they're going to lose some content in our bright shiny new editor" -- that's massively problematic as well for user trust. If you're starting something new, and want to place a hard cap on what your users can do markup-wise, sure, give this a shot. But be very aware of the restrictions that you're imposing.
- iopq 11y agoI hate markdown. I always use a single line break to indicate a single line break. Having to use two breaks the most basic expectation of editing text.
- jimktrains2 11y agoDo you mean you don't like Line1 Continuation of Line1 Line2 If you're wrapping text, how else would you be able to do it?
- vertex-four 11y agoHard-wrapping text probably isn't something most people should be doing in most cases, especially for text documents. Computers are generally at least OK at wrapping automatically for display or editing - we've had code for it almost as long as we've had GUIs. It's certainly not a concern for many of the places Markdown gets used - online systems where the primary form of entry is a textarea. Therefore, those places should likely not use Markdown.
- swalsh 11y agoI once used ContentEditable combined with Angular JS. It was the single worst UX development experience in my life. What a terrible control. I was trying to make an interface that binded an array of models, which had individual properties that bound to a properties panel on the side. Editing the property panel would instantly update the text, and updating the text would update the property panel. (the way i'm describing it you might wonder why do you need it in two places, but i assure you it made a bunch of sense... and was a super cool idea). I ran into the problem though that if you accidentally deleted the text, but than tried to write it again all the bindings instantly broke. Or conversely you might start writing some text with the intent of it being outside the binded area, but it would still be inside... so the analysis that set the property panel control didn't work as expected. I eventually got something that worked... but it was far from the original vision. I never really did figure out how to gracefully work with the control.
- jessaustin 11y agoFrankly, it's not surprising that what you describe was difficult. Very few libraries would have been designed with that sort of "updates in both directions" architecture in mind.
- underwater 11y agoIt could me possible if contentEditable had events that corresponded to edits that were about to happen. Instead it just emits the raw interactions (e.g. keypress) and then mutates the DOM. It's very easy to get a mutation cannot be retroactively mapped to an edit.
- Semiapies 11y agoIs anyone actually still using bare contenteditable in a serious way?
- RobertKerans 11y agoYeah, I just built an [internal] CSS documentation system; every item has a fully editable example using CSS in style tags on the page, each with contenteditable applied to allow users to play around with it; editing within the style tag immediately alters the styling of the associated example. Works beautifully, as I have no need to persist anything, and zero JS used. (I get this is an edge case; I've tried using it a couple of times for persisted input and, yeah, not a good idea past simple I/O)
- whistlerbrk 11y agocontenteditable stole 4 months of my life from me. I wish I'd read way way more before charging a hill so so many before me had died upon. Very happy we have sensible alternatives today like Medium.js amongst the others people have mentioned.
- rtcoms 11y agoI would like to see a comparison between Trix : https://github.com/basecamp/trix https://github.com/basecamp/trix (From Basecamp) ProseMirror : https://prosemirror.net/ https://prosemirror.net/ Draft.js : https://facebook.github.io/draft-js/ https://facebook.github.io/draft-js/
- javan 11y agoThey all use contenteditable for I/O only (no execCommand), and they all maintain their own internal document model.
- ohfunkyeah 11y agoWhich is why the interesting part of the comparison would focus on where they differ.
- ilmiont 11y agoRemember reading this article when it was first published... very interested to do so again!
- nickstefan12 11y agoMy attempt at implementing what medium describes: https://github.com/NickStefan/tome-editor https://github.com/NickStefan/tome-editor My favorite idea was using independent ranges data objects to track styling. Eg {start: 2, end: 3, range: color, value: blue}. Then only the rendering api needs to worry about overlapping ranges. Basically avoids manipulating trees. That's partly what makes content editable suck so much.
- dmix 11y agoCould you publish an online demo, even a gif if you don't want to host one? You're probably missing out on quite a few users who are too lazy to clone and install, just to bookmark for later use.
- nickstefan12 11y agoI've been meaning to do that! I'll definitely move it up the priority list. I had intended the api to be entirely programmatic and allow others to build GUIs for how they wanted, say, font size drop downs to look. I could host the test html page I've been testing it with. It exposes some random styling buttons and visualizes the data model below the rendered text.
- arxpoetica 11y agoHis description of the problem is brilliant. One might disagree with the axioms presented, but the conclusion is spot on: << It’s impossible to build what ContentEditable wants to be, because they have conflicting requirements. >> Brilliantly simple.
- douche 11y agoI've been pretty happy using TextAngular so far http://textangular.com/ http://textangular.com/
- morgante 11y agoThis article was very inspirational for me when developing the CMS for a previous startup and informed that development extensively. Personally, I found the most beneficial thing to be abandoning HTML entirely. Instead I developed a JSON data structure for documents which was stored internally. This is very powerful for a couple of reasons: 1. Any user input can be mapped as pure functions on top of your internal document structure. This way you can also enforce business rules easily. Additionally, any function which you don't support will never occur. (No more Word garbage!) ContentEditable works fine as an input though. 2. You can write functionally pure mappings from your internal structure to other formats. This of course includes HTML, but isn't exclusive to HTML. Content can also be mapped into native mobile components as well. 3. You can be flexible with input types. For example, it was fairly trivial to (for fun) add a Markdown mode which would map any Markdown input onto the internal document representation and then back to Markdown. 4. You can introduce new semantic concepts which HTML doesn't have elements for, like a "quiz." This makes it easy to rejigger the display of such elements later on, or to have the same semantic element render completely differently on mobile and desktop (for example). With HTML, you're stuck doing error-prone tree parsing or Regexes.
- degenerate 11y agoWere you able to handle paste-from-word? If so, would you mind sharing that bit of code on github? I would love to make a custom solution, but 90% of the content being put into our CMS is copied from Word. To clean it effectively, I resort to using CKEditor to clean it for me and then storing as HTML. I'd love to not do that, but CKEditor seems to have figured out all the problems, especially when pasting tables or adjacently aligned content. My users won't learn markdown and expect it to just "work". For complex Word documents, I never came up with a viable solution to parse it.
- morgante 11y agoYes, we were able to handle pasting from Word. We basically gathered a ton of examples of the HTML which Word generates and then developed mappings from that HTML to the actions we supported. TDD and unit testing made it fairly efficient. Keep in mind that we purposefully did not support the full scope of HTML which Word would output. Authors couldn't make their headlines 50pt Comic Sans in red, for example. I'd love to share the code, but unfortunately it's from an old employer and I no longer have access (or the right to share the code).
- frik 11y agoContentEditable (or rich text editor in general) would be very useful. But browser vendors like Microsoft, Google and Apple all have vast interest to keep the sad quirky status quo. It would cannibalise their web word processors of their cloud services. Weird is that Mozilla Firefox shows little interest as well.