1

Here's a working example: http://jsfiddle.net/0pxv3omh/6/

These two inputs have different heights (although it's very slight):

enter image description here

I can't follow the behaviour, I have this markup:

<div class="control">
  <div class="horizontal-wrapper">
    <input class="control__slider" id="input-range-year" type="range" min="1" max="40" value="30" step="1">
    <input class="control__input" type="number" value="30">
  </div>
</div>

And I basically duplicate it as a sibling and the height changes.

I found that I remothe this input

<input class="control__input" type="number" value="30">

The range inputs become the same height.

They also become the same height if I remove the display flex. I don't understand neither of those behaviours.

As far as I understand the two input should be the same height:

input[type="range"] {
    height: 0.66em;
}

And though em are context dependant, they should be on exactly the same context as far as I can understand.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Trufa
  • 39,971
  • 43
  • 126
  • 190
  • You can describe your issue in better detail? I can't tell what you're trying to achieve. It works fine as expected. – Terry Jan 21 '19 at 13:56
  • @Terry the two inputs are set to the same height, but display differently. I can expand my question. – Trufa Jan 21 '19 at 13:57
  • They are displaying the exactly the same in your screenshot. – Terry Jan 21 '19 at 13:58
  • @Terry it's very slight but they are not. https://i.imgur.com/09vHi6D.png vs https://i.imgur.com/RE1f0PQ.png – Trufa Jan 21 '19 at 14:03
  • @Terry, the top is 14 pixels in height, while the lower is 16 pixels in height. – jumps4fun Jan 21 '19 at 14:05
  • 1
    @Trufa, the jsfiddle displays the two bars with exactly the same height here. I can see your screenshot have different heights, but I can not get the same result here. How familiar are you with debugging in your browser? – jumps4fun Jan 21 '19 at 14:06
  • I have a feeling that when you're using 0.66em, you're getting a subpixel value. When you stack elements of subpixel values on top of each other, different browsers might round the numbers differently. – Terry Jan 21 '19 at 14:07
  • @KjetilNordin I a very familiar, let me know what I should check. – Trufa Jan 21 '19 at 14:08
  • Chrome displays same height, Firefox displays with different heights. I think @Terry is right in his feeling about subpixel calculations. – jumps4fun Jan 21 '19 at 14:10
  • @Terry I don;'t understand how that would explain it, if you just make it display without flex then they behave the same, same if you remove the input. – Trufa Jan 21 '19 at 14:11
  • @KjetilNordin they are different heights for me in chrome. – Trufa Jan 21 '19 at 14:12
  • I'm sorry to say, but I am as stumped as you are now. This is indeed weird. A very good question. I am very interested to see if anyone can explain this properly. Upvoted question at least – jumps4fun Jan 21 '19 at 14:13
  • @KjetilNordin thanks for they input, it's driving me a little bit crazy :) – Trufa Jan 21 '19 at 14:14
  • I half expected some other css values to influence your setup, but now that I was able to reproduce in firefox, I realize I was wrong. So I can not offer additional debugging help I'm afraid. – jumps4fun Jan 21 '19 at 14:14
  • If you use a pixel-precise value the issue goes away. The reason is that you're laying out elements of subpixel heights in a grid (aka your screen) whose smallest denominator is a pixel. So when your subpixel elements are painted on the grid, the browser will have to decide if the pixel above/below should belong to the element, or not. That subpixel rendering differs across browsers and that is why you see inconsistent height. The only reliable solution for pixel consistency is to use values that are pixel precise. Either use an `em` value that resolves to non-subpixel values, or use `px`. – Terry Jan 21 '19 at 14:14
  • @Terry this is a learning exercise so px is out of the question. ` Either use an em value that resolves to non-subpixel values` that's interesting. So the problem seems to be that I'm, using a root of 16px, an element that has 1rem, inside a component that has 0.75 (12px) and inside a component that wants to be 8px (0.666...). This seems to be true since if I pass it to 9px (0.75) the render the same height. – Trufa Jan 21 '19 at 14:27
  • I could've answered this, if there were one pixel in difference. Then it would have been about the sub-pixel start and end, which could result in one pixel difference. But I can't find anything to explain the second pixel. It seemed like a simple "there is no anti-aliasing, and subpixel calculations"-answer, but that will not work for two pixels... – jumps4fun Jan 21 '19 at 15:03
  • I'll tell you this though, your root of 16px is for some reason calculated to 13.333 after implementing the 0.75px in .calculator. I have no idea why, but this also gives 8.8px after applying the 0.66. 8.8px gives room for subpixel precision issues. 13.3333 *0.75 is a more or less precise 10.0, so that would always be the same height. I would try to understand why this 13.3333 font size appears, or at least check if the same thing happens in your browser. – jumps4fun Jan 21 '19 at 15:08

2 Answers2

0

In CSS the unit em is always about context. All parents influence the output of the child. If you want to make sure, that the calculations are based on the font-size of your html-tag you should use rem instead.

So changing your code to the following should deliver much more accurate results.

input[type="range"] {
    height: 0.66rem;
}
MaZoli
  • 1,388
  • 1
  • 11
  • 17
  • I understand it's about context, but they are identical siblings so the context should be exactly the same. I can use rem or px to solve the issue but 1) I want to understand 2) it shouldn't happen as far as I understand. – Trufa Jan 21 '19 at 14:09
  • The browser tries to fit the div to the given pixel grid of your monitor. If it would really render half pixels the output would be very washy. To fit the grid seems to be important to the browser as it is very important for fonts to look sharp to stay readable. If you move your html down via margin-top: 0.4px you will see that the rendering will shift at some point as the browser needs to adjust the output to the grid. It is hard to confirm but it looks like the browser hast to find a compromise between sharp displaying and accuracy. Looks like for em they decided to go with readability. – MaZoli Jan 21 '19 at 14:22
0

There is a user agent stylesheet, which sets your font size to 13.3333px. This is from my chrome inspector, from your jsfiddle:

input, textarea, select, button {
    text-rendering: auto;
    color: initial;
    letter-spacing: normal;
    word-spacing: normal;
    text-transform: none;
    text-indent: 0px;
    text-shadow: none;
    display: inline-block;
    text-align: start;
    margin: 0em;
    font: 400 13.3333px Arial;
}

When you refer to 0.66 em, your expected final output is 8px. You expect the relative font size to be 12px, as it is set to 16px for the whole html, and then multiplied with 0.75em in the calculator wrapper. however, the user agent stylesheet overwrites your 12px with 13.3333px, giving a final calculated height of 8.8px.

The rendering of the elements seems to not use anti-aliasing when painting (sub pixel gradients to soften edges), and will paint a pixel completely, based on if an element starts before or after half of the pixel.

I am not completely sure why there are two pixels of difference, as the subpixel calculations should only yield a maximum of one pixel of difference, but I suspect it might be some relative value with borders or box shadows. The actual blue areas are 14px and 16px in height, while the elements are at 8.8px.

jumps4fun
  • 3,994
  • 10
  • 50
  • 96