remix logo

Hacker Remix

Show HN: uWrap.js – A faster and more accurate text wrapping util in < 2KB

121 points by leeoniya 2 weeks ago | 21 comments

noduerme 2 weeks ago

I remember getting so deep in the weeds doing this kind of thing in responsively-resized Flash sites, a challenge similar to doing it in canvas. But what at that time I was trying to do (and what I'd really love to see now) was to reproduce runaround text the way you would have it in Quark or Pagemaker (or that newer Adobe program). Justifiable text flow within an arbitrary closed path shape, so you could have multi-column text with adjustable gutters, running with curved borders around scaling embedded graphics. My solutions for that involved a lot of setup/tear-down of invisible text fields relying on native text handling, line by line or paragraph by paragraph, then a lot of remeasuring, and then a lot of optimization to make it more performant. I wrote a similar set of code for handling text in generated PDF files.

As an old school print designer, I would love to see a return to a web with multi-column text on desktop, that reformatted to single column on mobile, and graphics runarounds much more complicated in shape than what a float can do. The art of typographic layout has been lost on the web, because those things are hard. An OS general-purpose engine that could handle layouts like that in any screen size, on Canvas or using absolute positioned divs or generating PDFs, would go a long way toward restoring artistic originality in the "layouting" of online publications.

leeoniya 2 weeks ago

> As an old school print designer, I would love to see a return to a web with multi-column text on desktop, that reformatted to single column on mobile, and graphics runarounds much more complicated in shape than what a float can do.

this has been possible for quite some time with CSS columns:

https://developer.mozilla.org/en-US/docs/Web/CSS/columns

plus media queries for desktop vs mobile layouts:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_q...

PinkSheep 2 weeks ago

Without sarcasm, that's great. Now what is there to prevent me from scrolling up and down on a 16:9 display to read the left column of a 10k letter text and then the right column?

I see it has "length" and "min/max-content" properties... even if there are sufficiently many <p>aragraphs (for vertical splitting), inevitably enough paragraphs will be single column due short length. So it becomes a mix and match between "here we were able to split into columns, and here you get a full width single column text flow"?

PS: Oh and don't get me on the CSS used to determine mobile layouts. My 9:16 4K often enough triggers that degraded experience of mobile.

leeoniya 2 weeks ago

> Now what is there to prevent me from scrolling up and down on a 16:9 display to read the left column of a 10k letter text and then the right column?

if the author decided on exactly 2 columns then, well, that's not a limitation of the tech. css columns support dynamic columns, but obviously the author would then need to specify a max height.

> My 9:16 4K often enough triggers that degraded experience of mobile.

again, sounds like incompetent authorship rather than a tech limitation.

somishere 2 weeks ago

I can count on one hand the number of times I've needed something like this in the last decade. But I'd also need to count the same number of times I've implemented a less than ideal solution that's ended up in prod. Great work!

leeoniya 2 weeks ago

we needed something like this for virtualization of the Table panel, data-heavy dropdowns, and long list views in Grafana. so i guess that's a three-in-one?

i looked for the fastest thing i could find but canvas-hypertxt wasnt accurate enough and allocated an array of split lines per item, which is really wasteful when all you need is a line count. i forked it with some optimizations which improved perf by 60% but still suffered from the accuracy issues. so then decided to DIY my own strategy, and uWrap is the result.

Jaxkr 2 weeks ago

Hi OP! Thanks for sharing.

I don’t totally understand the point of this. Why would you want to use a Canvas renderer for this use case? If you want to render a massive table, apps will render a subset of it on regular HTML elements like EveryUUID [1].

1: https://news.ycombinator.com/item?id=42342382

sroussey 2 weeks ago

From the introduction:

uWrap exists to efficiently predict varying row heights for list and grid virtualization[1], a technique for UI performance optimization when rendering large, scrollable datasets.

[1] https://www.patterns.dev/vanilla/virtual-lists/

kevlened 2 weeks ago

EveryUUID's virtual grid can assume every cell is the same height, but it's much more difficult if you assume cells have wrapped text. This is further complicated if you allow grid resizing.

bufferoverflow 2 weeks ago

What if you have to display it in a webgl environment?

nhatcher 2 weeks ago

Hmmm, I might have a brilliant usecase for it:

https://github.com/ironcalc/IronCalc/blob/main/webapp/IronCa...

Thanks!

leeoniya 2 weeks ago

yep, looks like it!