I did some deeper digging -- there are exactly two use cases within FX where snapping is turned off:
1. The dot in a radio button is rendered without snapping to ensure it is drawn exactly center of the radio button circle -- having snapping inherit would not break this as the dot has no children 2. The show-hide-columns icon in a table header row has snapping off for the same reasons (to ensure the icon is exactly centered in its box) -- inheritance again won't interfere here This is also precisely what I had speculated as a possible use case: tiny controls / stylings (only a few pixels in size) that would be better rendered in an exact location as even a single pixel deviation would be noticeable. --John On 10/09/2026 03:05, John Hendrikx wrote: > On 09/09/2026 20:31, Marius Hanl wrote: >> I'm especially wondering if we even need the 'snapToPixel' property at >> all. >> I never needed it, never saw it being used or set somewhere else. >> >> With that said, I was also wondering about potential consequences to >> performance if we try to track the parent snapping property. >> If we move forward with that, we need to find a good implementation >> for that. > There are already precedents here; see disableProperty (local, writable) > and disabledProperty (read-only effective). The effective snapping > setting to used is cached locally, so to querying it is just as fast as > it is now. The effective state needs to be computed when reparenting > (rare) or when someone actually changes it (even more rare). > > --John > > >> -- Marius >> >> On 9/9/26 4:52 PM, John Hendrikx wrote: >>> The docs on `snapToPixelProperty` state: >>> >>> /** >>> >>> * Defines whether this region adjusts position, spacing, and size >>> values of >>> >>> * its children to pixel boundaries. This defaults to true, which is >>> generally >>> >>> * the expected behavior in order to have crisp user interfaces. A >>> value of >>> >>> * false will allow for fractional alignment, which may lead to "fuzzy" >>> >>> * looking borders. >>> >>> */ >>> >>> This does leave a lot ambiguous as to what should happen when a region >>> is not snapped, but its children (or grand children) are snapped again. >>> >>> The problem: >>> >>> 1. When an ancestor is unsnapped, no amount of snapping of children will >>> return the claimed "crisp user interfaces" for those children. Once an >>> ancestor decides to allocate a non-integer number of pixels at a >>> non-grid aligned location, even snapped children will not look crisp. >>> >>> 2. Children that are snapped that receive a width/height that is not an >>> integer multiple will be faced with a dilemma: >>> >>> - Do they round their width/height down to not exceed their allocated >>> size? >>> - Do they round it up to ensure they cover the allocated size >>> potentially overlapping another child of the unsnapped parent? >>> - That could undo whatever the parent was trying to achieve... >>> >>> - What do they do with those fractional pixels that are left over >>> when >>> distributing (snapped) space over their own children? >>> - Add the "left over" space to one of those, which then pushes the >>> problem down another layer (the grand child receives a non-integer >>> number of pixels from a snapped(!!) parent)? >>> - Not pass them down to any child, but let the background of the >>> container fill that space? >>> >>> The current implementation in JavaFX for this situation, an unsnapped >>> parent with snapped children, essentially ignores these questions and >>> allows the layout algorithm to use the width and height as given. The >>> result can therefore depend on the exact implementation and order of >>> calculations, without the situation itself being explicitly accounted >>> for. >>> >>> Furthermore, re-enabling snapping below an unsnapped ancestor seems >>> counterintuitive and is unlikely to be useful in practice. If an >>> ancestor has explicitly opted out of pixel snapping, descendants cannot >>> generally undo that decision without either compromising the ancestor's >>> positioning or size allocations, or propagating the fractional-layout >>> problem further down the hierarchy >>> >>> Proposal: >>> >>> I think the existing API documentation has enough leeway to change how >>> we implement snapping in the case of an unsnapped ancestor. I therefore >>> propose to make snapping dependent on the ancestor. A node is only >>> snapped if all of its ancestors are snapped. >>> >>> This would eliminate a number of ambiguities with relatively little >>> downside: >>> >>> - As today, children of an unsnapped container can still end up looking >>> fuzzy. However, they would follow the unsnapped calculation path rather >>> than being presented with an inconsistent combination of snapped and >>> unsnapped constraints. >>> - There would be no need to define how a snapped child should resolve >>> fractional space received from an unsnapped parent. >>> - We would not need to decide where fractional space should go when >>> distributing space among descendants, or whether that space should be >>> propagated to another level. >>> - We would avoid having a snapped child round its dimensions up or down >>> in a way that could contradict the layout decisions made by its >>> unsnapped parent. >>> >>> So once an ancestor opts out of snapping, that should apply to the >>> entire subtree. This makes it much more predictable (and also is likely >>> what was intended) and avoids having to find an unsatisfactory solution >>> for all the edge cases when combining snapped nodes with unsnapped >>> ancestors. >>> >>> I'm curious what others think, and this is relevant as we're about to >>> enshrine snapping rules in the next release I think. >>> >>> --John
