Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-device-adapt] @viewport is preloader-hostile #258

Closed
RByers opened this issue Jul 1, 2016 · 36 comments
Closed

[css-device-adapt] @viewport is preloader-hostile #258

RByers opened this issue Jul 1, 2016 · 36 comments
Assignees

Comments

@RByers
Copy link
Contributor

RByers commented Jul 1, 2016

There's been a flury of discussion on twitter about how <meta viewport> is badly broken, but @viewport has performance properties that makes it a bad replacement.

We should hash this out. In particular, what's the right way to bring the features of <meta viewport> to all browsers (regardless of form factor) without introducing new barriers to performance?

/cc @jacobrossi @ChumpChief @yoavweiss @domenic @rune-opera @bokand

@ChumpChief
Copy link
Member

I've been doing a good bit of thinking on this one lately, and in general I feel like we should step back and scope this feature quite a bit. <meta viewport> is terrible because of all the magic behaviors and its strong association with mobile, specific device sizes, and assumptions of a fullscreen browser. @viewport is terrible because its behavior is too complex beyond the needs of most scenarios. And maybe this performance thing, though that hasn't really been a major source of pain for us compared to the functional issues of both viewport options.

Maybe a good first step would be for us to discuss the functionality that we want to support. I think a more scoped set of scenarios will allow more flexibility in the syntax used.

@RByers
Copy link
Contributor Author

RByers commented Jul 1, 2016

Sounds good to me. Maybe create a GitHub repo with a list of use cases (with the intention of incubating it in the WICG)?

@bradkemper
Copy link
Contributor

bradkemper commented Jul 1, 2016 via email

@jacobrossi
Copy link
Member

jacobrossi commented Jul 1, 2016

@bradkemper here's the issue, as I understand it:

When the parser loads the document, it may hit responsive images (srcset/picture). At that point, the parser wants to be able to kick off fetches for the right resource. However, if there's an at-viewport rule in an external stylesheet (which, by definition, is async loaded) then you don't actually know what the final viewport settings will be. As such, the parser/preloader doesn't know which resource to go fetch. So either (a) you guess and may end up loading the wrong one (make 2 img request, waste data, and possibly flash of the wrong content), or (b) block and wait until you've loaded the external stylesheets (non-starter, PLT would get killed).

meta viewport doesn't have this issue since it's inline in the HTML. Additionally, an inline style with at-viewport doesn't have the issue since it can be parsed synchronously.

@yoavweiss
Copy link

What @jacobrossi said. Also, the problem is particularly bad for images, but it also applies to any link element with a media attribute, including external styles, preload, and to some extent preconnect.

With @viewport you cannot know the dimensions of the viewport until you finished parsing (or at least tokenizing) all your HTML, found all external styles, downloaded all of them in their entirety and parsed them. If you also have blocking scripts before any one of your external styles, guess what? You have to wait on them as well** . Only then can you start downloading your responsive assets.

Otherwise, on the deployability front, browsers will have to continue to support <meta viewport> forever and authors would have to continue sending down <meta viewport> for years to come. So IMO, we have to properly spec what it does, and we might as well try to extend it in a backwards compatible way to support the use-cases that it doesn't cover today.

I very much support @ChumpChief's proposal to start with the use-cases that need handling and work our way from there.

** The script part can be optimized away by creating a CSS preloader that looks for @viewport tokens, but that'd definitely add complexity for no good reason other than @viewport's design.

@tabatkins
Copy link
Member

I agree with everything @yoavweiss just said, and I'd love to see @ChumpChief and/or @RByers start up a GH repo to hash this out.

@bradkemper
Copy link
Contributor

I don't know what the answer is, put from my point of view as an author, one of the biggest advantages is being able to have it in an external style sheet, instead of authored into every individual html document (which I often have no personal control over).

I don't mind limiting it to the common use cases.

Maybe there could be a requirement for the at-rule to be in the first 100 bytes of the file or something, and only when linked from the HEAD of the document (or inline in the HEAD).

@jacobrossi
Copy link
Member

Limiting to the first N bytes or the head doesn't really help. Parsing is fast, network is slow. It's the fact hat the rule has to be fetched at all that makes it a perf problem not that it is deep in the file.

@frivoal
Copy link
Collaborator

frivoal commented Jul 3, 2016

The fact that the design is preloader-hostile is indeed an issue we need to solve. But there's another tension in the other direction: regardles of the actual mechanism, this really is style, not content, and belongs on that side of the divide.

This is not just true philosophically (although it is as well), but also practically: whether you should have an @viewport / <meta viewport> / whatever-alternative-we-come-up-with and what parameters it should have depends on what's in your stylesheet. If the same document / app is styled differently, you may need different viewport settings. Even if you're not switching stylesheets, content and styles may be handled by different teams, and the style teams has access to the css but not to the markup, yet they're the one who know what needs to go in to the viewport settings.

But this requirement is at odds with being pre-loader friendly, since it implies (at least naïvely) to store this in the form of a css rule in the stylesheet, as the current iteration does it.

I am not entirely sure how to solve both problems at the same time. I'd be tempted to experiment with something along the lines of what @bradkemper said: keep it in css, but only accept it from inline styles in <head> or from a stylesheet directly linked from <head> (no @import), and only if there's not synchronous js before it, and... That feels a bit clucky, and I'd certainly welcome something simpler, but I am very reluctant to have this somewhere else than in CSS, regardless of what the final incarnation turns out to be.

@frivoal
Copy link
Collaborator

frivoal commented Jul 3, 2016

Hopefully we can find an elegant solution that is both preloader friendly and preserves the separation of concerns.

If we can't find a general one though, would it really be terrible to have a preloader that's specialized to look for @viewport in inline styles inside <head>, but still have @viewport work elsewhere, with the implied downsides in terms of perf (and have dev tools, linters and friends warn about that)?

People who have a workflow where they can put it in the document itself, as they do today, can do so, and other people who value flexibility over performance could but it wherever.

@alexelias
Copy link

My perspective on this is that the only truly useful feature of meta viewport is "width=device-width". This tells mobile browsers to behave like desktop browsers (set layout width to size of the window). Therefore, desktop browsers "already support" the useful part of meta viewport in some sense, so there is actually almost no action we need to take here.

Breaking down the other features of meta viewport:

  • width=[fixed number]; very rarely used (mainly ancient mobile content), enables actively non-responsive websites
  • height=[anything]; even more rarely used. interop is extremely poor between different mobile browsers on "height" but we treat this as a P3 bug since there is very little usage nor use cases (except non-responsive, short-height layouts)
  • minimum-scale, maximum-scale, initial-scale = non-1: I've never seen any use case for setting specific non-1 values of these
  • initial-scale=1: arguably useful to disable some mobile browsers' behavior to always zoom out to fit the content width (although this can also be addressed by simply sizing all of one's content properly). This one is moot for the same reason as width=device-width though -- setting this value to 1 makes mobile browsers behave more like desktop browsers, so there's nothing to support here on desktop.
  • user-scalable=no: arguably useful on desktop as well, although this can also be achieved by preventDefaulting input events (which use cases like maps which truly care about this are likely to do anyway).

Another way of phrasing this is that meta viewport is largely a way to declare "I designed my site with mobile browsers in mind, therefore disable all those mobile browser quirks that exist to compensate for non-responsive legacy desktop sites, and simply behave like a normal browser". It's just another piece of header boilerplate that will be on all sites moving forward, like the HTML DTD. It doesn't provide any functionality per se, it just disables some developer-hostile interventions.

@jacobrossi
Copy link
Member

FWIW at-viewport was attempting to do more than just disable the "developer-hostile intervention" of mobile scaling. For example, width=[fixed number] becomes more useful because you can target multiple fixed numbers based on media queries (e.g. scale the viewport to a set of well-tested fixed widths depending on the range the device-width falls in).

So this comes back to the need to enumerate the scenarios like this and decide which ones we care about delivering. I'm not sure I want to jump to the conclusion that the only scenario we're trying to enable is disabling mobile scaling.

@alexelias
Copy link

I feel that if there was any developer interest in nonresponsive fixed layouts, we would've seen uptake of those capabilities of meta viewport in the ~2008-2012 period where iPhone was ascendant and had a single screen size. The fact that we didn't is a pretty strong signal that those capabilities are useless, to me. (I think it's a big stretch to argue that the media query feature was the key missing piece that prevented that.) I also feel that I would've seen, in years of bug triage, at least one issue that made me think, "ah, if only we supported @Viewport sizing capabilities, this could be solved".

So I don't think I'm jumping to conclusions. I think we gave that layout model a good chance and experience has shown it's a dead end. The only thing that was actually needed, and the inexorable trend of how UAs and webdevs treat meta viewport in practice, is as a convoluted equivalent to the old "mobileOptimized=true/false" property.

@frivoal
Copy link
Collaborator

frivoal commented Jul 7, 2016

I think one of the more interesting feature of @viewport in addition to what you can get with meta viewport's width=device-width is @viewport { min-width: [some length]; } (or, equivalently, @media (max-width: [some length]) { @viewport { width: [some length]; } }). It says that the site is responsive and the viewport can safely be shrunk down, but only to a point, which you specify. Large enough phones don't mess with the viewport, small ones need to zoom out, but only a bit to cover the larger-phone-size, not all the way to the desktop-size. And this works just as well on desktop to let you deal with small windows.

@alexelias
Copy link

The min-width semantics are indeed good, that's why Chrome for Android and iOS Safari already treat meta width= quite similarly to @viewport min-width. I just tested this again on http://output.jsbin.com/dakihubara -- you can see on phones they zoom out to fit the entire image. (If developers don't want that behavior, they can set initial-scale=1, as I mentioned above.) The main difference is that min-width: 0 is no-op, whereas meta width=0 would break flexible layouts because mobile browsers also use the width value as the initial size in the absence of other constraints (whereas desktop browsers use the window size as initial size).

And this works just as well on desktop to let you deal with small windows.

If you're suggesting that when a responsive site is in a floating window that the user resizes below the min-width, the browser should start zooming out to keep a complete fit, I disagree. This would look jarring and silly -- it's too different from how windows normally react to resizing. (If anyone did want this, JS polyfills using CSS transforms to achieve the same behavior should already to be out there somewhere.)

If you're suggesting min-width should act as a hard "wall" against resize and prevent the user from shrinking the floating window any further, I think this is infeasible in a tabbed browser (imagine 1 of 20 tabs has this restriction), so that's the kind of powerful capability only suited to "webapp manifest" type things.

@frivoal
Copy link
Collaborator

frivoal commented Jul 8, 2016

If you're suggesting that when a responsive site is in a floating window that the user resizes below the min-width, the browser should start zooming out to keep a complete fit, I disagree

That is indeed what I am suggesting, and IE/Edge already do it. Variations are possible though, if zooming out is judged to be a poor UX (I don't think it is, but we can disagree on that), you can also deal with it without zooming and simply add scrollbars if your window is 400px and your viewport is min 500px. This is better than smashing everything together and causing overlap if the design is known not to work under 500px.

it's too different from how windows normally react to resizing

Is it? if you resize down an image viewer, or a pdf viewer, or any number of applications whose content is not reflowable, it will typically zoom out. Not always, but it is a common UI strategy. When web content is reflowable, it should be reflowed. But if it is known not to deal well with sizes bellow a certain limit, then opting into some other mode makes sense to me.

@alexelias
Copy link

OK, do you happen to have a sample page handy where I could experience Edge's behavior?

you can also deal with it without zooming and simply add scrollbars if your window is 400px and your viewport is min 500px

Sure, but that behavior is already easy to achieve, for example by just putting all your content in a min-width: 400px flexbox.

@frivoal
Copy link
Collaborator

frivoal commented Jul 8, 2016

you can also deal with it without zooming and simply add
scrollbars if your window is 400px and your viewport is min 500px

Sure, but that behavior is already easy to achieve, for example
by just putting all your content in a min-width: 400px flexbox.

That's not quite the same. Assuming this is combined with a width=device-width viewport, this would specifically be calling for a scrollbar. Not for a scrollbar or a zoom our or any UA dependent behavior to ensure this content isn't shrunk. Scrolling may not always be appropriate. Think of printing, or non interactive signage, or any number of UAs which may decide that the right way to avoid shrinking the content and keeping it viewable is something else than a scroll bar. @viewport {min-width: ..;} does that, and flexbox does not.

@alexelias
Copy link

If the argument is that UAs should be able to handle overflow in whatever way they want, they're already empowered to do so. That's how mobile browsers shipped in the first place, choosing to zoom out oversized desktop sites instead of showing a scrollbar. Chrome devtools "Device Emulation Mode" also makes ample use of zooming e.g. to display oversized tablet screens inside small windows. If we're go to the trouble of adding a new property like @viewport, there's no point making it a hint, it should specify a behavior, otherwise as usual the non-hint content will be more trustworthy.

@alexelias
Copy link

alexelias commented Jul 8, 2016

I am open to proposals like @viewport, but I perceive it emerges less out of any use case than the general feeling that meta viewport is a mess that should be cleaned up. And I agree it's a mess. In meta viewport crazy land:

  • width= means min-width=
  • device-width means window-width
  • initial-scale doesn't only affect initial scale but also has weird side effects on the width
  • height doesn't really mean anything
  • the existence of the tag also "randomly" disables behaviors like tap disambiguation menu and double-tap zoom
  • and all this only does anything at all on "mobile browsers", which is an increasingly hazily defined category of UAs.

The problem is: does trying to clean the mess by adding a new thing actually help matters at all, or is it just another case of https://xkcd.com/927/? And in practice, it does seem like most webdevs can get by simply knowing the "best practice" of slapping <meta name="viewport" content="width=device-width"> on all their pages (given a responsively designed site) and not really think too hard about it any further. That's why I'm currently leaning towards inaction.

@ChumpChief
Copy link
Member

My perspective on this is that the only truly useful feature of meta viewport is "width=device-width".

Mostly agree. This solves the main problem of "Many browsers on phones/tablets have a magical default scaling behavior that I need to disable (not control) to make my responsive layout work".

I would love to believe that developers would do something like this -- IMO this would be a pretty reasonable use of fixed-width:

/* My layout is responsive down to 360px but breaks below that */
@viewport { width: device-width; }
@media (max-width: 360px) {
    @viewport { width: 360px; }
}

But in reality I think the usage for fixed-width is more likely to utilize server-side UA detection and cultivate non-responsive sites as @alexelias mentions. And as @RByers data shows the number of sites using fixed widths is shrinking anyway -- I don't think it's wise to over-optimize for a dying trend.

So I'd be in favor of this feature being a simple "off" switch for magical browser scaling, at least for L1.

user-scalable=no: arguably useful on desktop as well, although this can also be achieved by preventDefaulting input events (which use cases like maps which truly care about this are likely to do anyway).

I think it's important to have a declarative mechanism for disabling user scaling rather than preventDefaulting input events for performance reasons. But I don't think it has to be tied to the feature that controls layout dimensions. And I don't think it's important for this part of the feature to be preloader-friendly if its only effect is to control user interaction after the page has completed loading. So while I think we need to retain this functionality in some feature, I'd actually prefer it be split out from layout dimension control.

In Edge we have the -ms-content-zooming property which can disable touch zooming:

html { -ms-content-zooming: none; }

Or enable it for specific elements in the page:

.thing {
    overflow: auto;
    -ms-content-zooming: zoom;
}

https://jsfiddle.net/31x0gsum/

This feature certainly has its flaws, but the part I really like is that it treats zoomability as an element behavior rather than as a page-level meta tag. Whether that's done through a separate CSS property like -ms-content-zooming, extensions to the overflow property, HTML attributes, etc. I have fewer opinions on, but I do think it's appropriate to provide control over zoomability that's as-granular as the already-existing control over scrollability with the overflow property.

I don't mean to derail this thread with discussion of how such a feature could/should work; just want to point out that we could support this functionality in other ways even if it's dropped from this feature, and that I would be in favor of that approach.

@frivoal
Copy link
Collaborator

frivoal commented Jul 12, 2016

If the argument is that UAs should be able to handle overflow in whatever way they want, they're already empowered to do so. That's how mobile browsers shipped in the first place, choosing to zoom out oversized desktop sites instead of showing a scrollbar.

I don't buy that. Browsers can handle overflow anyway they want, but overflowing is not the only negative effect of a viewport that's too small. Overlapping content or elements being squeezed too much happen as well. I don't care about the syntax all that much (other than the fact that this is presentation and should be somewhere in CSS), but the ability to say "don't squeeze the content below this size, and provide an appropriate UI if the window/screen's too small" is important.

We haven't missed it too much so far, because responsive has mostly meant going down to 320px. But:

  • The most popular phones now are more than 320px across
  • Things smaller than phones, like smartwatches, are emerging

This means that I expect the long term trend to be an increase in the number of sites which are responsive enough to deal with small/mobile devices with dominant marketshare (and anything larger), but not responsive enough to deal with all devices out there.

data shows the number of sites using fixed widths is shrinking anyway -- I don't think it's wise to over-optimize for a dying trend.

I agree that fixed-size sites are going down, and I am only interested in specifying a width when it is a min-width, (or when it is used in combination with @media (max-width), which boils down to the same thing).

No website is responsible all the way to width=1px. Device sizes vary, and I doubt that the area of the most popular device being the smallest device (iPhone) is ever coming back. So, if you combine these two facts, we need some way to indicate how small the viewport can get before the layout becomes broken, so that UAs that have a smaller screen/window can cope.

I think I'd be perfectly happy to drop the fixed width part of @viewport, and reduce the featureset to:
@viewport-min-width: <length>; (or rather some writing-modes aware equivalent).

Mobile UAs would have @viewport-min-width: 980px;, and you'd be free to set it to @viewport-min-width: 320px; or @viewport-min-width: 375px; or @viewport-min-width: 25em; or whatever makes sense for your design.

Maybe we need it in both dimensions, but if we do it logically rather than physically, I am not even sure about that.

I think this would be more robust than what we currently have with regards to progressive adoption by different classes of browsers. Unlike @viewport {width:...;} which needs to be supported from day one on mobile and desktop lest sites start relying on it only applying to mobile, we wouldn't have that problem, and adding support for this in a desktop browser even if most sites didn't expect it wouldn't break anything.

As for the preloader, being strict that this has to be at the top of the stylesheet like @import or @charset, maybe even with the restriction that it must either be inline in <head>, or in stylesheets directly linked from the document, and not in recursively @imported stylesheets would be accetable restrictions if that'd help.

I think it's important to have a declarative mechanism for disabling user scaling rather than preventDefaulting input events for performance reasons. But I don't think it has to be tied to the feature that controls layout dimensions. And I don't think it's important for this part of the feature to be preloader-friendly if its only effect is to control user interaction after the page has completed loading. So while I think we need to retain this functionality in some feature, I'd actually prefer it be split out from layout dimension control.

Sounds reasonable to me.

@pp-koch
Copy link

pp-koch commented Jul 12, 2016

In my opinion we should keep the current meta viewport tag, warts and all. As @alexelias argued, it already does what we want, and even though its syntax (and the fact that it's a tag) is not optimal, web developers and browser vendors are used to it and it already solves most of our problems.

I feel that this discussion fails to distinguish between two slightly different widths:

  1. The min-width of the layout viewport
  2. The initial width of the canvas that's actually visible once the browser finished initial zooming (or not)

The second one is the real problem, I think. The first one is already solvable right now.

What should happen when content flows out of the layout viewport horizontally? In other words, should the visible canvas be extended beyond the layout viewport or not? I did some research ages ago (http://www.quirksmode.org/blog/archives/2014/01/widthdevicewidt.html) and concluded that browsers are all over the place.

Maybe it would be a good idea to define what exactly should happen when content overflows. Should the browser zoom out in order to show all of it, or should it accept that the content is not fully visible? There are arguments to be made for both, and I'm not sure which scenario I'd support. Or should we leave this to individual browsers after all? I'd love to hear some opinions on that.

In any case, this is a question of what the initial width of the visible canvas should be. Equal to the layout viewport, or equal to the largest element if that element is larger than the layout viewport?

As to @frivoal 's point of overlapping or squeezed elements, that's caused by web developers not using a min-width for the layout viewport, and is solvable with the tools we have today. Adding a layout viewport min-width is already possible (though not intuitive) with the current meta viewport.

<meta name="viewport" content="width=400px,initial-scale=1">

Now 400px is the min-width of the layout viewport in all browsers except for Android WebKit. (Unless things changed significantly since my last full test run.)

Since this is not common knowledge I thought I'd mention it, even though I wouldn't be surprised if most participants already know this.

Maybe this should become common knowledge. It would help a bit with layout viewport min-width and squeezed elements, though it wouldn't solve the problem of the visible canvas initial width.

@alexelias
Copy link

I'm in favor of standardizing -ms-content-zooming: none;. I agree there is a clear need and it doesn't have the preload problems of the rest of @viewport.

As for min-width, I'm not really hearing the case. I want to hear an argument along the lines of "X is impossible to achieve without this new primitive" and I haven't heard that yet. UAs effectively already have a content-based calculation of minimum non-layout-breaking width, after which they already resort to scrollbars or zooming, and this seems to work OK and be manipulatable as needed by those webdevs who care about it. And I actually trust this calculated value more than a declaration that some webdevs might thoughtlessly copy-paste into their <head>.

@alexelias
Copy link

alexelias commented Jul 15, 2016

As for the behavior @pp-koch raised in http://www.quirksmode.org/blog/archives/2014/01/widthdevicewidt.html , that's a valid interop concern w.r.t. <meta viewport>, although it's somewhat orthogonal to whatever happens to @viewport. In principle, I agree all the browsers should pick one of the behaviors and behave the same. And I agree with you that Chrome 31's behavior makes the most sense, not surprisingly since I wrote it, so I'd suggest that other browsers converge with us :).

Note that one of the main reasons Chrome zooms out in the absence of initial-scale is because some desktop-sized pages copy-pasted a meta viewport width=device-width into their header, and it's preferable to zoom out on those pages just like any other desktop page. On the other hand, we respect the exact value of initial-scale when it's specified. This is also mostly interoperable with iOS Safari (except for Safari's quirky behavior with only "initial-scale=1" which I understand was a result of their trying to provide window-width capabilities back when device-width had its literal meaning -- it's not very relevant today).

@RByers
Copy link
Contributor Author

RByers commented Jul 15, 2016

I'm in favor of standardizing -ms-content-zooming: none;. I agree there is a clear need and it doesn't have the preload problems of the rest of @Viewport.

How is this different from using touch-action? Chromium has long supported html { touch-action: pan-x pan-y; }. as a declarative way of disabling zooming on the whole page without disabling any other touch gestures.

@bradkemper
Copy link
Contributor

Gestures are not the only way to zoom. There is the initial scaling of the page, and the automatic zooming in on focused fields.

@ChumpChief
Copy link
Member

Created #326 to fork off discussion of target scenarios, so we can leave this issue for discussing preloader-friendly syntax options.

@hexalys
Copy link

hexalys commented Sep 9, 2016

Just want to share my thought and experience with dynamic viewport changes and @Viewport.

As an author, I don't foresee a critical need for @Viewport for my work, as long as Edge would support the Meta Viewport, and a bug free way to modify it on the fly. I do that currently to automatically switch a phone or tablet viewport to a desktop size via JS, if the user enable their browser's desktop mode feature. It's been painful however and still somewhat is, because of zoom issues on some engines, and not others, requiring hacky tricks to apply per engine. And I am using @Viewport to on IEMobile with browser detection. While that works ok, the JS way of dealing with meta bugs and tricks is far from ideal.

It's not very hard to imagine legit needs for @Viewport in the context of an app or a game. To adjust the viewport on the fly in an inexpensive way, by just switching css files. Or to avoid dealing with various sizing constraints from legacy projects and/or easily change viewport size from one view to another. In which @Viewport does or may not necessarily have to be preloader friendly for those particular contexts.

I would favor recommending the feature as no more than a convenient way to resize app views that way, so that devs are well aware of what it should be used for. In that, I don't consider @Viewport broken. It's disabled in Edge Tablet Mode at the moment, because of the way it was implemented back in IE10, compatibility issues and technical constraints AFAICT.

i.e. For me @Viewport fits as a dynamic in-app on the fly solution. Not something that should aim at being preloader friendly or replace the standard initial viewport at initial load.

@zcorpan
Copy link
Member

zcorpan commented Sep 9, 2016

It's been painful however and still somewhat is, because of zoom issues on some engines, and not others, requiring hacky tricks to apply per engine.

Those bugs should be fixed for meta. Introducing a new syntax does not mean that the new syntax will not suffer from the same bugs; rather it's opportunity for more bugs and takes away focus from fixing existing bugs.

If you have a test case or link to the workarounds you have used, that could be helpful. :-)

@pp-koch
Copy link

pp-koch commented Sep 9, 2016

I have a test case for some zooming errors:

http://www.quirksmode.org/m/tests/metadynamic.html

Steps:

  1. Click the upper two test links without zooming in. Browsers display correct behaviour: the layout viewport is changed as you would expect and the visual viewport changes with it.

  2. Reload page, zoom in on the test links, and then click them. Although the layout viewport changes, the visual viewport may not change with it. All in all I would say that when the layout viewport size is changed, the visual viewport should zoom out to cover the entire layout viewport. This does not happen in most browsers, but they display various sorts of behaviour.

  • Safari/iOS doesn't change the visual viewport at all
  • Chrome 52 and Samsung Internet 4.0 do something funky with, I think, displaying the same percentage of the layout viewport as before.
  • BlackBerry 10 and Edge zoom out, as desired.

I don't have the time right now to do a full browser test, but I would suggest that this area, too, is in need of standardisation, and that the standard behaviour should be that the visual viewport zooms out to the layout viewport size if the layout viewport size is changed.

@hexalys
Copy link

hexalys commented Sep 9, 2016

@zcorpan Here a long version SO answer of the process I had to go through.

In brief for WebKit and Chrome the workaround for zoom issues was to prevent zoom on the first pass. And do a second pass to restore zoom at the appropriate timing.

Firefox required either document.write() or a force removal + re-add of a new meta viewport.

A major difficulty to note with Meta viewport and keeping a consistent width at screen rotations e.g., is that it requires a calculation of the new expected scale ratios according to the prior orientation and respective screen sizes. Not mentioning the necessity I had to first adjust for screen sizes wrongly reported as physical pixels on android webview or some other devices, in order to properly determine the rotated width correctly ahead or time. :(

Meta viewport changes lack that clean slate, or a way to change individual values independently. Something that @Viewport may be more suited to handle, without all the math headaches.

@bradkemper
Copy link
Contributor

A major difficulty to note with Meta viewport and keeping a consistent width at screen rotations e.g., is that it requires a calculation of the new expected scale ratios according to the prior orientation and respective screen sizes.

Note too that "consistent width at screen rotations" is not always desirable, but is definitely something the author wants to control. For the sites I work on, it is more important for the scale to stay consistent when the device is rotated, so that rotating can reveal wider areas (longer lines of text, images that are wider than the width of the vertical viewport, more table columns, etc.). For other sites, scaling is better when rotating, so that e.g. text will be larger and more readable on fixed-width text blocks (you can fit the whole line of text to the larger dimension of your phone just by rotating it).

@hexalys
Copy link

hexalys commented Sep 9, 2016

@bradkemper Agreed. Scaling is one use case of Desktop mode where it feels adequate to remain at 1024 width in either rotations. Or eventually an author could decide to rescale undesirable screen widths to a custom size for legibility purposes or responsive design convenience.

e.g. There are tablets with a pixel ratio so compact that almost require either bumping the font size up or reducing the viewport width for a more reasonable legibility. Recently, Amazon has switched my tablet portrait viewport from 533 to 600 with a system update, and I find it quite annoying as that ratio is now way too small for my taste.

Also @Viewport and a user stylesheet override (not a thing yet but why not) could allow users to customize their device to their preferred viewport width more permanently. I assume, that CSS origin would make it preloaded friendly if taking priority over device-with. That's speculation of course but that involves spec details to think about.

@hexalys
Copy link

hexalys commented Sep 10, 2016

@bradkemper I should clarify and correct myself on the scale factor required by my Desktop mode use case (as I slightly misspoke). The reason I involve changing the meta viewport initial-scale is that for phones in portrait, I set the desktop width at 768 (technically an average tablet portrait width, 1024 being too small to appear useful at 300-400ish) and the landscape width at 1024.

In case the user has zoomed, I apply a zoom reset (that zoom would get lost after rotation to a different width, and to make it clear that the width is different). So the initial-scale change and locking during the transition, is to zoom back-out at scale 1.0 for the new given width.

That's more or less trying to circumvent the annoying sticky zoom between one rotation and another, or during page reload, which @pp-koch is alluding to. That doesn't happen with @Viewport on IE/Edge. All you have to do with @Viewport is set the width and get an automatic initial-scale=1.0 at the given size with no sticky zoom. It zooms back out to cover the entire layout.

For that discrepancy, meta viewport could use an additional setting called maintain-zoom=yes/no or align behaviors. IMO I don't really see much of a point in maintaining zoom on rotation or reload. It create a bunch of other issues (like unwanted zooms on fixed content due to rotation as I currently see on iOS).

@smfr
Copy link
Contributor

smfr commented Feb 12, 2020

CSS WG just resolved to remove @Viewport (see #4766).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests