[HN Gopher] Infinite Pixels
       ___________________________________________________________________
        
       Infinite Pixels
        
       Author : OuterVale
       Score  : 206 points
       Date   : 2025-08-07 13:12 UTC (9 hours ago)
        
 (HTM) web link (meyerweb.com)
 (TXT) w3m dump (meyerweb.com)
        
       | RoryH wrote:
       | This article triggered flashbacks to 20 years ago and using all
       | sorts of crazy CSS to hack the browser to do what you needed it
       | to. Nowadays CSS is (usually) a remarkable land of sanity in
       | comparison.
        
         | Brajeshwar wrote:
         | It was also a fun time to interview. Can you write a CSS
         | snippet that will make a box red in IE5, Blue in IE6+, and is
         | Yellow in Firefox but black in Netscape? CSS these days is no
         | longer an adventure -- they just tend to work.
        
         | ge96 wrote:
         | I always grab the CSS reset Also the purple story
        
       | maxloh wrote:
       | Blink, Chrome's rendering engine, was forked from WebKit (Safari)
       | in 2013.
       | 
       | Since WebKit already supported the infinity value at the time of
       | the fork [0], it's highly probable that they share the same
       | underlying code. This would explain their similar behavior.
       | 
       | [0]: https://caniuse.com/?search=infinity
        
         | chrismorgan wrote:
         | You're confusing the JavaScript keyword Infinity, which has
         | been around forever, with the CSS keyword infinity, which has
         | only been around for 2-3 years <https://caniuse.com/mdn-
         | css_types_calc-keyword_infinity>.
         | 
         | And actually I'd be quite surprised if the infinity keyword is
         | even relevant here; I would expect the same results if you
         | changed each calc(infinity * 1px) to 9999999999999999px.
         | Firefox (and, if you go far enough back, IE) will still ignore
         | overly large height declarations, and WebKit-heritage browsers
         | will clamp it.
        
           | maxloh wrote:
           | Thanks for the clarification. However, the number is likely
           | encoded in binary format, which is why you're seeing 225 in
           | the article.
        
       | breckognize wrote:
       | Kinda related - our product, rowzero.io, is a browser-based
       | spreadsheet with a 2 billion row limit. We initially built the
       | client as anyone would, using a div per cell. We tried to use an
       | off-screen div to take advantage of the browser's native
       | scrollbars but ran into document height limits. Firefox's was 6M
       | pixels iirc. The solution was to do rendering in canvas and draw
       | the scrollbars ourselves.
        
         | mmastrac wrote:
         | Do you even need to have one scroll pixel == one screen pixel
         | (or even one scroll pixel == one spreadsheet row)? At the point
         | of 2 billion rows, the scrollbar really falls apart and just
         | jumping to an approximation of the correct location in the
         | document is all anyone can hope for.
        
         | zwnow wrote:
         | Is it completely client side? Why does it have a 2 billion row
         | limit? Where are the limitations coming from?
        
         | chrismorgan wrote:
         | Firefox's limit is 17,895,697 pixels. Others have a limit less
         | than twice as high, so given you're aiming for a value way
         | higher than that, it's not a browser-specific issue, except
         | insofar as Firefox ignores rather than clamping, so you have to
         | detect Firefox and clamp it manually.
         | 
         | In Fastmail's case (see my top-level comment), making the end
         | of a ridiculously large mailbox inaccessible was considered
         | acceptable. In a spreadsheet, that's probably not so, so you
         | need to do _something_ different. But frankly I think you
         | needed to use a custom scrollbar anyway, as a linear scrollbar
         | will be useless for almost all documents for anything except
         | returning to the top.
         | 
         | Rendering the _content_ , however, to a canvas is not
         | particularly _necessary_ : make a 4 million pixel square area,
         | hide its scrollbars, render the outermost million pixels of all
         | edges at their edge, and where you're anywhere in the middle
         | (e.g. 1.7 billion rows in), render starting at 2 million
         | pixels, and if the user scrolls a million pixels in any
         | direction, recentre (potentially disrupting scrolling inertia,
         | but that's about it). That's basically perfect, allowing native
         | rendering and scrolling interaction, meaning better behaviour
         | and lower latency.
        
       | echelon wrote:
       | > came across a toot
       | 
       | > For the sake of my aching skullmeats
       | 
       | > My skullmeats did not thank me for this
       | 
       | > I hear you asking.
       | 
       | > Maybe if I give my whimpering neurons a rest
       | 
       | > I'd be much happier if someone just explained it to me; bonus
       | points if their name is Clarissa.
       | 
       | > my gray matter needs a rest and possibly a pressure washing
       | 
       | There is a software engineering equivalent of the "theater kids"
       | meme, and this is it. There's an abundance of exuberance in this
       | writing.
       | 
       | I'm glad we have such diversity in perspective. It's a nice
       | change from the usual terseness, though I'm not sure I could read
       | in this style for an extended period.
        
         | baggy_trough wrote:
         | "skullmeats" definitely made me wince.
        
           | nine_k wrote:
           | The interaural nerve node.
        
         | allears wrote:
         | Totally refreshing to me. Imagine -- a techie who doesn't take
         | himself too seriously!
        
         | Pxtl wrote:
         | It works for this context, which is about an experiment that is
         | fundamentally a bit silly. 10 years ago this would've been all
         | memes, and 20 years ago it would've been performatively
         | elaborate insults. I'll definitely take it over those.
         | 
         | btw "toot" is the de-facto standard jargon for "post" on
         | Mastodon-based social media, so that sentence isn't actually an
         | example of this silliness.
        
       | calibas wrote:
       | What's the actual use case for "infinity" in CSS?
        
         | jdauriemma wrote:
         | Final boss of z-index
        
           | Rendello wrote:
           | What about `infinity + 1`? ;)
        
             | dole wrote:
             | z-index = i_love_you;
        
               | mceachen wrote:
               | pow(infinity, infinity) is aliased to no_i_love_you_more
               | in CSS5
        
             | elteto wrote:
             | That's the z-index of your nose.
        
           | PaulDavisThe1st wrote:
           | Cantor has entered the chat.
        
           | azangru wrote:
           | Isn't the final boss of z-index the top layer?
        
         | adamwathan wrote:
         | We use it in Tailwind CSS v4 for pill-shaped borders:
         | .rounded-full {         border-radius: calc(1px * infinity);
         | }
         | 
         | ...as opposed to what everyone has done historically, which is
         | pick some arbitrary huge value like:                 .rounded-
         | full {         border-radius: 9999px;       }
         | 
         | No real practical benefit, just satisfyingly more "correct".
        
         | szatkus wrote:
         | According to the spec:
         | 
         | These constants are defined mostly to make serialization of
         | infinite/NaN values simpler and more obvious, but can be used
         | to indicate a "largest possible value", since an infinite value
         | gets clamped to the allowed range. It's rare for this to be
         | reasonable, but when it is, using infinity is clearer in its
         | intent than just putting an enormous number in one's
         | stylesheet.
        
         | stronglikedan wrote:
         | Selling pixels at a dollar each to make an Infinity Dollar
         | Website(tm).
        
       | chrismorgan wrote:
       | Firefox simply ignores height declarations that resolve to a
       | value greater than exactly 17895697px. What's this value? Just a
       | smidgeon under 230 _sixtieths of a pixel_ , which is Firefox's
       | layout unit. (It's the last integer before 230 sixtieths, which
       | is 17,895,697.06 pixels, 4/60 more.) I presume Firefox is using a
       | 32-bit signed integer, and reserving another bit for something
       | else, maybe overflow control.
       | 
       | Five years ago, Firefox would ignore any CSS declarations
       | resolving like that, but somewhere along the way it changed so
       | that most things now clamp instead, matching WebKit-heritage
       | behaviour. But height is not acting like that, to my surprise (I
       | though it was).
       | 
       | WebKit-heritage browsers use a 1/64 pixel layout unit instead.
       | Viewed in that light, the 225 - 1 pixels is actually 231 - 1
       | layout units, a less-surprising number.
       | 
       | IE had the same behaviour as Firefox used to, but with a much
       | lower limit, 10,737,418.23 pixels (230 - 1 hundredth pixels),
       | which was low enough to realistically cause problems for
       | Fastmail, all you needed was about 200,000 messages in a mailbox.
       | I've written about that more a few times,
       | https://news.ycombinator.com/item?id=42347382,
       | https://news.ycombinator.com/item?id=34299569,
       | https://news.ycombinator.com/item?id=32010160.
        
         | AndriyKunitsyn wrote:
         | Firefox's units are quite smart, actually. 60 is divisible by
         | 3, 4, 5 and 6, so they are quite future-proof for the future
         | when we'll have the displays with devicePixelRatio = 6.
        
       | samweinig wrote:
       | For those curious, in WebKit, this stems from the use of the
       | LayoutUnit
       | (https://github.com/WebKit/webkit/blob/main/Source/WebCore/pl...)
       | for most computed length values. LayoutUnits use a fixed point
       | representation where the smallest unit is 1/64 of a pixel.
       | https://trac.webkit.org/wiki/LayoutUnit is a bit old, but has
       | some good information on the topic.
        
         | ethan_smith wrote:
         | This 2^25-1 pixel limit makes perfect sense - with 1/64 pixel
         | precision, that's exactly 2^31-1 layout units (the max value of
         | a signed 32-bit integer).
        
       | aarestad wrote:
       | Is the almost-24-bit limit related to the fact that 32-bit floats
       | have 24 bits of significand? (cf.
       | https://en.wikipedia.org/wiki/Single-precision_floating-poin...)
        
         | chriseing wrote:
         | The correct answer. In particular, up to 2 ^ 24 the float32
         | behaves like a regular integer, which can be important in some
         | cases. Above that value, the integer starts to have missing
         | values, and strange int behavior such as (n+1)+1 not equal to
         | (n+2)
        
           | yosefk wrote:
           | But why are 32b floats relevant? JS, the language famously
           | representing ints as floats, uses 64b floats. Who puts ints
           | into 32b floats and cares about precision loss?
        
             | matthewmacleod wrote:
             | Layout engines are not implemented in Javascript.
        
             | bobmcnamara wrote:
             | Plenty of embedded GPUs do coordinates that way. But I
             | doubt they're running browsers.
        
             | chriseing wrote:
             | I didn't say JavaScript anywhere in my comment. No relation
             | to JavaScript. Rendering is typically done in tiles, in
             | GPU, and the best precision that can be used across all
             | GPUs is float32. Some GPUs don't implement float64.
        
         | AnotherGoodName wrote:
         | But it's specifically 25bits not 24?
         | 
         | As in n+1 == n once you go past 2^24 on a float and here they
         | are at 2^25-1. So it doesn't quite make sense as a reason to
         | me.
         | 
         | There's a post above that browsers divide pixels into 1/64th of
         | a unit which accounts for 6bits which puts this limit at
         | precisely that of a signed 32bit integer. This makes much much
         | more sense than the significand of a float.
        
         | chrismorgan wrote:
         | No. Everyone has always used fixed-point numbers for layout,
         | see my comment for further details.
         | 
         | Now _SVG_ ... try defining a view box up where float precision
         | drops, and interesting things happen.
        
       | echoangle wrote:
       | > Chrome and Safari both get very close to 225-1 (33,554,431),
       | with Safari backing off from that by just 3 pixels, and Firefox
       | by 31.
       | 
       | Typo, the last browser in this sentence should be "Chrome",
       | right?
        
       | r0b05 wrote:
       | This website is pure art. I enjoyed visiting.
        
         | omnicognate wrote:
         | As befits the author of CSS: The Definitive Guide.
        
       | gregsadetsky wrote:
       | As noted by another comment here [0], when you use a virtual
       | DOM/canvas based "infinite" data grid such as Glide Data Grid [1]
       | or TanStack Virtual [2], you get the performance/usability of
       | native scrollbars because under the hood, both of those libraries
       | create scrollable DIVs with a very large height. ie, you're
       | scrolling a big empty div, and a viewport into the "infinite"
       | grid is actually drawn in the canvas.
       | 
       | But this does fall apart for very very large grids, as you get
       | close to the height limit described in this article.
       | 
       | For a project that I'm working on, I ended up re-implementing
       | scrollbars, but it's super janky - and even more so on mobile
       | where you lose the "flick"/inertia/momentum touch gestures (or
       | you have to re-implement them at your peril).
       | 
       | Are there any good tricks/libraries to tackle this? Thanks!
       | 
       | [0] https://news.ycombinator.com/item?id=44825028
       | 
       | [1] https://github.com/glideapps/glide-data-grid
       | 
       | [2] https://tanstack.com/virtual/latest
        
         | moritzwarhier wrote:
         | Since it seems unlikely that a single scroll gesture passes the
         | threshold, and also the scrollbar thumb probably is invisible
         | (either intentionally or due to the extreme height): maybe an
         | "infinite scroll" paginated stack of virtual lists would be
         | enough? I mean a dumb "load more" implementation that swaps out
         | the main container once you reach the end/start of each "item"
         | (virtual lists themselves)?
         | 
         | If that doesn't help, maybe check out this fun post (no native
         | scrolling experience):
         | 
         | https://everyuuid.com
         | 
         | https://eieio.games/blog/writing-down-every-uuid/
        
           | gregsadetsky wrote:
           | great point re: Nolen's site -- I've collab'ed with him on
           | https://eieio.games/blog/talk-paper-scissors/, I should have
           | remembered that! :-)
           | 
           | it's not crazy to stack virtual lists... at that point, I
           | might also just see that the user is near/at the end of the
           | list, and just swap out the content completely and place them
           | back at scrolling position y:0 or something
           | 
           | for sure, I shouldn't make perfect the enemy of good here.
           | thanks for the ideas!
        
             | moritzwarhier wrote:
             | Oh, I'm glad i wasn't talking past you :) that uuud site
             | and the post about it was genius, and haha, I didn't check
             | the RPS-via-phone number app yet.
             | 
             | Sounds equally fun! Just like the uuid one, also seems very
             | worth bookmarking for a fitting moment
        
       | fnordpiglet wrote:
       | So only slightly related Netscape used to assume the layout
       | during load was infinite and would resolve features to their size
       | as the sizes are known, which meant usually nothing showed until
       | everything was loaded in a world of div and tables.
       | 
       | IE4 did the opposite and assumed everything was sized zero and
       | filled sizes as they become known. this allowed them to load
       | objects and render them as the page objects load appearing to be
       | substantially faster at loading than Netscape.
       | 
       | Early engineering decisions like this can make or break a
       | company. Not saying this was the only challenge Netscape had, but
       | it was one that really drove the need to build the Gecko layout
       | engine. Despite some wildly misleading yet famous blogs written
       | by a Microsoft engineer discussing what happened internally at
       | Netscape that he couldn't possibly know about and basically got
       | totally upside down and self serving ......
        
       | waynecochran wrote:
       | if there was a period of time where 24-bit values were in vogue,
       | I must have missed it.
       | 
       | The mantissa in a single precision IEEE float is 23 bits. Count
       | the hidden bit for normalized floats and you have 24 bits.
        
       ___________________________________________________________________
       (page generated 2025-08-07 23:00 UTC)