A CSS nerd question about render scaling and viewport meta tags

- Posted in Uncategorized - 18 comments

We can set a site to be responsive with the standard meta tag to do so:

  <meta name="viewport" content="width=device-width">

This will adapt the content to the viewport width. We can also explicitly set a width – this is pretty uncommon, but it’s possible:

  <meta name="viewport" content="width=1024">

This will render the content at 1024. If your device has a width of 768 pixels (e.g. in portrait mode) it will shows the content at a smaller scale.

The reverse is also true, if your device has a width of 1366 pixels (e.g. an iPad Pro) it will show the content at a bigger scale.

The question

What if you want the content to render at 1024 pixels, but if there are more pixels it should render the content at it’s native resolution? Basically it would behave like a liquid website with a minimum width.

The only solution I can think of is to only show the meta tag when you detected the width to be 1024 or less on the server side.

Who has any ideas?

Why?

The use case for this is to get the best user experience possible for a web app that has a minimum width of 1024 (because of the content of the pages e.g. tables, datagrids, calendars), but that is not specifically made responsive, on as many devices as possible.

People with good eyesight could theoretically use the app at on a tablet in portrait mode – typically supplying 600 to 800 pixels. But they should really turn their tablets around for their own comfort.

People could also theoretically use the app on a phone by doing a lot of pinching and zooming. Think about a situation where you just have to change a single setting and all you have is your phone.

The app should render at its “native scale” on viewports wider than 1024 pixels. This is the case for large tablets like the iPad. I am also pretty sure there are some larger Android tablets on the market.

I can already hear some people asking “why not just make it fully responsive?”. The answer is that phone usage for the app’s use case is uncommon enough to not make it worth it to build a fully responsive web app.

This is a “cheap” solution to realistically use a web app on as many devices as possible without breaking the bank.

(P.S. Looking at the issues in the spec my theory is that a non-hacky solution to this is basically unimplemented in browsers at this point)

18 Comments

  • Pieter says:

    Haven’t tested this on actual devices but seems to work in Chrome Dev Tools.

    HTML:

    <meta name="viewport", content="width=device-width">

    CSS:

    html {
      min-width: 1024px;
      max-width: 100vw;
    }
  • Bramus says:

    Use vw/vh units for your box and font sizes. That should do it.

  • Johan says:

    Pieter’s solution introduces scrolling, not scaling on an regular sized iPad.

    Bramus: what is the “box” in your comment? Your outside container?

  • Pieter says:

    Pity it doesn’t work on actual devices…

    Have you tried swapping the viewport value on DOM ready?

    if window.innerWidth > 1024, then set width=device-width, else set width=1024.

  • Johan says:

    I think that would not actually reload the page, and just display whatever initial value it found. But it is worth a shot. In the meantime I asked the devs if they can get the device width on the server but that feels so 2003 ;).

  • Bramus says:

    @johan: box as in “box model”. Easiest method to implement this is to size all box sizes in em units (which you already do), and change the body font-size to a vw-based unit.

  • Johan says:

    @Bramus Well, the specific implementations that I want this for are based on Bootstrap and are unfortunately all pixel based, but I can see how that might help to achieve the exact scaling you want on every “size class”.

  • Bramus says:

    In that case: resort to JavaScript. Calculate the scaling-percentage based upon the screenWidth and requiredWith and then apply that as a scale on the main wrapper/container using a CSS Transform.

    Say you have a screenWidth of 1250px. The scalingFactor would then become 1,220703125 (= 1250/1024).

    Don’t forget to adjust the transform-origin on the wrapper though ;-)

  • Johan says:

    @Bramus Interesting suggestion but I don’t think all the pixels are going to land correctly if you start messing around with CSS transforms across browsers ? that seems highly unlikely to me.

  • Bramus says:

    It is a hack of course, since the proper fix (using vw units) became nulled due to bootstrap being pixel based ;-)

  • Johan says:

    This is a question for software that will be in production for 10.000+ users, I cannot depend on hacks :D

  • Bramus says:

    Drop the px-based bootstrap then ¯\_(ツ)_/¯ #technicaldebt

  • Bart says:

    Bootstrap 4 will be em-based. It’s in alpha right now…

  • Johan says:

    By the looks of it it will be in alpha forever :) I tested it and I think it’s pretty much done and they shot themselves in the foot by staying in “alpha” so long.

  • Could this be what you’re looking for?

    content=”width=1024, maximum-scale=1″

  • Johan says:

    @Willem no, this just disables pinch to zoom for the < 1024 devices - and renders the content at a scale that is too large for the > 1024 devices.

  • Willem says:

    @Johan: I agree with the disabled zoom (at least before iOS10) but for the >1024 devices scale shouldn’t be too large. Because of the maximum-scale, the width property acts as ‘minimum-width’. You can try this out here: https://jsbin.com/gerixu.

    If you want to keep pinch-to-zoom, ‘initial-scale=1’ is the other option, with the side-effect that on <1024 devices users are already zoomed in on the 1024px wide viewport.

    Probably both not ideal, but an interesting exercise anyway!

  • Johan says:

    O wow Willem, that actually seems to work. Very cool. I will test it some more in a real-world situation and report back :)

Leave a Reply

Your email address will not be published. Required fields are marked *