Coder Social home page Coder Social logo

wicg / visual-viewport Goto Github PK

View Code? Open in Web Editor NEW
176.0 17.0 28.0 195 KB

A proposal to add explicit APIs to the Web for querying and setting the visual viewport

Home Page: https://wicg.github.io/visual-viewport/

License: MIT License

HTML 82.26% JavaScript 17.74%

visual-viewport's Issues

scale shouldn't be spec'd as relative to the ideal viewport

If the developer has modified the layout viewport size (e.g. meta viewport with width=1024 on a device where device-width would have been 384), pageScale should probably reflect the ratio against that adjusted viewport rather than the ideal viewport.

So I think this should instead use "layout viewport", though I'd be interested to make sure we're on the same page with the nastier cases you called out with wide elements and min-scale.

Code sample is calculating offsetX/Y incorrectly

Currently:

var offsetX = viewport.scrollLeft;
var offsetY = viewport.clientHeight - document.documentElement.clientHeight + viewport.scrollTop;

Should instead be this I think:

var offsetX = viewport.scrollLeft - document.scrollingElement.scrollLeft;
var offsetY = document.documentElement.clientHeight - (viewport.scrollTop - document.scrollingElement.scrollTop) - viewport.clientHeight;

changing visual viewport dynamically

As in stackoverflow, I think of changing visual viewport dynamicly. This will be useful in routings, when user changes its position in a SPA.
As I searched a lot, I found out these parameters are read only (visual viewport height and width) but there are changing according to focus or user behavior. So, changing it by code is necessary.
Thanks for any help, or information.

Should window.scrollTo() preserve visualViewport.offset{Left,Top}?

This is less a question about the Visual Viewport API per se, and more about the underlying behaviour of the visual viewport itself, but it came up while investigating a Visual Viewport API web platform test so I thought I'd ask it here.

The test in question sets up a scenario where visualViewport.offsetLeft and offsetTop are nonzero, then performs window.scrollTo() (which has room to perform layout scrolling and does so), and then asserts that offsetLeft and offsetTop are unchanged.

The accompanying comment says:

// The visual viewport should be fully scrolled so even if
// scrollTo does normally "push" the layout viewport with the
// visual, there should be no change to either offsetValue

I'm not fully clear on the intended underlying conceptual model. Under what circumstances is window.scrollTo() expected to preserve the offset of the visual viewport relative to the layout viewport? (The comment suggests to me that it's not "always", though perhaps I'm misreading it.)

In the current Firefox implementation, window.scrollTo() sets both the layout and visual viewport offsets to the specified location (in other words, collapses the relative offset to zero). We chose this because we figured that a page performing window.scrollTo() may be trying to bring the user's attention to an element / section header etc. at the specified location, and so keeping that location out of view by preserving a potentially-large relative offset may be unexpected (kind of like how Element.scrollIntoView() should scroll an element into the visual viewport, which I note is a behaviour Chrome fixed recently).

Before considering a change to the Firefox behaviour, I'd like to understand the underlying conceptual model and the motivation for it better.

cc @bokand

scale not changing with browser zoom on desktop

Preface: I am looking into new ways to detect the Desktop browser zoom with visualViewport. Used to do that efficiently with svg.currentScale but it's no longer working on Chrome. So I wanted to experiment:

As I am testing in Chrome 59 atm. If I zoom in or out, the current visualViewport scale remains at 1. It seems like it shouldn't be the case, and give the proper Browser zoom scale instead.

Per your formula:
physicalWidth = cssWidth / (visualViewport.scale * window.devicePixelRatio)

However with view.scale at 1 while zoomed, I do not get a good equivalent of physicalWidth (outerWidth).

Interaction with window.scrollTo/scrollBy

I think the interaction of the visual viewport with the window.scrollTo/scrollBy is also worth specifying as part of this proposal. The intuitive (to me, anyway) behaviour from the author's point of view would be that calling window.scrollTo also resets the visual viewport to the top-left of the layout viewport, and that calling window.scrollBy leaves the visual viewport as-is relative to the layout viewport.

Should we allow setting pageScale?

My initial draft has scrollLeft and scrollTop as writable but pageScale as read-only. On reflection, a writable scroll offset seems pointless without a writable pageScale. We should either make them all read-only or all writable.

scrollTop and scrollLeft should be clearer about their sign

The definition of scrollTop and scrollLeft could be interpreted as requiring a negative sign in the normal case, although probably not, given that it says "distance" rather than "location" or "offset", since it's described as from the visual viewport to the layout viewport (rather than the other way around).

However, I'm not 100% sure that we can promise that it always should be a nonnegative number, e.g., with touch overscrolling.

This makes me think that it should be described as an offset or location, but with the "from" and the "to" swapped from the way they currently are.

Noticed while reviewing the spec for w3ctag/design-reviews#128 .

Alignment opportunity with foldable and multi-screen proposal

@bokand I wonder if there's an opportunity to align some active proposals with the Visual Viewport API, particularly the Window Segments Enumeration JS API (see also the proposed CSS MQ). +CC @zouhir & @dlibby- Perhaps folds or screen edges within the content area could be exposed as visual viewport information, or general insights from this work could inform that proposal.

Please consider joining our TPAC breakout session to discuss the foldables and multi-screen problem space and alignment opportunities between some active proposals. That will continue discussion from the Second Screen CG meeting; minutes. Thanks!

Split visualviewportchanged into scroll/resize?

Currently a visualviewportchanged listener will trigger on every scroll. If a developer is really only interested in observing the size of the visual viewport, this would be more noisy than intended.

How will this interact with non-layout-affecting URL bars?

The proposal in https://github.com/bokand/URLBarSizing is something that Safari already does and we're likely to switch to shortly. We should be explicit about how the two interact.

In short, I think the real problem here is that when we say "layout viewport" we're actually referring to the "position: fixed viewport". We've often said that the visual viewport is bounded by the layout viewport but in that many cases, the layout viewport doesn't have much to do with layout. In the case of the static-layout URL bar, hiding the URL bar will increase the height of the visual viewport and the position: fixed viewport (what we currently call the layout viewport), but not the initial containing block (the "real" layout viewport"). Perhaps we need a shift in terminology...

Avaibality of the Visual Viewport API in non-secure contexts

The spec does not mention if the Visual Viewport API is restricted to secure contexts only. Currently, in Chrome the Visual Viewport API is available in non-secure contexts. The W3C spec for secure contexts https://w3c.github.io/webappsec-secure-contexts/#new recommends all new features to be restricted to secure contexts. For existing features which are not widely used but widely implemented, the spec suggests applying this restriction and modifying the specs of the existing feature. What do you think about restricting the Visual Viewport API to secure contexts?

Add properties/mechanism to get clientWidth/Height of the visual viewport in unscaled coordinates

I believe the intent of the spec currently is to return lengths/offsets in the layout viewport's coordinate space -- e.g. as I zoom in, the visual viewport's clientWidth and clientHeight properties "shrink".

However, pending the addition of real device-fixed positioning, it's interesting to additionally receive these properties in the coordinate space of the visual viewport (basically just unaffected by pageScale). Since these elements are laid out in the visual viewport's coordinate space, it's more convenient to receive the measurements in the visual viewport's coordinate space directly rather than multiplying by pageScale (and introducing risk of floating point error).

I imagine other scenarios could also benefit from this, but that's the one that immediately pops into my mind for now :)

resize/scroll events on visualviewport are underspecified

The draft spec says e.g. "The user agent must fire an Event named resize on the window.visualViewport object" - but it doesn't provide any details about this event. Does it bubble up to the window? Is it cancelable? Does it have any relatedTarget elements or anything of that nature? Does it extend from UIEvent or Event?

Difficult to react to changes in visualViewport

Let's say I wanted to style an element so it appeared "attached" to the visual viewport:

visualViewport.addEventListener('scroll', visualViewportUpdate);
// But it's possible for the viewport to update without scrolling, so
// we need to track resize too:
visualViewport.addEventListener('resize', visualViewportUpdate);
// Neither of those events fire when just pageLeft/pageTop changes
// so we have to listen to something that represents the layout
// viewport too:
window.addEventListener('scroll', visualViewportUpdate);

// Problem: it's now possible for visualViewportUpdate to be called
// three times for a single update, so we need to work around that:

let pendingUpdateHandler = false;

function visualViewportUpdate() {
  // Avoid additional calls within the same frame.
  if (pendingUpdateHandler) return;
  pendingUpdateHandler = true;
  
  // Flip the boolean after we've processed all the events.
  requestAnimationFrame(() => {
    pendingUpdateHandler = false;
  });

  // Handle visual viewport change…
}

This seems pretty tough going, and requires a pretty detailed understanding of the event loop to get right.

Initially I was worried that the events may fire across different visual updates, but I stumbled across #25 which cleared that up.

It feels like we need a single event that fires when any of the properties update, including pageLeft/pageTop, that would turn the above example into:

visualViewport.addEventListener('update', () => {
  // Handle visual viewport change…
});

Parallel API for layout viewport?

Should there be a parallel API for layout viewport?

A couple reasons this might be interesting:

  1. Enables developers to move away from the ambiguous APIs altogether. Those that do will be explicitly thinking about which viewport they're interested in when consuming the API.
  2. If a developer is really only interested in responding to changes to the layout viewport and not the visual viewport, the "scroll" event is noisier than needed today. It fires when the user has zoomed and is moving the visual viewport around within the layout viewport but not touching the edges of the layout viewport.

Use `zoom` instead of `scale`

This terminology is more in line with what web devs use. Scale is what we've used internally to distinguish browser and pinch zooms and it leaked out here. Perhaps having it on the visual viewport is distinguishing enough?

visual viewport behavior underdefined for detached windows and non-active documents

https://wicg.github.io/visual-viewport/#extensions-to-the-window-interface says:

If the window has a Browsing Context set, return the VisualViewport object associated with it. Otherwise, return null.

But in the spec windows don't have a browsing context set at all. There's a concept of "document's browsing context" which is affected by discarding, and there's a browsing context stored in the settings object which apparently is not affected by discarding (but maybe should be? I just filed whatwg/html#3846 on that). but nothing on Window.

Even apart from this, though, what happens if a script takes a reference to a VisualViewport and then the browsing context involved gets discarded?

And separately, what happens if there is no browsing context discarding, but the document of the Window the VisualViewport comes from stops being active? Concretely, say I grab a VisualViewport from site A, then navigate that browsing context to a different-origin site B. Can I use the VisualViewport I am holding to examine the user's interaction with site B? That would be quite undesirable.

Feature detection of inert-visual-viewport

As far as I know, the inert-visual-viewport flag just changes the behavior of properties like window.innerWidth and body.scrollX. Is there any preferable/standard way to feature detect which version of the API is present? Possibly, it is the idea to simultaneously release this API change and the viewport API, in which case one could simply check for the presents of window.viewport; or is the idea to first release the viewport API and later on the inert-visual-viewport stuff?

definition of scroll event should be clearer about what constitutes a scroll

The definition of the scroll and resize events should be clearer about when, exactly, the scroll event is fired.

In particular, a resize, by definition, changes some edges of the visual viewport. Does the scroll event fire at the same time as a resize event if the resize involves a change to certain edges (the top or left, or something dependent on directionality?) of the viewport, does a scroll event always also fire along with a resize event, or does a scroll event never fire at the same time as a resize event since a resize event implicitly changes some of the edges of the visual viewport?

visualviewportchanged event will be async

The proposal suggests firing a visualviewportchanged event to content. With async panning/zooming, this event will necessarily be async and laggy, just like the scroll event. I don't really have any better ideas at the moment but I wanted to raise an issue for it as I think it merits further discussion. If authors start relying on this event to implement scroll-linked effects then it can result in bad-looking behaviour if the main thread is busy or under load.

Is visualViewport useful for iframes?

We're looking at implementing the Visual Viewport API in Firefox. One thing we noticed was that the spec seems to define visualViewport for iframes as well. Is that useful? My understanding is that iframes don't have distinct notions of visual and layout viewports, since they cannot be zoomed.

Should scrollTop/Left be relative to document origin rather than layout viewport?

And similarly, visualviewportchanged fire when the position changes relative to the document origin rather than just the layout viewport.

Arguments for document origin:

  1. Better matches the current behavior of pageXOffset/YOffset which these APIs are intended to supplant.
  2. Better matches scenarios involving triggers at particular scroll offsets -- e.g. load in more content when the visual viewport is at 95% of the scrollHeight.
  3. Better matches scenarios involving positioning of non-fixed content, e.g. absolute-positioned modal dialogs that should be centered in the visible region.
  4. Better matches scenarios of scrolling a particular part of the document into view by setting visualViewport.scrollTop
  5. visualviewportchanged is sufficient to detect visual viewport motion relative to the document -- the developer doesn't need to additionally register for the scroll event

Arguments for layout viewport origin:

  1. Better matches scenarios involving positioning of fixed content, e.g. pseudo-device-fixed as your code sample demonstrates.
  2. Better matches "is in view" checks since the offsets can be directly compared against the getBoundingClientRect() of the target, which is also measured relative to the layout viewport origin.
  3. visualviewportchanged can fire more rarely, particularly in usage scenarios with prolonged panning against the edge of the layout viewport.

I lean towards document origin but can see the pros for each side. I'm guessing you may have had additional reasoning for selecting layout viewport origin in your draft -- anything I'm missing above?

How to get the size of the visual viewport + scrollbars?

The size returned by the Visual Viewport API excludes any space taken up by scrollbars.

What if a web page wants to know the size including the scrollbars? In Firefox, it can currently use window.innerWidth. However, if we switch window.innerWidth to report the size of the layout viewport instead as Chrome has done, that will no longer work; is there a replacement?

cc @mstange @bokand

Rename `window.view` to `window.visualViewport`

We originally changed this the other way in the context of #35 but this has compatibility issues. There's a non-trivial number of pages using a global view which could cause them to break if we add this. Last I checked visualViewport was unused in the HTTPArchive and so has much less risk.

The original complaint was that it's cumbersome and "java-like". IMO, it actually fits in well with other window properties like sessionStorage, localStorage, and devicePixelRatio. Worst-case, authors can always alias it to something more convenient.

@hexalys, @dbaron, any concerns?

Polyfill calculation of clientWidth/Height uses magic number 15

I think this is maybe supposed to represent the scrollbar width? If so then it will be incorrect at scale values other than 1.0 (since the scrollbar doesn't scale as the user zooms) and also incorrect for any UAs with scrollbars of differing widths.

Should window.visualViewport be null if there's no associated browsing context?

Several Window APIs currently return null when there's no associated browsing context (e.g., this happens when we have a window object corresponding to an iframe element that has been removed from the DOM). See calls to "IsCurrentlyDisplayedInFrame" in LocalDOMWindow.cpp in Blink for examples.

Should window.visualViewport behave the same way? Currently in Blink, it's non-null even when there's no associated browsing context, but the question of whether it should really be null came up in a WebKit code review: https://bugs.webkit.org/show_bug.cgi?id=179385#c7

Should specify the order of scroll event with respect to other pending scroll event targets

This specification doesn't specify when resize event on visual viewport is dispatched before or after other pending scroll event targets. Because document itself is a pending scroll event target, even specifying the order relative to document's resize event itself is insufficient; there could be more pending scroll event targets such as other scrollable elements in the same document.

Use Case: Scaling of Bitmap Data

I am experimenting with visualViewport.scale to detect the best resolution needed for bitmap elements (e.g. image or canvas). Currently I multiply the CSS pixel size of an HTML canvas by the factor (visualViewport.scale*window.devicePixelRatio). This accounts for pinch zoom, browser zoom, and physical device pixel ratio. window.devicePixelRatio already contains the physical device pixel ratio multiplied by the browser zoom factor and visualViewport.scale accounts for the pinch zoom. This part works fine on Chrome Canary Win 8.1.

I also use window.innerWidth in order to limit the size of a WebGL canvas (which is an important performance optimization) to the part of the canvas that is actually visible. I tried to replace window.innerWidth by visualViewport.clientWidth, however it turns out that visualViewport.clientWidth is a bit smaller than window.innerWidth (according to the old semantics, i.e. with disabled inert-visual-viewport), which probably accounts for the space of the scroll bar. When pinch zooming-in this difference seems to stay constant and does not scale with the pinch zoom. (Tested emulating a laptop with touch in developer tools on windows 8.1, 54.0.2820.0 canary, enabled enable-experimental-web-platform-features and disabled inert-visual-viewport).

The fixed-to-keyboard.html seems to experience this problem as well: Add a horizontal scroll bar below the red box, (e.g. by increasing the width of the text area in the elements panel of developer tools). Then pinch zooming-in makes the red box move up and no longer stay directly on top of the scroll bar. (Tested emulating a laptop with touch in developer tools on windows 8.1, 54.0.2821.0 canary, enabled enable-experimental-web-platform-features and enabled inert-visual-viewport).

Is emulating `position:device-fixed` really the best use case for this API?

We are about to ship this API in Firefox, and I'm working on coordinating some MDN documentation.

I notice that in this repo, the headline example is emulating position: device-fixed. I wonder, though -- is this the best use case for this API?

In browsers with asynchronous scrolling, which includes both Chrome and Firefox on Android, updating a position property from script in response to scrolling is going to cause flickering during scrolling. (And indeed, if I open the headline example on Android with either Chrome or Firefox, the red box flickers as you scroll.)

It feels strange to me to be encouraging web developers to author websites with flickering elements. I would feel better about promoting examples that don't involve such artifacts.

(On a related note: if we want users to be able to have position: device-fixed behaviour, perhaos a better approach would be to actually implement position: device-fixed, which then doesn't need to cause such a flickering artifact?)

Definition of scale is not clear

The definition provided for the scale property is not fully clear to me. That's probably because terms like "device pixel" are not well-defined specially when dealing with things like retina displays and automatic OS-level pixel doubling. An example scenario with both pinch-zoom and browser zoom applied would also help clarify the "note".

Please don't call it "viewport"

Everywhere else on the web platform, viewport means (or will soon mean) the layout viewport. For example:

  • meta viewport
  • CSS @Viewport
  • CSS vw,vh units
  • throughout the CSSOM View module

So it would be very confusing for document.viewport to mean something different. People will try to use document.viewport.clientWidth to get the layout viewport width, etc.

Whilst the Chrome team internally uses terminology like layout viewport and visual viewport, and understands the difference, many web developers don't know there are two viewports.

Instead how about:

  • document.visibleArea
  • document.visibleRect
  • document.visualViewport
  • document.zoomRect
  • document.zoomViewport
  • document.zoomArea

Should pageScale be a property of the visualViewport, or something else?

pageScale represents a scale ratio between two viewports (visual and layout), and conceptually isn't wholly owned by either.

Similar concepts would include the ratio between layout viewport and physical resolution (in Edge this is represented by devicePixelRatio). Or ideal viewport and physical resolution (devicePixelRatio in Safari). Or layout viewport and ideal viewport (@Viewport {width: 200%}).

My main concern is that as we find and develop interest in these other ratios we'll need to add more and more member properties to the viewport object. Issue #8 talks about the naming of this property which would become more confusing as well if/when these additional ratios are added.

I think this could be more generally solved by a coordinate space conversion API accepting two objects each defining a coordinate space and return a transformation matrix. A partial solution might just return a scale ratio, and maybe a translation.

Polyfill calculation of scale is incorrect

outerWidth is not a safe property to use in polyfills since its value varies per each UA's browser chrome. This calculation is wrong on all non-maximized desktop browsers as a result.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.