I developed a website on a macbook pro with retina, where my display settings are scaled to 'more space'. The webapp looks great this way.
But when I set the display back to 'default' scaling, it looks pretty bad, with all the components far too big.
How does display scaling work? My best guess is that it's a different mapping between device pixels and CSS pixels, but other websites seem to handle this so much more gracefully. I want my webapp to look roughly the same for people with different resolutions and display settings. Does CSS have any sort of elegant way of handling this? Or does Stylus? (the CSS preprocessor I'm using)
My current plan is to just go through the CSS by hand and cut all the sizes in there in half. But I'd rather not have to go through there if there exists a better way.
Figured this out!
Turns out that when you go back to unscaled "default" view settings, the number of css pixels actually diminishes as well (down to like 1100 or so when fullscreened) and grows to 1500 or so when fullscreened on "more space". So in order not to scale the page, we need a version of the CSS where every px value is A for "more space" and A/2 for "default" (more or less). I was considering doing this by hand, but then realized that I would also have to do this for bootstrap (go through and change every css px
value from A to A/2. This didn't sound fun.
But then, Bootstrap 4 came out and I learned about the rem
unit in css. That would mean that if I went through and changed every px
value to its associated rem
value, I could do something like:
@media(min-width: 768px)
html
font-size 12px
@media(min-width: 1150px)
html
font-size 14px
@media(min-width: 1300px)
html
font-size 16px
And that's exactly what I did. In order to do that, I needed to write a script to go through a minified bootstrap string and change px to rem with a base html size of 16:
import re
def toRem(match):
return str(float(match.group(0))/16.0)
def main(string):
splits = string.split('px')
values = [re.sub('[0-9]+$', toRem, split) for split in splits]
output = 'rem'.join(values)
print output
The only issue with this approach was one value: 1px is converted to 0.0625rem, which when you drop the html font size, is too small to display, so all your 1px borders disappear. I fixed this by changin every occurrence of 0.0625rem to 1px, since 1px should always be 1px.
Now the page looks great for all display resolutions, we even preserved the mobile view for sizes below 768px.