Lessons learned trying to build an InDesign clone in React
CSS supports some pretty powerful layout capabilities these days, and I thought it would be fun to try build a simplified clone of InDesign (Adobe’s document layout app) using React, rendering everything to standard HTML and CSS. I realised pretty quickly that some medium-complexity print layouts are still not possible. Below I’ve outlined a few gaps I encountered.
Text wrap in CSS is limited
Let’s say I wanted to flow a
<div>’s text around a circular shape or image like this:
It turns out that CSS features for flowing text around an arbitrary shape are still nascent and not universally supported.
CSS Shapes, proposed by Adobe in 2012, is supported by the major browsers (except IE/Edge), but it comes with limitations: it can only be applied to floated elements, and it only supports wrapping text around one side of an image. Thus, the example layout above would not be possible using CSS Shapes.
CSS Exclusions would be able to achieve this layout, but it’s only supported in IE/Edge.
Linking text boxes is not yet possible
The CSS Regions spec aims to add this functionality, but it was created in 2014 and the major browsers still don’t support it.
contenteditable is hard — use a plugin like Slate
To make text boxes editable on the web, you add the
<div contenteditable="true"> A browser would let the user edit this content. </div>
contenteditable element in React is more complex than a simple
<input> element, but thankfully there is an excellent library called Slate which makes it super easy. It also has an extensive set of plugin points to do things like enforce document schemas, perform rich-text formatting, and intercept keyboard shortcuts. I would highly recommend this library for anyone using
contenteditable elements in React.
Apple’s iCloud Pages uses a custom rendering engine
Apple’s web-based implementation of Pages allows most functionality you’ll find in the desktop, including flowing text across boxes and complex word wrap. They can do this because they’ve built a custom rendering engine that renders everything to SVGs. This is the page source behind the layout above:
Browser updates can break your document layout
Even in the short time span that I was working on this project, one update of Chrome led to one text box on a page shifting by one pixel. One pixel might not be much on some blog webpage layout, but if you’re about to get thousands of copies of your new book printed, you want to have faith that your pages are laid out exactly as you intended. I didn’t dig into the root cause of this particular issue, but it highlighted how risky it could be to build a document layout application where you don’t control the rendering layer.
To be continued…
I only scratched the surface of trying to port print layout features onto the web, but it showed that pure HTML and CSS are not quite ready for building a document layout application. Here’s hoping Adobe pushes more of these CSS specs into reality.