The ideal viewport doesn’t exist
Some lovely scroll-driven animations illustrate this great little microsite.
There’s something very pleasy about the chunky design that harkens back to the Zeldmanesque early web.
Some lovely scroll-driven animations illustrate this great little microsite.
There’s something very pleasy about the chunky design that harkens back to the Zeldmanesque early web.
This is a terrrific presentation by Chris, going through some practical implementations of modern CSS: logical properties, viewport units, grid, subgrid, container queries, cascade layers, new colour spaces, and view transitions.
I’ve been thinking about some of the default behaviours that are built into web browsers.
First off, there’s the decision that a browser makes if you enter a web address without a protocol. Let’s say you type in example.com
without specifying whether you’re looking for http://example.com
or https://example.com
.
Browsers default to HTTP rather than HTTPS. Given that HTTP is older than HTTPS that makes sense. But given that there’s been such a push for TLS on the web, and the huge increase in sites served over HTTPS, I wonder if it’s time to reconsider that default?
Most websites that are served over HTTPS have an automatic redirect from HTTP to HTTPS (enforced with HSTS). There’s an ever so slight performance hit from that, at least for the very first visit. If, when no protocol is specified, browsers were to attempt to reach the HTTPS port first, we’d get a little bit of a speed improvement.
But would that break any existing behaviour? I don’t know. I guess there would be a bit of a performance hit in the other direction. That is, the browser would try HTTPS first, and when that doesn’t exist, go for HTTP. Sites served only over HTTP would suffer that little bit of lag.
Whatever the default behaviour, some sites are going to pay that performance penalty. Right now it’s being paid by sites that are served over HTTPS.
Here’s another browser default that Rob mentioned recently: the viewport
meta
tag:
I thought I might be able to get away with omitting
meta name="viewport"
. Apparently not! Maybe someday.
This all goes back to the default behaviour of Mobile Safari when the iPhone was first released. Most sites wouldn’t display correctly if one pixel were treated as one pixel. That’s because most sites were built with the assumption that they would be viewed on monitors rather than phones. Only weirdos like me were building sites without that assumption.
So the default behaviour in Mobile Safari is assume a page width of 1024 pixels, and then shrink that down to fit on the screen …unless the developer over-rides that behaviour with a viewport
meta
tag. That default behaviour was adopted by other mobile browsers. I think it’s a universal default.
But the web has changed since the iPhone was released in 2007. Responsive design has swept the web. What would happen if mobile browsers were to assume width=device-width
?
The viewport
meta
element always felt like a (proprietary) band-aid rather than a long-term solution—for one thing, it’s the kind of presentational information that belongs in CSS rather than HTML. It would be nice if we could bid it farewell.
Some tips for getting responsive images to work well on the Apple Watch:
- test your layouts down to 136-
px
wide- include
300w
-ish resources in your full-widthimg’
ssrcset
s- art direct to keep image subjects legible
- say the magic
meta
words
One more reason not to use sticky headers on mobile.
It’s no substitute for testing with real devices, but the “device wall” view in this Chrome plug-in is a nifty way of getting an overview of a site’s responsiveness at a glance.
A nice rundown of some of the fun you can have with viewport units.
I’m very glad the problems with vh
units I wrote about a little while back is getting fixed in Chrome for mobile.
When I was first styling Resilient Web Design, I made heavy use of vh
units. The vertical spacing between elements—headings, paragraphs, images—was all proportional to the overall viewport height. It looked great!
Then I tested it on real devices.
Here’s the problem: when a page loads up in a mobile browser—like, say, Chrome on an Android device—the URL bar is at the top of the screen. The height of that piece of the browser interface isn’t taken into account for the viewport height. That makes sense: the viewport height is the amount of screen real estate available for the content. The content doesn’t extend into the URL bar, therefore the height of the URL bar shouldn’t be part of the viewport height.
But then if you start scrolling down, the URL bar scrolls away off the top of the screen. So now it’s behaving as though it is part of the content rather than part of the browser interface. At this point, the value of the viewport height changes: now it’s the previous value plus the height of the URL bar that was previously there but which has now disappeared.
I totally understand why the URL bar is squirrelled away once the user starts scrolling—it frees up some valuable vertical space. But because that necessarily means recalculating the viewport height, it effectively makes the vh
unit in CSS very, very limited in scope.
In my initial implementation of Resilient Web Design, the one where I was styling almost everything with vh
, the site was unusable. Every time you started scrolling, things would jump around. I had to go back to the drawing board and remove almost all instances of vh
from the styles.
I’ve left it in for one use case and I think it’s the most common use of vh
: making an element take up exactly the height of the viewport. The front page of the web book uses min-height: 100vh
for the title.
But as soon as you scroll down from there, that element changes height. The content below it suddenly moves.
Let’s say the overall height of the browser window is 600 pixels, of which 50 pixels are taken up by the URL bar. When the page loads, 100vh
is 550 pixels. But as soon as you scroll down and the URL bar floats away, the value of 100vh
becomes 600 pixels.
(This also causes problems if you’re using vertical media queries. If you choose the wrong vertical breakpoint, then the media query won’t kick in when the page loads but will kick in once the user starts scrolling …or vice-versa.)
There’s a mixed message here. On the one hand, the browser is declaring that the URL bar is part of its interface; that the space is off-limits for content. But then, once scrolling starts, that is invalidated. Now the URL bar is behaving as though it is part of the content scrolling off the top of the viewport.
The result of this messiness is that the vh
unit is practically useless for real-world situations with real-world devices. It works great for desktop browsers if you’re grabbing the browser window and resizing, but that’s not exactly a common scenario for anyone other than web developers.
I’m sure there’s a way of solving it with JavaScript but that feels like using an atomic bomb to crack a walnut—the whole point of having this in CSS is that we don’t need to use JavaScript for something related to styling.
It’s such a shame. A piece of CSS that’s great in theory, and is really well supported, just falls apart where it matters most.
Update: There’s a two-year old bug report on this for Chrome, and it looks like it might actually get fixed in February.
This is a clever technique by Dave—use viewport units to make a lightweight lightbox.
Some really great CSS tips from Rich on sizing display text for multiple viewports.
In the latest issue of Justin’s excellent Responsive Web Design weekly newsletter, he includes a segment called “The Snippet Show”:
This is what tells all our browsers on all our devices to set the viewport to be the same width of the current device, and to also set the initial scale to 1 (not scaled at all). This essentially allows us to have responsive design consistently.
<meta name="viewport" content="width=device-width, initial-scale=1">
The viewport
value for the meta
element was invented by Apple when the iPhone was released. Back then, it was a safe bet that most websites were wider than the iPhone’s 320 pixel wide display—most of them were 960 pixels wide …because reasons. So mobile Safari would automatically shrink those sites down to fit within the display. If you wanted to over-ride that behaviour, you had to use the meta viewport
gubbins that they made up.
That was nine years ago. These days, if you’re building a responsive website, you still need to include that meta
element.
That seems like a shame to me. I’m not suggesting that the default behaviour should switch to assuming a fluid layout, but maybe the browser could just figure it out. After all, the CSS will already be parsed by the time the HTML is rendering. Perhaps a quick test for the presence of a crawlbar could be used to trigger the shrinking behaviour. No crawlbar, no shrinking.
Maybe someday the assumption behind the current behaviour could be flipped—assume a website is responsive unless the author explicitly requests the shrinking behaviour. I’d like to think that could happen soon, but I suspect that a depressingly large number of sites are still fixed-width (I don’t even want to know—don’t tell me).
There are other browser default behaviours that might someday change. Right now, if I type example.com
into a browser, it will first attempt to contact http://example.com
rather than https://example.com
. That means the example.com
server has to do a redirect, costing the user valuable time.
You can mitigate this by putting your site on the HSTS preload list but wouldn’t it be nice if browsers first checked for HTTPS
instead of HTTP
? I don’t think that will happen anytime soon, but someday …someday.
A comparison of when to use percentages and when to use vw/vh in your CSS.
A handy little bookmarklet for quickly checking how a site might look at different screen sizes, and you can customise it to use whichever screen sizes you like.
Useful advice from Tim on preparing your responsive site for IE10’s new “snap mode”. Don’t worry: it doesn’t involve adding any proprietary crap …quite the opposite, in fact.
Dear Apple Claus,
I’ve been a very good boy this year so I hope you don’t me asking for a little present. What I’d really like for Christmas is for you to fix that strange orientation scaling bug in Mobile Safari.
Just in case you’ve forgotten about it, my friend Scott—who has been a very, very good boy this year (what with that whole Boston Globe thing)—put together a test page quite a while back to demonstrate the problem.
Basically, if I set meta name="viewport" content="width=device-width, initial-scale=1.0"
then it means a pixel should be equal to a pixel: in portrait view, the width should be 320 pixels; in landscape view the width should be 480 pixels. But in Mobile Safari, if I move from portrait to landscape, the width jumps to a value larger than 480 pixels, which means the hapless user must double tap to bring the scale down to 1:1.
Now, admittedly, I could just set meta name="viewport" content="width=device-width"
and leave it at that (or I could additionally declare minimum-scale=1.0
). But then when the user changes from portrait to landscape, although it doesn’t have the same over-zooming behaviour, it does scale up. That means I’m not getting the full 480 pixels (it’s effectively still a 320 pixel wide display, even in landscape).
I could make the bug disappear by adding maximum-scale=1.0
or user-scaleable=no
but that’s the cure that kills the patient. I also did some hacking with Shi Chuan but what we come up with still feels fairly clunky.
So that’s why I’m writing to you, Father Applemas. Won’t you fix this bug for me?
My friend PPK thinks you won’t fix this bug because it would trigger a reflow (and repaint) of the page …but I know that can’t be the reason because the bug doesn’t occur when going from landscape to portrait!
Also—and this is the really strange part—If I’m looking at a web page on my iPhone/Pod in a custom browser (like the Twitter app), rather than using Mobile Safari, then the bug doesn’t occur.
I don’t get, Apple Claus. Why have one behaviour for webviews in other people’s apps and a different behaviour for your own app?
Anyway, if you could see your way to granting this boy’s wish, it would make for a webby Christmas.
Hugs and kisses,
Jeremy
P.S. By this time next year, it would be lovely to have access to the camera (and other device APIs) from the browser …but I’m getting ahead of myself.
Update: the bug has been fixed in iOS 6.
A handy little tool for testing responsive designs by automatically changing your browser viewport size.