Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Default precision too low #1122

Open
glebm opened this Issue · 31 comments
@glebm

Can the default Number#precision be changed to a higher value?

Because it's 5 now, and there is no standard way of setting precision across the forest of Sass environments (many not being Ruby), it causes lots of 1-px off errors, e.g. zurb/foundation#4336 and twbs/bootstrap-sass#409.

libsass also sets precision to 5 by default, same as ruby sass. Perhaps a higher value such as 10 is better as it would mean much less configuration pain for everyone?


ratio rounded error
2/3 66.66667% 0.33333333333E-5
1/6 16.66667% 0.33333333333E-5
3/7 42.85714% -0.28571428571E-5
7/11 63.63636% -0.36363636364E-5
7/31 22.58065% 0.48387096774E-5
p = 5
puts [2/3r, 1/6r, 3/7r, 7/11r, 7/31r].map { |r|
  v = r * 100
  rounded = BigDecimal.new(v, p + Math.log10(v).floor + 1)
  "| #{r} | #{rounded.to_s('F')}% | `#{(rounded - v).to_s('E')}` |" }
@lolmaus

The unwanted offset might be caused by browser rounding erros. See http://www.palantir.net/blog/responsive-design-s-dirty-little-secret

@glebm

@lolmaus It is caused by Sass rounding "errors", please see the issues linked above

@glebm glebm referenced this issue in sass/libsass
Closed

Precision #287

@oskarrough

If someone could change this it would be great.

@chriseppstein

This is truly a situation where I don't think Sass can make a default that meets everyone's needs. 10 units of precision causes bloat for many users unnecessarily. I think maybe this is a situation where Sass needs a way to specify precision in the Sass file itself instead of as a compiler option.

Some ideas:

  1. @option (numeric-precision: 10); - a directive that would specify the precision for the Sass file it is contained within. I'm sure there are other sass options that would be useful to set via a sass file.
  2. Similar to above, the option directive be a wrapping directive @option (numeric-precision: 10) { ... } that affects the contained code instead of the entire file.
  3. precision($value, $units-of-precision: 5) - function that sets the desired output precision on a number and returns that number. If two numbers with precision set are arithmetically combined, we would keep the max precision of the two. This allows the precision to be set on a per-value basis where it is especially important.
@nex3
Owner

I don't like attaching hidden information to SassScript values. I'd feel better if the precision function just converted a number to a string, but I think increasing the precision wholesale may be a better option. I'd like users not to have to think about it, and I'd rather err on the side of correctness than terseness.

@glebm, what is the smallest precision that would make your use-cases work?

@glebm

@nex3 it's hard to say because the error only happens on some browsers / versions. Perhaps rounding errors compound with IEEE 754 (?) errors, and then get multiplied by the viewport raster size, which depends on pixel density, screen size, whether subpixel rendering is present, etc... 10 has been consistently reported to work in Foundation and Bootstrap, but this value is not necessarily the minimum.

@Ne-Ne

Thanks @glebm for escalating this issue.

@chriseppstein

I don't like attaching hidden information to SassScript values

Please explain the definition of "hidden". You made a similar objection to !important and to my eye both seem really nice and useful. What is the use case where this breaks for users?

@glebm

@chriseppstein Higher precision causes less bloat than it may seem since common fractions are gzipped efficiently.

@nex3
Owner

@chriseppstein It erodes user faith that they know what values their variables contain. If 1 doesn't mean the exact same thing in all contexts, even if the differences seem benign, it encourages users to believe that other values may mean different things in other contexts. If their stylesheet isn't working how they expect, even in ways that have nothing to do with numeric precision or !important, they may (reasonably) suspect that it's because of some other hidden behavior that they're unaware of. Once users start believing this, their belief that they understand what Sass is doing goes down, which means effectively that their understanding goes down as well. This is bad.

I agree with @glebm that increased precision will add less pain than it will alleviate. Even if I weren't against hidden metadata in general, I would be against it here. HTML pages being displayed correctly are more important than the relatively few extra bytes that a precision increase will bring.

@chriseppstein

@nex3 I think you're very mistaken on this. The extra precision is useful in only very specific situations. Mostly when assigning column widths for float-based layouts. It's a lot of extra bloat for this use case. We don't need a sledgehammer to fix this, we need a scalpel.

Furthermore, I don't accept your argument for this erosion of confidence in this case (I do in general, btw, which is why I tend to shun action at a distance). 1 is always the same value. 2/7 however will print out the default precision and precision(2/7, 10) will print out 10 digits of precision. The source of that precision difference is something that isn't magical, it's readable in the stylesheet itself and usually at the exact site where the precision is being output. There's not magic here; there's just functions with clear and documented behavior.

If you absolutely hate the precision attribute as an instance attribute for numbers then I'd rather just return a string from the precision function.

@glebm

I've added 2 interactive examples here, with minimum required precisions for some browsers:
http://codepen.io/glebm/pen/Fhfoc. The error thresholds range from precision 1 to 7 for the three browsers I used, so I think a safe margin would be best.

@nex3
Owner

@chriseppstein Making the function documentation clear doesn't reassure me at all. My point is that this will affect users who aren't familiar with all the Sass documentation. It doesn't matter that the hidden information that actually exists can be inspected using functions--what I'm worried about is the hidden information that users think might exist.

I'm also worried about it becoming a de facto standard that users write precision() every time they declare a number in case that number ends up getting used somewhere where it matters. Users shouldn't have to worry about precision at all; if we're able to allow them not to think about it, we should do so.

If @glebm's research is accurate, a seven-digit precision will be adequate. This is only an increase of two digits; do you find that acceptable?

@glebm

@nex3 If I understand this right, when we get 10,000px displays, this number may go up to 8.

@Snugug
@lolmaus

@Snugug, did you have a look at @glebm's test case?

@chriseppstein

This is only an increase of two digits

The precision change we've already made (to 5 digits) isn't the basis I would use. If we did this, I'd like to go back to 3 digits as the default. There's just no reason for more precision than that for most use cases.

I'm also worried about it becoming a de facto standard that users write precision() every time they declare a number in case that number ends up getting used somewhere where it matters.

Numbers aren't declared willy-nilly like this. They have a known purpose.

Users shouldn't have to worry about precision at all

I can find at least a dozen quotes from you that say that Sass cares about the aesthetic beauty and readability of the output. With this approach you're taking the control away from the users who care about this aspect of their output. Make the default something that works all the time (E.g. 7 digits), but don't let the search for something simple take away the power of the craftspersons who are trying to author attractive output. I don't accept that we can't accommodate both of these use cases for our authors.

@nex3
Owner

The precision change we've already made (to 5 digits) isn't the basis I would use. If we did this, I'd like to go back to 3 digits as the default. There's just no reason for more precision than that for most use cases.

Decreasing the default precision will break many existing stylesheets in confusing ways. Moreover, there's no way to provide a deprecation warning for this. There's no way we could safely do this.

Numbers aren't declared willy-nilly like this. They have a known purpose.

If we assumed all users knew what they were doing all the time, Sass would be a very different language. Power users may understand every way every variable will be used and exactly in what circumstances precision matters, but the average user won't. If a user can't tell when precision will be important and when it won't, the only safe reaction is to set the precision high everywhere.

I can find at least a dozen quotes from you that say that Sass cares about the aesthetic beauty and readability of the output. With this approach you're taking the control away from the users who care about this aspect of their output. Make the default something that works all the time (E.g. 7 digits), but don't let the search for something simple take away the power of the craftspersons who are trying to author attractive output. I don't accept that we can't accommodate both of these use cases for our authors.

I'm not interested in giving people arbitrarily fine-grained control of their output. That way lies a quagmire of complexity. Everything is a balance, and in this case power and aesthetics are less important than simplicity of the users' mental model, the API they have to deal with, and the amount of time they have to spend tracking down bugs.

The way I see it, each of our proposals has a failure scenario. Under your proposal, the failure scenario begins with a user seeing their page fail to render correctly. If they trust Sass, they'll spend a lot of time looking through their own math to find the issue before it'll even occur to them that it could be an issue with the compiled output. Once they figure out that the cause of the failure is precision, they need to read the Sass documentation to figure out how to fix it. In the worst failure scenario, they'll then start using precision() everywhere for the reasons I outlined above.

My proposal's failure scenario starts with a user inspecting their CSS output and feeling that the numbers have too much precision. They'll search around or ask on the mailing list why this is, and they'll learn that it's because that's the minimum precision that works in all known use cases. This is a satisfying answer; most users will accept it.

@chriseppstein

Please re-read my comments because I proposed a third option that you seem to have completely missed which I will TL;DR for you here: Make the default precision as high as it needs to be for the average developer but don't take away the tools that the craftspersons in our industry need to make output they are proud of.

I'm not wedded to my solution, but the goal of enabling beautiful output isn't something I'm ok with discarding. Please keep thinking about this until you have an alternate solution that meets both of these requirements, I'm confident one exists.

@nex3
Owner

You seem to weigh the aesthetic benefit of lower precision numbers much more heavily than I do. I think it's unlikely that practically anyone will care if there are more digits after the period; certainly not enough people to justify adding a core function to control it.

If any community members have strong opinions that match Chris's intuitions on this, I'd like to hear from them.

@lolmaus

I doubt my opinion matters, but i'm totally on @chriseppstein's side here.

First of all, i fail to understand why one would want to make precision lower than maximum possible.

Second, i would expect any calculations to be precise and would search for a bug in my calculations before i realize that it's low precision that causes inconsistencies.

Third, i believe that low precision is able to cause a lot of unexpected problems, especially for people lacking advanced programming backround. @glebm has produced a demonstration of the issue, where a gap appears out of nowhere.

Fourth, there are (sometimes unusual) applications of Sass where math is used extensively. For example, mother effing text shadow or modular scale. Precision doesn't matter for all of them, of course, but it might matter to some. And you're forcing their users to revert to Ruby or JS.

@chriseppstein

@lolmaus it seems like you're more in agreement with @nex3 on this issue.

@nex3 My intuition is based on the numerous times where people cared about the output format that we felt they shouldn't. E.g. Selector formatting, comment formatting, color formatting. People care about the way their output looks. I don't think I'm being unreasonable by saying that users who care -- those users I most want to be using Sass -- should have a documented, simple way to achieve their desired output.

@nex3
Owner

@chriseppstein I don't think we have evidence that people will care about the numeric precision in particular, and I don't think it makes sense to pre-emptively make every aspect of the output format configurable. In fact, I think there are aspects—possibly including precision—that it doesn't make sense to make configurable at all.

@chriseppstein

I've made my arguments clearly. It sounds like you've made up your mind without doing the thought experiments I've requested. I'm tired of arguing this point.

@nex3
Owner

I'm not sure what thought experiments you're referring to, but please understand that I have considered your points. As I said above, we weigh different things differently. You care about providing deep output customization; I don't think it's worth sacrificing a small function surface or strong precision guarantees for. I don't think providing deep output customization is necessarily a good goal in general if it comes at a complexity cost, and in this case in particular I don't see any evidence that users have any aesthetic feelings about the number of digits of precision their numbers have.

@Ne-Ne

I can see a divided opinion above, but after finding the grid bug with foundation @glebm has done many examples to show the importance of getting the precision working.

I can see that the foundation grid breaks (or a big bug at least). I would agree that clean output is important but this is now a month old..

I feel that the precision should be minimum to what is needed, but it goes hand in hand with 33.33% as a percentage. Browsers should respect this decimal. However this thread seems to be a double ended sword as a high precision will be needed for graceful fallback.

@Skoks

Any upcoming plans to add precision configuration feature ?

@webdesserts

As an average sass user, I just wanted to drop my opinion in here (I know this is a bit older). I don't do extremely complicated sass, but I have ran into the precision issues more than once. My preference would be high precision by default, with a possible configuration option. If a configuration option isn't possible, then let's just do the high precision default.

@nex3 nex3 added this to the 4.0 milestone
@PanzerKunst

Hi, I just wanted to give an example why this issue is important. Buttons in the Bootstrap-sass project are 33px high because of this 5 decimal limit. They should be 34px high.

@easy-one

I was lucky to quickly determine the problem and not waste the whole day on it. Using a 12-cell grid I loose a pixel because of rounding issues in libsass. The issue is not visible on desktop but is very noticeable on Retina, where precision is twice as important. Dear developers, maybe retina argument will be valuable for you. If you change precision number to 6, most of problems will go.

I paste the screenshot as an example of what can happen if one pixel is lost. A lot of junior developers can have pain we can easily avoid

screen shot 2015-03-14 at 00 06 54

@dustindowell22

@easy-one I think it was already decided that there's no such thing as a default that everyone is going to be okay with. I think 6 decimal places might fix your grid system but could break others. My personal grid uses 5. I think the argument now is whether or not we need a syntax for changing this on the fly rather than all together once at compile. I want to be able to change this on the fly. I want to distribute components that work no matter what the end user decides to use throughout the rest of their project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.