Search code examples
cssmacosretina-displaystylusretina

How to fix sizes when I developed my website with 'more space' display setting on macbook retina


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.

Tuftslife with 'More Space' scale

But when I set the display back to 'default' scaling, it looks pretty bad, with all the components far too big.

Display Scaling on a mac Tuftslife with 'Default' Scale

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.


Solution

  • 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.