How to prevent fractional pixels in an element with width set to auto?
Asked Answered
I

2

22

I have a row of inline-block elements that all have auto width, so they draw as wide as the varying text content in each of them plus a bit of padding. This results in the actual width of each element having fractional pixels.

This would be fine, but each element contains an icon font that is very sensitive to being drawn when not aligned to the pixel grid, the subpixel rendering of it just looks nasty and blurry if the glyph's origin is not at an integer pixel value.

How can I keep the width of these elements dynamic while preventing decimal pixel values? For example, one of the elements ends up with the width 60.183px when I'd like it to be rounded up to 61px. Sass can do ciel(), which would be perfect, but there is seemingly no way to apply it to auto values.

Or alternatively, is there any way I can ensure that the icon glyphs have an origin that is a full integer pixel without rounding the container widths?

Because of the way these elements are used I'd like to avoid doing this with JS and find a CSS/SASS only solution.

Indraft answered 4/10, 2016 at 21:2 Comment(4)
Possible duplicate of CSS how to round of percent values to whole number pixelCounterscarp
Hmm, that is a similar question but none of the answers or comments there actually resolve the issue. The real issue here is that the icons need to have integer pixel origins, and as far as I can tell the only way to accomplish that is by rounding the width of the containers.Indraft
The main takeaway from that question is that value rounding isn't possible to force using only CSS. It may be worth reading this question on rendering icon fonts, though: #12643491Counterscarp
Unfortunately no answers there either. The only way I've found to make sure the font is crisp is to make sure they have an origin that is a whole number of pixels. No amount of fussing with font-smoothing, text-rendering, font-weight, transform, or any other CSS property suggested by Google or Stack Overflow has helped.Indraft
M
50

I have found that if you use display: inline-table; instead of display: inline-block; it will force it to render exact pixel widths/heights. This may fix your issue however using table/inline-table will make the space within container collapse in some browsers so you would have to wrap the contents in another element.

Marmoset answered 21/7, 2017 at 10:4 Comment(5)
Awesome! Just to let you know: i upvoted 9 Times. This one also fixes a nasty problem with pixel fonts and automatic witdths / margins.Ampereturn
@Indraft I think it's just down to how it needs to render the table, tables are much more 'rigid' than most elements because all the rows/columns should show without any spaces between them so I guess it needs to force a pixel layout to avoid any sub pixel gaps. But I admit that is mostly speculation, I would be interested to know if anybody else has any other insight.Marmoset
This works in chrome. But in Fire fox looks worse and solution not working. In Microsoft Edge the problem is not showing at all (thumbs up to Microsoft Edge).Languedoc
This old answer of yours is also great to fix blurry text or pixel shifting after applying CSS transformationsMisbecome
In my case display: inline-block worked tooQuacksalver
S
1

The solution may someday be the CSS property round() which can round dimensions to whole pixels.

width: round(var(--width), 50px);
width: round(up, 101, 10);
width: round(down, 106, 10);
margin: round(to-zero, -105, 10);

This may be the solution at some point in time, but as of early 2023 it is only supported in Safari.

If this property is ever widely adopted make sure to provide a fallback value like this:

.my-box
{
    width: 25vw;
    width: round(up, 25vw);
}
Strutting answered 10/2, 2023 at 3:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.