├── .clang-format ├── .editorconfig ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Motivation.md ├── README.md ├── study-group ├── Angular-Material-virtual-scroll.md ├── Polymer-iron-list.md ├── README.md ├── REQUIREMENTS.md ├── WinJS.md └── iOS-UITableView.md └── w3c.json /.clang-format: -------------------------------------------------------------------------------- 1 | # Defines the Chromium style for automatic reformatting. 2 | # http://clang.llvm.org/docs/ClangFormatStyleOptions.html 3 | BasedOnStyle: Chromium 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_size = 2 8 | indent_style = space 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | yarn.lock 4 | .vscode -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Web Platform Incubator Community Group 2 | 3 | This repository is being used for work in the W3C Web Platform Incubator Community Group, governed by the [W3C Community License 4 | Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To make substantive contributions, 5 | you must join the CG. 6 | 7 | If you are not the sole contributor to a contribution (pull request), please identify all 8 | contributors in the pull request comment. 9 | 10 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 11 | 12 | ``` 13 | +@github_username 14 | ``` 15 | 16 | If you added a contributor by mistake, you can remove them in a comment with: 17 | 18 | ``` 19 | -@github_username 20 | ``` 21 | 22 | If you are making a pull request on behalf of someone else but you had no part in designing the 23 | feature, you can remove yourself with the above syntax. 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors 2 | under the 3 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 4 | 5 | Contributions to Specifications are made under the 6 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 7 | 8 | Contributions to Test Suites are made under the 9 | [W3C 3-clause BSD License](https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) 10 | 11 | -------------------------------------------------------------------------------- /Motivation.md: -------------------------------------------------------------------------------- 1 | # Why a virtual scroller? 2 | 3 | As explained in [the README](./README.md), virtualized content is an important and common pattern on the web, but it's a hard one to get right. Here we dive into those arguments further, to justify why we believe this is an important feature to provide out of the box with the web platform. 4 | 5 | ## Performance 6 | 7 | **The most important reason that we believe that virtual scrollers are a good pattern, and that we want to provide a solution as part of the web's standard library, is because they are one of the most effective things developers can do to get reliably good rendering performance.** 8 | 9 | Good rendering performance is about rendered DOM size. Fundamentally, having a lot of rendered DOM nodes causes significant performance impact in ways that browsers can only optimize so much. 10 | 11 | It’s not uncommon to see pages with tens of thousands of DOM nodes, and on those pages, style recalcs and layouts are often quite expensive in unpredictable ways (e.g. changing a class name ends up causing a huge DOM subtree to recalc and relayout). 12 | 13 | Native mobile platforms immediately steer you towards a virtualized view. As a result, apps are naturally in a pit of success because they just don’t end up with thousands of views that the OS framework needs to manage. 14 | 15 | If most pages on the web defaulted to using a virtualized view, then many of the performance problems we see would never happen in the first place. 16 | 17 | ## Standardization 18 | 19 | So, we think virtual scrollers can have a huge impact on performance. Why bake it into the browser, instead of continuing with the current trend of hoping web developers use libraries? There are a few reasons. 20 | 21 | One of the primary impacts of standardization is as a coordination function, to shift the ecosystem. As such, we think having a standard virtual scroller element in the browser will have a big impact on usage. Using virtualized content—which, per the above, is key to building fast pages on the web—would be considerably easier and require considerably less expertise. 22 | 23 | We'd like to get to a world where the browser's built-in virtual scroller is good enough, and easy enough to use, to make it a default path for most web pages. Imagine not just virtualized contact lists or social media streams, but also long-form articles where each paragraph is virtualized, or GitHub issue threads where each comment is virtualized. (The [virtualized single-page HTML Standard](https://github.com/valdrinkoshi/virtual-scroller/tree/virtual-content/demo/html-standard) is a good demo in this vein.) Any scrollable content should end up in a virtual scroller. 24 | 25 | For example, if you go look at any Cocoa (iOS) starter tutorial, the first code they tell you to write is to use a `UITableView` (a virtualized view). It’s hard to imagine how we could get starter tutorials to point developers to virtualized views if there isn’t at least one variant built into the browser. ("OK, so first pick a framework; these three are popular this week. Make sure to learn it in enough detail to understand how third party components fit into those frameworks. Then, if you're using React, React Virtualized is good, and works this way, but has these caveats... If you're using Angular...") 26 | 27 | Shipping a virtual scroller with the browser also means that developers only need to ship the code for their virtualized view over the wire if they need to do something bespoke. This makes the web easier to develop on for everyone, increases the pit of success for developers, and improves the experience for users who are now interfacing with more lightweight sites. 28 | 29 | ## Layering 30 | 31 | While we do want a standardized virtual scroller that ships with the browser, we insist on [building it in a layered way](https://extensiblewebmanifesto.org/), on top of primitives that web developers can already access. This is in contrast to other semi-recent HTML controls, like `
` or ``, which cannot be replicated on top of primitives. 32 | 33 | This layered approach ensures that all the primitives that make for a good virtual scroller are also accessible to other frameworks building virtualization solutions. This includes already-existing primitives like `IntersectionObserver`, `ResizeObserver`, and shadow DOM, as well as still-speculative primitives like [display locking](https://github.com/WICG/display-locking/), designed to solve the problems of accessibility, indexability, find-in-page, in-page anchors, and other ways in which the disconnect between content and DOM cause user experience issues. 34 | 35 | In particular, we don't insist that the virtual-scroller element we ship with the browser be the perfect solution for 100% of virtualized content cases. We're aiming more for 90%. This is inevitable; higher-level APIs need to be more opinionated than lower-level primitives, so they can’t meet all the developer needs. As such, it’s critical that people who have other needs can meet them with the same richness as browser built-ins. The layered strategy for virtual scroller ensures this. It also gives an easy transition path for existing virtualized content solutions and libraries which do fall within that 90% case: they can, over time, port their implementations to be a wrapper around the browser built-in one, with even more (likely framework-specific) opinions. 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A built-in virtual scroller for the web platform 2 | 3 | This repository hosts explorations for a new web platform feature, a virtual scroller control. The idea of a virtual scroller is to provide a scrolling "viewport" onto some content, allow extremely large numbers of elements to exist, but maintain high performance by only paying the cost for those that are currently visible. Traditionally, we say that the non-visible content is _virtualized_. 4 | 5 | ## Current status 6 | 7 | This project is no longer being actively developed. Instead we are pursuing primitives [here](https://github.com/WICG/display-locking). 8 | 9 | ## Why a virtual scroller? 10 | 11 | Virtualized content is a popular and important pattern on the web. Most content uses it in some form: the https://m.twitter.com and https://facebook.com feeds; Google Photos and YouTube comments; and many news sites which have an automatic "scroll to next article" feature. Most popular frameworks have at least one high-usage virtualization component, e.g. [React Virtualized](https://bvaughn.github.io/react-virtualized/) with [~290K weekly downloads](https://www.npmjs.com/package/react-virtualized). See the [infinite list study group](https://github.com/domenic/infinite-list-study-group) for more research on existing virtualization solutions, both on the web and in other platforms like iOS. 12 | 13 | At the same time, virtual scrollers are complex and hard to get right. In fact, having a first-class experience with virtualized content is currently impossible, because browsers don't expose the right hooks: things like accessible landmark navigation, find in page, or intra-page anchor navigation are based solely on DOM structure, and virtualized content is by definition not in the DOM. Additionally, today's virtualized content does not work with search engine crawlers, which means that sites that care about search engine ranking are unable to apply this important performance technique. This is bad for the web. 14 | 15 | We believe that, like native platforms, the web deserves a first-class virtual scroller implementation that works out of the box. 16 | 17 | For more details on the motivation, see [Motivation.md](./Motivation.md). 18 | 19 | ## Sample code 20 | 21 | ```html 22 | 26 | 29 | 30 | 37 | 38 |
Item 1
39 |
Item 2
40 | ... 41 |
Item 1000
42 |
43 | 44 | 62 | ``` 63 | 64 | ## Goals 65 | 66 | * Be flexible enough to be used for various kinds of scrolling, larger-than-viewport content, from news articles to typeaheads to contact lists to photo galleries. 67 | * Only pay the rendering costs for _visible_ child elements of the scroller (with some margin). 68 | * Allow contents of the scroller to work with find-in-page, accessibility features, focus, fragment URL navigation, etc., just as they would in a non-virtualized context. 69 | * Be flexible enough to allow developers to integrate advanced features and behaviors, such as groupings, sticky headers, animations, swiping, item selection, etc. 70 | * Support 1D horizontal/1D vertical/2D wrapped-grid layouts. 71 | 72 | ## Non-goals 73 | 74 | * Allow data that are not part of the DOM to work with find-in-page, accessibility, etc. The DOM remains the source of truth for these browser features, not e.g. the server-side, or other in-memory JavaScript data structures. See [below](#almost-infinite-data-from-the-server) for more elaboration. 75 | 76 | And, at least in v1, the following are out of scope: 77 | 78 | * Built-in support for advanced features and behaviors, such as those mentioned above. 79 | * Support infinite-grid (spreadsheet-like), multi-column (content continues from bottom of col(N) to top of col(N+1)) or masonry layouts. 80 | 81 | ## Proposed APIs 82 | 83 | ### `` element 84 | 85 | The `` element represents a container that will manage the rendering of its children. 86 | The children of this element might not get rendered/updated if they are not near or in the viewport. 87 | The element is aware of changes to the viewport, as well as to its own size, and will manage the rendered state of its children accordingly. 88 | 89 | Its children can be any element. 90 | Semantically, the element is similar to a `
`, with the addition of focus on only the visible contents when the element overflows its container and is scrolled. 91 | 92 | The sizes and other layout values of the non-rendered children, which might affect scrollbar height, etc., are approximate sizes and might not be always accurate. 93 | The rendered children always have accurate style and layout values, just like other normal DOM nodes. 94 | 95 | All children, rendered or non-rendered, will work with find-in-page, focus navigation, fragment URL navigation, and accessibility technology, just like normal DOM nodes. 96 | 97 | ### `rangechange` event 98 | 99 | Fired when `` is about to render a new range of items, e.g. because the user scrolled. 100 | This will fire at `requestAnimationFrame` timing, i.e. before the browser is about to paint. 101 | 102 | The event has the following properties: 103 | 104 | * `first`: an integer, the 0-based index of the first children currently rendered. 105 | * `last`: an integer, the 0-based index of the last children currently rendered. 106 | * `bubbles`: false 107 | * `cancelable`: false 108 | * `composed`: false 109 | 110 | As an example, this can be used to delay more costly rendering work. 111 | For example, a scrolling code listing could perform just-in-time syntax highlighting on lines right before they become visible, leaving the un-adorned code accessible by find-in-page/etc. but improving the code's appearance before the user sees it. 112 | 113 | _TODO: do we need `first` and `last` on the event, or should we just use the properties of the element?_ 114 | 115 | ### `rangeFirst` and `rangeLast` getters 116 | 117 | These return 0-based indices giving the first and last children currently rendered. 118 | 119 | _TODO: these names are kind of bad?_ 120 | 121 | ### Constraints and effects 122 | 123 | Ideally, we would like there to be zero constraints on the contents of the `` element, or on the virtual-scroller element itself. 124 | 125 | Similarly, we would like to avoid any observable effects on the element or its children. Just like how `