Show HN: OverType – A Markdown WYSIWYG editor that's just a textarea

447 points by panphora 2 days ago

Hi HN! I got so frustrated with modern WYSIWYG editors that I started to play around with building my own.

The problem I had was simple: I wanted a low-tech way to type styled text, but I didn't want to load a complex 500KB library, especially if I was going to initialize it dozens of times on the same page.

Markdown in a plain <textarea> was the best alternative to a full WYSIWYG, but its main drawback is how ugly it looks without any formatting. I can handle it, but my clients certainly can't.

I went down the ContentEditable rabbit hole for a few years, but always came to realize others had solved it better than I ever could.

I kept coming back to this problem: why can't I have a simple, performant, beautiful markdown editor? The best solution I ever saw was Ghost's split-screen editor: markdown on the left, preview on the right, with synchronized scrolling.

Then, about a year ago, an idea popped into my head: what if we layered a preview pane behind a <textarea>? If we aligned them perfectly, then even though you were only editing plain text, it would look and feel like you were editing rich text!

Of course, there would be downsides: you'd have to use a monospace font, all content would have to have the same font size, and all the markdown markup would have to be displayed in the final preview.

But those were tradeoffs I could live with.

Anyways, version 1 didn't go so well... it turns out it's harder to keep a textarea and a rendered preview in alignment than I thought. Here's what I discovered:

- Lists were hard to align - bullet points threw off character alignment. Solved with HTML entities (• for bullets) that maintain monospace width

- Not all monospace fonts are truly monospace - bold and italic text can have different widths even in "monospace" fonts, breaking the perfect overlay

- Embedding was a nightmare - any inherited CSS from parent pages (margin, padding, line-height) would shift alignment. Even a 1px shift completely broke the illusion

The solution was obsessive normalization:

    // The entire trick: a transparent textarea over a preview div
    layerElements(textarea, preview)
    applyIdenticalSpacing(textarea, preview)

    // Make textarea invisible but keep the cursor
    textarea.style.background = 'transparent'
    textarea.style.color = 'transparent'
    textarea.style.caretColor = 'black'

    // Keep them in sync
    textarea.addEventListener('input', () => {
      preview.innerHTML = parseMarkdown(textarea.value)
      syncScroll(textarea, preview)
    })
A week ago I started playing with version 2 and discovered GitHub's <markdown-toolbar> element, which handles markdown formatting in a plain <textarea> really well.

That experiment turned into OverType (https://overtype.dev), which I'm showing to you today -- it's a rich markdown editor that's really just a <textarea>. The key insight was that once you solve the alignment challenges, you get everything native textareas provide for free: undo/redo, mobile keyboard, accessibility, and native performance.

So far it works surprisingly well across browsers and mobile. I get performant rich text editing in one small package (45KB total). It's kind of a dumb idea, but it works! I'm planning to use it in all my projects and I'd like to keep it simple and minimal.

I would love it if you would kick the tires and let me know what you think of it. Happy editing!

---

Demo & docs: https://overtype.dev

GitHub: https://github.com/panphora/overtype

pedrovhb a day ago

Nice! Seems very useful if you can drop in and have everything work.

Nitpicking a bit: it's not as much _rendering_ markdown as it's _syntax highlighting_ it. Another interesting approach there could be to use the CSS Custom Highlight API [0]. Then it wouldn't need the preview div, and perhaps it'd even be possible to have non-mono fonts and varying size text for headers.

[0] https://developer.mozilla.org/en-US/docs/Web/API/CSS_Custom_...

pwdisswordfishz 20 hours ago

Calling it WYSIWYG is a misnomer: this is just syntax highlighting, it just so happens that the highlighting styles agree to an extent with the final rendering. And the idea is not exactly new: https://mediawiki.org/wiki/User:Remember_the_dot/Syntax_high...

Two issues I saw:

- on my phone, the framerate noticeably drops as I scroll over the widget

- caret positioning within the textarea seems to desync against the letter positions in the highlighted div

And the whole concept severely constrains the styling choices that could be applied to the highlighted output, but I suppose that was a given.

mmastrac a day ago

This is pretty nice, though I'd suggest you call it a transparent syntax highlighter.

For https://grack.com/demos/adventure/, I used a hidden <input text> for something similar. I wanted to take advantage of paste/selection and all the other goodies of text, but with fully-integrated styling.

Like you, I found that standard text input boxes were far more interesting than contentEditable because they're just so simple overall.

I think there's probably an interesting middle ground here where you render real markdown with the textarea effectively fully hidden (but still with focus), emulate the selection events of the rendered markup into the textarea, and basically get a beautiful editor with all the textarea solidness.

  • rockwotj a day ago

    Fun fact: this is how github adds syntax highlighting in its search bar. A while back I built the same syntax highlighting in Shortwave (an email client) using the same “view on top of a transparent input” trick. Pair it all with the following blog, for a top notch search UX

    https://blog.superhuman.com/delightful-search-more-than-meet...

vmurthy a day ago

Went down the rabbit hole which is the overtype.dev website (nice work btw!) and found and even nicer rabbit hole - https://hyperclay.com/ Single HTML apps :). Enjoy!

  • pavlov a day ago

    This is coming close to WWW's original vision because the very first web browser was also an editor. Tim Berners-Lee's application on the NeXT was basically a wrapper for the operating system's built-in rich text editing class named TextView. (It later became NSTextView on Apple's Mac OS X and still powers the TextEdit app on Mac.)

    We lost editing for two reasons:

    1) The HTTP PUT method didn't exist yet, so edited HTML files could only be saved locally.

    2) Mosaic built a cross-platform web browser that defined what the WWW was for 99% of users, and they didn't include editing because that would have been too complex to build from scratch in their multi-platform code base.

  • dcreater a day ago

    I don't say this often or lightly: my mind is blown.

    Why is this not catching fire? Especially in the day of vibe coding this is a far better and far more effective route to app building

  • runako a day ago

    This reminds me of some of the better experiments in mid-aughts Web dev, and is exactly the kind of project that helps push standards & user expectations forward.

phonon a day ago
  • Imustaskforhelp a day ago

    what is this tom foolery. I am so amazed by it, this also seems to be a WYSIWYG but though it doesn't support markdown exactly per se but it has way more features than overtype (no offense to overtype which is also a really really cool project)

    My mind is utterly blown with what you can do with 912 bytes.

    I imagine that I can create a really simple blog post that can load under 14 kb so that it can be sent in a (single request?) while still having comment feature with this one while also being super fast..

    So good that words can't explain lol

    • WA a day ago

      It uses queryCommandState(), which is a deprecated browser feature [1]. It's quite common in many simpler WYSIWYG editors. Thing is, it might be so widespread that some people claim that it will never be truly deprecated.

      OverType doesn't use this and the result is that you gotta build all the features in JS.

      [1]: https://developer.mozilla.org/en-US/docs/Web/API/Document/qu...

janwilmake 2 days ago

Really cool! I just love the simplicity of it: has no drawbacks compared to regular textarea, but has lots of benefits. you basically improved textarea, by a lot!

I also made a similar thing a while ago called contextarea.com, maybe, I should add overtype!

  • ikurei 2 days ago

    Having to use a monospaced font is a pretty big drawback. To me, it means I wouldn't use this for a product that wasn't intended for a techie programmer audience.

    Not that it isn't a really cool project! I'm only saying it has clear drawbacks.

garbageoverflow 2 days ago

If it were a WYSIWYG editor, there'd be previews for images. But it seems like it's just syntax highlighting for textareas. Nice project either way, but false advertising.

  • ricardobeat a day ago

    Indeed it is a misuse of the term. An actual WYSIWYG editor would not show any of the formatting markers.

    By definition a “Markdown editor” cannot be WYSIWYG - you can have a WYSIWYG editor that is powered by markdown underneath though, which this is not.

  • calmworm a day ago

    I didn’t see an option for images. Am I missing something?

    • macintux a day ago

      I assume that was the point. The parent commenter feels "WYSIWYG" by definition includes images.

  • WA a day ago

    I can type text, mark it, click "B" for bold and it works. This is WYSIWYG minus images.

    • clippyplz a day ago

      WYSIWYG does not refer to the icons in the toolbar, but rather the text itself. This is not WYSIWYG because when I make something bold, I see a bunch of asterisks around it.

      Still a cool project, but someone who does not understand markdown would wonder why pressing the heading button makes my text into a hashtag instead of making it bigger.

      • WA 19 hours ago

        I see both. It's bold and has asterisks around the bolded text.

    • eviks a day ago

      You see _ text _, but instead of 2 underscores you get formatted text. That's a definitional violation of WYSIWYG editing style

reactordev a day ago

This is actually really clever. Just don’t let it balloon out to be a 500kb full fledged WYSIWYG editor, just keep it simple like you do.

splitbrain a day ago

> Embedding was a nightmare - any inherited CSS from parent pages (margin, padding, line-height) would shift alignment.

This seems to be the perfect use case for a web component and its shadow DOM. Instead of using a div.editor, this component could wrap around a textarea and it would progressively enhance the textarea experience.

Jonovono 2 days ago

Nice, I was playing around with Milkdown. it's pretty cool: https://milkdown.dev/playground. It's like a block editor like notion for markdown so you don't need the split pane markdown/preview either

c-smile 19 hours ago

Well, Highlight API ( https://developer.mozilla.org/en-US/docs/Web/API/Highlight ) should just work inside <textarea> too.

At least it works in my Sciter like this:

    <style>
      textarea::mark(myHighlight) {
        background-color: yellow;
        color: red;
      }
    </style>
    <body>
       <textarea>Lorem ipsum dolor sit amet</textarea>
    </body>
    <script>

      // Select a range of text to highlight
      const range = document.createRange();
      const textNode = document.querySelector('textarea').firstChild; 

      range.setStart(textNode, 6); // Start at the 6th character
      range.setEnd(textNode, 11); // End at the 11th character

      // Highlight the range
      range.highlight("myHighlight")

    </script>
Ask your browser vendor to enable highlight API in <textarea> too :) so such tricks will not be required.
rendaw a day ago

I made something similar! https://github.com/andrewbaxter/malarkdowney - The main difference (I think) is that mine applies h* style changes and isn't visually separated from the rest of the page. I.e. it's not just syntax highlighting, it's a more fully-blown output preview.

The text overlay approach doesn't work if you want width-affecting/height style changes (I assume) since that'd cause the overlay to stop matching. The downside is contenteditable cursor movement is broken for inexplicable reasons.

z5h 16 hours ago

I tried exactly this idea a few years ago (inspired by how Bear app did Markdown at the time). But I never solved all the issues to get it working 100%.Eventually I just gave up and moved on. So bravo and thank you for making it work!!

bloppe a day ago

This isn't really WYSIWYG because it keeps the formatting symbols like * or # etc.

  • matthews3 21 hours ago

    WYSISTWYG: What You See Is Similar To What You'll Get

  • lifthrasiir a day ago

    Still, what you see is what you get (plus some formatting symbols). It's marginally WYSIWYG.

iambateman 20 hours ago

This is really cool! Thanks for sharing your work. As a live Markdown styler, it's beautiful and quite well done.

My life-long gripe is that Microsoft Word forms the basis for what people think text editing is and should be. This could be incredibly useful for developers though.

mosselman 2 days ago

Very cool! So simple, I love it.

One thing that would be great is a bit better support for lists (todos, unordered and ordered) where when you press enter once it will add another `-` or `- [ ]`, etc item and when you press it a second time it becomes a blank line.

tomsmeding 2 days ago

In Firefox on Android, the bold font is wider than the upright and italic fonts, breaking alignment.

(It works fine in Chrome on the same Android phone. Android 16, Firefox 141.0.3)

  • lifthrasiir a day ago

    In fact, depending on font-synthesis [1] and the exact choice of fonts (even when they are monospaced), the alignment can be easily off. That's why this approach only works to some extent and not universal. One possible remedy is to wrap each grapheme into a cell that contains both fonts, where the visible one is bolden and the invisible one affects the advance width. But then you lose ligatures. (Personally I don't like ligatures in coding fonts so it's plus for me, though.)

    [1] https://developer.mozilla.org/en-US/docs/Web/CSS/font-synthe...

holler a day ago

Looks nice! I like how simple/clean it is. I spent 3+ months building a contenteditable component from scratch for https://sqwok.im, learned a lot and was fun but oh my did it get challenging, especially with cross-browser issues.

gethly a day ago

Syntax highlighting for markdown input is a good idea. I too have a markdown input and i have two modes for render - either the github style where you manually toggle between editing and rendering or i have two columns with editing on one side and live render on the other.

I too was close to making my own wysiwyg, trello for example has a md wysiwyg, so i knew it was doable with contenteditabe. But after talking with the dev community I was constantly warned by people who took the path before to not do it. So in the end i did not as i did not want to invest more time than i wanted to commit to the project.

Good for you, that you did and you made it to the finish line.

nbbaier a day ago

Isn't this just syntax highlighting and not wysiwyg?

SamInTheShell a day ago

This is a nifty little project. If I wasn't already neck deep in blocknote adoption in a small experiment I'm doing, I'd be taking this for a spin.

I noticed on the site the really cool animation you got has a 1px solid border on one of the overlays in firefox. Figure you might care since it's clearly supposed to be flashy.

ingigauti 2 days ago

Great idea & solution

I noticed toolbar is missing from options doc, reason I went looking was if I could add my own custom button to the toolbar

aschelch 2 days ago

Looks awesome. Like the simplicity. I'll keep that in mind for future project ;)

(Btw, there might be a typo on the landing page on the set up part. There is 2 times de <div> instead of the textarea i guess;))

Edit: and the link to the Github is brocken

  • panphora 2 days ago

    The idea is that two instances of overtype would be initialized inside those divs!

TeddyDD a day ago

Have you considered wrapping this in web component so it can be used without the div + constructor call ceremony?

jona777than a day ago

Love the simplicity. These sort of “less is more” solutions should become more prevalent as average code volume continues to rapidly increase

zoom6628 a day ago

This is great. I was a huge fan of typora for writing docs a few an ago and now do all in obsidian. In both the editing is plaintext but the visible text is rendered inline with formatting.

Love what you have done and will use in a project next week.

Especially applaud your avoidance of npm, dependencies, and the usual ubiquitous JavaScript deluge.

jtbayly 19 hours ago

I'm not understanding the difference between Main Editor and Live Preview on the demo page. They look identical to me. And both seem to have a live preview, as far as I can tell.

wesz a day ago

I used exactly the same approach years ago working on code editor with js evaluation - http://labs.onether.com/javascript-sandbox/ (this is some old version only with whitespace characters, it also had syntax highlighting but i couldn't find it).

Anyway, nice work mate.

WA a day ago

Great project! I was looking into this area too for a while. Any reasons you didn't turn this into a web component? Seems like a no-brainer if I can basically use it like `<overtype-textarea>` or something like that.

philo23 2 days ago

The first time I saw this technique was while trying to figure out how GitHub styled the keyword:value tokens in their search box. It's a very cool technique, and you've done a very nice job of integrating it with a markdown parser!

Only down side to it is that you cant apply any padding to the styled inline elements.

jv22222 a day ago

Smart! I’ve been working with contenteditable for 3 years. You found a great shortcut!

pyromaker a day ago

I also got frustrated with text editors and decided to build something for myself too, so I don't have to repeat the process over and over.

https://www.texteditors.dev

  • dcreater a day ago

    Why do I have to sign up?

indigodaddy a day ago

This is pretty awesome. Now I’m just a dumbo sysadmin with limited webdev/JS skills, so is there a high level way to integrate this into a site so that it could create MD files that could be saved server side?

  • small_scombrus a day ago

    Most JS/TS runtimes have filesystem modules, at it's simplest/least secure you could implement it with client-side fetch and:

    On get request - find matching .MD file and return

    On put request - write to given location

nm980 2 days ago

Can you send the GitHub link again?

And how does this handle rendering larger documents?

ForceBru a day ago

I thought it should be extremely portable ("everything just works, it's native"), but it doesn't work on iOS 9.3.6. It doesn't even let me input text into the textarea...

A natural extension seems to be a source code editor with syntax highlighting, like those used in https://marimo.io/, Jupyter, https://plutojl.org/ and other notebook-like Web editors.

  • acherion a day ago

    I'm not sure why you are testing in iOS 9.3.6. (which was released in 2015), when the documentation says support for Safari is for versions 16 and above.

    • ForceBru a day ago

      Well, as I said, I thought this should work everywhere because it's just a textarea, so I didn't read the docs and rushed to test my hypothesis on an old and widely unsupported device

neilv a day ago

Am I doing it wrong?

The animation shows variable-pitch fonts, but the demo seems to be all the same fixed-pitch font for me. (On Firefox ESR and Chromium.)

drob518 a day ago

This is cool (and amazingly simple). Would be even cooler than it already is if it would syntax highlight code in code blocks, too.

maz1b 2 days ago

Nice job. How is this different than marked on npm?

rafram a day ago

The scroll syncing in the demo doesn’t seem to work well on iOS Safari. I can’t scroll all the way to the bottom.

walterlw a day ago

would absolutely love this for a personal note-taking project, but having image support and some sort of auto-completion for commands, lists, tags etc is crucial for something i'd use every day on desktop and mobile. Still love seeing more options for different purposes.

bullen a day ago

Anyone knows a good in browser coding editor widget?

That supports color coding for different languages?

  • farley13 a day ago

    Codemirror is pretty decent. Last time I looked for this (6+ years ago) it's what we landed on for an internal tool. Things may have changed tho!

ZYbCRq22HbJ2y7 a day ago

That is not just a textarea, but it is a pattern seen in many other projects

Imustaskforhelp a day ago

This is a really good project, kudos!

What I am wondering is if I can modify the project enough so that lets say when I do # test, then it can automatically modify it to be enlarged instead of just colored/ basically i think that this is how reddit comments work..

Image support would be really preferred too, but honestly, this is seriously so cool that I can iamgine using this right now, but someone here mentioned spell/pell https://github.com/sylvainpolletvillard/spell and https://github.com/jaredreich/pell and so they are in the size of 1kb-2kb, even bytes and this is 40kb iirc, so why is there such a big size difference and how are those guys being so small.

Once again, amazing project, my mind is truly blown by how simple it is, I will try to integrate this or spell or just anything whenever I can!

kaboomshebang a day ago

Very cool and useful!! Thanks for OSS this :)

jackbridger a day ago

12 pages of docs vs it’s a textarea. Great job, gonna try it out.

rakag a day ago

This is exactly what I need for my project :)

cchance 2 days ago

is there a way to show the rendered preview (not with the markdown characters)

jerpint 2 days ago

This is great! Gonna try this on my next project

albert_e a day ago

Minor typo:

> A PEAK UNDER THE HOOD

I think you meant "PEEK"

octobereleven 2 days ago

Love this. Pretty much markdown on steroids!

ivape 18 hours ago

Can you find a way to turn of mobile zoom? Gotta mess with the viewport a bit. It messes up the whole flow of clicking in and out.

6510 19 hours ago

It is just wildly annoying that this still isn't available out of the box. Try control+selecting multiple bits of text. I'm suppose to re-implement this?

sdairs a day ago

This is really nice

grigio a day ago

what about tables?

nodesocket 2 days ago

Very cool. I’m gonna implement into my hobby project today and see how it goes.

breakfastduck 2 days ago

I really like the simplicity of this.

I have a couple projects I could see this being really useful in, at least as an option instead of pure plain text. I still feel like consumers don't like markdown though, it's frustrating.

One thing I noticed, when doing a list (bullet, numbered etc) it would be great if the list continued on barrage return (enter) - most general users would expect that I think.

Bengalilol 2 days ago

> That's it. No npm. No build. No config.

That's it, I am loving it.

  • sitkack 2 days ago

    If it doesn't have an NPM build, it isn't a serious project. Not using anything w/o a build.

    • neilv a day ago

      If it doesn't work with crack pipes, it's not a serious pharmaceutical.

    • vid a day ago

      I agree with sitkack. npm (packaged software) is really handle to bundle code and keep a repo up to date. But I guess if you just want a markdown editor on a page, this is fine.

      • 3836293648 a day ago

        You are arguing two (subtly) different points. Not requiring npm or any build step is great. Always.

        Having it available to simplify integration into larger projects is also great.

        These two things are entirely orthogonal, even if this only does the first one.

        • vid a day ago

          It's fine that the points are different.

          If you need to use npm in the rest of the project, which can be helpful for any project that uses front end Javascript, having one library (essentially) that uses a different mechanism is not great.

          I have built many projects and while I swore at convoluted bundlers in the past, they are pretty nice these days.