Skip to content

Instantly share code, notes, and snippets.

@rik
Created March 29, 2017 21:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rik/e784cf5f56d8a1b60c7d27eb6a3032e4 to your computer and use it in GitHub Desktop.
Save rik/e784cf5f56d8a1b60c7d27eb6a3032e4 to your computer and use it in GitHub Desktop.
Microsoft Edge Dev Blog
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
<channel>
<title>Microsoft Edge Dev Blog</title>
<atom:link href="https://blogs.windows.com/msedgedev/feed/" rel="self" type="application/rss+xml"/>
<link>https://blogs.windows.com/msedgedev</link>
<description>Official blog of the Microsoft Edge Web Platform Team</description>
<lastBuildDate>Fri, 24 Mar 2017 16:06:25 +0000</lastBuildDate>
<language>en-US</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<generator>https://wordpress.org/?v=4.7.3</generator>
<image>
<url>https://winblogs.azureedge.net/win/2016/12/cropped-Windows-logo13-32x32.png</url>
<title>Microsoft Edge Dev Blog</title>
<link>https://blogs.windows.com/msedgedev</link>
<width>32</width>
<height>32</height>
</image>
<item>
<title>CSS Custom Properties in Microsoft Edge</title>
<link>https://blogs.windows.com/msedgedev/2017/03/24/css-custom-properties/</link>
<comments>https://blogs.windows.com/msedgedev/2017/03/24/css-custom-properties/#comments</comments>
<pubDate>Fri, 24 Mar 2017 16:00:46 +0000</pubDate>
<dc:creator><![CDATA[Greg Whitworth]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Announcements]]></category>
<category><![CDATA[CSS]]></category>
<category><![CDATA[CSS Custom Properties]]></category>
<category><![CDATA[CSS Variables]]></category>
<category><![CDATA[Layout]]></category>
<category><![CDATA[New Platform Features]]></category>
<category><![CDATA[Platform Demos]]></category>
<category><![CDATA[Test Drive]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>Beginning with EdgeHTML 15 in the Windows 10 Creators Update, Microsoft Edge introduces support for CSS Custom Properties, a new primitive value type to fully cascade variables across CSS properties. You can preview CSS Custom Properties in Windows Insider Preview builds beginning with EdgeHTML 15.15061. Check out our Custom Properties Pooch demo to see them [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/24/css-custom-properties/">CSS Custom Properties in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>Beginning with EdgeHTML 15 in the Windows 10 Creators Update, Microsoft Edge introduces support for CSS Custom Properties, a new primitive value type to fully cascade variables across CSS properties. You can preview CSS Custom Properties in Windows Insider Preview builds beginning with EdgeHTML 15.15061. Check out our <a href="https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/custom-props/"><u>Custom Properties Pooch demo</u></a> to see them in action!</p>
<div id="attachment_20057" style="width: 837px" class="wp-caption aligncenter"><a href="https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/custom-props/"><img class="wp-image-20057 size-full" src="https://winblogs.azureedge.net/win/2017/03/pooch.png" alt="Illustration of a dog wearing a sweater in an urban park" width="827" height="477" /></a><p class="wp-caption-text">Check out our <strong><a href="https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/custom-props/">Custom Properties Pooch demo</a></strong> to see CSS Custom Properties in action!</p></div>
<h1>What are CSS Custom Properties?</h1>
<p>SASS/LESS and other pre-processors have been offering variables in CSS for years, which is one of the reasons why, <a href="https://twitter.com/gregwhitworth/status/829904441931214848">in an informal poll</a>, ~75% of polled web developers incorporate these tools in their day to day workflow. However, the biggest downfall of these tools is that they are effectively a “find &amp; replace” of the specified value. This means that the variables can’t be updated without needing to recompile the stylesheets.</p>
<p>Enter CSS Custom Properties (née CSS Variables). While Custom Properties enable the same fundamental use cases, they have the additional benefits of being fully cascaded, being interacted with via JavaScript, and not requiring the additional build step to work.</p>
<h1>How to use Custom Properties</h1>
<p>Here&#8217;s a practical example: setting up primary and secondary colors for your site.</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="gregwhitworth/76d8b3f1680cb557a67fe7808338faa6.json"></div>
<p>Let’s look at what is happening here, to declare a new custom property you precede a valid ident with two dashes. In our example, we are setting up our color scheme by creating custom properties for our <code>--primary</code> and <code>--secondary</code> colors. Then to utilize these properties, we need to reference them using the <a href="http://www.w3.org/TR/css-variables-1/#using-variables"><code>var() </code>function</a>.</p>
<p>It’s worth noting that a custom property can store any valid CSS, so feel free to get creative with how you utilize them! For example, the following is a valid custom property:</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="gregwhitworth/9851a17058adebf8447b6e26ab6e8833.json"></div>
<blockquote><p><strong>Note:</strong> We utilized this methodology of color math extensively in our <a href="https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/custom-props/"><strong>Custom Properties Pooch demo</strong>—check it out here</a>!</p></blockquote>
<h1>Creating a fallback</h1>
<p>A common use case for custom properties is in components. You may design a component, and you want to provide sensible defaults for all of your custom properties. Custom Properties follows the same pattern as other CSS values and allows you to set fallback values. Here’s an example:</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="kypflug/fa31dcf09b3df13148b7a43d0705285b.json"></div>
<p>In this case, if the <code>--primary</code> custom property doesn’t exist when substitution occurs we’ll use <code>blue</code> instead of transparent.</p>
<p>Note: This does not allow a fallback for a value that doesn’t work for the given property. For example:</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="kypflug/9d3d502520ffec4f4a9f4bb0352c0382.json"></div>
<p>This doesn&#8217;t work because <code>blue</code> is not a valid value for <code>margin-top</code>, but Custom Properties don’t know the syntax rules for properties they&#8217;re use in. All that matters is whether we have a value for <code>--primary</code> or not. Since we do have a value, we substitute it in, try to parse <code>margin-top: blue</code>, and discard it as invalid per normal CSS rules.</p>
<h1>Custom property scoping</h1>
<p>Custom Properties are scoped like other CSS properties, by harnessing the cascade. This is valuable when, for instance, a team might be collaborating to build components or aspects of a site. To illustrate, let’s take our previous example, and add in a component we’re building that also has its own <code>--primary</code> custom property:</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="gregwhitworth/352afbab7bc06a7f1b4c14d63606306e.json"></div>
<p>This will result in a <code>blue</code> background for the body and a <code>yellow</code> background for the <code>.my-component</code>.</p>
<h1>Detecting support for Custom Properties</h1>
<p>It’s important to remember that CSS is designed to fail silently, so if a browser doesn’t support Custom Properties, you’ll only be able to see this if your styles have visual implications. An easy way to progressively enhance your site with Custom Properties is to provide different styles to browsers that don’t support Custom Properties. You can do this by wrapping your custom property work in a <code>@supports</code> declaration block.</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="gregwhitworth/d12e7f20de97aa9d7f959e174bfbe38e.json"></div>
<p>It’s important to note that <code>@supports</code> only checks that <code>--foo</code> is syntactically correct, not that the property and value match what has been declared. For example, both the previous and following examples will result in the body having a <code>green</code> background in browsers that support Custom Properties, even though the current value for <code>--foo</code> is not <code>false</code>.</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="gregwhitworth/7550a2c4cc3b9b93cb9781287b977ae5.json"></div>
<h1>Modifying a custom property via script</h1>
<p>One of the primary benefits of native support for Custom Properties is the capability of dynamically modifying them via script. In order to do this you need to modify custom properties using the <code>setProperty()</code> and <code>getPropertyValue()</code> APIs. For example, to modify our <code>--primary</code> color on <code>.my-component</code>, we can do the following:</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="gregwhitworth/ff8ce6d59ccdd6dd8234d4ffd4acd7a9.json"></div>
<p>Then, to retrieve the computed value of the custom property, you utilize <code>getPropertyValue()</code> from <code>getComputedStyle()</code>:</p>
<style>.gist table { margin-bottom: 0; }</style>
<div class="gist-oembed" data-gist="gregwhitworth/b3135bb9775ca7e73882e474a499201e.json"></div>
<h1>Animating a custom property</h1>
<p>You can animate custom properties, but you can’t interpolate them. What exactly does it mean to be able to animate but not interpolate a custom property? Well, let’s take the following example:</p>
<p>Remember that you can store any valid ident in a custom property, so think of it as being stored as a string in an engine. The browser understands how to interpolate <code>color: green</code> to <code>color: blue</code> but it doesn’t know how to interpolate between “hello” and “world.” So, what does the browser do in the previous example? The browser takes the duration and assigns the possible values amongst the frames. For this example, that would result in a value of <code>50px</code> for <code>500ms</code> and <code>0</code> for the other <code>500ms</code>; this is referred to in the spec as doing a 50% flip.</p>
<h1>But I want them to interpolate!</h1>
<p>We do too! The CSS Houdini Task Force is actively working on ways to make this happen with the <a href="https://drafts.css-houdini.org/css-properties-values-api/">Properties &amp; Values API</a>. If this work pans out, you’ll be able to register your custom property and inform the engine of its type, so that it can correctly interpolate values. Keep a look out for this API to start making its way into the wild, as browsers begin to experiment with these APIs to test their viability and help evolve the specification.</p>
<h1>Improvements beyond Custom Properties</h1>
<p>While working on our implementation of Custom Properties, we looked at a few demos that web developers had built. While some of them worked, others didn’t. When we reduced the broken demos to look for bugs, we narrowed the problems down to other gaps in our engine – not necessarily as a result of bugs in our Custom Properties implementation. For example, the largest gap we found was support for <code>calc()</code> within color functions (eg: <code>rgb()</code>, <code>hsl()</code>). Because this is an exciting use case where custom properties can be very powerful, we addressed this issue in our parser.</p>
<h1>“A rising tide lifts all boats”</h1>
<p>As we worked to fill gaps in our engine, we also wanted to be sure that web developers can rely on interoperable implementations for the feature to be useful. As we began our implementation efforts, we found that no browser had implemented the 50% flip behavior suggested in the specification for animating custom properties. Additionally, we found that no browser supported the capability of referencing variables via the <code>var()</code> function, within a keyframe at-rule. We worked with the CSSWG to resolve upon these issues and provide an implementation in Microsoft Edge.</p>
<p>Of course, the work in Edge is only one part of making sure the feature is interoperable. As we worked on our implementation, we found bugs in the implementations in existing browsers. As a result of this, we opened bugs against Blink, Gecko, and WebKit, and look forward to improved implementations across the board – including fixes shipping <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=660026">as early as Chrome 56</a> that will make Custom Properties more interoperable.</p>
<h1>&#8211;in: &#8220;conclusion&#8221;</h1>
<p>CSS Custom Properties not only solve a common developer request and makes your code more manageable, but it also unlocks a lot of potential for more creative work on the web. The future of the web looks bright and we&#8217;re just getting started. We&#8217;re excited to have CSS Custom Properties in the Windows 10 Creators Update, and can’t wait to see what you create!</p>
<p>― <a href="https://twitter.com/gregwhitworth">Greg Whitworth</a>, Program Manager, Microsoft Edge</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/24/css-custom-properties/">CSS Custom Properties in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/03/24/css-custom-properties/feed/</wfw:commentRss>
<slash:comments>4</slash:comments>
</item>
<item>
<title>Strengthening the Microsoft Edge Sandbox</title>
<link>https://blogs.windows.com/msedgedev/2017/03/23/strengthening-microsoft-edge-sandbox/</link>
<comments>https://blogs.windows.com/msedgedev/2017/03/23/strengthening-microsoft-edge-sandbox/#comments</comments>
<pubDate>Thu, 23 Mar 2017 17:00:03 +0000</pubDate>
<dc:creator><![CDATA[Crispin Cowan]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[App Container]]></category>
<category><![CDATA[Behind the Scenes]]></category>
<category><![CDATA[Creators Update]]></category>
<category><![CDATA[EdgeHTML 15]]></category>
<category><![CDATA[Sandbox]]></category>
<category><![CDATA[Security]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>In a recent post, we outlined the layered strategy that the Microsoft Edge security team employs to protect you from vulnerabilities that could be used to compromise your device or personal data. In particular, we showed how Microsoft Edge is leveraging technologies like Code Integrity Guard (CIG) and Arbitrary Code Guard (ACG) to break some [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/23/strengthening-microsoft-edge-sandbox/">Strengthening the Microsoft Edge Sandbox</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>In a <a href="https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution">recent post</a>, we outlined the layered strategy that the Microsoft Edge security team employs to protect you from vulnerabilities that could be used to compromise your device or personal data. In particular, we showed how Microsoft Edge is leveraging technologies like Code Integrity Guard (CIG) and Arbitrary Code Guard (ACG) to break some of the techniques that hackers rely on when exploiting vulnerabilities to obtain Remote Code Execution (RCE). This is where the attacker seeks to escape from web code (JS and HTML) in the browser to run native CPU code of the attacker’s choosing. This lets the attacker violate all of the browser’s rules for the web, such as <a href="https://www.w3.org/Security/wiki/Same_Origin_Policy">same-origin policy</a>, and so it is important to web users that we try as hard as possible to block RCE attacks.</p>
<p>However, despite our best efforts, sometimes attackers get RCE anyway. In this post, we’ll explore some of the significant improvements we’ve made in the Windows 10 Creators Update to strengthen our next line of defense: the Microsoft Edge sandbox.</p>
<h1>The history of the Microsoft Edge sandbox</h1>
<p>Because RCE can happen, and in the past, often did, browser vendors have sought to sandbox the browser to defend the rest of the user’s PC from attack. In 2007, IE7 introduced <a href="https://msdn.microsoft.com/en-us/library/bb250462(v=vs.85).aspx">Protected Mode</a>, the first web browser sandbox. Windows 8 added <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt595898(v=vs.85).aspx">app container</a> to the OS, primarily to support the new Windows Store app model and support the <a href="https://blogs.msdn.microsoft.com/b8/2012/05/17/delivering-reliable-and-trustworthy-metro-style-apps/">confidence promise</a> that apps are safe to use. IE10 and IE11 leveraged app container to create <a href="https://blogs.msdn.microsoft.com/ieinternals/2012/03/23/understanding-enhanced-protected-mode/">EPM (Enhanced Protected Mode)</a> a stronger browser sandbox. However, the EPM sandbox restrictions were incompatible with older ActiveX controls that predated app container, and so EPM was provided as a security enhancing option.</p>
<p>Microsoft Edge <a href="https://blogs.windows.com/msedgedev/2015/05/06/a-break-from-the-past-part-2-saying-goodbye-to-activex-vbscript-attachevent/#pCT7chbtqKqQykcr.97">does not support ActiveX,</a> so it is able to <a href="https://blogs.windows.com/msedgedev/2015/05/11/microsoft-edge-building-a-safer-browser/#FpKk718Uy4bUltJk.97">run entirely inside app container sandboxes at all times</a>. Since the beginning, Microsoft Edge has used several app containers. At first there was a parent app container for the Manager, which created a small number of additional app containers to host content from the internet separate from intranet content. The <a href="https://www.microsoft.com/en-US/windows/features">Windows 10 Anniversary Update</a> moved Flash into its own, separate AC. Today the Microsoft Edge app container model looks like this:</p>
<p><img class="aligncenter wp-image-20108 size-large" src="https://winblogs.azureedge.net/win/2017/03/edge-appcontainer-1024x333.png" alt="Diagram of the Microsoft app container structure. A manager app container governs individual app containers for the Internet, Intranet, Extensions, Service UI, and Adobe Flash." width="1024" height="333" /></p>
<p>The Manager provides browser features such as the URL bar, the back button, tabs, and your favorites list. The other app containers are:</p>
<ul>
<li><strong>Internet AC:</strong> hosts content from Internet sites.</li>
<li><strong>Intranet AC:</strong> hosts content from Intranet sites. For enterprise users, that is enterprise web sites. For consumers, that is “web sites” that are control interfaces for devices on your home network, such as your Wi-Fi router, or IoT devices. Separating this RAC from the Internet e.g. protects your home Wi-Fi router from Internet attackers.</li>
<li><strong>Extensions AC: </strong>hosts the new <a href="https://blogs.windows.com/windowsexperience/2016/03/17/bringing-extensions-to-microsoft-edge/">extensions</a> for Microsoft Edge.</li>
<li><strong>Flash AC:</strong> hosts the Adobe Flash player, to isolate it from the main content processes.</li>
<li><strong>Service UI AC:</strong> hosts special web pages, such as about:flags, and the default home page.</li>
</ul>
<p>The Internet AC is where the action is. Its job is to host web pages from anywhere, including the JS code provided by that web page, images, and multimedia. Hosting web pages is extremely complex, due to the richness of the modern web; this is the platform of the Internet, and developers need to be able to create any application and run it in this environment. Because it is complex, and hosts web pages from anywhere, this is where web security attacks begin. A malicious web site presents content intended to exploit bugs in the content hosting system, to take over control of the content process.</p>
<p>If an attacker gains control of an Internet AC process, they need to find some way to achieve their goals. If their goals involve compromising the user’s device or personal data stored on the device, then they’ll need to contend with escaping from the sandbox first.</p>
<h1>Reducing the attack surface of the Microsoft Edge sandbox</h1>
<p>One of the most effective ways to eliminate vulnerabilities in complex applications is to minimize the amount of code that an attacker can try to find vulnerabilities in. This is often referred to as <em>attack surface reduction</em> and it is a key tactic in our overall strategy security. To this end, Microsoft Edge in the Creators Update of Windows 10 has significantly reduced the attack surface of the sandbox by configuring the app container to further reduce its privilege.</p>
<p>To understand how we tuned the Microsoft Edge AC, it is first necessary to know how app container itself works. An app container process is <em>deny-by-default</em> for any secured object unless the object security descriptor has an allow access control entry (ACE) that would permit the app container to have access. There are three kinds of SIDs that can be used in such ACEs:</p>
<ul>
<li>Capabilities: if a Capability SID based allow ACE is in the security descriptor, and the requesting AC has that Capability SID in its token, then it gets access. E.g. Webcam-related devices are accessible to processes that have the WEBCAM Capability SID such as Microsoft Edge.</li>
<li>AppID SIDs: if a specific AppID SID based allow ACE is in the security descriptor, and the requesting AC is that specific AppID, then it gets access. The main use for this is per-app storage, which uses the AppID of that app in the security descriptor, ensuring that its storage is private to that app.</li>
<li>“ALL APPLICATION PACKAGES” (“AC” SID): this is the AC wild card, allowing <em>all</em> app containers to access the resource. The “AC” SID exists so that Windows can provide an app platform that is useful to developers, allowing rich UWPs in the Windows Store. For instance, most of the <a href="https://docs.microsoft.com/en-us/uwp/api/">WinRT API surface</a> is open to the “AC” SID, so that all UWP apps can access the WinRT APIs.</li>
</ul>
<p>The Microsoft Edge AC has been made different in only one way: the “AC” SID is not sufficient to let a requesting process access a resource. To get access, the AC must either have a matching Capability SID, or be precisely one of the named AppIDs in the security descriptor.</p>
<p>Thus the AC loses access to the entire WinRT API set, and every other resource that app containers normally can access. That’s great for security, with the <em>slight</em> problem that it would break everything about the browser, turning it into a highly secure brick.</p>
<div id="attachment_20114" style="width: 215px" class="wp-caption alignright"><img class="size-medium wp-image-20114" src="https://winblogs.azureedge.net/win/2017/03/tuned-AC-205x300.png" alt="Diagram showing the AC access scope. The Edge content process only has access to a specific subset of the AC access scope, based on capabilities." width="205" height="300" /><p class="wp-caption-text">Microsoft Edge &#8220;Tuned&#8221; AC</p></div>
<div id="attachment_20111" style="width: 214px" class="wp-caption alignright"><img class="wp-image-20111 size-medium" src="https://winblogs.azureedge.net/win/2017/03/normal-AC-204x300.png" alt="Diagram of a normal app container, consisting of a full AC access scope authorized by the AC SID." width="204" height="300" /><p class="wp-caption-text">&#8220;Normal&#8221; app container</p></div>
<p>So to make Microsoft Edge work again, we used specific Capabilities to light up specific areas of functionality. For instance, we created a Capability that enables COM to work. We similarly added other new capabilities, granting access to specific resources, until Microsoft Edge worked again. Then we added some telemetry to detect access control failures for the content process and shared it to users in the Windows Insider Program (WIP) to ensure that we had granted access to all resources needed for all scenarios.</p>
<p>What we just did here was to create a <em>tuned</em> sandbox for the Microsoft Edge content process, with a much tighter fit to the functional needs of the software than a normal app container provides. That is a lot of work, which is why this is <em>not</em> how the UWP platform works. But because web browsers are among some of the most threatened software there is, it is worth it in this case.</p>
<p>We repeated this work of hand-tuning a sandbox for the Flash AC, because it also is subject to a lot of attacks. Placing Flash in a tighter sandbox complements our work in this release to make <a href="https://blogs.windows.com/msedgedev/2016/12/14/edge-flash-click-run/#gET812Eh3L4RWyvC.97">Flash be click-to-run</a>.</p>
<h1>Making it more difficult to exploit sandbox escape vulnerabilities</h1>
<p>The main threats in a sandbox are the broker interfaces that provide access to resources according to a defined policy. So why have brokers at all? Brokers exist to grant access according to policy, e.g. the File broker allows a website to say “upload a file by browsing your files” and the <em>user</em> gets to pick the file to be uploaded, without giving the web site access to <em>all</em> of the user’s files.</p>
<p>Brokers are a threat to sandboxes because brokers are <em>code</em> (and therefore can have bugs) and because the brokers run outside the sandbox. If an attacker can hack a broker and run code <em>in the broker</em>, then the attacker can escape, similar to an inmate mugging a prison guard and then putting on the guard’s uniform to escape.</p>
<p>The tightened Microsoft Edge content process sandbox cuts off access to many brokers (reduced attack surface) but leaves the needed brokers accessible (residual threat). An attacker might try to exploit bugs in the accessible brokers to elevate privileges and execute arbitrary native code in the broker, and thus escape. To mitigate this threat, we have applied many of the same exploit mitigation technologies to the brokers that provide service to Microsoft Edge.</p>
<p>Microsoft Edge also has some surprising brokers, because the <a href="https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/">exploit mitigation work</a> forced several components to move out-of-process (OOP), including the Chakra JIT code generator and the Flash runtime process. These components had to move out of process because they necessarily do code generation (JIT) and that is not compatible with the ACG mitigation applied to the content process. Thus, these components function as the “JS code generator” broker and the “Run Flash bytecode” broker.</p>
<p>They can be viewed as brokers precisely because they have permission to do something that the content process is not permitted to do for itself. They are also a threat, because an attacker that can gain control of OOP JIT or the Flash sandbox could e.g. create executable code and use that for further exploitation, bypassing ACG. Because they are a threat, we have also have put these processes into tuned, less privileged app containers, again with a custom-crafted container profile built from capabilities.</p>
<h1>Impact to attackers</h1>
<p>Making the Microsoft Edge content process run in this tighter sandbox reduces the sandbox attack surface, but by how much? As it turns out, the reduction is quite significant:</p>
<ul>
<li>100% reduction access to MUTEXes: allow a process to lock up a resource, causing hangs.</li>
<li>90% reduction in access to WinRT and DCOM APIs: this is the <strong>large</strong> win here, dramatically reducing Microsoft Edge’s attack surface against the WinRT API set.</li>
<li>70% reduction access to events and symlinks: symlinks are especially interesting, because they are often used in <a href="https://packetstormsecurity.com/files/127245/MS13-097-Registry-Symlink-IE-Sandbox-Escape.html">creative bait &amp; switch attacks to escape sandboxes</a>.</li>
<li>40% reduction in access to devices: Windows supports many device drivers, and their quality is somewhat beyond Microsoft’s control. The tuned sandbox cuts off access to any device that Microsoft Edge does not explicitly need, preventing attackers from using vulnerabilities in device drivers to escape, or from abusing the devices.</li>
</ul>
<p>While attack surface reduction does not guarantee that an attacker cannot escape the sandbox, it does dramatically reduce the opportunities for attack, much like reducing the number of windows and doors in a fortress. In addition, the enabling of additional exploit mitigations for the brokers that Microsoft Edge is legitimately able to access also increases the difficulty of exploiting vulnerabilities that remain.</p>
<h1>Conclusion</h1>
<p>Security is a process, not a destination, so we will continue to invest in both RCE and sandbox mitigations for Microsoft Edge. These exploit mitigations combined with the strengthened sandboxing should make Microsoft Edge significantly more work for attackers to exploit, and thus discourage attackers from trying in the first place.</p>
<p>― <a href="https://twitter.com/CrispinCowan0">Crispin Cowan</a>, Senior Program Manager, Microsoft Edge</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/23/strengthening-microsoft-edge-sandbox/">Strengthening the Microsoft Edge Sandbox</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/03/23/strengthening-microsoft-edge-sandbox/feed/</wfw:commentRss>
<slash:comments>3</slash:comments>
</item>
<item>
<title>Notes from the Node.js VM Summit</title>
<link>https://blogs.windows.com/msedgedev/2017/03/13/notes-from-nodejs-vm-summit/</link>
<comments>https://blogs.windows.com/msedgedev/2017/03/13/notes-from-nodejs-vm-summit/#respond</comments>
<pubDate>Mon, 13 Mar 2017 16:00:09 +0000</pubDate>
<dc:creator><![CDATA[Microsoft Edge Team]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Chakra]]></category>
<category><![CDATA[ChakraCore]]></category>
<category><![CDATA[Node.js]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>The Chakra team was delighted to host the third Node.js VM Summit recently here at Microsoft. These meetings bring together JavaScript VM vendors, Node collaborators, and CTC members including participants from Google, IBM, Intel, Microsoft, nearForm, and NodeSource. This group is currently focused on addressing ABI compatibility problems facing the Node native module ecosystem. Today, [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/13/notes-from-nodejs-vm-summit/">Notes from the Node.js VM Summit</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>The Chakra team was delighted to host the third <a href="https://github.com/nodejs/vm/issues/4">Node.js VM Summit</a> recently here at Microsoft. These meetings bring together JavaScript VM vendors, Node collaborators, and CTC members including participants from Google, IBM, Intel, Microsoft, nearForm, and NodeSource. This group is currently focused on addressing ABI compatibility problems facing the Node native module ecosystem. Today, we’d like to share a quick recap of the meeting and some of the next steps.</p>
<p><a href="https://winblogs.azureedge.net/win/2017/03/untitled.png"><img class="aligncenter size-large wp-image-20006" src="https://winblogs.azureedge.net/win/2017/03/untitled-1024x768.png" alt="Image showing VM Summit attendees in a conference room at Microsoft" width="1024" height="768" /></a></p>
<h2>Node Native Modules</h2>
<p>Node native modules are written in C/C++ and directly depend on V8 and/or <a href="https://github.com/nodejs/nan">NAN</a> APIs. These modules may need to be updated or re-compiled for every major Node.js release because of ABI/API changes. This adds to the maintenance burden for native module authors and it presents barrier to upgrading Node versions in production deployments for module consumers. The first half of the session included presentations from the two complimentary projects intended to help with this: <strong>Fast FFI</strong> (foreign function interface) and <a href="https://github.com/nodejs/abi-stable-node"><strong>N-API (Node.js API)</strong></a>.</p>
<h3>Fast FFI</h3>
<p>Fast FFI aims to automatically project native APIs into JavaScript which will allow module authors to expose existing native code to Node.js without having to write additional C/C++ code. The FFI <a href="https://docs.google.com/presentation/d/1rLBk9Erx1pbqLUBjcq_V2bLsiSxfPWT36dC0yLfFMOE/edit">presentation</a> discussed its architecture and use cases. Currently, this project is in its early stages of prototyping and more work is required for it to be considered as a Node.js feature. We will update the community as we make progress and keep evaluating its readiness.</p>
<h3>N-API</h3>
<p>N-API provides an ABI-stable abstraction layer for native APIs in JavaScript VMs. This helps native module authors compile their module once per platform and architecture and run it on any N-API compliant version of Node.js. The N-API <a href="https://github.com/nodejs/abi-stable-node/blob/doc/VM%20Summit.pdf">presentation</a> included a demonstration of some ported modules and performance comparisons with their V8/NAN equivalents. N-API has made great progress over the last year and now it is ready for broader usage and feedback. As reflected in the graph below which shows native API usage pattern among top 30 depended-on modules, we have 100% N-API coverage for V8 APIs used in 5 or more modules.  The core team has successfully ported <a href="https://github.com/boingoing/node-sass">Node-Sass</a>, <a href="https://github.com/jasongin/node-canvas">Canvas</a>, <a href="https://github.com/boingoing/leveldown/">LevelDown</a>, <a href="https://github.com/sampsongao/node-nanomsg">Nanomsg</a> and <a href="https://github.com/gabrielschulhof/iotivity-node/tree/abi-stable">IoTivity</a> to use N-API.</p>
<div id="attachment_19994" style="width: 1034px" class="wp-caption aligncenter"><a href="https://winblogs.azureedge.net/win/2017/03/napi-coverage.png"><img class="size-large wp-image-19994" src="https://winblogs.azureedge.net/win/2017/03/napi-coverage-1024x577.png" alt="Chart showing N-API Coverage in top third most-depended-on native modules. 195 total V8 APIs are used. Of these, 140 have an equivalent N-API. " width="1024" height="577" /></a><p class="wp-caption-text">N-API coverage for popular native APIs</p></div>
<p>VM Summit attendees evaluated the progress and readiness of both projects, and agreed to consider a pull request to include <strong>N-API in Node 8.0 as an experimental</strong> <strong>feature</strong> making it easier for native module authors to try out N-API and enable the team to test it broadly and get more feedback. The Fast FFI project will continue to evolve and may be included in a future Node.js release.</p>
<h3><strong>Key next steps for N-API project:</strong></h3>
<ul>
<li>Submit N-API Pull Request to Node.js master to be included in Node.js 8.0</li>
<li>After stabilization, port it to Node.js v6.9 LTS and Node-ChakraCore</li>
<li>Broader community engagement to identify API gaps</li>
<li>Performance fine tuning</li>
</ul>
<h2>Other topics:</h2>
<p>In the second half of the session the discussion focused on other VM compatibility topics including compatibility of the Inspector Protocol for debugging and baseline conformance requirements for Node.js VMs. The attendees also agreed on meeting again around <a href="http://nodesummit.com/">NodeSummit</a> later this year and evaluate progress on Fast FFI, N-API adoption, feedback and next steps. <strong> </strong></p>
<p>It was a very successful and productive VM Summit, and we look forward to feedback on the forthcoming N-API PR. You can review the <a href="http://youtu.be/ZRVjWhBEwB0">full recording of the session here</a>, review the <a href="https://github.com/nodejs/vm/pull/5">raw notes from the meeting</a>, or <a href="https://github.com/nodejs/abi-stable-node/blob/api-prototype-8.x/src/node_jsvmapi.h">take an early look at the API here</a>. Thanks to all the attendees for making the VM Summit awesome!</p>
<p>― <a href="https://twitter.com/AruneshC">Arunesh Chandra</a>, Senior Program Manager, Chakra</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/13/notes-from-nodejs-vm-summit/">Notes from the Node.js VM Summit</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/03/13/notes-from-nodejs-vm-summit/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Next-generation web apps for education</title>
<link>https://blogs.windows.com/msedgedev/2017/03/10/progressive-web-apps-education/</link>
<comments>https://blogs.windows.com/msedgedev/2017/03/10/progressive-web-apps-education/#respond</comments>
<pubDate>Fri, 10 Mar 2017 18:21:25 +0000</pubDate>
<dc:creator><![CDATA[Jeff Burtoft]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Deployment]]></category>
<category><![CDATA[Hosted Web Apps]]></category>
<category><![CDATA[InTune]]></category>
<category><![CDATA[Progressive Web Apps]]></category>
<category><![CDATA[PWABuilder]]></category>
<category><![CDATA[Web App Manifest]]></category>
<category><![CDATA[Web Apps]]></category>
<category><![CDATA[Windows Store]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>Just a short time ago, the new Microsoft Intune for Education was announced for teachers and technologists to manage devices, accounts, and apps for students. Since that time, we’ve heard from a number of developers and app publishers who work in education, who have questions about how their apps can take full advantage of this [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/10/progressive-web-apps-education/">Next-generation web apps for education</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>Just a short time ago, the new <a href="https://blogs.windows.com/windowsexperience/2017/01/24/announcing-intune-education-new-windows-10-pcs-school-starting-189/#rmdFc7arGrC1iaFU.97">Microsoft Intune for Education</a> was announced for teachers and technologists to manage devices, accounts, and apps for students. Since that time, we’ve heard from a number of developers and app publishers who work in education, who have questions about how their apps can take full advantage of this new system.  For those app builders who are already publishing their apps on the web (and there are a lot of them!) we have a great solution today – and it’s about to get a lot better.</p>
<p>In Windows 10, we introduced the concept of “Hosted Web Apps” – applications which serve your web content from your server, outside of the context of the browser and with both a native feel and access to native capabilities. Now, we’re excited about what’s coming next for web apps: <a href="https://medium.com/web-on-the-edge/progressive-web-apps-on-windows-8d8eb68d524e">Progressive Web Apps</a> (PWAs). Together with other browsers and the web community, we’re working on enabling the next wave of native-like web experiences, where web content can have the essential capabilities and user experience of native desktop or mobile apps. These web apps can start up instantly, can run in the background and have additional APIs available for developers.  With Progressive Web Apps, web content gets <a href="https://medium.com/dev-channel/the-new-and-improved-add-to-home-screen-1f79bdd464b0#.ryvo5yfgj">promoted to app status</a> when the user chooses and the environment allows for it.</p>
<div id="attachment_19946" style="width: 1034px" class="wp-caption aligncenter"><a href="https://winblogs.azureedge.net/win/2017/03/jig-1.png"><img class="size-large wp-image-19946" src="https://winblogs.azureedge.net/win/2017/03/jig-1-1024x320.png" alt="Screen capture showing http://jig.space open in Microsoft Edge and as a native app on Windows 10" width="1024" height="320" /></a><p class="wp-caption-text"><a href="https://jig.space/">JigSpace</a> is a platform for creating and sharing interactive, 3D instructions for anything. It&#8217;s simple, powerful and is available on desktop and mobile at <a href="https://jig.space/">https://jig.space</a>, and can be ran as an app or in the browser.</p></div>
<p>The component technologies that make up PWAs are <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/status/serviceworker/?q=service%20worker">in development or supported on most browser platforms</a> today. Additionally, <a href="https://blog.chromium.org/2016/08/from-chrome-apps-to-web.html">Google has begun requiring Chrome apps to migrate to PWAs</a> in order to remain accessible in Chrome, so there’s never been a better time for education-focused web apps to make the transition to a full PWA experience.</p>
<h1>How to Write a Progressive Web App</h1>
<p>Before migrating to a PWA you should make sure that your site is cross-browser compliant. Browser makers have gone to great lengths to make sure the rendering delta between browsers is small, but you’ll still want to make sure your app runs in all browsers before moving to a PWA.</p>
<p>To create a PWA you need to define your web project as an application. In the past, you’ve done this with a manifest file and image assets.  The problem was that each platform (like Chrome Apps and Windows Apps) had different manifest formats and asset requirements. PWAs require those same components, but standardize them so you build the app once and run it across all platforms that support PWAs.  There are three requirements for building a PWA:</p>
<ol>
<li>Your site must be hosted on an encrypted environment. This means it needs to be send as https instead of http. This has always been a recommendation for Chrome and Windows apps, but with PWAs it’s a requirement. If you don’t have an HTTPS certificate for your site already, get one today. The good news is this is easier than ever, thanks to resources like <a href="https://letsencrypt.org/">Let’s Encrypt</a>.</li>
<li>You need to have a W3C Web App Manifest. This is one standard manifest that supports your PWA across all platforms. We recently introduced <a href="http://preview.pwabuilder.com/generator">PWA Builder</a>, which simplifies and automates building a manifest so it’s as easy as providing resources and a description for your app.</li>
<li>You need to have a service worker. A service worker is a JavaScript file that that runs between your HTML page and the Networking stack. SWs are also installed independently on host OSes to handle offline and push. You can also use service workers in a comparable way to make your site faster. PWA Builder also provides a selection <a href="http://preview.pwabuilder.com/generator">of pre-built service workers</a> based on the functionality you desire for your app.</li>
</ol>
<h2></h2>
<h2>Run your new PWA today as a “Hosted Web App” on Windows 10</h2>
<p>Because PWAs are designed around the principle of progressive enhancement, building a PWA today will not only prepare you for next-generation experiences on desktop and mobile devices, but PWAs can already run as Hosted Web Apps today on Windows 10, and with a <a href="http://manifoldjs.com/generator">polyfill on Android and iOS</a>.</p>
<p>Education-focused web apps, like other web apps, can be published to the Windows Store as “Hosted Web Apps.” These apps will run as standalone apps, just like PWAs. The primary differences between Hosted Web Apps and Progressive Web Apps today are simply in capabilities: while Progressive Web Apps support a Service Worker (and associated features like server push, cache, etc.), and require a secure connection, Hosted Web Apps currently do not. As support for the Service Worker family of features is added to the Windows web platform, HWAs with a Service Worker and HTTP will naturally evolve into PWAs.</p>
<p>Hosted Web Apps have some key user experience and discoverability advantages over remaining in the browser. Depending on your app’s customers and scenarios, you should review this list of benefits and determine whether your app is best delivered in the browser, as a hosted web app, or both.</p>
<h3><strong>Easier app management</strong></h3>
<p>As previously mentioned, a few weeks ago Microsoft announced a <a href="https://blogs.windows.com/windowsexperience/2017/01/24/announcing-intune-education-new-windows-10-pcs-school-starting-189/">new version of Intune directed towards EDU</a> to help teachers and schools better manager devices. By moving your web app to a HWA/PWA, it allows teachers and administrators to prep students devices with your app along side of the other store apps they use.</p>
<h3><strong>User</strong><strong> notifications</strong></h3>
<p>You may already be using web notifications for re-engaging your users. These notifications will appear in the action center, where users are accustomed to find them. With a small amount of code added to your app, you can send <a href="https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/tiles-badges-notifications">push notifications</a> or use the <a href="https://docs.microsoft.com/en-us/windows/uwp/monetize/configure-your-app-to-receive-dev-center-notifications">notification gateway</a> to send toast notifications or Tile updates even when your app isn’t running.</p>
<h3><strong>Store listing</strong></h3>
<p>Hosted Web Apps get a listing in the Windows Store just like any application. When a user goes to the Windows Store to find education apps, your app will appear alongside the others and will participate in other store discovery mechanisms such as “recommended apps”.</p>
<div id="attachment_19949" style="width: 1034px" class="wp-caption aligncenter"><a href="https://winblogs.azureedge.net/win/2017/03/jig-2.png"><img class="size-large wp-image-19949" src="https://winblogs.azureedge.net/win/2017/03/jig-2-1024x640.png" alt="Screen capture showing Jig.Space hosted in the Windows 10 Store" width="1024" height="640" /></a><p class="wp-caption-text">Hosted Web Apps (and, in the future, Progressive Web Apps) can be listed in the Windows 10 Store for better discoverability and manageability.</p></div>
<p>The store also provides you with additional benefits such as usage reports and performance data. You also receive ratings and reviews, which gives you a way to get feedback from your users, and respond to that feedback in ways we just don’t have on the web today.</p>
<h3><strong>More surfaces for discovery</strong></h3>
<p>In Windows 10 HWA/PWAs will appear wherever users expect to find apps. This includes discoverability in areas like “related apps” in the store, Cortana search, the start menu and even installs from within the bing.com search listing.</p>
<div id="attachment_19952" style="width: 1034px" class="wp-caption aligncenter"><a href="https://winblogs.azureedge.net/win/2017/03/jig-3.png"><img class="size-large wp-image-19952" src="https://winblogs.azureedge.net/win/2017/03/jig-3-1024x640.png" alt="Screen capture showing Bing search results for JigSpace, featuring the &quot;Jig.Space&quot; Windows App featured in the search results." width="1024" height="640" /></a><p class="wp-caption-text">Web apps listed in the Windows Store are featured in related Bing search results</p></div>
<h3><strong>Integration with the host operating system</strong></h3>
<p>HWA / PWA appear to a user as any other app. This means that a user and easily install and uninstall the apps. It means that the web app will be integrated into the settings panel (for example, with notifications).</p>
<div id="attachment_19955" style="width: 452px" class="wp-caption aligncenter"><a href="https://winblogs.azureedge.net/win/2017/03/jig-4.png"><img class="wp-image-19955 size-full" src="https://winblogs.azureedge.net/win/2017/03/jig-4.png" alt="Screen capture showing the Jig.Space web app installed in the Windows Start Menu. A context menu is open, with options to Pin/Unpin, Resize, Uninstall, and more." width="442" height="284" /></a><p class="wp-caption-text">Web apps are managed just like native apps, including all the relevant contextual controls and management options.</p></div>
<p>These apps work as stand-alone apps, so they have their own tile, their own task bar menus and even appear as apps within the task manager.</p>
<h3><strong>Access to expanded resources</strong></h3>
<p>When your web app runs as a HWA / PWA is has more access to resource. This means data caps on storage like IndexedDB and local storage are <a href="https://msdn.microsoft.com/en-us/library/hh673548(v=vs.85).aspx">removed</a>. It also means your app will have a dedicated cache that will never be deprioritized by another app.</p>
<div id="attachment_19958" style="width: 1034px" class="wp-caption aligncenter"><a href="https://winblogs.azureedge.net/win/2017/03/jig-5.png"><img class="size-large wp-image-19958" src="https://winblogs.azureedge.net/win/2017/03/jig-5-1024x642.png" alt="Screen capture showing the Jig.Space app open to a 3d image of a Mars rover." width="1024" height="642" /></a><p class="wp-caption-text"><a href="https://jig.space/">JigSpace </a>provides interactive guidance for complex objects like this “jig” of the mars rover.</p></div>
<h3><strong>API access for expanded functionality</strong></h3>
<p>HWA / PWA apps have access to <a href="https://docs.microsoft.com/en-us/uwp/api/">the Windows Store App APIs</a> through JavaScript. This allows you to take advantage of features like BTLE, USB access or access to the user’s calendar or contacts with appropriate permission controls.</p>
<h2>Simplifying the PWA Transition</h2>
<p>Developers have shared with us that moving from a web site (or Chrome OS App) to a Progressive Web App is not an easy task. With that in mind, we’ve recently shared a preview to some of the open source tools we are supporting to ease the transition from web site to Progressive Web Apps. As an education ISV, you can start using these tools today. Lear more about these tools at <a href="http://preview.pwabuilder.com">http://preview.pwabuilder.com</a> .</p>
<p>PWA Builder helps you build out the components needed for a Progressive Web App and get your listing in the Windows Store and other markets, so you can reach users regardless of platform or device.</p>
<p>We’ll have lots more to share about the road to Progressive Web Apps in Microsoft Edge and Windows 10 soon – in the meantime, <a href="https://twitter.com/msedgedev">reach out on Twitter</a> or in the comments below if you have questions!</p>
<p>― <a href="https://twitter.com/boyofgreen">Jeff Burtoft</a>, Principal Program Manager, Partner App Experience</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/10/progressive-web-apps-education/">Next-generation web apps for education</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/03/10/progressive-web-apps-education/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Scrolling on the web: A primer</title>
<link>https://blogs.windows.com/msedgedev/2017/03/08/scrolling-on-the-web/</link>
<comments>https://blogs.windows.com/msedgedev/2017/03/08/scrolling-on-the-web/#comments</comments>
<pubDate>Wed, 08 Mar 2017 18:17:22 +0000</pubDate>
<dc:creator><![CDATA[Nolan Lawson]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Independent Rendering]]></category>
<category><![CDATA[Passive Event Listeners]]></category>
<category><![CDATA[Performance]]></category>
<category><![CDATA[Pointer Events]]></category>
<category><![CDATA[Scrolling]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>Scrolling is one of the oldest interactions on the web. Long before we had pull-to-refresh or infinite-loading lists, the humble scrollbar solved the web’s original scaling problem: how can we interact with content that’s stretched beyond the available viewport? Animations by Rachel Nabors Today, scrolling is still the most fundamental interaction on the web, and [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/08/scrolling-on-the-web/">Scrolling on the web: A primer</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>Scrolling is one of the oldest interactions on the web. Long before we had pull-to-refresh or infinite-loading lists, the humble scrollbar solved the web’s original scaling problem: how can we interact with content that’s stretched beyond the available viewport?</p>
<div>
<div class="illo_lineup">
<div class="illustration illo_2fingers">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_2fingers_touchpad" viewbox="0 0 102 52" name="illo_2fingers_touchpad"><path class="illo_2fingers_touchpad_bg" d="M 2.3 47.7 L 33.8 1.4 l 39 0.8 l 27.4 1.6 l -10.6 27.4 l -9.1 19.6 L 30 46.9 Z"></path><path d="M 32.4 2.8 h -0.8 c 0.3 -1.2 1.2 -1.4 2.2 -1.4 c 1.2 -0.1 2.5 -0.2 3.7 -0.2 C 42.2 1.1 47 1 51.8 1 h 7.6 c 3.1 0 6.2 0.1 9.4 0.2 c 2.1 0.1 4.2 0.1 6.4 0.2 c 2.5 0.1 5.1 0.2 7.6 0.4 c 2.2 0.1 4.3 0.2 6.5 0.4 c 3 0.2 6.1 0.3 9.1 0.5 c 0.7 0 1.3 0.1 2 0.1 c 0.9 0 1 0.3 0.7 1.1 c -0.7 1.7 -1.3 3.4 -2 5.2 l -4.2 10.2 c -1 2.5 -2 5.1 -2.9 7.7 c -1.2 3.5 -2.8 6.7 -4.4 10 c -0.7 1.3 -1.1 2.7 -1.7 4.1 c -0.8 1.7 -1.6 3.5 -2.4 5.2 c -0.6 1.2 -1.1 2.5 -1.6 3.7 c -0.4 0.8 -0.8 1.3 -1.9 1.2 c -2.4 -0.2 -4.9 -0.2 -7.3 -0.3 c -1.8 -0.1 -3.6 -0.2 -5.4 -0.2 c -2.6 -0.1 -5.1 -0.2 -7.7 -0.4 c -2.4 -0.1 -4.7 -0.3 -7.1 -0.5 c -2.4 -0.2 -4.9 -0.4 -7.3 -0.6 c -2.4 -0.2 -4.9 -0.4 -7.3 -0.6 c -2.1 -0.1 -4.2 -0.3 -6.3 -0.4 c -2.7 -0.1 -5.4 -0.2 -8.1 -0.2 c -2.8 -0.1 -5.6 -0.1 -8.4 -0.1 c -2.6 0 -5.2 0.2 -7.8 0.2 H 3.8 c -0.7 0 -1.3 0.2 -2 0.3 c -0.6 0.1 -0.4 -0.6 -0.7 -0.8 l 0.6 -0.6 c 0.2 -0.2 0.5 -0.3 0.6 -0.5 c 2.9 -4.4 5.7 -8.8 8.6 -13.2 c 2.4 -3.6 5.1 -7 7.6 -10.5 c 2.8 -3.9 5.6 -7.7 8.3 -11.7 c 1.6 -2.3 3.1 -4.7 4.6 -7 c 0.2 -0.4 0.6 -0.8 1 -1.3 Z m 67 1.4 c -1.1 -0.1 -2.2 -0.1 -3.2 -0.2 c -2.1 -0.1 -4.2 -0.2 -6.3 -0.4 c -2.2 -0.1 -4.4 -0.2 -6.6 -0.4 c -2.5 -0.1 -4.9 -0.2 -7.4 -0.4 c -2.1 -0.1 -4.2 -0.2 -6.3 -0.2 c -2.6 -0.1 -5.2 -0.2 -7.8 -0.2 c -2.1 -0.1 -4.2 -0.1 -6.3 -0.1 c -3.4 0 -6.8 0.1 -10.2 0.1 s -6.9 0.1 -10.3 0.1 c -0.7 0 -1.5 -0.2 -1.9 0.9 c -0.4 1 -1.2 1.9 -1.7 2.9 c -3.5 6.1 -7.7 11.8 -11.9 17.5 c -2.8 3.9 -5.7 7.8 -8.5 11.7 c -2 2.8 -3.8 5.7 -5.7 8.6 c -0.6 0.9 -1.1 1.8 -1.7 2.7 c 1.2 -0.1 2.3 -0.1 3.4 -0.2 c 1.8 -0.1 3.6 -0.2 5.5 -0.2 c 1.9 -0.1 3.7 -0.1 5.6 -0.1 c 1.3 0 2.5 0.1 3.8 0.1 c 3 0.1 5.9 0.1 8.9 0.2 c 2.3 0.1 4.6 0.2 6.9 0.4 c 1.9 0.1 3.9 0.3 5.8 0.5 c 2.9 0.2 5.8 0.5 8.7 0.7 c 2.3 0.2 4.6 0.3 6.9 0.5 c 2.5 0.1 5.1 0.2 7.6 0.4 c 1.8 0.1 3.6 0.2 5.4 0.2 c 2.4 0.1 4.7 0.2 7.1 0.2 c 0.5 0 1.2 0.3 1.5 0 c 0.3 -0.2 0.3 -1 0.5 -1.4 l 3 -6.6 c 0.8 -1.9 1.6 -3.8 2.4 -5.6 c 1.2 -2.6 2.7 -5.1 3.6 -7.8 c 2 -6.5 5.4 -12.4 7.5 -18.8 c 0.4 -1.6 1 -3.4 1.7 -5.1 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_2fingers_fingers" viewbox="0 0 41 60" name="illo_2fingers_fingers"><path class="illo_component_bg" d="M 2.1 53.5 l 17.1 -37.4 l 5.6 -9.4 l 4.9 -4.6 L 31.6 1 l 2.6 2.2 l -1.6 9.9 l 2.1 -1.6 l 2.7 0.5 l 2 4.1 v 12.8 l -5.8 18.5 l -3.3 7.3 l -18.4 4.9 Z"></path><path d="M 31.3 14.6 c 1 -1.4 1.2 -3 1.6 -4.6 c 0.2 -0.9 0.5 -1.9 0.6 -2.8 c 0.1 -1.3 0.3 -2.7 -0.3 -4 c -0.3 -0.8 -1 -1.1 -1.8 -1.4 c -0.4 0 -1.1 0.2 -1.7 0.3 h -0.2 c 0.5 -0.8 1.4 -0.8 2.1 -1.1 c 1.8 0.6 2.6 1.7 2.9 3.4 c 0.3 1.8 -0.1 3.6 -0.5 5.3 l -0.3 1.5 c -0.2 0.2 -0.2 0.4 0.1 0.5 c 0 0.1 0.1 0.1 0.1 0.2 c 0.5 -0.2 1 -0.5 1.6 -0.6 c 1.1 -0.2 1.8 0.3 2.4 1.2 c 0.8 1.1 1.2 2.3 1.6 3.6 c 0.4 1.4 0.6 2.8 0.6 4.3 c 0 1 0.2 1.9 0.1 2.9 c -0.1 1.7 -0.3 3.3 -0.5 5 l -0.6 3.9 c -0.3 1.7 -0.7 3.5 -1.2 5.1 c -0.7 2.5 -1.4 5 -2.3 7.5 c -0.9 2.8 -2.3 5.5 -3.8 8.1 l -1.2 1.8 h -0.2 c 0.4 -1 0.7 -2 1.1 -3 c 0.6 -1.5 1.1 -3.1 1.7 -4.6 c 1.8 -4.4 3 -9 4.1 -13.6 c 0.4 -1.8 0.6 -3.7 0.9 -5.6 l 0.6 -3.3 c 0.4 -1.8 0.5 -3.6 0.2 -5.4 c -0.2 -1.4 -0.4 -2.9 -0.8 -4.3 c -0.2 -0.9 -0.8 -1.6 -1.2 -2.4 c -0.6 -0.9 -1.5 -0.8 -2.4 -0.6 c -0.8 0.2 -1.5 0.5 -1.6 1.5 c 0 0.4 -0.4 0.7 -0.6 1.1 c -0.1 0.1 -0.1 0.3 -0.2 0.4 c -0.2 0.2 -0.4 0.3 -0.5 0.5 l -1.5 3.3 c -0.5 1.1 -0.9 2.2 -1.5 3.3 c -1 2.1 -2 4.1 -2.9 6.2 c -0.6 1.4 -1.3 2.8 -1.8 4.2 c -0.5 1.2 -0.8 2.4 -1.3 3.6 c -0.3 0.7 -0.6 1.3 -0.9 2 c -0.4 0.9 -0.8 1.7 -1.2 2.6 l -0.9 2.1 c -0.8 1.9 -1.6 3.7 -2.4 5.6 c -0.8 1.9 -1.5 3.8 -2.2 5.7 c -0.6 1.6 -1.4 3.2 -2.3 4.7 l -0.6 0.9 c -0.1 0 -0.2 -0.1 -0.2 -0.1 c 0.5 -1.1 1 -2.1 1.5 -3.2 c 0.6 -1.3 1.1 -2.6 1.6 -4 c 0.5 -1.2 0.9 -2.5 1.4 -3.7 c 0.8 -2 1.6 -3.9 2.4 -5.9 c 0.7 -1.7 1.4 -3.3 2.1 -5 c 1.1 -2.6 2.1 -5.3 3.2 -7.9 c 0.7 -1.7 1.5 -3.5 2.3 -5.2 c 0.7 -1.4 1.5 -2.7 2.1 -4.1 l 2.4 -5.4 c 0.1 -0.2 0.2 -0.3 0.2 -0.5 h 0.1 Z"></path><path d="M 29.5 2.1 h 0.2 l -0.8 0.8 c -2.3 2.1 -4.1 4.6 -5.5 7.3 c -1.2 2.2 -2.4 4.4 -3.5 6.6 c -0.7 1.4 -1.2 2.9 -1.9 4.4 c -1 2.1 -2 4.1 -2.9 6.1 c -1.9 4.3 -3.9 8.4 -6 12.6 c -2 4 -3.8 8 -5.8 12 c -0.5 1 -1.3 1.8 -2 2.8 c -0.1 0 -0.2 -0.1 -0.2 -0.1 c 0.2 -0.7 0.4 -1.5 0.7 -2.2 l 3 -6.3 C 5.9 43.5 7 41 8.3 38.4 c 1.1 -2.1 2.3 -4.2 3.3 -6.3 l 3.6 -7.5 c 1.3 -2.8 2.7 -5.7 4 -8.5 c 1.5 -3.1 3.3 -6 5.2 -8.8 c 1.3 -2 2.9 -3.7 4.9 -5.1 c 0.1 -0.1 0.2 -0.1 0.2 -0.1 Z"></path><path d="M 24.5 10.9 c 0.6 0.4 1.1 1 1.7 1.2 c 0.6 0.3 1.4 0.5 2.1 0.4 c 0.7 0 1.4 -0.4 2.1 -0.7 c -0.6 1.2 -1.7 1.5 -2.9 1.3 c -0.7 -0.1 -1.4 -0.4 -2 -0.7 c -0.7 -0.3 -1 -0.8 -1 -1.5 Z M 31.2 21 c 1.6 0.9 3.2 0.2 4.7 0.1 c -0.2 0.9 -1.8 1.4 -3.2 1.2 c -0.9 -0.2 -1.5 -0.7 -1.5 -1.3 Z"></path></svg></div>
</div>
<div class="illustration illo_1finger-scroll">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_1finger-scroll_screen" viewbox="0 0 63 90" name="illo_1finger-scroll_screen"><path class="illo_component_bg" d="M 16.5 1.7 l 1.5 -0.5 l 43.3 1.5 l 0.2 1.1 l -17.9 85.5 h -1.2 L 1.7 84.9 Z"></path><path d="M 62.1 3.4 c -0.2 1.1 -0.4 2.1 -0.6 3.2 c -0.4 2 -0.7 4 -1 5.9 l -1.2 6 c -1 4.5 -2.1 9 -3.1 13.6 c -1.2 5.2 -2.3 10.5 -3.5 15.7 c -0.8 3.5 -1.5 7 -2.2 10.5 c -0.5 2.5 -1 5.1 -1.4 7.6 c -0.7 3.8 -1.4 7.6 -2.2 11.4 c -0.4 2.2 -1 4.3 -1.5 6.5 c -0.4 1.7 -0.8 3.5 -1.2 5.2 c 0 0.2 -0.2 0.4 -0.3 0.4 c -0.8 0.4 -1.6 0.4 -2.5 0.3 c -0.6 -0.1 -1.2 -0.2 -1.8 -0.2 l -6 -0.6 c -1.7 -0.2 -3.4 -0.3 -5.1 -0.5 c -1.7 -0.2 -3.3 -0.4 -4.9 -0.6 c -1.4 -0.1 -2.8 -0.2 -4.2 -0.4 c -1.4 -0.1 -2.9 -0.3 -4.3 -0.5 c -1.3 -0.1 -2.6 -0.2 -3.9 -0.4 c -1.5 -0.2 -3.1 -0.4 -4.6 -0.6 c -1.3 -0.2 -2.7 -0.3 -4 -0.5 c -0.5 -0.1 -1.1 -0.2 -1.6 -0.4 c -0.1 0 0 -0.3 -0.1 -0.4 c 0.7 0 0.5 -0.7 0.6 -1 c 0.5 -2.4 0.8 -4.8 1.3 -7.2 c 0.6 -3.1 1.2 -6.1 1.9 -9.2 c 0.5 -2.6 1 -5.1 1.5 -7.7 c 0.4 -2.2 0.8 -4.4 1.1 -6.5 c 0.4 -2.3 0.8 -4.5 1.2 -6.8 c 0.4 -2.2 0.7 -4.5 1.1 -6.7 c 0.3 -1.8 0.6 -3.7 1 -5.5 c 0.4 -2.3 0.8 -4.5 1.3 -6.8 c 0.5 -2.2 1 -4.4 1.4 -6.6 c 0.5 -2.5 1.1 -5.1 1.5 -7.6 c 0.4 -2.4 0.7 -4.8 1.1 -7.2 c 0.2 -1.4 0.3 -2.7 0.5 -4.1 c 0 -0.4 0.2 -0.6 0.6 -0.3 h 0.2 C 17.8 0.8 18.4 1 19 1 h 7.8 c 1.9 0 3.8 0.1 5.7 0.1 c 1.9 0.1 3.7 0.2 5.6 0.2 c 1.7 0.1 3.5 0.2 5.2 0.2 c 1.6 0.1 3.2 0.2 4.8 0.2 c 1.7 0.3 3.3 0.3 5 0.4 c 1.3 0.1 2.6 0.1 3.9 0.2 c 1.5 0.1 2.9 0.2 4.4 0.4 c 0.4 0.1 0.7 0.3 0.7 0.7 Z M 17.8 1.8 c -0.4 -0.2 -0.8 -0.2 -0.8 0.4 c -0.1 1.3 -0.2 2.6 -0.4 3.9 c -0.3 2.4 -0.6 4.8 -1 7.2 c -0.5 3 -1.1 6 -1.7 9 c -0.6 3.2 -1.4 6.4 -2 9.6 c -0.7 3.8 -1.4 7.7 -2.1 11.5 c -0.6 3.1 -1.1 6.3 -1.7 9.4 c -0.4 2.5 -0.8 5 -1.3 7.5 C 6 64.5 5 68.6 4.2 72.8 c -0.8 3.7 -1.5 7.4 -2.2 11.1 c 0 0.8 0 0.8 0.7 0.9 l 2.7 0.3 c 1.4 0.1 2.7 0.3 4.1 0.5 c 1 0.1 1.9 0.2 2.9 0.3 c 1.7 0.2 3.3 0.3 5 0.5 c 1.1 0.1 2.1 0.2 3.2 0.3 c 1.5 0.1 3.1 0.3 4.6 0.5 c 1.4 0.1 2.8 0.2 4.3 0.4 c 1.3 0.1 2.7 0.3 4 0.5 c 1.3 0.1 2.6 0.2 3.9 0.4 c 1.9 0.3 3.9 0.6 5.8 0.9 c 0.1 0 0.4 -0.2 0.4 -0.3 c 0.3 -1.5 0.7 -3 1 -4.5 l 3 -14.1 c 0.4 -1.7 0.6 -3.4 1 -5.1 c 0.6 -3 1.1 -5.9 1.7 -8.9 c 0.7 -3.7 1.5 -7.3 2.3 -11 c 0.7 -3.4 1.5 -6.7 2.2 -10 c 1.1 -5 2.3 -9.9 3.4 -14.9 c 0.6 -2.5 1.1 -5 1.6 -7.5 c 0.6 -3 1.1 -5.9 1.7 -8.9 c 0.1 -0.5 0 -0.5 -0.4 -0.6 c -2.4 0 -4.8 -0.1 -7.2 -0.1 c -1.7 0 -3.5 -0.1 -5.2 -0.2 c -2.4 -0.1 -4.8 -0.2 -7.2 -0.4 c -1.6 -0.1 -3.3 -0.2 -4.9 -0.2 c -1.9 -0.1 -3.9 -0.2 -5.8 -0.2 c -1.7 -0.5 -3.3 -0.5 -4.9 -0.6 c -2.7 0 -5.4 -0.1 -8.1 -0.1 Z"></path></svg></p>
<div class="illo_component illo_1finger-scroll_fingers"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 43 118" name="illo_1finger-scroll_fingers"><path class="illo_component_bg" d="M 8.8 47.7 l 8.5 -17 L 31.8 8.1 l 6.5 -6.8 H 40 l 1.7 5 l -4.2 12.8 l -19.8 37.5 Z"></path><path class="illo_1finger-scroll_finger_1" d="M 27.5 14 c 1.3 -1.8 2.5 -3.7 3.9 -5.3 C 33.3 6.4 35.3 4 37.5 2 C 39 0.6 40.2 0.8 41 2.7 c 0.8 1.8 0.9 3.6 0.5 5.5 c -1 4.6 -2.9 8.9 -5 13.1 c -1.2 2.4 -2.4 4.9 -3.6 7.4 c -1.3 2.7 -2.5 5.5 -3.9 8.3 c -1.8 3.5 -3.5 7 -5.4 10.5 c -1.5 2.7 -3.2 5.4 -4.9 8 c -0.3 0.5 -0.6 0.9 -0.9 1.3 l -0.2 -0.2 c 0.7 -1.4 1.5 -2.8 2.2 -4.2 c 0.8 -1.4 1.5 -2.9 2.3 -4.3 c 1 -1.8 2 -3.6 2.9 -5.4 c 0.9 -1.7 1.7 -3.5 2.6 -5.3 c 0.6 -1.4 1.3 -2.7 1.9 -4.1 c 1.1 -2.4 2.2 -4.7 3.3 -7.1 c 0.9 -1.9 1.9 -3.7 2.7 -5.6 c 1.2 -2.5 2.4 -5.1 3.4 -7.7 c 0.7 -1.8 1.2 -3.8 1.7 -5.7 c 0.4 -1.5 0.1 -3.1 -0.5 -4.5 c -0.5 -1.1 -1.2 -1.2 -2 -0.4 c -0.9 0.8 -1.7 1.7 -2.5 2.6 c -1.2 1.4 -2.5 2.8 -3.6 4.3 c -2.6 3.7 -5.3 7.4 -7.7 11.2 c -2.5 3.9 -4.7 7.9 -7 11.9 c -1.6 2.8 -3.1 5.6 -4.7 8.5 c -1.1 2.1 -2.2 4.2 -3.3 6.2 c -0.1 0.2 -0.3 0.5 -0.6 0.6 C 14.1 36 20.2 24.7 27.4 14 c 0 0.1 0.1 0 0.1 0 Z"></path><path class="illo_component_bg" d="M 5.6 115.1 l 14.8 1.7 l -0.6 -5.4 l -2.5 -7.6 l -1.8 -7.5 h 11.9 l 12 -7.8 l 1.8 -3 l 0.5 -3.4 V 80 l -10.4 2.6 s -17.6 1.6 -17.4 1.6 c 0.3 0 -11.8 -1.1 -11.8 -1.1 l -0.4 0.7 l 3 15.8 l 0.9 15.5 Z"></path><path class="illo_1finger-scroll_finger_2" d="M 1.8 82.6 c 0.6 0 1.2 -0.1 1.8 -0.1 c 0.7 0 1.3 0.1 2 0.1 c 1.5 0.1 2.9 0.4 4.4 0.5 c 2.1 0.1 4.1 0.3 6.2 0.2 c 2.4 0 4.7 -0.1 7.1 -0.4 c 2.9 -0.3 5.8 -0.6 8.6 -1.1 c 3 -0.6 6 -1.4 8.9 -2.1 c 0.2 -0.1 0.4 -0.2 0.7 -0.4 h 0.4 c 0.3 0.4 0.6 0.8 0.8 1.2 v 2.8 c -0.1 0.1 -0.2 0.2 -0.2 0.3 c -0.6 2.1 -1.5 4.1 -3 5.7 l -0.1 0.1 c -2.4 2.3 -5.2 4 -8 5.7 c -1.6 0.9 -3.3 1.6 -5.2 1.6 c -1.6 0.1 -3.3 0.2 -4.9 0.2 h -5.1 c 0.4 1.4 0.8 2.7 1.3 3.9 c 1.2 3 2 6.1 2.7 9.2 c 0.4 1.9 0.7 3.8 0.6 5.7 c 0 0.5 0 1 -0.1 1.5 h -0.2 c -0.1 -0.4 -0.3 -0.9 -0.4 -1.3 c -0.4 -1.9 -0.9 -3.9 -1.3 -5.8 c -0.3 -1.3 -0.5 -2.7 -0.9 -4 c -0.5 -1.7 -1 -3.5 -1.8 -5.1 c -0.7 -1.3 -0.9 -2.7 -1.4 -4.1 c -0.2 -0.6 -0.4 -1.2 -0.6 -1.9 c -0.1 -0.3 -0.2 -0.7 0.2 -0.9 c 0.4 -0.2 0.7 0.1 0.8 0.5 c 0.2 0.6 0.7 0.7 1.2 0.7 c 1.8 0.1 3.6 0.1 5.4 0.1 c 1.8 0 3.6 0 5.4 -0.3 c 1.3 -0.2 2.6 -0.7 3.7 -1.4 c 2 -1.2 4 -2.5 5.9 -3.9 c 2.7 -1.8 4.2 -4.5 4.8 -7.6 c 0.1 -0.7 0 -1.4 0 -2.1 c -1.7 0.5 -3.2 1 -4.7 1.3 c -2.5 0.5 -5 1 -7.6 1.4 c -2 0.3 -4.1 0.4 -6.1 0.6 c -1.5 0.1 -3.1 0.2 -4.6 0.2 c -1.9 0.1 -3.7 0.2 -5.6 0.1 c -1.6 0 -3.2 -0.3 -4.8 -0.4 c -1.2 -0.1 -2.4 -0.3 -3.7 -0.4 c -0.9 -0.1 -1.7 -0.2 -2.6 -0.3 h -0.7 c 0.1 -0.2 0.2 -0.3 0.2 -0.5 l 0.5 0.5 Z"></path><path class="illo_1finger-scroll_finger_2" d="M 1 83.4 c 0.2 -0.1 0.5 -0.2 0.6 -0.3 c 3.9 10.4 4.5 21.1 4.2 31.9 h -0.2 c -0.1 -0.5 -0.1 -0.9 -0.2 -1.4 c -0.2 -1.9 -0.3 -3.9 -0.5 -5.8 c -0.1 -1.2 -0.1 -2.4 -0.3 -3.6 c -0.1 -1.5 -0.3 -3.1 -0.5 -4.6 c -0.1 -1.1 -0.2 -2.3 -0.4 -3.4 c -0.2 -1.6 -0.4 -3.3 -0.8 -4.9 c -0.4 -2.1 -1 -4.3 -1.4 -6.4 c -0.1 -0.5 -0.3 -0.8 -0.7 -1 c 0.2 -0.1 0.2 -0.3 0.2 -0.5 Z"></path></svg></div>
</div>
</div>
<div class="illustration illo_scrolling">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_scrolling_scrollbar" viewbox="0 0 19 122" name="illo_scrolling_scrollbar"><path d="M 18.6 1.4 v 8.2 c 0 0.3 0.3 0.7 0.3 1 c 0 0.3 -0.2 0.5 -0.3 0.8 c -0.1 0.5 0 1.1 0 1.7 c 0 4.6 -0.1 9.2 -0.1 13.7 c -0.1 9.1 -0.1 18.2 -0.3 27.4 c -0.2 18.2 -0.3 36.3 -0.5 54.5 c 0 2.3 0 4.5 -0.1 6.8 c 0 1 0 2.1 -0.1 3.1 c 0 0.8 0.2 2.1 -0.8 2.3 c -1.1 0.2 -2.3 0.1 -3.4 0.1 c -1.2 0 -2.4 0.1 -3.6 0.1 c -2.1 0.1 -4.3 0.1 -6.4 0.2 c -0.5 0 -1.9 0.6 -2.3 0.2 c -0.4 -0.5 -0.1 -2.2 -0.1 -2.8 c 0.1 -2.1 0.1 -4.2 0.1 -6.3 c 0.1 -4.4 0.2 -8.8 0.3 -13.1 c 0.1 -2.3 0.1 -4.6 0.2 -6.9 c 0.1 -2.2 0 -4.5 0.2 -6.7 c 0.5 -2.4 0.4 -4.7 0.3 -7 c 0 -2.3 0.1 -4.5 0.2 -6.8 c 0.2 -8.7 0.4 -17.5 0.7 -26.2 c 0.2 -9 0.5 -18 0.7 -27 l 0.3 -13 c 0 -1 0.1 -2.1 0.1 -3.1 S 4.4 0.9 5.5 0.9 c 2.3 -0.1 4.6 0.1 6.9 0.2 c 2 0.1 4.3 -0.1 6.2 0.3 Z M 5.3 11.6 C 4.7 24 4.5 36.6 4.2 49 c -0.4 12.7 -0.6 25.3 -1 38 c -0.1 3.5 -0.2 7 -0.3 10.6 c -0.1 3.3 0 6.7 -0.3 10 c 3.4 0 6.8 -0.2 10.1 -0.3 c 0.9 0 1.7 0 2.6 -0.1 c 0.3 0 0.9 0.1 1 -0.1 c 0.2 -0.2 0 -1 0 -1.3 c 0 -1.8 0 -3.6 0.1 -5.4 c 0.1 -7.3 0.1 -14.5 0.2 -21.8 c 0.1 -14.4 0.3 -28.9 0.4 -43.3 c 0.1 -8 0.2 -16 0.2 -24 c -1.9 0.1 -3.9 0.1 -5.8 0.2 c -2 0.1 -4.1 0.3 -6.1 0.1 Z M 2.4 120 c 3.2 0 6.4 -0.3 9.7 -0.4 c 0.8 0 1.6 0 2.3 -0.1 h 1 c 0.2 0 0.4 0 0.6 -0.1 c 0.4 -0.1 0.2 0 0.3 -0.4 c 0.1 -0.7 0 -1.6 0 -2.3 V 114 v -4.8 c 0 -0.6 0 -0.6 -0.6 -0.6 h -1.1 c -0.8 0 -1.7 0.1 -2.5 0.1 c -1.6 0 -3.3 0.1 -4.9 0.1 H 4.7 c -0.5 0 -1.7 -0.2 -2 0.2 c -0.3 0.6 -0.2 2 -0.2 2.6 v 2.7 c 0 2 -0.1 3.9 -0.1 5.7 Z M 17.2 2.7 c -3.5 -0.1 -7 -0.1 -10.6 -0.2 c -0.2 0 -1.1 -0.1 -1.2 0 c -0.1 0.1 -0.1 1 -0.1 1.1 c 0 0.8 -0.1 1.7 -0.1 2.5 v 2.2 c 0 0.3 -0.2 2.5 0 2.6 c 0.3 0.2 1.5 -0.3 1.9 -0.3 c 0.8 -0.1 1.6 -0.2 2.4 -0.2 c 1.6 -0.1 3.2 0 4.8 0 c 0.7 0 1.8 0.1 2.5 -0.1 c 0.5 -0.2 0.4 -0.2 0.4 -0.8 V 8.3 V 2.7 Z"></path><path d="M 8.6 115.3 c 0.3 -1.2 -2.1 -2.7 -2.8 -3.4 c 0.9 -0.6 2.4 -0.4 3.5 -0.4 c 1 0 2.3 -0.3 3.3 -0.1 c 0.6 0.1 0.9 0.2 0.5 0.7 c -0.4 0.5 -1.1 0.9 -1.6 1.4 c -0.6 0.4 -2.3 2.4 -2.9 1.8 Z m -1.4 -3.2 c -0.1 0.3 0.7 0.9 0.9 1.2 c 0.4 0.5 0.6 1 0.9 1.5 c 1 -0.9 2 -1.8 3.1 -2.7 H 7.2 Z M 15.2 7.2 c -0.2 0.6 -1.2 0.4 -1.7 0.4 c -0.8 0 -1.6 0.1 -2.4 0.1 c -1 0.1 -2.9 0.5 -3.6 -0.4 c 0.8 -0.6 1.6 -1.1 2.4 -1.7 l 1.2 -0.9 c 0.2 -0.1 0.4 -0.3 0.6 -0.4 c 0.1 0.1 0.2 0.1 0.4 0.2 c 0.7 0.2 1.5 0.8 2.1 1.2 c 0.8 0.4 0.7 0.8 1 1.5 Z M 11.8 5 c -0.4 0.3 -3.4 2 -3.3 2.4 c 2.1 -0.2 4.1 -0.3 6.2 -0.5 c -1 -0.6 -1.9 -1.3 -2.9 -1.9 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_scrolling_scroller" viewbox="0 0 23 43" name="illo_scrolling_scroller"><path class="illo_component_bg" d="M 2 2 l 13.2 -0.2 V 25 l 6.3 5.8 l -3.9 3 l 3.3 6.8 l -2 0.8 l -4.1 -6.3 l -3.6 1.7 l -0.6 -4.3 l -9.1 0.4 Z"></path><path d="M 14.6 35.8 c -0.8 0.3 -1.5 0.7 -2.3 1 c -0.5 0.2 -1.4 0.8 -2 0.5 c -0.5 -0.3 -0.3 -1 -0.3 -1.5 c 0.1 -0.9 0.1 -1.8 0.1 -2.6 H 3.8 c -0.6 0 -2.1 0.2 -2.5 -0.3 c -0.4 -0.5 -0.1 -2 -0.1 -2.6 c 0.1 -3.5 -0.2 -7 -0.1 -10.4 c 0 -1.5 -0.1 -3.1 -0.1 -4.6 c 0.1 -1.4 0.1 -2.8 0.2 -4.2 c 0.1 -2 0.1 -3.9 0.1 -5.9 c 0 -0.9 0 -1.9 0.1 -2.8 c 0.2 -1 0.6 -1 1.5 -1.1 C 5 1.3 7 1.2 9 1 c 1 -0.1 2 0 3 0 c 1.1 0 2.2 -0.1 3.2 0.2 c 1 0.2 0.6 0.6 0.6 1.4 c 0 1 0.2 2.1 0.2 3.1 c 0 2.2 0.1 4.4 0 6.6 c -0.1 2.2 -0.1 4.3 -0.1 6.5 V 22 c 0 1 -0.1 2.3 0.3 3.1 c 0.4 0.8 1.3 1.5 1.9 2.1 c 0.8 0.8 1.6 1.4 2.4 2.1 c 0.5 0.4 1.5 0.9 1.8 1.5 c 0.3 0.8 -0.4 1.2 -0.9 1.6 c -1 0.6 -2 1.1 -3 1.7 c -0.6 0.4 -0.4 0.4 -0.1 1 c 0.2 0.4 0.5 0.7 0.8 1.1 c 0.5 0.7 1 1.3 1.3 2.1 c 0.2 0.4 0.2 0.9 0.4 1.4 c 0.1 0.4 -0.1 0 0.3 0.5 c 0.1 0.2 0.3 0.2 0.3 0.5 c 0 0.7 -1.4 1.1 -1.9 1.3 c -0.4 0.2 -0.4 0.2 -0.8 -0.2 c -0.4 -0.3 -0.7 -0.8 -1 -1.1 c -0.6 -0.7 -1.2 -1.5 -1.7 -2.3 c -0.3 -0.6 -0.8 -2.6 -1.4 -2.6 Z m 5.7 3.9 c -1.3 -1.3 -2.2 -3.4 -3.1 -5 c -0.3 -0.5 -0.3 -0.5 0 -0.9 c 0.3 -0.3 0.6 -0.5 0.9 -0.8 c 0.9 -0.6 1.8 -1.2 2.6 -1.8 c -1.4 -1.6 -3.1 -2.6 -4.8 -3.9 c -1.6 -1.3 -3 -2.8 -4.6 -4.1 c 0 4.3 -0.1 8.6 -0.3 13 c 1 -0.4 1.9 -0.8 2.9 -1.3 c 0.3 -0.1 0.9 -0.6 1.2 -0.5 c 0.4 0.1 0.3 0.5 0.5 0.8 c 1 2 2.5 3.8 3.5 5.8 l 1.5 -0.9 c -0.1 -0.2 -0.2 -0.3 -0.3 -0.4 Z m -10.1 -7.9 c 0.1 -2.8 0 -5.6 0 -8.5 c 0 -1.1 0.3 -1.8 1.4 -1.2 c 1.2 0.6 2.2 1.5 3.3 2.2 c -0.2 -4.2 -0.3 -8.4 0.1 -12.6 c 0.2 -2.1 0.3 -4.2 0.2 -6.3 V 3.9 c 0 -0.2 0 -1.3 -0.1 -1.4 c -0.2 -0.2 -1.3 -0.1 -1.6 -0.1 c -0.6 0 -1.3 -0.1 -1.9 -0.1 c -2.1 -0.1 -4.2 0 -6.4 0.1 H 3.9 c -0.2 0 -1.4 -0.1 -1.5 0 c -0.2 0.1 -0.2 1.1 -0.2 1.4 c 0 0.6 -0.1 1.2 -0.1 1.8 c -0.2 4.3 -0.1 8.6 0 12.9 c 0.1 2.3 0.1 4.7 0.1 7 c 0 1 0.1 2.1 0.2 3.1 c 0.1 1.3 0 2.4 -0.2 3.6 c 2.7 -0.1 5.3 -0.3 8 -0.4 Z"></path></svg></div>
</div>
<div class="illustration illo_keypress">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_bg-keys" viewbox="0 0 68 30" name="illo_keypress_bg-keys"><path d="M 11.7 18.5 v 3 c -1.3 -1.3 -0.7 -2.8 -0.9 -4.2 C 8.3 13.8 5 11 2.2 7.6 c 0.1 1.5 0.5 2.9 0.3 4.4 c -1.1 -1.4 -1 -3 -1.2 -4.7 c -0.2 0 -0.5 -0.2 -0.2 -0.8 C 8.2 4.4 15.5 2.3 23 1 c 4 2.4 7.3 5.8 11 8.5 c -0.1 2.4 -0.2 4.7 -0.3 7 c -0.2 0.2 -0.4 0.2 -0.8 0 v -5.8 c -7.3 2.1 -14.2 4.9 -21.2 7.8 Z m 0 -1.1 c 6.5 -3.2 13.2 -5.7 20.2 -7.8 c -3.5 -2.7 -6.8 -5.5 -10.4 -8 C 15.3 3.9 8.8 5 2.3 7.1 c 1.3 0.7 1.9 1.9 2.9 2.7 c 1.7 1.4 3.4 2.9 4.8 4.6 c 0.7 0.9 1.6 1.7 1.7 3 Z M 51.8 29.2 c -0.4 -1.2 -1 -2.3 -1 -3.4 c 0 -1.5 -1.3 -2.2 -2.1 -3.2 c -1.4 -1.7 -2.8 -3.4 -4.5 -4.9 c -2 -1.8 -4 -3.4 -6 -5.2 c -0.3 -0.2 -0.5 -0.5 -0.9 -0.9 v 5.3 c -0.3 0.3 -0.5 0.2 -0.8 0.1 v -5.8 c 0.6 -0.8 1.6 -0.9 2.5 -1.1 c 2.4 -0.7 4.9 -1.1 7.2 -1.9 c 1.8 -0.7 3.7 -1.1 5.6 -1.6 c 0.3 -0.1 0.5 -0.1 0.8 0 c 5.5 2.8 10.3 6.6 15 10.5 c 0.1 2.2 -0.2 4.3 -0.5 6.5 c -0.7 -1.1 -0.9 -3.4 -0.5 -5.2 c -4.9 2.2 -9.9 4.2 -15 6.2 c 0.4 1.5 0.6 3 0.2 4.6 Z M 38.1 11.4 C 43 15.2 47.6 18.9 51 24 c 5.3 -2.3 10.5 -4.6 16.1 -6.2 c -4.4 -4.5 -9.8 -7.2 -14.8 -10.5 c -4.8 1.4 -9.4 3 -14.2 4.1 Z"></path><path d="M 19.3 6.8 h -1.8 c 0.8 1 1.6 2 2.3 3 v 0.6 c -0.1 0.1 -0.3 0.2 -0.6 0.4 h -0.4 c -1.1 -0.9 -1.6 -2.2 -2.7 -3 c -0.2 0.4 0 1 -0.6 1.3 c -0.5 -0.2 -0.6 -0.6 -0.6 -1 c 0 -0.5 -0.1 -0.9 -0.2 -1.3 c -0.2 -0.9 0.2 -1.3 1.1 -1.1 c 0.7 0.1 1.3 0.2 1.9 0.5 c 0.5 0.1 0.9 0.3 1.6 0.6 Z M 55.8 13 c 0.2 1 -1.2 3.5 -2.1 3.7 c -0.6 -0.7 0.1 -1.3 0.2 -2 c -1.4 0.5 -2.8 1.1 -4.3 1.5 c -0.2 -0.1 -0.4 -0.1 -0.6 -0.4 c 0.6 -1 1.9 -0.9 2.8 -1.6 h -0.7 c -0.4 -0.2 -0.5 -0.5 -0.4 -0.8 c 0.2 -0.4 0.7 -0.5 1.1 -0.4 c 0.9 0.2 1.9 0.1 2.8 0.1 c 0.3 0 0.7 -0.3 1.2 -0.1 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_pressed-key" viewbox="0 0 39 30" name="illo_keypress_pressed-key"><path class="illo_component_bg" d="M 2 9.4 l 22.5 -7.9 l 13.3 14.6 l -0.2 4.7 l -24.4 8.5 L 1.5 13.8 Z"></path><path d="M 2.1 10.1 c 0.1 1.3 0.2 2.4 0.2 3.5 c -1.7 -1 -1.7 -3.1 -0.7 -4.5 c 0.3 -0.4 1 -0.4 1.5 -0.6 c 6.1 -2.3 12.1 -4.6 18.2 -6.9 c 0.5 -0.2 1 -0.3 1.4 -0.4 c 2 -0.7 3.3 0.8 4.4 1.9 c 3.1 3.3 6 6.8 9 10.2 c 0.7 0.8 1.4 1.7 2 2.5 c 0.2 0.2 0.1 0.6 0.1 1 c 0 1.1 0 2.2 -0.1 3.3 c 0 0.3 -0.4 0.5 -0.6 0.7 c -0.1 -0.2 -0.2 -0.5 -0.2 -0.7 v -2.5 c 0 -0.1 -0.3 -0.3 -0.4 -0.3 c -5.2 1.9 -10.5 3.8 -15.7 5.7 L 14 25.7 c -0.2 0.1 -0.4 0.4 -0.4 0.6 c 0 0.9 0.2 1.8 0.2 2.7 c 0 0.3 -0.3 0.6 -0.5 0.9 c -0.2 -0.2 -0.6 -0.5 -0.7 -0.7 c -0.1 -1.3 0 -2.7 -0.1 -4 c 0 -0.5 -0.5 -0.9 -0.8 -1.4 l -6.9 -9.6 c -0.9 -1.4 -1.7 -2.7 -2.7 -4.1 Z m 22.4 -8.6 c -0.5 0.2 -0.8 0.3 -1.2 0.5 c -6.7 2.5 -13.3 5 -20 7.5 c -0.1 0 -0.2 0.5 -0.1 0.6 c 1.9 2.5 3.9 4.8 5.7 7.3 c 1.6 2.3 2.8 4.8 4.2 7.2 c 0.1 0.1 0.5 0.2 0.7 0.2 c 1.2 -0.5 2.4 -1.2 3.6 -1.6 c 6.4 -2.2 12.7 -4.4 19.1 -6.6 c 0.6 -0.2 0.6 -0.4 0.2 -0.8 c -0.7 -0.7 -1.3 -1.4 -1.9 -2.1 C 31.5 9.8 28.3 6 25 2.1 c -0.2 -0.2 -0.3 -0.4 -0.5 -0.6 Z"></path><path d="M 22.5 17.9 c -1.3 -0.3 -2.3 -0.4 -3.3 -0.7 c -0.2 -0.1 -0.6 -0.7 -0.5 -0.8 c 0.2 -0.3 0.6 -0.5 1 -0.6 c 0.2 -0.1 0.4 0.1 0.6 0.1 h 0.9 c -0.2 -0.3 -0.3 -0.6 -0.5 -0.8 c -0.9 -1.1 -1.9 -2.2 -2.9 -3.3 c -0.2 -0.2 -0.1 -0.6 -0.2 -0.9 c 0.3 0 0.7 0 0.9 0.1 c 1.2 1.2 2.4 2.4 3.5 3.6 c 0.3 0.3 0.5 0.7 0.9 0 c 0.1 -0.2 0.5 -0.3 0.8 -0.4 c 0.1 0.3 0.3 0.6 0.3 0.9 c -0.1 0.7 -0.1 1.4 -0.4 2 c -0.2 0.4 -0.8 0.6 -1.1 0.8 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_fg-keys" viewbox="0 0 34 30" name="illo_keypress_fg-keys"><path class="illo_component_bg" d="M 1.5 10 l 0.8 7.5 s 11.3 12 11.6 11.9 s 19.6 -8 19.6 -8 l -0.5 -4.5 L 20.3 1.7 L 1.5 10 Z"></path><path d="M 14.1 28.8 c -0.2 -0.9 -0.5 -1.7 -0.7 -2.6 c -0.1 -0.3 -0.4 -0.5 -0.5 -0.7 c -0.1 -0.4 -0.2 -0.8 -0.5 -1.1 l -6.3 -8.7 c -1.2 -1.7 -2.6 -3.3 -4 -4.8 c 0.1 0.7 0.3 1.5 0.4 2.2 c 0.1 0.8 0.3 1.5 0.3 2.3 c 0 0.8 -0.1 1.6 -0.2 2.4 c -0.8 -0.9 -0.9 -1.8 -1 -2.8 c -0.2 -1.7 -0.3 -3.5 -0.5 -5.2 c 0 0 -0.1 0 -0.1 -0.1 v -0.1 c 0.2 -0.1 0.4 -0.2 0.6 -0.4 c 0 0 0 -0.1 -0.1 -0.1 c 0.3 -0.2 0.6 -0.3 0.9 -0.5 c 0.2 -0.1 0.4 -0.1 0.7 -0.2 c 2.2 -1 4.3 -2 6.5 -3 c 1.5 -0.7 3.1 -1.4 4.7 -2.1 c 1.7 -0.6 3.4 -1.3 5.1 -2.1 c 0.1 -0.1 0.3 -0.1 0.5 -0.2 c 1.1 0.5 2 1.2 2.9 2.2 c 1.5 1.7 3 3.4 4.4 5.1 c 1.6 1.9 3.2 3.9 4.8 5.9 c 0.2 0.2 0.4 0.5 0.6 0.7 c 0.8 0.7 0.9 1.8 0.9 2.7 c 0.1 1.1 0 2.1 0 3.4 c -1.1 -0.9 -0.6 -2 -0.9 -2.8 c -5.9 2.5 -11.9 5.1 -18 7.7 c -0.1 0.9 -0.3 1.9 -0.5 2.9 c 0.1 0 0 0 0 0 Z m 6.3 -26.7 C 14.3 4.6 8.5 7.7 2.3 9.8 c 0.5 0.4 1 0.9 1.6 1.4 c 2.5 2.4 4.7 5.1 6.6 8 c 1.1 1.6 2.3 3.2 3.4 4.8 c 0.1 0.1 0.3 0.2 0.6 0.4 c 6 -2.5 12 -5 18.2 -7.6 c -3 -3.6 -5.8 -7.1 -8.7 -10.7 c -0.1 0.3 -0.1 0.4 -0.1 0.3 c -0.9 -1.6 -2.2 -3 -3.5 -4.3 Z"></path><path d="M 14.7 13.4 c 1.8 -0.9 3.8 -1.8 5.7 -2.7 c 0.2 -0.1 0.6 -0.1 0.7 0.1 c 0.1 0.1 0.1 0.5 0 0.7 c -0.1 0.3 -0.4 0.5 -0.7 0.6 c -1.6 0.8 -3.1 1.5 -4.7 2.3 c -0.3 0.2 -0.6 0.3 -1.1 0.6 c 0.9 -0.1 1.7 -0.2 2.5 -0.3 c 0.1 0.2 0.3 0.3 0.6 0.7 c -0.4 0.3 -0.7 0.7 -1 0.7 c -1.2 0 -2.4 0 -3.6 -0.1 c -0.5 0 -1.2 0.2 -1.4 -0.9 c 0.6 -0.7 1.3 -1.5 2 -2.3 c 0.1 -0.1 0.5 -0.1 0.5 -0.1 c 0.4 0.2 0.4 0.5 0.5 0.7 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_finger" viewbox="0 0 24.9 37.5" name="illo_keypress_finger"><path class="illo_component_bg" d="M 9.4 0 L 0.7 34.9 l 0.7 1.6 h 1.9 l 6.7 -2.8 l 3.4 -2.6 l 3.4 -3.4 l 2.9 -4.9 l 4.8 -14.3 V 6.2 L 9.4 0 Z"></path><path d="M 9.8 0 c -1 4.7 -2 9.4 -3.1 14.1 s -2.5 9.3 -3.7 14 c -0.6 2.2 -1.1 4.4 -1.5 6.7 S 1.8 36.3 3 36 l 1 -0.3 c -2.4 -1.9 -1.8 -4.2 -1.2 -6.6 s 0.6 -1.8 0.8 -2.5 c -0.2 1.8 -0.4 3.8 -0.5 5.8 s 1.2 3 3 2.3 a 22.2 22.2 0 0 0 8.6 -5.6 a 29.3 29.3 0 0 0 5.6 -10 c 1.6 -4.7 3 -9.5 4.3 -13.9 c 0.5 3.3 -0.4 6.9 -1.6 10.5 s -3.2 9.2 -6.3 13 a 25 25 0 0 1 -5.7 5.1 a 41.3 41.3 0 0 1 -7.4 3.4 c -2.5 1 -4.1 -0.6 -3.4 -3.2 q 2.6 -10 5.3 -20 C 6.8 9.3 8.1 4.7 9.4 0 Z"></path></svg></div>
</div>
<div class="illustration illo_scroll-wheel" role="presentation">
<div class="illo_wrapper">
<svg class="illo_component illo_scroll-wheel_hand" name="illo_scroll-wheel_hand" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 111 57"><path d="M90.5 22.6c1.3.3 2.2 1.1 3 2.1 1 1.2 2 2.5 3.1 3.6 2.1 2.3 3.9 4.8 5.6 7.4.8 1.2 1.7 2.3 2.6 3.4l2.1 2.4c.4.4.2.7-.4.8-.5.1-.9.5-1.3.5-.8.1-1.6 0-2.4-.1-2-.5-3.9-1-5.8-1.6.9.5 1.8 1.1 2.8 1.8 2.1 1.5 4.2 3.2 6.2 4.7.1 0 .1.1.2.2.8.4 1.1 1.1.9 1.9-.2.8-.5 1.5-.7 2.2-.1.2 0 .4 0 .5-.1.8-.9.7-1.3.7l-5.4.3c-2.3.1-4.5.2-6.8.2-2.1.1-4.1.2-6.2.2-2.2.1-4.4.2-6.7.2-1.8.1-3.6.2-5.4.2-2.3.1-4.5.2-6.8.2-1.8.1-3.6.2-5.4.2-1.8.1-3.6.2-5.4.2-1.7.1-3.3.2-5 .2-1.8.1-3.5.2-5.3.2-1.8.1-3.5.2-5.3.2-2 .1-4 .2-6 .2-2.1.1-4.2.2-6.3.2-1.1 0-2.1.1-3.2.1-.7 0-.8-.4-.8-.9-.1-.4-.1-1.6-.1-2.7 0-.9.2-1.9.4-2.8.2-1.1.5-2.1.8-3.2-1-.2-2-.3-3.1-.5-2.8-.6-5.6-1-8.1-2.3-1.6-.9-3.2-2-4.6-3.2-1.8-1.4-3.5-3-5.3-4.5-.2-.1-.3-.4-.3-.6l3.9 3c1.6 1.3 3.3 2.5 4.9 3.7 1.9 1.4 4.1 2 6.4 2.5 2 .4 4 .8 6 1.1 2 .2 4.1.3 6.1.2 2.1-.1 4.2-.4 6.3-.7 2.1-.3 4.3-.5 6.4-.9 2.5-.4 4.9-.9 7.4-1.3 1.7-.3 3.4-.6 5.1-.7 1.9-.2 3.7-.2 5.6-.3 2.3-.1 4.6-.2 6.9-.4 2.1-.2 4.1-.5 6.2-.7.6-.1 1.1-.2 1.7-.4.9-.4 1-1.7.3-2.4-1.8-1.5-4-2.3-6.3-2.5-1.6-.2-3.2-.2-4.7-.4-2.1-.2-4.1-.3-6.2-.5-1.6-.2-3.2-.5-4.8-.8l-2.4-.3c-2.5-.1-4.9-.4-7.3-.9-.6-.1-.9-.4-1.3-.8-.4-.5-1-1-1.3-1.5-.5-.8-.3-1.5.3-2.1.1-.1.2-.3.4-.5-.2 1.6.9 3.2 2.3 3.8h.4l4.5-.9c.2 0 .4-.1.6-.2-.3-.1-.7-.1-1-.2v-.3c6.7-.6 13.3-1.3 20-1.9v.2c-.3.1-.6.1-1 .2 1.1.4 2.2.8 3.3 1.3l7.8 3.3c.9.4 1.8.7 2.7 1.1.1.1.4-.1.5-.1 1.3-.5 2.5-1 3.6-1.4-2-.8-3.9-1.9-5-4.6-1.6-.2-3.5-.5-5.4-.8 0 .1 0 .1-.1.2 2.9 1.6 5.7 3.2 8.6 4.9v.1c-.9-.3-1.9-.6-2.8-.9-2.1-.8-4-1.8-5.6-3.4-.7-.7-1.5-.9-2.4-1-2.1-.3-4.3-.7-6.3-1.3-1.7-.4-5.2-1.8-5.3-1.8-2.4.5 1-.3 1.8-.1 2.5.7 5 1.3 7.5 1.9 2.1.5 4.3.9 6 1.2-1.6-.9-3.6-1.9-5.5-3s-3.8-2.3-5.3-4c-1.3 0-4.4.1-7.5.2-3.1.1-2.6-.6.9-.7h3.9c2.2 0 4.3-.1 6.5-.1 1 0 2 0 3.1.1-2.1.2-4.1.4-6.2.6 5.6 3.9 11.5 7.2 18.2 9-.5-.1-.9-.2-1.4-.2-.5-.1-.9-.2-1.5-.1.7.6 1.3 1.3 2 1.9.6.6 1.4 1.1 2 1.7.4.4.7.5 1.3.5 1.4-.1 2.7.2 3.9.8 1.9 1 2.7 2.6 3.1 4.5.1.6.1 1.2.1 1.8 0 .5.2.7.6.8 1.9.6 3.9 1.3 5.8 1.9.9.2 1.9.5 2.8-.2-.6-.7-1.3-1.5-1.9-2.2-.6-.7-1.3-1.4-1.7-2.2-1.1-2.7-3.2-4.8-4.8-7.1-1-1.4-2.2-2.6-3.3-3.9-.6-.7-1.2-1.5-1.9-2.3-.6-.6-1.3-1.2-2-1.8.1-.2.2-.2.2-.3zm-41.7 9.2v.1c.6.1 1.3.2 1.9.3 1.4.1 2.9.2 4.3.4 2.4.3 4.8.7 7.2.9 1.8.2 3.5.3 5.3.5 1.5.1 3 .2 4.5.4 2.4.2 4.6 1 6.5 2.4.7.5 1.4 1.1 1.2 2-.2 1-.5 2.1-1.7 2.4-2 .4-4 .9-6.1 1.2-2.1.3-4.2.3-6.3.4-2.4.1-4.8.1-7.2.3-1.4.1-2.9.3-4.3.5-1.8.3-3.6.6-5.3.9-1.6.3-3.3.5-4.9.7-2 .3-4.1.6-6.1.8-1.3.2-2.5.2-3.8.4-2 .3-4 .2-6 0-.4 0-1 0-1.1.2-.4 1.1-.8 2.3-.9 3.5-.1 1.8.1 3.7.2 5.6 1.5-.1 2.9-.1 4.3-.2 1.9-.1 3.8-.2 5.7-.2 2.1-.1 4.2-.2 6.3-.2 1.5-.1 3-.2 4.6-.2 2.7-.1 5.5-.2 8.2-.4 1.5-.1 3.1-.2 4.6-.2 1.9-.1 3.8-.2 5.8-.2 1.8-.1 3.7-.2 5.5-.2 2.2-.1 4.4-.2 6.7-.2 2.1-.1 4.1-.2 6.2-.2 2.5-.1 4.9-.2 7.4-.2 1 0 1.9-.1 2.9-.1 2.3-.1 4.6-.2 6.9-.2h3.7c.3-.9.6-1.6.7-2.3.1-.4.1-1.1-.1-1.3-1.2-1.1-2.5-2.2-3.8-3.1-1.8-1.3-3.7-2.6-5.7-3.8-2.2-1.4-4.3-2.8-6.6-4-2.7-1.4-5.5-2.5-8.3-3.7-1.3-.5-2.5-1-3.8-1.5-2.6-.9-5.3-1.3-8-1.7-2.5-.4-4.9-.8-7.4-.7-1.7.1-3.4.1-5.1.2-1.5.1-3 .3-4.5.5-1.1-.2-2.3 0-3.6.2zm35.7 3c4 1.4 7.5 3.3 11.1 5.6-.1-.9-.1-1.6-.2-2.3-.2-1.1-.4-2.1-1.2-2.9-1.2-1.2-2.8-1.6-4.4-1.7-1.8-.1-3.5.4-5.3 1.3zm-9.6-3.7s-.1 0 0 0c-1.7-.9-3.3-1.7-4.9-2.5-.2-.1-.4-.1-.5-.1-2 .3-3.9.7-5.6 1 3.4.5 7.2 1.1 11 1.6z" /><path d="M90.5 22.6l-.1.1c-1.4-.9-2.8-1.8-4.2-2.8-1.8-1.4-3.5-3-5.3-4.6-1.9-1.6-3.9-3-6.1-4.2-1.9-1-3.8-2-5.7-3.1-1-.6-2.1-.6-3.1-.8-2.6-.6-5.2-1.2-7.8-1.7-1.3-.3-2.6-.5-4-.8-3.1-.5-6.2-1-9.3-1.6-1.3-.3-2.5 0-3.8 0-.3 0-.7-.1-1-.1-1.5.1-3 .3-4.5.5s-3 .5-4.5.7c-1.5.2-2.9.4-4.4.6-1.6.3-3.3.5-4.9.8-1.9.3-3.8.6-5.7 1-2.3.4-4.7.9-7 1.4-2 .4-4 .9-6 1.2-.6.3-1.3.3-2.1.4v-.2c.8-.2 1.5-.5 2.3-.7 4.6-1.1 9.2-2.1 13.8-3.1 2.9-.6 5.9-1 8.8-1.5 2.3-.4 4.7-.7 7.1-1 2.2-.3 4.4-.6 6.7-.8 1.2-.1 2.3 0 3.5 0 .7 0 1.5-.1 2.2 0 2.8.3 5.6.8 8.3 1.5 2.1.5 4.2.9 6.3 1.4h.1c.6.2 1.3.5 1.9.6 1.9.4 3.7.6 5.6 1 .9.2 2 .4 2.7.9.9.8 1.9 1 2.8 1.6 2.5 1.6 5.1 3.1 7.6 4.6.7.4 1.2 1.1 1.9 1.7l4.2 3.6c.7.6 1.4 1.3 2.1 1.9.4.6 1 1.1 1.6 1.5z" /></svg></p>
<div class="illo_component illo_scroll-wheel_finger">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 62 74"><path class="illo_component_bg" d="M1 12.8L30.3 1.6l9.1 15.2-1.2 9.5s.7 6.8 1.3 6.5c.6-.3-1.6.3-1.6.3h-2.6L32.6 31l-1.1-4.7.2-5-6.5-7.9L8.1 23.9 1 12.8z" /><path d="M30.6 1c1.1 1.8 2.2 3.7 3.2 5.5 1.4 2.6 2.9 5.2 4.8 7.6.3.4.5.9.8 1.4 0 .1 0 .1.1.2.3.4.5.8.8 1.2v.1c-.2.2-.4.3-.5.5-.2 1.1-.3 2.2-.4 3.2-.2 1.7-.5 3.3-.6 5-.1 2 0 4 .3 6 .2 1.1-.4 1.8-1.5 1.9-.6 0-1.2.1-1.7.2h-.5l-.3-.3c-2.3-1-3.6-2.7-3.9-5.2-.1-.6-.3-1.2-.4-1.8-.2-1.4-.4-2.9.1-4.3.1-.4 0-.8.7-.9v3.9c0 .8.1 1.5.1 2.3 0 .6 0 1.3.6 1.7.1.1.1.2.2.3.6 1.5 1.8 2.4 3.2 2.9.8.3 1.8.2 2.7.3-.1-.9-.3-1.6-.3-2.4-.1-1.2 0-2.4 0-3.6 0-.7.1-1.4.1-2.1.1-1.4.1-2.8.3-4.2.1-.9.2-1.8.3-2.8.1-.8-.2-1.5-.7-2.1-.6-.6-.9-1.3-1.3-2-.3-.6-.8-1.2-1.2-1.8-.4-.6-.9-1.1-1.2-1.8-.8-1.5-1.4-3-2.2-4.5-.6-1.1-1.3-2.1-1.9-3.1-.1-.1-.3-.2-.4-.1-1 .3-2 .7-2.9 1.1-.9.4-1.9.7-2.8 1.1L11.3 9.2c-2.2.8-4.5 1.6-6.7 2.5-1.1.4-2.3.9-3.4 1.4H.9v-.4c2.2-1.3 4.6-2.1 7-3 2.9-1.2 5.8-2.4 8.7-3.5 2.9-1.2 5.9-2.3 8.8-3.4 1.4-.5 2.7-1.2 4-1.8h1.2z" /><path d="M7.7 24.2c.1-.1.3-.2.4-.3 0-.1.1-.1.1-.2 2.1-1.3 4.1-2.6 6.2-3.8 3.2-1.9 6.6-3.6 9.6-5.7.4-.3.7-.5 1.1-.8.4-.3.8-.3 1.1.1 1 1.3 2.1 2.6 3 4 .8 1.1 1.4 2.2 2.1 3.4-.7.1-1-.3-1.3-.6-1.4-1.8-2.8-3.6-4.1-5.4-.1-.2-.2-.4-.4-.7-.6.5-1.1 1-1.7 1.3-1.9 1.3-3.8 2.6-5.8 3.7-2 1.2-4.1 2.2-6.1 3.2-1.1.6-2.3 1.1-3.5 1.6l-.9.3c.2 0 .2-.1.2-.1z" /><path class="illo_component_bg" d="M6.3 44.4l2.4 14 44.6 14.7h4.3l3.1-2.8-22.9-12.8-9.7-5.6-19.2-7.2z" /><path d="M52.8 73.9c-.8-.2-1.7-.5-2.5-.7-1-.3-2.2-.4-3.1-.9-1.3-.8-2.8-1.1-4.2-1.7-1.4-.5-3-.9-4.4-1.5-1.4-.5-2.7-1.1-4-1.6-3.1-1.1-6.3-2.1-9.5-2.9-1.9-.4-3.9-1.1-5.8-1.7-2.3-.8-4.5-1.7-6.8-2.5-1.7-.6-3.2-1.5-4.6-2.6 0 0-.1-.1-.2-.3.4.1.8 0 1 .2 2.2 1.3 4.7 2 7.2 2.9 3 1 6 2.1 9 3 1.8.6 3.6.8 5.3 1.4 2 .6 3.9 1.4 5.9 2.1 1.7.6 3.5 1.2 5.2 1.8 2.2.8 4.4 1.5 6.5 2.3 1.8.6 3.5 1.4 5.3 1.9.8.2 1.7 0 2.6 0 1.6 0 2.9-.8 4.2-1.7l.1.1c-.2.2-.3.6-.5.7-1.1.8-2.2 1.4-3.5 1.4-.1 0-.2.1-.3.2h-2.6c.1.1-.1.1-.3.1zM7.6 44.4c1 .3 2 .5 3 .8 2.9.7 5.7 1.8 8.4 3.1 1.9.9 4 1.6 6 2.4l2.7.9c.2.1.4.3.5.4.5.3.9.7 1.4 1 2 1.1 3.9 2.2 5.9 3.3 2.4 1.3 4.7 2.5 7.1 3.7 1.2.6 2.5 1.1 3.7 1.7.9.4 1.7 1 2.6 1.4 1.3.8 2.7 1.5 4 2.3 2.3 1.5 4.8 2.6 7.2 3.8.7.3 1.3.7 1.9 1.1l-.1.1c-.2.1-.4.1-.5.2-.3.2-.5.3-.8.5l-.1-.1c.1-.2.2-.4.3-.7-2.3-1.1-4.7-2.3-7.2-3.6v2c0 .1.2.2.3.3.6.2 1.1.4 1.7.6.2.1.4.2.5.3-1 0-2 0-2.9-.5-.5-.4-.2-.9-.3-1.4-.1-.6-.1-1.2-.2-1.8 0-.2-.3-.4-.5-.5-.9-.5-1.7-.9-2.6-1.4l-.1-.1c-1.3-.7-2.5-1.4-3.8-2-1.1-.6-2.3-1-3.4-1.6-1.5-.7-3.1-1.5-4.6-2.3-1.1-.6-2-1.2-3.1-1.9-2.2-1.3-4.4-2.7-6.6-3.9-.7-.4-1.5-.5-2.3-.7-1.9-.7-3.7-1.4-5.6-2.1-2.6-1-5.2-1.9-7.8-3-1.5-.7-3.1-1.1-4.7-1.5-.7-.2-1.3-.1-2 .2-.7.3-1.4.5-2.2.8-.1.1-.3.1-.6.1.5-.7 1.1-.9 1.7-1.2.3-.2.7-.3 1-.4.1 0 .1-.2.1-.3h2z" /></svg>
</div>
</p></div>
</div>
</div>
<p style="text-align: center">Animations by <a href="http://rachelnabors.com/">Rachel Nabors</a></p>
</div>
<p>Today, scrolling is still the most fundamental interaction on the web, and perhaps the most misunderstood. For instance, do you know the difference between the following scenarios?</p>
<ul>
<li>User scrolls with two fingers on a touch pad</li>
<li>User scrolls with one finger on a touch screen</li>
<li>User scrolls with a mouse wheel on a physical mouse</li>
<li>User clicks the sidebar and drags it up and down</li>
<li>User presses up, down, PageUp, PageDown, or spacebar keys on a keyboard</li>
</ul>
<p>If you ask the average web user (or even the average web developer!) they might tell you that these interactions are all equivalent. The truth is far more interesting.</p>
<p>As it turns out, all five of these input methods have vastly different characteristics, especially when it comes to performance and cross-browser behavior. Some of them (such as touch screen scrolling) are likely to be smooth even on a page with heavy JavaScript usage, whereas others (such as keyboard scrolling) will make the same page feel laggy and unresponsive. Furthermore, some kinds of scrolling can be slowed down by DOM event handlers, whereas others won’t. What’s going on here?</p>
<p>To answer that question, and to understand how to unlock the smoothest-possible scrolling on your website, let’s take a step back and understand how browsers deal with multithreading and input.</p>
<h2>The multithreaded web</h2>
<p>Conceptually, the web is a single-threaded environment. JavaScript blocks the DOM, and the DOM blocks JavaScript, because both are fighting over the same thread – frequently referred to as the “main thread” or “UI thread.”</p>
<p>For instance, if you were to add this (horrible) JavaScript snippet to your page, you’d immediately see jankiness across the entire user experience:</p>
<pre class="brush: jscript; title: ; notranslate">setInterval(() =&gt; {
var start = Date.now();
while (Date.now() - start &lt; 500) {/* wheeeee! */}
}, 1000);
</pre>
<p>While this JavaScript is spinning in a useless loop, buttons don’t work, form elements are unresponsive, and even animated GIFs grind to a halt – for all intents and purposes, the page is frozen. You can see this in action in <a href="http://bl.ocks.org/nolanlawson/raw/053d34c55b4f56abdf87b49946a8a2c9/">a simple demo</a>.</p>
<div class="gifv">
<iframe src='https://gfycat.com/ifr/oldfashionedcheapestuarinecrocodile' frameborder='0' scrolling='no' width='500' height='281.25' allowfullscreen></iframe>
</div>
<p>Furthermore, if you try to scroll with the keyboard up/down arrows, the page remains predictably stuck until the JavaScript stops running. All of this is strong evidence for our view of the web as a single-threaded environment.</p>
<p>There’s a curious anomaly, though: if you try to scroll using touch screen scrolling, the page happily moves up and down, even while JavaScript is blocking nearly everything else on the page. This also works for touch pad scrolling, mouse wheel scrolling, and click-and-drag scrolling (depending on your browser).</p>
<p>Somehow, certain scroll actions can manipulate the page state, even while everything else – buttons, input, GIFs – are totally frozen. How can we square this with our theory of the single-threaded web?</p>
<div class="illustration illo_keypress">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_bg-keys" viewbox="0 0 68 30" name="illo_keypress_bg-keys"><path d="M 11.7 18.5 v 3 c -1.3 -1.3 -0.7 -2.8 -0.9 -4.2 C 8.3 13.8 5 11 2.2 7.6 c 0.1 1.5 0.5 2.9 0.3 4.4 c -1.1 -1.4 -1 -3 -1.2 -4.7 c -0.2 0 -0.5 -0.2 -0.2 -0.8 C 8.2 4.4 15.5 2.3 23 1 c 4 2.4 7.3 5.8 11 8.5 c -0.1 2.4 -0.2 4.7 -0.3 7 c -0.2 0.2 -0.4 0.2 -0.8 0 v -5.8 c -7.3 2.1 -14.2 4.9 -21.2 7.8 Z m 0 -1.1 c 6.5 -3.2 13.2 -5.7 20.2 -7.8 c -3.5 -2.7 -6.8 -5.5 -10.4 -8 C 15.3 3.9 8.8 5 2.3 7.1 c 1.3 0.7 1.9 1.9 2.9 2.7 c 1.7 1.4 3.4 2.9 4.8 4.6 c 0.7 0.9 1.6 1.7 1.7 3 Z M 51.8 29.2 c -0.4 -1.2 -1 -2.3 -1 -3.4 c 0 -1.5 -1.3 -2.2 -2.1 -3.2 c -1.4 -1.7 -2.8 -3.4 -4.5 -4.9 c -2 -1.8 -4 -3.4 -6 -5.2 c -0.3 -0.2 -0.5 -0.5 -0.9 -0.9 v 5.3 c -0.3 0.3 -0.5 0.2 -0.8 0.1 v -5.8 c 0.6 -0.8 1.6 -0.9 2.5 -1.1 c 2.4 -0.7 4.9 -1.1 7.2 -1.9 c 1.8 -0.7 3.7 -1.1 5.6 -1.6 c 0.3 -0.1 0.5 -0.1 0.8 0 c 5.5 2.8 10.3 6.6 15 10.5 c 0.1 2.2 -0.2 4.3 -0.5 6.5 c -0.7 -1.1 -0.9 -3.4 -0.5 -5.2 c -4.9 2.2 -9.9 4.2 -15 6.2 c 0.4 1.5 0.6 3 0.2 4.6 Z M 38.1 11.4 C 43 15.2 47.6 18.9 51 24 c 5.3 -2.3 10.5 -4.6 16.1 -6.2 c -4.4 -4.5 -9.8 -7.2 -14.8 -10.5 c -4.8 1.4 -9.4 3 -14.2 4.1 Z"></path><path d="M 19.3 6.8 h -1.8 c 0.8 1 1.6 2 2.3 3 v 0.6 c -0.1 0.1 -0.3 0.2 -0.6 0.4 h -0.4 c -1.1 -0.9 -1.6 -2.2 -2.7 -3 c -0.2 0.4 0 1 -0.6 1.3 c -0.5 -0.2 -0.6 -0.6 -0.6 -1 c 0 -0.5 -0.1 -0.9 -0.2 -1.3 c -0.2 -0.9 0.2 -1.3 1.1 -1.1 c 0.7 0.1 1.3 0.2 1.9 0.5 c 0.5 0.1 0.9 0.3 1.6 0.6 Z M 55.8 13 c 0.2 1 -1.2 3.5 -2.1 3.7 c -0.6 -0.7 0.1 -1.3 0.2 -2 c -1.4 0.5 -2.8 1.1 -4.3 1.5 c -0.2 -0.1 -0.4 -0.1 -0.6 -0.4 c 0.6 -1 1.9 -0.9 2.8 -1.6 h -0.7 c -0.4 -0.2 -0.5 -0.5 -0.4 -0.8 c 0.2 -0.4 0.7 -0.5 1.1 -0.4 c 0.9 0.2 1.9 0.1 2.8 0.1 c 0.3 0 0.7 -0.3 1.2 -0.1 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_pressed-key" viewbox="0 0 39 30" name="illo_keypress_pressed-key"><path class="illo_component_bg" d="M 2 9.4 l 22.5 -7.9 l 13.3 14.6 l -0.2 4.7 l -24.4 8.5 L 1.5 13.8 Z"></path><path d="M 2.1 10.1 c 0.1 1.3 0.2 2.4 0.2 3.5 c -1.7 -1 -1.7 -3.1 -0.7 -4.5 c 0.3 -0.4 1 -0.4 1.5 -0.6 c 6.1 -2.3 12.1 -4.6 18.2 -6.9 c 0.5 -0.2 1 -0.3 1.4 -0.4 c 2 -0.7 3.3 0.8 4.4 1.9 c 3.1 3.3 6 6.8 9 10.2 c 0.7 0.8 1.4 1.7 2 2.5 c 0.2 0.2 0.1 0.6 0.1 1 c 0 1.1 0 2.2 -0.1 3.3 c 0 0.3 -0.4 0.5 -0.6 0.7 c -0.1 -0.2 -0.2 -0.5 -0.2 -0.7 v -2.5 c 0 -0.1 -0.3 -0.3 -0.4 -0.3 c -5.2 1.9 -10.5 3.8 -15.7 5.7 L 14 25.7 c -0.2 0.1 -0.4 0.4 -0.4 0.6 c 0 0.9 0.2 1.8 0.2 2.7 c 0 0.3 -0.3 0.6 -0.5 0.9 c -0.2 -0.2 -0.6 -0.5 -0.7 -0.7 c -0.1 -1.3 0 -2.7 -0.1 -4 c 0 -0.5 -0.5 -0.9 -0.8 -1.4 l -6.9 -9.6 c -0.9 -1.4 -1.7 -2.7 -2.7 -4.1 Z m 22.4 -8.6 c -0.5 0.2 -0.8 0.3 -1.2 0.5 c -6.7 2.5 -13.3 5 -20 7.5 c -0.1 0 -0.2 0.5 -0.1 0.6 c 1.9 2.5 3.9 4.8 5.7 7.3 c 1.6 2.3 2.8 4.8 4.2 7.2 c 0.1 0.1 0.5 0.2 0.7 0.2 c 1.2 -0.5 2.4 -1.2 3.6 -1.6 c 6.4 -2.2 12.7 -4.4 19.1 -6.6 c 0.6 -0.2 0.6 -0.4 0.2 -0.8 c -0.7 -0.7 -1.3 -1.4 -1.9 -2.1 C 31.5 9.8 28.3 6 25 2.1 c -0.2 -0.2 -0.3 -0.4 -0.5 -0.6 Z"></path><path d="M 22.5 17.9 c -1.3 -0.3 -2.3 -0.4 -3.3 -0.7 c -0.2 -0.1 -0.6 -0.7 -0.5 -0.8 c 0.2 -0.3 0.6 -0.5 1 -0.6 c 0.2 -0.1 0.4 0.1 0.6 0.1 h 0.9 c -0.2 -0.3 -0.3 -0.6 -0.5 -0.8 c -0.9 -1.1 -1.9 -2.2 -2.9 -3.3 c -0.2 -0.2 -0.1 -0.6 -0.2 -0.9 c 0.3 0 0.7 0 0.9 0.1 c 1.2 1.2 2.4 2.4 3.5 3.6 c 0.3 0.3 0.5 0.7 0.9 0 c 0.1 -0.2 0.5 -0.3 0.8 -0.4 c 0.1 0.3 0.3 0.6 0.3 0.9 c -0.1 0.7 -0.1 1.4 -0.4 2 c -0.2 0.4 -0.8 0.6 -1.1 0.8 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_fg-keys" viewbox="0 0 34 30" name="illo_keypress_fg-keys"><path class="illo_component_bg" d="M 1.5 10 l 0.8 7.5 s 11.3 12 11.6 11.9 s 19.6 -8 19.6 -8 l -0.5 -4.5 L 20.3 1.7 L 1.5 10 Z"></path><path d="M 14.1 28.8 c -0.2 -0.9 -0.5 -1.7 -0.7 -2.6 c -0.1 -0.3 -0.4 -0.5 -0.5 -0.7 c -0.1 -0.4 -0.2 -0.8 -0.5 -1.1 l -6.3 -8.7 c -1.2 -1.7 -2.6 -3.3 -4 -4.8 c 0.1 0.7 0.3 1.5 0.4 2.2 c 0.1 0.8 0.3 1.5 0.3 2.3 c 0 0.8 -0.1 1.6 -0.2 2.4 c -0.8 -0.9 -0.9 -1.8 -1 -2.8 c -0.2 -1.7 -0.3 -3.5 -0.5 -5.2 c 0 0 -0.1 0 -0.1 -0.1 v -0.1 c 0.2 -0.1 0.4 -0.2 0.6 -0.4 c 0 0 0 -0.1 -0.1 -0.1 c 0.3 -0.2 0.6 -0.3 0.9 -0.5 c 0.2 -0.1 0.4 -0.1 0.7 -0.2 c 2.2 -1 4.3 -2 6.5 -3 c 1.5 -0.7 3.1 -1.4 4.7 -2.1 c 1.7 -0.6 3.4 -1.3 5.1 -2.1 c 0.1 -0.1 0.3 -0.1 0.5 -0.2 c 1.1 0.5 2 1.2 2.9 2.2 c 1.5 1.7 3 3.4 4.4 5.1 c 1.6 1.9 3.2 3.9 4.8 5.9 c 0.2 0.2 0.4 0.5 0.6 0.7 c 0.8 0.7 0.9 1.8 0.9 2.7 c 0.1 1.1 0 2.1 0 3.4 c -1.1 -0.9 -0.6 -2 -0.9 -2.8 c -5.9 2.5 -11.9 5.1 -18 7.7 c -0.1 0.9 -0.3 1.9 -0.5 2.9 c 0.1 0 0 0 0 0 Z m 6.3 -26.7 C 14.3 4.6 8.5 7.7 2.3 9.8 c 0.5 0.4 1 0.9 1.6 1.4 c 2.5 2.4 4.7 5.1 6.6 8 c 1.1 1.6 2.3 3.2 3.4 4.8 c 0.1 0.1 0.3 0.2 0.6 0.4 c 6 -2.5 12 -5 18.2 -7.6 c -3 -3.6 -5.8 -7.1 -8.7 -10.7 c -0.1 0.3 -0.1 0.4 -0.1 0.3 c -0.9 -1.6 -2.2 -3 -3.5 -4.3 Z"></path><path d="M 14.7 13.4 c 1.8 -0.9 3.8 -1.8 5.7 -2.7 c 0.2 -0.1 0.6 -0.1 0.7 0.1 c 0.1 0.1 0.1 0.5 0 0.7 c -0.1 0.3 -0.4 0.5 -0.7 0.6 c -1.6 0.8 -3.1 1.5 -4.7 2.3 c -0.3 0.2 -0.6 0.3 -1.1 0.6 c 0.9 -0.1 1.7 -0.2 2.5 -0.3 c 0.1 0.2 0.3 0.3 0.6 0.7 c -0.4 0.3 -0.7 0.7 -1 0.7 c -1.2 0 -2.4 0 -3.6 -0.1 c -0.5 0 -1.2 0.2 -1.4 -0.9 c 0.6 -0.7 1.3 -1.5 2 -2.3 c 0.1 -0.1 0.5 -0.1 0.5 -0.1 c 0.4 0.2 0.4 0.5 0.5 0.7 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_keypress_finger" viewbox="0 0 24.9 37.5" name="illo_keypress_finger"><path class="illo_component_bg" d="M 9.4 0 L 0.7 34.9 l 0.7 1.6 h 1.9 l 6.7 -2.8 l 3.4 -2.6 l 3.4 -3.4 l 2.9 -4.9 l 4.8 -14.3 V 6.2 L 9.4 0 Z"></path><path d="M 9.8 0 c -1 4.7 -2 9.4 -3.1 14.1 s -2.5 9.3 -3.7 14 c -0.6 2.2 -1.1 4.4 -1.5 6.7 S 1.8 36.3 3 36 l 1 -0.3 c -2.4 -1.9 -1.8 -4.2 -1.2 -6.6 s 0.6 -1.8 0.8 -2.5 c -0.2 1.8 -0.4 3.8 -0.5 5.8 s 1.2 3 3 2.3 a 22.2 22.2 0 0 0 8.6 -5.6 a 29.3 29.3 0 0 0 5.6 -10 c 1.6 -4.7 3 -9.5 4.3 -13.9 c 0.5 3.3 -0.4 6.9 -1.6 10.5 s -3.2 9.2 -6.3 13 a 25 25 0 0 1 -5.7 5.1 a 41.3 41.3 0 0 1 -7.4 3.4 c -2.5 1 -4.1 -0.6 -3.4 -3.2 q 2.6 -10 5.3 -20 C 6.8 9.3 8.1 4.7 9.4 0 Z"></path></svg></div>
</div>
<h1>A tale of two threads</h1>
<p>As it turns out, the whole “browsers are single-threaded” story is largely true, but there are important exceptions. Scrolling, in all its various flavors, is one of those exceptions.</p>
<p>Over the years, browser vendors have recognized that offloading work to background threads can yield enormous improvements to smoothness and responsiveness. Scrolling, being so important to the core user experience of every browser, was quickly identified as a ripe target for such optimizations. Nowadays, every major browser engine (Blink, EdgeHTML, Gecko, WebKit) supports off-main-thread scrolling to one degree or another (with Firefox being the most recent member of the club, <a href="https://hacks.mozilla.org/2016/02/smoother-scrolling-in-firefox-46-with-apz/">as of Firefox 46</a>).</p>
<p>With off-thread scrolling, even a noisy page will appear smooth as you scroll through it, because all scrolling is handled on a separate thread. It’s only when you try to interact with the page through some non-scrolling mechanism – tapping a button, typing into an input, clicking a link – that the façade fades away and the parlor trick is revealed for what it is. (Considering how well it works, though, it’s a great trick!)</p>
<p>There is a tradeoff with asynchronous scrolling, however, which is a common effect called <a href="http://www.masonchang.com/blog/2014/3/2/wow-such-checkerboard">checkerboarding</a>, so named because of the way it originally appeared on Safari for iOS (as gray-and-white checkers). In most modern browsers, it manifests as a blank space that appears when you’ve scrolled faster than the browser can paint. This isn’t perfect, but it’s a worthy tradeoff compared to blocked, jerky, or unresponsive scrolling.</p>
<div class="gifv">
<iframe src='https://gfycat.com/ifr/sarcasticspeedyicelandgull' frameborder='0' scrolling='no' width='500' height='281.25' allowfullscreen></iframe>
</div>
<p>Unfortunately, it’s not always easy to move scrolling to a background thread. Browsers can only do this if the host operating system allows for concurrent input, and it can vary from device to device. In particular, keyboard input is not as optimized as input from mouse or touch devices, ultimately leading to laggier keyboard scrolling across browsers.</p>
<p>A little history is instructive here. When operating systems like Windows and macOS were first designed, one thread was all you got, and so there was little foresight to allow for concurrent input. It was only when multi-core machines started to appear that OSes began to retro-fit concurrency into their design.</p>
<p>So, in the same way that vestigial organs can reveal an animal’s evolutionary history, the single-threaded origin of operating systems starts to peek through the seams when you look at scrolling input across the web. It’s only if the host operating system allows for concurrent input – from a mouse, keyboard, or other device – that browsers can efficiently optimize scrolling to be unaffected by long-running JavaScript operations that hog the main thread.</p>
<p>On the Microsoft Edge team, though, we’ve been making strides to ensure that scrolling remains smooth and responsive, regardless of the scrolling method you prefer. As of EdgeHTML 14 (which shipped in the Windows 10 Anniversary Update), we support off-thread scrolling for the following input methods:</p>
<ul>
<li>Single-finger, touchscreen</li>
<li>Two-finger, touchpad</li>
<li>Mouse wheel</li>
<li>Sidebar</li>
</ul>
<p>If you compare Edge to other desktop browsers, you’ll find that it’s the only one to support asynchronous sidebar scrolling  – i.e. clicking-and-dragging the scroll handle, or clicking on the trackbar or arrows. (In fact, this is a feature we quietly introduced in the Anniversary Update!)</p>
<p>Testing on Windows 10 (14393, Surface Book) and macOS Sierra (10.12, MacBook Air), we can derive the following results:</p>
<table width="624">
<tbody>
<tr>
<td width="104"></td>
<td width="104">Two-finger trackpad</td>
<td width="104">Touch</td>
<td width="104">Mouse wheel</td>
<td width="104">Sidebar</td>
<td width="104">Keyboard</td>
</tr>
<tr>
<td width="104">Edge 14 (Windows)</td>
<td width="104">Y</td>
<td width="104">Y</td>
<td width="104">Y</td>
<td width="104">Y</td>
<td width="104">N</td>
</tr>
<tr>
<td width="104">Chrome 56 (Windows)</td>
<td width="104">Y</td>
<td width="104">Y</td>
<td width="104">Y</td>
<td width="104">N</td>
<td width="104">N</td>
</tr>
<tr>
<td width="104">Firefox 51 (Windows)</td>
<td width="104">N</td>
<td width="104">N</td>
<td width="104">N</td>
<td width="104">N</td>
<td width="104">N</td>
</tr>
<tr>
<td width="104">Chrome 56 (MacOS)</td>
<td width="104">Y</td>
<td width="104">N/A</td>
<td width="104">Y</td>
<td width="104">N</td>
<td width="104">N</td>
</tr>
<tr>
<td width="104">Firefox 51 (MacOS)</td>
<td width="104">Y</td>
<td width="104">N/A</td>
<td width="104">Y</td>
<td width="104">N</td>
<td width="104">N</td>
</tr>
<tr>
<td width="104">Safari 10.1 (MacOS)</td>
<td width="104">Y</td>
<td width="104">N/A</td>
<td width="104">Y</td>
<td width="104">N</td>
<td width="104">N</td>
</tr>
</tbody>
</table>
<p>As this table demonstrates*, scrolling performance can vary dramatically from browser to browser, and even from OS to OS. If you’re only testing on one browser with one scrolling method, then you might be getting a very narrow view of your site’s performance as it’s actually experienced by users!</p>
<p>Overall, though, it should be clear that scrolling has a special place on the web, and browsers have worked very hard to make sure that scrolling is snappy and responsive. However, there are subtle ways that a web developer can inadvertently disable a browser’s built-in optimizations. Let’s take a look at how web developers can influence browser scrolling, for good and bad.</p>
<div class="illustration illo_1finger-scroll">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_1finger-scroll_screen" viewbox="0 0 63 90" name="illo_1finger-scroll_screen"><path class="illo_component_bg" d="M 16.5 1.7 l 1.5 -0.5 l 43.3 1.5 l 0.2 1.1 l -17.9 85.5 h -1.2 L 1.7 84.9 Z"></path><path d="M 62.1 3.4 c -0.2 1.1 -0.4 2.1 -0.6 3.2 c -0.4 2 -0.7 4 -1 5.9 l -1.2 6 c -1 4.5 -2.1 9 -3.1 13.6 c -1.2 5.2 -2.3 10.5 -3.5 15.7 c -0.8 3.5 -1.5 7 -2.2 10.5 c -0.5 2.5 -1 5.1 -1.4 7.6 c -0.7 3.8 -1.4 7.6 -2.2 11.4 c -0.4 2.2 -1 4.3 -1.5 6.5 c -0.4 1.7 -0.8 3.5 -1.2 5.2 c 0 0.2 -0.2 0.4 -0.3 0.4 c -0.8 0.4 -1.6 0.4 -2.5 0.3 c -0.6 -0.1 -1.2 -0.2 -1.8 -0.2 l -6 -0.6 c -1.7 -0.2 -3.4 -0.3 -5.1 -0.5 c -1.7 -0.2 -3.3 -0.4 -4.9 -0.6 c -1.4 -0.1 -2.8 -0.2 -4.2 -0.4 c -1.4 -0.1 -2.9 -0.3 -4.3 -0.5 c -1.3 -0.1 -2.6 -0.2 -3.9 -0.4 c -1.5 -0.2 -3.1 -0.4 -4.6 -0.6 c -1.3 -0.2 -2.7 -0.3 -4 -0.5 c -0.5 -0.1 -1.1 -0.2 -1.6 -0.4 c -0.1 0 0 -0.3 -0.1 -0.4 c 0.7 0 0.5 -0.7 0.6 -1 c 0.5 -2.4 0.8 -4.8 1.3 -7.2 c 0.6 -3.1 1.2 -6.1 1.9 -9.2 c 0.5 -2.6 1 -5.1 1.5 -7.7 c 0.4 -2.2 0.8 -4.4 1.1 -6.5 c 0.4 -2.3 0.8 -4.5 1.2 -6.8 c 0.4 -2.2 0.7 -4.5 1.1 -6.7 c 0.3 -1.8 0.6 -3.7 1 -5.5 c 0.4 -2.3 0.8 -4.5 1.3 -6.8 c 0.5 -2.2 1 -4.4 1.4 -6.6 c 0.5 -2.5 1.1 -5.1 1.5 -7.6 c 0.4 -2.4 0.7 -4.8 1.1 -7.2 c 0.2 -1.4 0.3 -2.7 0.5 -4.1 c 0 -0.4 0.2 -0.6 0.6 -0.3 h 0.2 C 17.8 0.8 18.4 1 19 1 h 7.8 c 1.9 0 3.8 0.1 5.7 0.1 c 1.9 0.1 3.7 0.2 5.6 0.2 c 1.7 0.1 3.5 0.2 5.2 0.2 c 1.6 0.1 3.2 0.2 4.8 0.2 c 1.7 0.3 3.3 0.3 5 0.4 c 1.3 0.1 2.6 0.1 3.9 0.2 c 1.5 0.1 2.9 0.2 4.4 0.4 c 0.4 0.1 0.7 0.3 0.7 0.7 Z M 17.8 1.8 c -0.4 -0.2 -0.8 -0.2 -0.8 0.4 c -0.1 1.3 -0.2 2.6 -0.4 3.9 c -0.3 2.4 -0.6 4.8 -1 7.2 c -0.5 3 -1.1 6 -1.7 9 c -0.6 3.2 -1.4 6.4 -2 9.6 c -0.7 3.8 -1.4 7.7 -2.1 11.5 c -0.6 3.1 -1.1 6.3 -1.7 9.4 c -0.4 2.5 -0.8 5 -1.3 7.5 C 6 64.5 5 68.6 4.2 72.8 c -0.8 3.7 -1.5 7.4 -2.2 11.1 c 0 0.8 0 0.8 0.7 0.9 l 2.7 0.3 c 1.4 0.1 2.7 0.3 4.1 0.5 c 1 0.1 1.9 0.2 2.9 0.3 c 1.7 0.2 3.3 0.3 5 0.5 c 1.1 0.1 2.1 0.2 3.2 0.3 c 1.5 0.1 3.1 0.3 4.6 0.5 c 1.4 0.1 2.8 0.2 4.3 0.4 c 1.3 0.1 2.7 0.3 4 0.5 c 1.3 0.1 2.6 0.2 3.9 0.4 c 1.9 0.3 3.9 0.6 5.8 0.9 c 0.1 0 0.4 -0.2 0.4 -0.3 c 0.3 -1.5 0.7 -3 1 -4.5 l 3 -14.1 c 0.4 -1.7 0.6 -3.4 1 -5.1 c 0.6 -3 1.1 -5.9 1.7 -8.9 c 0.7 -3.7 1.5 -7.3 2.3 -11 c 0.7 -3.4 1.5 -6.7 2.2 -10 c 1.1 -5 2.3 -9.9 3.4 -14.9 c 0.6 -2.5 1.1 -5 1.6 -7.5 c 0.6 -3 1.1 -5.9 1.7 -8.9 c 0.1 -0.5 0 -0.5 -0.4 -0.6 c -2.4 0 -4.8 -0.1 -7.2 -0.1 c -1.7 0 -3.5 -0.1 -5.2 -0.2 c -2.4 -0.1 -4.8 -0.2 -7.2 -0.4 c -1.6 -0.1 -3.3 -0.2 -4.9 -0.2 c -1.9 -0.1 -3.9 -0.2 -5.8 -0.2 c -1.7 -0.5 -3.3 -0.5 -4.9 -0.6 c -2.7 0 -5.4 -0.1 -8.1 -0.1 Z"></path></svg></p>
<div class="illo_component illo_1finger-scroll_fingers"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 43 118" name="illo_1finger-scroll_fingers"><path class="illo_component_bg" d="M 8.8 47.7 l 8.5 -17 L 31.8 8.1 l 6.5 -6.8 H 40 l 1.7 5 l -4.2 12.8 l -19.8 37.5 Z"></path><path class="illo_1finger-scroll_finger_1" d="M 27.5 14 c 1.3 -1.8 2.5 -3.7 3.9 -5.3 C 33.3 6.4 35.3 4 37.5 2 C 39 0.6 40.2 0.8 41 2.7 c 0.8 1.8 0.9 3.6 0.5 5.5 c -1 4.6 -2.9 8.9 -5 13.1 c -1.2 2.4 -2.4 4.9 -3.6 7.4 c -1.3 2.7 -2.5 5.5 -3.9 8.3 c -1.8 3.5 -3.5 7 -5.4 10.5 c -1.5 2.7 -3.2 5.4 -4.9 8 c -0.3 0.5 -0.6 0.9 -0.9 1.3 l -0.2 -0.2 c 0.7 -1.4 1.5 -2.8 2.2 -4.2 c 0.8 -1.4 1.5 -2.9 2.3 -4.3 c 1 -1.8 2 -3.6 2.9 -5.4 c 0.9 -1.7 1.7 -3.5 2.6 -5.3 c 0.6 -1.4 1.3 -2.7 1.9 -4.1 c 1.1 -2.4 2.2 -4.7 3.3 -7.1 c 0.9 -1.9 1.9 -3.7 2.7 -5.6 c 1.2 -2.5 2.4 -5.1 3.4 -7.7 c 0.7 -1.8 1.2 -3.8 1.7 -5.7 c 0.4 -1.5 0.1 -3.1 -0.5 -4.5 c -0.5 -1.1 -1.2 -1.2 -2 -0.4 c -0.9 0.8 -1.7 1.7 -2.5 2.6 c -1.2 1.4 -2.5 2.8 -3.6 4.3 c -2.6 3.7 -5.3 7.4 -7.7 11.2 c -2.5 3.9 -4.7 7.9 -7 11.9 c -1.6 2.8 -3.1 5.6 -4.7 8.5 c -1.1 2.1 -2.2 4.2 -3.3 6.2 c -0.1 0.2 -0.3 0.5 -0.6 0.6 C 14.1 36 20.2 24.7 27.4 14 c 0 0.1 0.1 0 0.1 0 Z"></path><path class="illo_component_bg" d="M 5.6 115.1 l 14.8 1.7 l -0.6 -5.4 l -2.5 -7.6 l -1.8 -7.5 h 11.9 l 12 -7.8 l 1.8 -3 l 0.5 -3.4 V 80 l -10.4 2.6 s -17.6 1.6 -17.4 1.6 c 0.3 0 -11.8 -1.1 -11.8 -1.1 l -0.4 0.7 l 3 15.8 l 0.9 15.5 Z"></path><path class="illo_1finger-scroll_finger_2" d="M 1.8 82.6 c 0.6 0 1.2 -0.1 1.8 -0.1 c 0.7 0 1.3 0.1 2 0.1 c 1.5 0.1 2.9 0.4 4.4 0.5 c 2.1 0.1 4.1 0.3 6.2 0.2 c 2.4 0 4.7 -0.1 7.1 -0.4 c 2.9 -0.3 5.8 -0.6 8.6 -1.1 c 3 -0.6 6 -1.4 8.9 -2.1 c 0.2 -0.1 0.4 -0.2 0.7 -0.4 h 0.4 c 0.3 0.4 0.6 0.8 0.8 1.2 v 2.8 c -0.1 0.1 -0.2 0.2 -0.2 0.3 c -0.6 2.1 -1.5 4.1 -3 5.7 l -0.1 0.1 c -2.4 2.3 -5.2 4 -8 5.7 c -1.6 0.9 -3.3 1.6 -5.2 1.6 c -1.6 0.1 -3.3 0.2 -4.9 0.2 h -5.1 c 0.4 1.4 0.8 2.7 1.3 3.9 c 1.2 3 2 6.1 2.7 9.2 c 0.4 1.9 0.7 3.8 0.6 5.7 c 0 0.5 0 1 -0.1 1.5 h -0.2 c -0.1 -0.4 -0.3 -0.9 -0.4 -1.3 c -0.4 -1.9 -0.9 -3.9 -1.3 -5.8 c -0.3 -1.3 -0.5 -2.7 -0.9 -4 c -0.5 -1.7 -1 -3.5 -1.8 -5.1 c -0.7 -1.3 -0.9 -2.7 -1.4 -4.1 c -0.2 -0.6 -0.4 -1.2 -0.6 -1.9 c -0.1 -0.3 -0.2 -0.7 0.2 -0.9 c 0.4 -0.2 0.7 0.1 0.8 0.5 c 0.2 0.6 0.7 0.7 1.2 0.7 c 1.8 0.1 3.6 0.1 5.4 0.1 c 1.8 0 3.6 0 5.4 -0.3 c 1.3 -0.2 2.6 -0.7 3.7 -1.4 c 2 -1.2 4 -2.5 5.9 -3.9 c 2.7 -1.8 4.2 -4.5 4.8 -7.6 c 0.1 -0.7 0 -1.4 0 -2.1 c -1.7 0.5 -3.2 1 -4.7 1.3 c -2.5 0.5 -5 1 -7.6 1.4 c -2 0.3 -4.1 0.4 -6.1 0.6 c -1.5 0.1 -3.1 0.2 -4.6 0.2 c -1.9 0.1 -3.7 0.2 -5.6 0.1 c -1.6 0 -3.2 -0.3 -4.8 -0.4 c -1.2 -0.1 -2.4 -0.3 -3.7 -0.4 c -0.9 -0.1 -1.7 -0.2 -2.6 -0.3 h -0.7 c 0.1 -0.2 0.2 -0.3 0.2 -0.5 l 0.5 0.5 Z"></path><path class="illo_1finger-scroll_finger_2" d="M 1 83.4 c 0.2 -0.1 0.5 -0.2 0.6 -0.3 c 3.9 10.4 4.5 21.1 4.2 31.9 h -0.2 c -0.1 -0.5 -0.1 -0.9 -0.2 -1.4 c -0.2 -1.9 -0.3 -3.9 -0.5 -5.8 c -0.1 -1.2 -0.1 -2.4 -0.3 -3.6 c -0.1 -1.5 -0.3 -3.1 -0.5 -4.6 c -0.1 -1.1 -0.2 -2.3 -0.4 -3.4 c -0.2 -1.6 -0.4 -3.3 -0.8 -4.9 c -0.4 -2.1 -1 -4.3 -1.4 -6.4 c -0.1 -0.5 -0.3 -0.8 -0.7 -1 c 0.2 -0.1 0.2 -0.3 0.2 -0.5 Z"></path></svg></div>
</div>
</div>
<h1>How event listeners interfere with scrolling</h1>
<p>Off-thread scrolling represents a great gain in efficiency – scrolling and JavaScript are completely decoupled, allowing them to work in parallel without blocking each other.</p>
<p>Anyone who’s been building web pages for a while, though, probably knows how to introduce a choke point between JavaScript and scrolling:</p>
<pre class="brush: jscript; title: ; notranslate">window.addEventListener(“wheel”, function (e) {
e.preventDefault(); // oh no you don’t!
});</pre>
<p>When we attach a “wheel” listener that calls <code>event.preventDefault()</code>, it will 100% block scrolling, for both wheel and touch pad scrolling. And obviously, if scrolling is blocked, then off-thread scrolling is also blocked.</p>
<p>What’s less obvious, though, is the impact in this case:</p>
<pre class="brush: jscript; title: ; notranslate">window.addEventListener(“wheel”, function (e) {
console.log(‘wheel!’);
// innocent listener, not calling preventDefault()
});</pre>
<p>You might naïvely think that a function that doesn’t call <code>preventDefault()</code> can’t block scrolling at all, or that, at the very worst, it can only block for the duration of the function itself. The truth, however, is that even an empty listener will totally block scrolling until <em>any</em> JavaScript operation on the page has finished, which you can verify with <a href="http://bl.ocks.org/nolanlawson/raw/dc026a93b91cb448401bb0f1cb3ebad2/">this demo</a>.</p>
<p>Even though the wheel listener has nothing to do with our big blocking JavaScript operation, they share the same JavaScript event loop, and so the background thread must wait for the longer JavaScript operation to finish before it can get a response from the listener function.</p>
<p>Why does it have to wait? Well, JavaScript is a dynamic language, and the browser can’t know for sure that <code>preventDefault()</code> will never get called. Even if it’s obvious to the developer that the function is just doing a simple <code>console.log()</code>, browser vendors have opted not to take any chances. In fact, even an empty <code>function() {}</code> will exhibit this behavior.</p>
<p>Note that this applies to more than just “wheel” events: on touchscreen devices, scrolling can also be blocked by “touchstart” or “touchmove” listeners. One should be very careful when adding listeners to a page, because of this impact on performance!</p>
<p>There are a few scroll-related JavaScript APIs, however, that don’t block scrolling. The “scroll” event, somewhat counterintuitively, can’t block scrolling because it fires <em>after</em> the scroll event, and thus it isn’t cancelable. Also, the new <a href="https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events">Pointer Events API</a>, which was pioneered in IE and Microsoft Edge and has recently started to appear in <a href="https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/UY1EfjaGF_E/OU7W_s3PAgAJ">Chrome</a> and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=822898">Firefox</a>, has an explicit design goal to avoid unintentional scroll-blocking.</p>
<p>Even in cases where we absolutely need to listen to “wheel” or “touchstart” events, there are certain tricks that web developers can employ to ensure that scrolling remains on the fast path. Let’s take a look at a few of these tricks.</p>
<div class="illustration illo_2fingers">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_2fingers_touchpad" viewbox="0 0 102 52" name="illo_2fingers_touchpad"><path class="illo_2fingers_touchpad_bg" d="M 2.3 47.7 L 33.8 1.4 l 39 0.8 l 27.4 1.6 l -10.6 27.4 l -9.1 19.6 L 30 46.9 Z"></path><path d="M 32.4 2.8 h -0.8 c 0.3 -1.2 1.2 -1.4 2.2 -1.4 c 1.2 -0.1 2.5 -0.2 3.7 -0.2 C 42.2 1.1 47 1 51.8 1 h 7.6 c 3.1 0 6.2 0.1 9.4 0.2 c 2.1 0.1 4.2 0.1 6.4 0.2 c 2.5 0.1 5.1 0.2 7.6 0.4 c 2.2 0.1 4.3 0.2 6.5 0.4 c 3 0.2 6.1 0.3 9.1 0.5 c 0.7 0 1.3 0.1 2 0.1 c 0.9 0 1 0.3 0.7 1.1 c -0.7 1.7 -1.3 3.4 -2 5.2 l -4.2 10.2 c -1 2.5 -2 5.1 -2.9 7.7 c -1.2 3.5 -2.8 6.7 -4.4 10 c -0.7 1.3 -1.1 2.7 -1.7 4.1 c -0.8 1.7 -1.6 3.5 -2.4 5.2 c -0.6 1.2 -1.1 2.5 -1.6 3.7 c -0.4 0.8 -0.8 1.3 -1.9 1.2 c -2.4 -0.2 -4.9 -0.2 -7.3 -0.3 c -1.8 -0.1 -3.6 -0.2 -5.4 -0.2 c -2.6 -0.1 -5.1 -0.2 -7.7 -0.4 c -2.4 -0.1 -4.7 -0.3 -7.1 -0.5 c -2.4 -0.2 -4.9 -0.4 -7.3 -0.6 c -2.4 -0.2 -4.9 -0.4 -7.3 -0.6 c -2.1 -0.1 -4.2 -0.3 -6.3 -0.4 c -2.7 -0.1 -5.4 -0.2 -8.1 -0.2 c -2.8 -0.1 -5.6 -0.1 -8.4 -0.1 c -2.6 0 -5.2 0.2 -7.8 0.2 H 3.8 c -0.7 0 -1.3 0.2 -2 0.3 c -0.6 0.1 -0.4 -0.6 -0.7 -0.8 l 0.6 -0.6 c 0.2 -0.2 0.5 -0.3 0.6 -0.5 c 2.9 -4.4 5.7 -8.8 8.6 -13.2 c 2.4 -3.6 5.1 -7 7.6 -10.5 c 2.8 -3.9 5.6 -7.7 8.3 -11.7 c 1.6 -2.3 3.1 -4.7 4.6 -7 c 0.2 -0.4 0.6 -0.8 1 -1.3 Z m 67 1.4 c -1.1 -0.1 -2.2 -0.1 -3.2 -0.2 c -2.1 -0.1 -4.2 -0.2 -6.3 -0.4 c -2.2 -0.1 -4.4 -0.2 -6.6 -0.4 c -2.5 -0.1 -4.9 -0.2 -7.4 -0.4 c -2.1 -0.1 -4.2 -0.2 -6.3 -0.2 c -2.6 -0.1 -5.2 -0.2 -7.8 -0.2 c -2.1 -0.1 -4.2 -0.1 -6.3 -0.1 c -3.4 0 -6.8 0.1 -10.2 0.1 s -6.9 0.1 -10.3 0.1 c -0.7 0 -1.5 -0.2 -1.9 0.9 c -0.4 1 -1.2 1.9 -1.7 2.9 c -3.5 6.1 -7.7 11.8 -11.9 17.5 c -2.8 3.9 -5.7 7.8 -8.5 11.7 c -2 2.8 -3.8 5.7 -5.7 8.6 c -0.6 0.9 -1.1 1.8 -1.7 2.7 c 1.2 -0.1 2.3 -0.1 3.4 -0.2 c 1.8 -0.1 3.6 -0.2 5.5 -0.2 c 1.9 -0.1 3.7 -0.1 5.6 -0.1 c 1.3 0 2.5 0.1 3.8 0.1 c 3 0.1 5.9 0.1 8.9 0.2 c 2.3 0.1 4.6 0.2 6.9 0.4 c 1.9 0.1 3.9 0.3 5.8 0.5 c 2.9 0.2 5.8 0.5 8.7 0.7 c 2.3 0.2 4.6 0.3 6.9 0.5 c 2.5 0.1 5.1 0.2 7.6 0.4 c 1.8 0.1 3.6 0.2 5.4 0.2 c 2.4 0.1 4.7 0.2 7.1 0.2 c 0.5 0 1.2 0.3 1.5 0 c 0.3 -0.2 0.3 -1 0.5 -1.4 l 3 -6.6 c 0.8 -1.9 1.6 -3.8 2.4 -5.6 c 1.2 -2.6 2.7 -5.1 3.6 -7.8 c 2 -6.5 5.4 -12.4 7.5 -18.8 c 0.4 -1.6 1 -3.4 1.7 -5.1 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_2fingers_fingers" viewbox="0 0 41 60" name="illo_2fingers_fingers"><path class="illo_component_bg" d="M 2.1 53.5 l 17.1 -37.4 l 5.6 -9.4 l 4.9 -4.6 L 31.6 1 l 2.6 2.2 l -1.6 9.9 l 2.1 -1.6 l 2.7 0.5 l 2 4.1 v 12.8 l -5.8 18.5 l -3.3 7.3 l -18.4 4.9 Z"></path><path d="M 31.3 14.6 c 1 -1.4 1.2 -3 1.6 -4.6 c 0.2 -0.9 0.5 -1.9 0.6 -2.8 c 0.1 -1.3 0.3 -2.7 -0.3 -4 c -0.3 -0.8 -1 -1.1 -1.8 -1.4 c -0.4 0 -1.1 0.2 -1.7 0.3 h -0.2 c 0.5 -0.8 1.4 -0.8 2.1 -1.1 c 1.8 0.6 2.6 1.7 2.9 3.4 c 0.3 1.8 -0.1 3.6 -0.5 5.3 l -0.3 1.5 c -0.2 0.2 -0.2 0.4 0.1 0.5 c 0 0.1 0.1 0.1 0.1 0.2 c 0.5 -0.2 1 -0.5 1.6 -0.6 c 1.1 -0.2 1.8 0.3 2.4 1.2 c 0.8 1.1 1.2 2.3 1.6 3.6 c 0.4 1.4 0.6 2.8 0.6 4.3 c 0 1 0.2 1.9 0.1 2.9 c -0.1 1.7 -0.3 3.3 -0.5 5 l -0.6 3.9 c -0.3 1.7 -0.7 3.5 -1.2 5.1 c -0.7 2.5 -1.4 5 -2.3 7.5 c -0.9 2.8 -2.3 5.5 -3.8 8.1 l -1.2 1.8 h -0.2 c 0.4 -1 0.7 -2 1.1 -3 c 0.6 -1.5 1.1 -3.1 1.7 -4.6 c 1.8 -4.4 3 -9 4.1 -13.6 c 0.4 -1.8 0.6 -3.7 0.9 -5.6 l 0.6 -3.3 c 0.4 -1.8 0.5 -3.6 0.2 -5.4 c -0.2 -1.4 -0.4 -2.9 -0.8 -4.3 c -0.2 -0.9 -0.8 -1.6 -1.2 -2.4 c -0.6 -0.9 -1.5 -0.8 -2.4 -0.6 c -0.8 0.2 -1.5 0.5 -1.6 1.5 c 0 0.4 -0.4 0.7 -0.6 1.1 c -0.1 0.1 -0.1 0.3 -0.2 0.4 c -0.2 0.2 -0.4 0.3 -0.5 0.5 l -1.5 3.3 c -0.5 1.1 -0.9 2.2 -1.5 3.3 c -1 2.1 -2 4.1 -2.9 6.2 c -0.6 1.4 -1.3 2.8 -1.8 4.2 c -0.5 1.2 -0.8 2.4 -1.3 3.6 c -0.3 0.7 -0.6 1.3 -0.9 2 c -0.4 0.9 -0.8 1.7 -1.2 2.6 l -0.9 2.1 c -0.8 1.9 -1.6 3.7 -2.4 5.6 c -0.8 1.9 -1.5 3.8 -2.2 5.7 c -0.6 1.6 -1.4 3.2 -2.3 4.7 l -0.6 0.9 c -0.1 0 -0.2 -0.1 -0.2 -0.1 c 0.5 -1.1 1 -2.1 1.5 -3.2 c 0.6 -1.3 1.1 -2.6 1.6 -4 c 0.5 -1.2 0.9 -2.5 1.4 -3.7 c 0.8 -2 1.6 -3.9 2.4 -5.9 c 0.7 -1.7 1.4 -3.3 2.1 -5 c 1.1 -2.6 2.1 -5.3 3.2 -7.9 c 0.7 -1.7 1.5 -3.5 2.3 -5.2 c 0.7 -1.4 1.5 -2.7 2.1 -4.1 l 2.4 -5.4 c 0.1 -0.2 0.2 -0.3 0.2 -0.5 h 0.1 Z"></path><path d="M 29.5 2.1 h 0.2 l -0.8 0.8 c -2.3 2.1 -4.1 4.6 -5.5 7.3 c -1.2 2.2 -2.4 4.4 -3.5 6.6 c -0.7 1.4 -1.2 2.9 -1.9 4.4 c -1 2.1 -2 4.1 -2.9 6.1 c -1.9 4.3 -3.9 8.4 -6 12.6 c -2 4 -3.8 8 -5.8 12 c -0.5 1 -1.3 1.8 -2 2.8 c -0.1 0 -0.2 -0.1 -0.2 -0.1 c 0.2 -0.7 0.4 -1.5 0.7 -2.2 l 3 -6.3 C 5.9 43.5 7 41 8.3 38.4 c 1.1 -2.1 2.3 -4.2 3.3 -6.3 l 3.6 -7.5 c 1.3 -2.8 2.7 -5.7 4 -8.5 c 1.5 -3.1 3.3 -6 5.2 -8.8 c 1.3 -2 2.9 -3.7 4.9 -5.1 c 0.1 -0.1 0.2 -0.1 0.2 -0.1 Z"></path><path d="M 24.5 10.9 c 0.6 0.4 1.1 1 1.7 1.2 c 0.6 0.3 1.4 0.5 2.1 0.4 c 0.7 0 1.4 -0.4 2.1 -0.7 c -0.6 1.2 -1.7 1.5 -2.9 1.3 c -0.7 -0.1 -1.4 -0.4 -2 -0.7 c -0.7 -0.3 -1 -0.8 -1 -1.5 Z M 31.2 21 c 1.6 0.9 3.2 0.2 4.7 0.1 c -0.2 0.9 -1.8 1.4 -3.2 1.2 c -0.9 -0.2 -1.5 -0.7 -1.5 -1.3 Z"></path></svg></div>
</div>
<h1>Global vs local event listeners</h1>
<p>In the example above, we covered the case of global listeners (i.e. listeners attached to the “window” or “document”). But what about listeners on individually scrolling elements?</p>
<p>In other words, imagine a page that is scrollable, but there is also a subsection of the page that itself is independently scrollable. Will the browser block the entire page’s scrolling if you only attach a listener to the scrollable subsection?</p>
<pre class="brush: jscript; title: ; notranslate">document.getElementById(‘scrollableDiv’)
.addEventListener(“wheel”, function (e) {
// In theory, I can only block scrolling on the div itself!
});</pre>
<p>If you test this out using <a href="http://bl.ocks.org/nolanlawson/raw/4079c1b7dff33fddfb8cf4cbe2c79b98/">a simple demo page</a>, you’ll find that both Microsoft Edge and Safari will allow the document to scroll smoothly, even if there’s a scroll listener on the scrollable div, and the page has heavy JavaScript operations running.</p>
<p>Here is a chart of the browsers and their behaviors:</p>
<table width="677">
<tbody>
<tr>
<td width="113"></td>
<td width="113">Two-finger touchpad</td>
<td width="113">Touch</td>
<td width="113">Mouse wheel</td>
<td width="113">Click-and-drag</td>
<td width="113">Keyboard</td>
</tr>
<tr>
<td width="113">Edge 14 Desktop (Windows)</td>
<td width="113">Y</td>
<td width="113">Y</td>
<td width="113">Y</td>
<td width="113">Y</td>
<td width="113">N</td>
</tr>
<tr>
<td width="113">Chrome 56 Desktop (Windows)</td>
<td width="113">N</td>
<td width="113">Y</td>
<td width="113">N</td>
<td width="113">N</td>
<td width="113">N</td>
</tr>
<tr>
<td width="113">Firefox 51 Desktop (Windows)</td>
<td width="113">N</td>
<td width="113">N</td>
<td width="113">N</td>
<td width="113">N</td>
<td width="113">N</td>
</tr>
<tr>
<td width="113">Chrome 56 Desktop (MacOS)</td>
<td width="113">N</td>
<td width="113">N/A</td>
<td width="113">N</td>
<td width="113">N</td>
<td width="113">N</td>
</tr>
<tr>
<td width="113">Firefox 51 Desktop (MacOS)</td>
<td width="113">Y</td>
<td width="113">N/A</td>
<td width="113">Y</td>
<td width="113">N</td>
<td width="113">N</td>
</tr>
<tr>
<td width="113">Safari 10.1 (MacOS)</td>
<td width="113">Y</td>
<td width="113">N/A</td>
<td width="113">Y</td>
<td width="113">N</td>
<td width="113">N</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>These results show* that there’s a potential optimization that web developers can employ to take advantage of these browser features. Instead of attaching wheel/touch listeners to the entire document, it’s preferable to add listeners to <em>a targeted subsection of the document</em>, so that scrolling can remain smooth for unaffected parts of the page. In other words, rather than delegating wheel/touchstart listeners to the highest-possible level, it’s best to keep them isolated to the element that needs the scroll event.</p>
<p>Sadly, not all JavaScript frameworks follow this practice – in particular, React tends to add global listeners to the entire document even if it should only apply to a subsection of the page. However, there is <a href="https://github.com/facebook/react/issues/1254">an open issue </a>for this very problem, and the React folks have said they would be happy to accept a pull request. (Kudos to the React folks for being so receptive when we <a href="https://github.com/facebook/react/issues/1254#issuecomment-244137395">provided this feedback</a>!)</p>
<div class="illustration illo_scrolling">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_scrolling_scrollbar" viewbox="0 0 19 122" name="illo_scrolling_scrollbar"><path d="M 18.6 1.4 v 8.2 c 0 0.3 0.3 0.7 0.3 1 c 0 0.3 -0.2 0.5 -0.3 0.8 c -0.1 0.5 0 1.1 0 1.7 c 0 4.6 -0.1 9.2 -0.1 13.7 c -0.1 9.1 -0.1 18.2 -0.3 27.4 c -0.2 18.2 -0.3 36.3 -0.5 54.5 c 0 2.3 0 4.5 -0.1 6.8 c 0 1 0 2.1 -0.1 3.1 c 0 0.8 0.2 2.1 -0.8 2.3 c -1.1 0.2 -2.3 0.1 -3.4 0.1 c -1.2 0 -2.4 0.1 -3.6 0.1 c -2.1 0.1 -4.3 0.1 -6.4 0.2 c -0.5 0 -1.9 0.6 -2.3 0.2 c -0.4 -0.5 -0.1 -2.2 -0.1 -2.8 c 0.1 -2.1 0.1 -4.2 0.1 -6.3 c 0.1 -4.4 0.2 -8.8 0.3 -13.1 c 0.1 -2.3 0.1 -4.6 0.2 -6.9 c 0.1 -2.2 0 -4.5 0.2 -6.7 c 0.5 -2.4 0.4 -4.7 0.3 -7 c 0 -2.3 0.1 -4.5 0.2 -6.8 c 0.2 -8.7 0.4 -17.5 0.7 -26.2 c 0.2 -9 0.5 -18 0.7 -27 l 0.3 -13 c 0 -1 0.1 -2.1 0.1 -3.1 S 4.4 0.9 5.5 0.9 c 2.3 -0.1 4.6 0.1 6.9 0.2 c 2 0.1 4.3 -0.1 6.2 0.3 Z M 5.3 11.6 C 4.7 24 4.5 36.6 4.2 49 c -0.4 12.7 -0.6 25.3 -1 38 c -0.1 3.5 -0.2 7 -0.3 10.6 c -0.1 3.3 0 6.7 -0.3 10 c 3.4 0 6.8 -0.2 10.1 -0.3 c 0.9 0 1.7 0 2.6 -0.1 c 0.3 0 0.9 0.1 1 -0.1 c 0.2 -0.2 0 -1 0 -1.3 c 0 -1.8 0 -3.6 0.1 -5.4 c 0.1 -7.3 0.1 -14.5 0.2 -21.8 c 0.1 -14.4 0.3 -28.9 0.4 -43.3 c 0.1 -8 0.2 -16 0.2 -24 c -1.9 0.1 -3.9 0.1 -5.8 0.2 c -2 0.1 -4.1 0.3 -6.1 0.1 Z M 2.4 120 c 3.2 0 6.4 -0.3 9.7 -0.4 c 0.8 0 1.6 0 2.3 -0.1 h 1 c 0.2 0 0.4 0 0.6 -0.1 c 0.4 -0.1 0.2 0 0.3 -0.4 c 0.1 -0.7 0 -1.6 0 -2.3 V 114 v -4.8 c 0 -0.6 0 -0.6 -0.6 -0.6 h -1.1 c -0.8 0 -1.7 0.1 -2.5 0.1 c -1.6 0 -3.3 0.1 -4.9 0.1 H 4.7 c -0.5 0 -1.7 -0.2 -2 0.2 c -0.3 0.6 -0.2 2 -0.2 2.6 v 2.7 c 0 2 -0.1 3.9 -0.1 5.7 Z M 17.2 2.7 c -3.5 -0.1 -7 -0.1 -10.6 -0.2 c -0.2 0 -1.1 -0.1 -1.2 0 c -0.1 0.1 -0.1 1 -0.1 1.1 c 0 0.8 -0.1 1.7 -0.1 2.5 v 2.2 c 0 0.3 -0.2 2.5 0 2.6 c 0.3 0.2 1.5 -0.3 1.9 -0.3 c 0.8 -0.1 1.6 -0.2 2.4 -0.2 c 1.6 -0.1 3.2 0 4.8 0 c 0.7 0 1.8 0.1 2.5 -0.1 c 0.5 -0.2 0.4 -0.2 0.4 -0.8 V 8.3 V 2.7 Z"></path><path d="M 8.6 115.3 c 0.3 -1.2 -2.1 -2.7 -2.8 -3.4 c 0.9 -0.6 2.4 -0.4 3.5 -0.4 c 1 0 2.3 -0.3 3.3 -0.1 c 0.6 0.1 0.9 0.2 0.5 0.7 c -0.4 0.5 -1.1 0.9 -1.6 1.4 c -0.6 0.4 -2.3 2.4 -2.9 1.8 Z m -1.4 -3.2 c -0.1 0.3 0.7 0.9 0.9 1.2 c 0.4 0.5 0.6 1 0.9 1.5 c 1 -0.9 2 -1.8 3.1 -2.7 H 7.2 Z M 15.2 7.2 c -0.2 0.6 -1.2 0.4 -1.7 0.4 c -0.8 0 -1.6 0.1 -2.4 0.1 c -1 0.1 -2.9 0.5 -3.6 -0.4 c 0.8 -0.6 1.6 -1.1 2.4 -1.7 l 1.2 -0.9 c 0.2 -0.1 0.4 -0.3 0.6 -0.4 c 0.1 0.1 0.2 0.1 0.4 0.2 c 0.7 0.2 1.5 0.8 2.1 1.2 c 0.8 0.4 0.7 0.8 1 1.5 Z M 11.8 5 c -0.4 0.3 -3.4 2 -3.3 2.4 c 2.1 -0.2 4.1 -0.3 6.2 -0.5 c -1 -0.6 -1.9 -1.3 -2.9 -1.9 Z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_scrolling_scroller" viewbox="0 0 23 43" name="illo_scrolling_scroller"><path class="illo_component_bg" d="M 2 2 l 13.2 -0.2 V 25 l 6.3 5.8 l -3.9 3 l 3.3 6.8 l -2 0.8 l -4.1 -6.3 l -3.6 1.7 l -0.6 -4.3 l -9.1 0.4 Z"></path><path d="M 14.6 35.8 c -0.8 0.3 -1.5 0.7 -2.3 1 c -0.5 0.2 -1.4 0.8 -2 0.5 c -0.5 -0.3 -0.3 -1 -0.3 -1.5 c 0.1 -0.9 0.1 -1.8 0.1 -2.6 H 3.8 c -0.6 0 -2.1 0.2 -2.5 -0.3 c -0.4 -0.5 -0.1 -2 -0.1 -2.6 c 0.1 -3.5 -0.2 -7 -0.1 -10.4 c 0 -1.5 -0.1 -3.1 -0.1 -4.6 c 0.1 -1.4 0.1 -2.8 0.2 -4.2 c 0.1 -2 0.1 -3.9 0.1 -5.9 c 0 -0.9 0 -1.9 0.1 -2.8 c 0.2 -1 0.6 -1 1.5 -1.1 C 5 1.3 7 1.2 9 1 c 1 -0.1 2 0 3 0 c 1.1 0 2.2 -0.1 3.2 0.2 c 1 0.2 0.6 0.6 0.6 1.4 c 0 1 0.2 2.1 0.2 3.1 c 0 2.2 0.1 4.4 0 6.6 c -0.1 2.2 -0.1 4.3 -0.1 6.5 V 22 c 0 1 -0.1 2.3 0.3 3.1 c 0.4 0.8 1.3 1.5 1.9 2.1 c 0.8 0.8 1.6 1.4 2.4 2.1 c 0.5 0.4 1.5 0.9 1.8 1.5 c 0.3 0.8 -0.4 1.2 -0.9 1.6 c -1 0.6 -2 1.1 -3 1.7 c -0.6 0.4 -0.4 0.4 -0.1 1 c 0.2 0.4 0.5 0.7 0.8 1.1 c 0.5 0.7 1 1.3 1.3 2.1 c 0.2 0.4 0.2 0.9 0.4 1.4 c 0.1 0.4 -0.1 0 0.3 0.5 c 0.1 0.2 0.3 0.2 0.3 0.5 c 0 0.7 -1.4 1.1 -1.9 1.3 c -0.4 0.2 -0.4 0.2 -0.8 -0.2 c -0.4 -0.3 -0.7 -0.8 -1 -1.1 c -0.6 -0.7 -1.2 -1.5 -1.7 -2.3 c -0.3 -0.6 -0.8 -2.6 -1.4 -2.6 Z m 5.7 3.9 c -1.3 -1.3 -2.2 -3.4 -3.1 -5 c -0.3 -0.5 -0.3 -0.5 0 -0.9 c 0.3 -0.3 0.6 -0.5 0.9 -0.8 c 0.9 -0.6 1.8 -1.2 2.6 -1.8 c -1.4 -1.6 -3.1 -2.6 -4.8 -3.9 c -1.6 -1.3 -3 -2.8 -4.6 -4.1 c 0 4.3 -0.1 8.6 -0.3 13 c 1 -0.4 1.9 -0.8 2.9 -1.3 c 0.3 -0.1 0.9 -0.6 1.2 -0.5 c 0.4 0.1 0.3 0.5 0.5 0.8 c 1 2 2.5 3.8 3.5 5.8 l 1.5 -0.9 c -0.1 -0.2 -0.2 -0.3 -0.3 -0.4 Z m -10.1 -7.9 c 0.1 -2.8 0 -5.6 0 -8.5 c 0 -1.1 0.3 -1.8 1.4 -1.2 c 1.2 0.6 2.2 1.5 3.3 2.2 c -0.2 -4.2 -0.3 -8.4 0.1 -12.6 c 0.2 -2.1 0.3 -4.2 0.2 -6.3 V 3.9 c 0 -0.2 0 -1.3 -0.1 -1.4 c -0.2 -0.2 -1.3 -0.1 -1.6 -0.1 c -0.6 0 -1.3 -0.1 -1.9 -0.1 c -2.1 -0.1 -4.2 0 -6.4 0.1 H 3.9 c -0.2 0 -1.4 -0.1 -1.5 0 c -0.2 0.1 -0.2 1.1 -0.2 1.4 c 0 0.6 -0.1 1.2 -0.1 1.8 c -0.2 4.3 -0.1 8.6 0 12.9 c 0.1 2.3 0.1 4.7 0.1 7 c 0 1 0.1 2.1 0.2 3.1 c 0.1 1.3 0 2.4 -0.2 3.6 c 2.7 -0.1 5.3 -0.3 8 -0.4 Z"></path></svg></div>
</div>
<h1>Passive event listeners</h1>
<p>Avoiding global listeners for wheel/touchstart is a good practice, but sometimes it just isn’t possible, depending on the effect you’re trying to achieve. And in a way, it may feel silly that a simple event listener should force the browser to halt the world, just on the offchance that it might call <code>preventDefault()</code>.</p>
<p>Luckily there is a new feature that is just starting to appear in browsers, where web developers can explicitly mark a listener as “passive” and thus avoid waiting:</p>
<pre class="brush: jscript; title: ; notranslate">window.addEventListener(“wheel”, function (e) {
// Not calling preventDefault()!
}, { passive: true } // I pinkie-swear I won't call preventDefault()
);</pre>
<p>With this fix in place, the browser will treat scrolling exactly as if the “wheel” listener had never been added. This feature is <a href="http://caniuse.com/#feat=passive-event-listener">already available</a> in the latest versions of Chrome, Firefox, and Safari, and <a href="https://developer.microsoft.com/microsoft-edge/platform/status/passiveeventlisteners/">should appear soon in an upcoming release of Microsoft Edge</a>. (Note: you will need to use <a href="https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection">feature detection</a> to support browsers that don’t have passive event listeners.)</p>
<p>For some events (notably “touchstart,” and “touchmove”) Chrome has also opted for an intervention in version 56 to make them <a href="https://www.chromestatus.com/features/5093566007214080">passive by default</a>. Be aware of these subtle browser differences when you add event listeners!</p>
<div class="illustration illo_scroll-wheel">
<div class="illo_wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="illo_component illo_scroll-wheel_hand" viewbox="0 0 111 57" name="illo_scroll-wheel_hand"><path d="M 90.5 22.6 c 1.3 0.3 2.2 1.1 3 2.1 c 1 1.2 2 2.5 3.1 3.6 c 2.1 2.3 3.9 4.8 5.6 7.4 c 0.8 1.2 1.7 2.3 2.6 3.4 l 2.1 2.4 c 0.4 0.4 0.2 0.7 -0.4 0.8 c -0.5 0.1 -0.9 0.5 -1.3 0.5 c -0.8 0.1 -1.6 0 -2.4 -0.1 c -2 -0.5 -3.9 -1 -5.8 -1.6 c 0.9 0.5 1.8 1.1 2.8 1.8 c 2.1 1.5 4.2 3.2 6.2 4.7 c 0.1 0 0.1 0.1 0.2 0.2 c 0.8 0.4 1.1 1.1 0.9 1.9 c -0.2 0.8 -0.5 1.5 -0.7 2.2 c -0.1 0.2 0 0.4 0 0.5 c -0.1 0.8 -0.9 0.7 -1.3 0.7 l -5.4 0.3 c -2.3 0.1 -4.5 0.2 -6.8 0.2 c -2.1 0.1 -4.1 0.2 -6.2 0.2 c -2.2 0.1 -4.4 0.2 -6.7 0.2 c -1.8 0.1 -3.6 0.2 -5.4 0.2 c -2.3 0.1 -4.5 0.2 -6.8 0.2 c -1.8 0.1 -3.6 0.2 -5.4 0.2 c -1.8 0.1 -3.6 0.2 -5.4 0.2 c -1.7 0.1 -3.3 0.2 -5 0.2 c -1.8 0.1 -3.5 0.2 -5.3 0.2 c -1.8 0.1 -3.5 0.2 -5.3 0.2 c -2 0.1 -4 0.2 -6 0.2 c -2.1 0.1 -4.2 0.2 -6.3 0.2 c -1.1 0 -2.1 0.1 -3.2 0.1 c -0.7 0 -0.8 -0.4 -0.8 -0.9 c -0.1 -0.4 -0.1 -1.6 -0.1 -2.7 c 0 -0.9 0.2 -1.9 0.4 -2.8 c 0.2 -1.1 0.5 -2.1 0.8 -3.2 c -1 -0.2 -2 -0.3 -3.1 -0.5 c -2.8 -0.6 -5.6 -1 -8.1 -2.3 c -1.6 -0.9 -3.2 -2 -4.6 -3.2 c -1.8 -1.4 -3.5 -3 -5.3 -4.5 c -0.2 -0.1 -0.3 -0.4 -0.3 -0.6 l 3.9 3 c 1.6 1.3 3.3 2.5 4.9 3.7 c 1.9 1.4 4.1 2 6.4 2.5 c 2 0.4 4 0.8 6 1.1 c 2 0.2 4.1 0.3 6.1 0.2 c 2.1 -0.1 4.2 -0.4 6.3 -0.7 c 2.1 -0.3 4.3 -0.5 6.4 -0.9 c 2.5 -0.4 4.9 -0.9 7.4 -1.3 c 1.7 -0.3 3.4 -0.6 5.1 -0.7 c 1.9 -0.2 3.7 -0.2 5.6 -0.3 c 2.3 -0.1 4.6 -0.2 6.9 -0.4 c 2.1 -0.2 4.1 -0.5 6.2 -0.7 c 0.6 -0.1 1.1 -0.2 1.7 -0.4 c 0.9 -0.4 1 -1.7 0.3 -2.4 c -1.8 -1.5 -4 -2.3 -6.3 -2.5 c -1.6 -0.2 -3.2 -0.2 -4.7 -0.4 c -2.1 -0.2 -4.1 -0.3 -6.2 -0.5 c -1.6 -0.2 -3.2 -0.5 -4.8 -0.8 l -2.4 -0.3 c -2.5 -0.1 -4.9 -0.4 -7.3 -0.9 c -0.6 -0.1 -0.9 -0.4 -1.3 -0.8 c -0.4 -0.5 -1 -1 -1.3 -1.5 c -0.5 -0.8 -0.3 -1.5 0.3 -2.1 c 0.1 -0.1 0.2 -0.3 0.4 -0.5 c -0.2 1.6 0.9 3.2 2.3 3.8 h 0.4 l 4.5 -0.9 c 0.2 0 0.4 -0.1 0.6 -0.2 c -0.3 -0.1 -0.7 -0.1 -1 -0.2 v -0.3 c 6.7 -0.6 13.3 -1.3 20 -1.9 v 0.2 c -0.3 0.1 -0.6 0.1 -1 0.2 c 1.1 0.4 2.2 0.8 3.3 1.3 l 7.8 3.3 c 0.9 0.4 1.8 0.7 2.7 1.1 c 0.1 0.1 0.4 -0.1 0.5 -0.1 c 1.3 -0.5 2.5 -1 3.6 -1.4 c -2 -0.8 -3.9 -1.9 -5 -4.6 c -1.6 -0.2 -3.5 -0.5 -5.4 -0.8 c 0 0.1 0 0.1 -0.1 0.2 c 2.9 1.6 5.7 3.2 8.6 4.9 v 0.1 c -0.9 -0.3 -1.9 -0.6 -2.8 -0.9 c -2.1 -0.8 -4 -1.8 -5.6 -3.4 c -0.7 -0.7 -1.5 -0.9 -2.4 -1 c -2.1 -0.3 -4.3 -0.7 -6.3 -1.3 c -1.7 -0.4 -5.2 -1.8 -5.3 -1.8 c -2.4 0.5 1 -0.3 1.8 -0.1 c 2.5 0.7 5 1.3 7.5 1.9 c 2.1 0.5 4.3 0.9 6 1.2 c -1.6 -0.9 -3.6 -1.9 -5.5 -3 s -3.8 -2.3 -5.3 -4 c -1.3 0 -4.4 0.1 -7.5 0.2 c -3.1 0.1 -2.6 -0.6 0.9 -0.7 h 3.9 c 2.2 0 4.3 -0.1 6.5 -0.1 c 1 0 2 0 3.1 0.1 c -2.1 0.2 -4.1 0.4 -6.2 0.6 c 5.6 3.9 11.5 7.2 18.2 9 c -0.5 -0.1 -0.9 -0.2 -1.4 -0.2 c -0.5 -0.1 -0.9 -0.2 -1.5 -0.1 c 0.7 0.6 1.3 1.3 2 1.9 c 0.6 0.6 1.4 1.1 2 1.7 c 0.4 0.4 0.7 0.5 1.3 0.5 c 1.4 -0.1 2.7 0.2 3.9 0.8 c 1.9 1 2.7 2.6 3.1 4.5 c 0.1 0.6 0.1 1.2 0.1 1.8 c 0 0.5 0.2 0.7 0.6 0.8 c 1.9 0.6 3.9 1.3 5.8 1.9 c 0.9 0.2 1.9 0.5 2.8 -0.2 c -0.6 -0.7 -1.3 -1.5 -1.9 -2.2 c -0.6 -0.7 -1.3 -1.4 -1.7 -2.2 c -1.1 -2.7 -3.2 -4.8 -4.8 -7.1 c -1 -1.4 -2.2 -2.6 -3.3 -3.9 c -0.6 -0.7 -1.2 -1.5 -1.9 -2.3 c -0.6 -0.6 -1.3 -1.2 -2 -1.8 c 0.1 -0.2 0.2 -0.2 0.2 -0.3 Z m -41.7 9.2 v 0.1 c 0.6 0.1 1.3 0.2 1.9 0.3 c 1.4 0.1 2.9 0.2 4.3 0.4 c 2.4 0.3 4.8 0.7 7.2 0.9 c 1.8 0.2 3.5 0.3 5.3 0.5 c 1.5 0.1 3 0.2 4.5 0.4 c 2.4 0.2 4.6 1 6.5 2.4 c 0.7 0.5 1.4 1.1 1.2 2 c -0.2 1 -0.5 2.1 -1.7 2.4 c -2 0.4 -4 0.9 -6.1 1.2 c -2.1 0.3 -4.2 0.3 -6.3 0.4 c -2.4 0.1 -4.8 0.1 -7.2 0.3 c -1.4 0.1 -2.9 0.3 -4.3 0.5 c -1.8 0.3 -3.6 0.6 -5.3 0.9 c -1.6 0.3 -3.3 0.5 -4.9 0.7 c -2 0.3 -4.1 0.6 -6.1 0.8 c -1.3 0.2 -2.5 0.2 -3.8 0.4 c -2 0.3 -4 0.2 -6 0 c -0.4 0 -1 0 -1.1 0.2 c -0.4 1.1 -0.8 2.3 -0.9 3.5 c -0.1 1.8 0.1 3.7 0.2 5.6 c 1.5 -0.1 2.9 -0.1 4.3 -0.2 c 1.9 -0.1 3.8 -0.2 5.7 -0.2 c 2.1 -0.1 4.2 -0.2 6.3 -0.2 c 1.5 -0.1 3 -0.2 4.6 -0.2 c 2.7 -0.1 5.5 -0.2 8.2 -0.4 c 1.5 -0.1 3.1 -0.2 4.6 -0.2 c 1.9 -0.1 3.8 -0.2 5.8 -0.2 c 1.8 -0.1 3.7 -0.2 5.5 -0.2 c 2.2 -0.1 4.4 -0.2 6.7 -0.2 c 2.1 -0.1 4.1 -0.2 6.2 -0.2 c 2.5 -0.1 4.9 -0.2 7.4 -0.2 c 1 0 1.9 -0.1 2.9 -0.1 c 2.3 -0.1 4.6 -0.2 6.9 -0.2 h 3.7 c 0.3 -0.9 0.6 -1.6 0.7 -2.3 c 0.1 -0.4 0.1 -1.1 -0.1 -1.3 c -1.2 -1.1 -2.5 -2.2 -3.8 -3.1 c -1.8 -1.3 -3.7 -2.6 -5.7 -3.8 c -2.2 -1.4 -4.3 -2.8 -6.6 -4 c -2.7 -1.4 -5.5 -2.5 -8.3 -3.7 c -1.3 -0.5 -2.5 -1 -3.8 -1.5 c -2.6 -0.9 -5.3 -1.3 -8 -1.7 c -2.5 -0.4 -4.9 -0.8 -7.4 -0.7 c -1.7 0.1 -3.4 0.1 -5.1 0.2 c -1.5 0.1 -3 0.3 -4.5 0.5 c -1.1 -0.2 -2.3 0 -3.6 0.2 Z m 35.7 3 c 4 1.4 7.5 3.3 11.1 5.6 c -0.1 -0.9 -0.1 -1.6 -0.2 -2.3 c -0.2 -1.1 -0.4 -2.1 -1.2 -2.9 c -1.2 -1.2 -2.8 -1.6 -4.4 -1.7 c -1.8 -0.1 -3.5 0.4 -5.3 1.3 Z m -9.6 -3.7 s -0.1 0 0 0 c -1.7 -0.9 -3.3 -1.7 -4.9 -2.5 c -0.2 -0.1 -0.4 -0.1 -0.5 -0.1 c -2 0.3 -3.9 0.7 -5.6 1 c 3.4 0.5 7.2 1.1 11 1.6 Z"></path><path d="M 90.5 22.6 l -0.1 0.1 c -1.4 -0.9 -2.8 -1.8 -4.2 -2.8 c -1.8 -1.4 -3.5 -3 -5.3 -4.6 c -1.9 -1.6 -3.9 -3 -6.1 -4.2 c -1.9 -1 -3.8 -2 -5.7 -3.1 c -1 -0.6 -2.1 -0.6 -3.1 -0.8 c -2.6 -0.6 -5.2 -1.2 -7.8 -1.7 c -1.3 -0.3 -2.6 -0.5 -4 -0.8 c -3.1 -0.5 -6.2 -1 -9.3 -1.6 c -1.3 -0.3 -2.5 0 -3.8 0 c -0.3 0 -0.7 -0.1 -1 -0.1 c -1.5 0.1 -3 0.3 -4.5 0.5 s -3 0.5 -4.5 0.7 c -1.5 0.2 -2.9 0.4 -4.4 0.6 c -1.6 0.3 -3.3 0.5 -4.9 0.8 c -1.9 0.3 -3.8 0.6 -5.7 1 c -2.3 0.4 -4.7 0.9 -7 1.4 c -2 0.4 -4 0.9 -6 1.2 c -0.6 0.3 -1.3 0.3 -2.1 0.4 v -0.2 c 0.8 -0.2 1.5 -0.5 2.3 -0.7 c 4.6 -1.1 9.2 -2.1 13.8 -3.1 c 2.9 -0.6 5.9 -1 8.8 -1.5 c 2.3 -0.4 4.7 -0.7 7.1 -1 c 2.2 -0.3 4.4 -0.6 6.7 -0.8 c 1.2 -0.1 2.3 0 3.5 0 c 0.7 0 1.5 -0.1 2.2 0 c 2.8 0.3 5.6 0.8 8.3 1.5 c 2.1 0.5 4.2 0.9 6.3 1.4 h 0.1 c 0.6 0.2 1.3 0.5 1.9 0.6 c 1.9 0.4 3.7 0.6 5.6 1 c 0.9 0.2 2 0.4 2.7 0.9 c 0.9 0.8 1.9 1 2.8 1.6 c 2.5 1.6 5.1 3.1 7.6 4.6 c 0.7 0.4 1.2 1.1 1.9 1.7 l 4.2 3.6 c 0.7 0.6 1.4 1.3 2.1 1.9 c 0.4 0.6 1 1.1 1.6 1.5 Z"></path></svg></p>
<div class="illo_component illo_scroll-wheel_finger">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 62 74"><path class="illo_component_bg" d="M1 12.8L30.3 1.6l9.1 15.2-1.2 9.5s.7 6.8 1.3 6.5c.6-.3-1.6.3-1.6.3h-2.6L32.6 31l-1.1-4.7.2-5-6.5-7.9L8.1 23.9 1 12.8z" /><path d="M30.6 1c1.1 1.8 2.2 3.7 3.2 5.5 1.4 2.6 2.9 5.2 4.8 7.6.3.4.5.9.8 1.4 0 .1 0 .1.1.2.3.4.5.8.8 1.2v.1c-.2.2-.4.3-.5.5-.2 1.1-.3 2.2-.4 3.2-.2 1.7-.5 3.3-.6 5-.1 2 0 4 .3 6 .2 1.1-.4 1.8-1.5 1.9-.6 0-1.2.1-1.7.2h-.5l-.3-.3c-2.3-1-3.6-2.7-3.9-5.2-.1-.6-.3-1.2-.4-1.8-.2-1.4-.4-2.9.1-4.3.1-.4 0-.8.7-.9v3.9c0 .8.1 1.5.1 2.3 0 .6 0 1.3.6 1.7.1.1.1.2.2.3.6 1.5 1.8 2.4 3.2 2.9.8.3 1.8.2 2.7.3-.1-.9-.3-1.6-.3-2.4-.1-1.2 0-2.4 0-3.6 0-.7.1-1.4.1-2.1.1-1.4.1-2.8.3-4.2.1-.9.2-1.8.3-2.8.1-.8-.2-1.5-.7-2.1-.6-.6-.9-1.3-1.3-2-.3-.6-.8-1.2-1.2-1.8-.4-.6-.9-1.1-1.2-1.8-.8-1.5-1.4-3-2.2-4.5-.6-1.1-1.3-2.1-1.9-3.1-.1-.1-.3-.2-.4-.1-1 .3-2 .7-2.9 1.1-.9.4-1.9.7-2.8 1.1L11.3 9.2c-2.2.8-4.5 1.6-6.7 2.5-1.1.4-2.3.9-3.4 1.4H.9v-.4c2.2-1.3 4.6-2.1 7-3 2.9-1.2 5.8-2.4 8.7-3.5 2.9-1.2 5.9-2.3 8.8-3.4 1.4-.5 2.7-1.2 4-1.8h1.2z" /><path d="M7.7 24.2c.1-.1.3-.2.4-.3 0-.1.1-.1.1-.2 2.1-1.3 4.1-2.6 6.2-3.8 3.2-1.9 6.6-3.6 9.6-5.7.4-.3.7-.5 1.1-.8.4-.3.8-.3 1.1.1 1 1.3 2.1 2.6 3 4 .8 1.1 1.4 2.2 2.1 3.4-.7.1-1-.3-1.3-.6-1.4-1.8-2.8-3.6-4.1-5.4-.1-.2-.2-.4-.4-.7-.6.5-1.1 1-1.7 1.3-1.9 1.3-3.8 2.6-5.8 3.7-2 1.2-4.1 2.2-6.1 3.2-1.1.6-2.3 1.1-3.5 1.6l-.9.3c.2 0 .2-.1.2-.1z" /><path class="illo_component_bg" d="M6.3 44.4l2.4 14 44.6 14.7h4.3l3.1-2.8-22.9-12.8-9.7-5.6-19.2-7.2z" /><path d="M52.8 73.9c-.8-.2-1.7-.5-2.5-.7-1-.3-2.2-.4-3.1-.9-1.3-.8-2.8-1.1-4.2-1.7-1.4-.5-3-.9-4.4-1.5-1.4-.5-2.7-1.1-4-1.6-3.1-1.1-6.3-2.1-9.5-2.9-1.9-.4-3.9-1.1-5.8-1.7-2.3-.8-4.5-1.7-6.8-2.5-1.7-.6-3.2-1.5-4.6-2.6 0 0-.1-.1-.2-.3.4.1.8 0 1 .2 2.2 1.3 4.7 2 7.2 2.9 3 1 6 2.1 9 3 1.8.6 3.6.8 5.3 1.4 2 .6 3.9 1.4 5.9 2.1 1.7.6 3.5 1.2 5.2 1.8 2.2.8 4.4 1.5 6.5 2.3 1.8.6 3.5 1.4 5.3 1.9.8.2 1.7 0 2.6 0 1.6 0 2.9-.8 4.2-1.7l.1.1c-.2.2-.3.6-.5.7-1.1.8-2.2 1.4-3.5 1.4-.1 0-.2.1-.3.2h-2.6c.1.1-.1.1-.3.1zM7.6 44.4c1 .3 2 .5 3 .8 2.9.7 5.7 1.8 8.4 3.1 1.9.9 4 1.6 6 2.4l2.7.9c.2.1.4.3.5.4.5.3.9.7 1.4 1 2 1.1 3.9 2.2 5.9 3.3 2.4 1.3 4.7 2.5 7.1 3.7 1.2.6 2.5 1.1 3.7 1.7.9.4 1.7 1 2.6 1.4 1.3.8 2.7 1.5 4 2.3 2.3 1.5 4.8 2.6 7.2 3.8.7.3 1.3.7 1.9 1.1l-.1.1c-.2.1-.4.1-.5.2-.3.2-.5.3-.8.5l-.1-.1c.1-.2.2-.4.3-.7-2.3-1.1-4.7-2.3-7.2-3.6v2c0 .1.2.2.3.3.6.2 1.1.4 1.7.6.2.1.4.2.5.3-1 0-2 0-2.9-.5-.5-.4-.2-.9-.3-1.4-.1-.6-.1-1.2-.2-1.8 0-.2-.3-.4-.5-.5-.9-.5-1.7-.9-2.6-1.4l-.1-.1c-1.3-.7-2.5-1.4-3.8-2-1.1-.6-2.3-1-3.4-1.6-1.5-.7-3.1-1.5-4.6-2.3-1.1-.6-2-1.2-3.1-1.9-2.2-1.3-4.4-2.7-6.6-3.9-.7-.4-1.5-.5-2.3-.7-1.9-.7-3.7-1.4-5.6-2.1-2.6-1-5.2-1.9-7.8-3-1.5-.7-3.1-1.1-4.7-1.5-.7-.2-1.3-.1-2 .2-.7.3-1.4.5-2.2.8-.1.1-.3.1-.6.1.5-.7 1.1-.9 1.7-1.2.3-.2.7-.3 1-.4.1 0 .1-.2.1-.3h2z" /></svg>
</div>
</div>
</div>
<h1>Conclusion</h1>
<p>As we’ve seen, scrolling on the web is a fantastically complicated process, and all the browsers are at various stages of improving their performance. In general, though, we can land on some solid pieces of advice for web developers.</p>
<p>First off, it’s best to avoid attaching wheel or touch listeners to the global document or window objects, and instead add them to smaller scrollable elements. Developers should also use passive event listeners whenever possible, with <a href="https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection">feature detection</a> to avoid compatibility issues. Using Pointer Events (there is a <a href="https://github.com/jquery/PEP">polyfill</a>) and “scroll” listeners are also surefire ways to prevent unintentional scroll-blocking.</p>
<p>Hopefully this post has provided some helpful guidance for web developers, as well as a peek into how browsers work under the covers. No doubt, as browsers evolve and the web continues to grow, scrolling mechanics will become even more complex and sophisticated.</p>
<p>On the Microsoft Edge team, we’re excited to keep innovating in this space and to provide smoother scrolling for more websites and more users. Let’s hear it for the humble scrollbar, the oldest and most nuanced interaction on the web!</p>
<p>― <a href="https://twitter.com/nolanlawson">Nolan Lawson</a>, Program Manager, Microsoft Edge</p>
<p>* These results were collected using the latest version of each browser as of February 2017. Since then, Firefox 52 has updated their scrolling support, and now matches Edge 14&#8217;s behavior in all tests except those for sidebar scrolling. We look forward to all browsers improving their scrolling implementations and making the web faster and more responsive!</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/03/08/scrolling-on-the-web/">Scrolling on the web: A primer</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/03/08/scrolling-on-the-web/feed/</wfw:commentRss>
<slash:comments>11</slash:comments>
</item>
<item>
<title>Mitigating arbitrary native code execution in Microsoft Edge</title>
<link>https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/</link>
<comments>https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/#comments</comments>
<pubDate>Thu, 23 Feb 2017 18:01:11 +0000</pubDate>
<dc:creator><![CDATA[Matt Miller]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Arbitrary Code Guard]]></category>
<category><![CDATA[Code Integrity Guard]]></category>
<category><![CDATA[Control Flow Guard]]></category>
<category><![CDATA[MemGC]]></category>
<category><![CDATA[Security]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>Some of the most important security features in modern web browsers are those that you never actually see as you browse the web. These security features work behind the scenes to protect you from browser-based vulnerabilities that could be abused by hackers to compromise your device or personal data. In previous blog posts and presentations, [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/">Mitigating arbitrary native code execution in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>Some of the most important security features in modern web browsers are those that you never actually see as you browse the web. These security features work behind the scenes to protect you from browser-based vulnerabilities that could be abused by hackers to compromise your device or personal data.</p>
<p>In previous <a href="https://blogs.windows.com/msedgedev/2015/05/11/microsoft-edge-building-a-safer-browser/">blog posts</a> and <a href="https://www.blackhat.com/docs/us-16/materials/us-16-Weston-Windows-10-Mitigation-Improvements.pdf">presentations</a>, we described some of the recent improvements that have been made to Windows 10 and Microsoft Edge in this space. Today we’re kicking off a two-part blog post that describes our vulnerability mitigation strategy and provides a technical deep-dive into some of the major security improvements that are coming to Microsoft Edge in the Creators Update of Windows 10.</p>
<h1>Framing our Vulnerability Mitigation Strategy</h1>
<p>Before we dive in, it may help to start with an overview of how we approach the problem of web browser vulnerabilities. The Microsoft Edge security team employs a layered, data-driven defense strategy that focuses investments at key points along the kill-chain that attackers follow when exploiting vulnerabilities.</p>
<p><a href="https://winblogs.azureedge.net/win/2017/02/mitigtation-strategy.png"><img class="aligncenter size-full wp-image-19724" src="https://winblogs.azureedge.net/win/2017/02/mitigtation-strategy.png" alt="Table illustrating the Edge vulnerability mitigation strategy. The Strategy row reads: &quot;Make it difficult &amp; costly to find, exploit, and leverage software vulnerabilities.&quot; The &quot;Tactics&quot; read: &quot;Eliminate entire classes of vulnerabilities,&quot; &quot;Break exploitation techniques,&quot; &quot;Contain damage &amp; prevent persistence,&quot; and &quot;Limit hte window of opportunity to exploit.&quot;" width="772" height="338" /></a></p>
<p>First and foremost in this strategy, we look for ways to <strong>eliminate classes of vulnerabilities</strong> by reducing attack surface and by finding or mitigating specific patterns of vulnerabilities (such as <em>use after free</em> issues, see <a href="https://blogs.windows.com/msedgedev/2015/05/11/microsoft-edge-building-a-safer-browser/">MemGC</a>). In this way, we try to counter the classic asymmetry between attackers and defenders, e.g. where attackers only need to find one good security issue whereas defenders need to ensure there are none.</p>
<p>Still, we assume that we won’t be able to eliminate all vulnerabilities, so we look for ways to <strong>break the techniques</strong> that attackers can use to exploit them. This helps to spoil the recipes that attackers prefer to use when trying to transform a vulnerability into a way of running code on a device. This further counters the asymmetry by removing the underlying ingredients and primitives that enable vulnerabilities to be exploited.</p>
<p>We assume that we won’t be able to break all exploits, so we look for ways to <strong>contain damage and prevent persistence</strong> on a device if a vulnerability is exploited. We do this by once again applying the two previous tactics but this time directed at the attack surface that is accessible from code running within Microsoft Edge’s browser sandbox. This helps constrain attacker capabilities and further increases the cost of achieving their objective.</p>
<p>Finally, assuming all else fails, we look to <strong>limit the window of opportunity</strong> for an attacker to exploit a vulnerability by having effective tools and processes in place. On the processes side, we take advantage of the well-oiled security incident response processes in the <a href="https://blogs.technet.microsoft.com/msrc/">Microsoft Security Response Center</a> (MSRC). On the tools side, we have technologies like Windows Defender and SmartScreen which can be used to block malicious URLs that attempt to deliver an exploit and Windows Update to rapidly deploy and install security updates.</p>
<p>While we’re continuing to invest in security improvements along all of these fronts, the remainder of this post will focus on investments we’ve made to break techniques that are used to exploit the most common type of security issue in modern browsers: <a href="http://2012.ruxconbreakpoint.com/assets/Uploads/bpx/Modeling%20the%20exploitation%20and%20mitigation%20of%20memory%20safety%20vulnerabilities.pptx">memory safety</a> vulnerabilities. More specifically, the next section will explore the technologies we’ve built to help mitigate arbitrary native code execution.</p>
<h2>Transparency</h2>
<p>Browser security is a difficult problem space. Despite the best efforts of all browser vendors, vulnerabilities exist and can potentially be exploited. This is why Microsoft currently offers bug bounties of up to $15,000 USD for <a href="https://technet.microsoft.com/en-us/mt761990.aspx">vulnerabilities found in Microsoft Edge</a> and up to $200,000 USD for novel mitigation bypasses and defenses as part of our <a href="https://technet.microsoft.com/en-us/security/dn425049.aspx">Mitigation Bypass and Defense Bounty</a>. These bounty programs reinforce our commitment to our vulnerability mitigation strategy and help us reward the great work of security researchers around the world.</p>
<h1>Mitigating Arbitrary Native Code Execution</h1>
<p><a href="https://www.rsaconference.com/writable/presentations/file_upload/br-t07-exploitation-trends-from-potential-risk-to-actual-risk.pdf">Most modern browser exploits</a> attempt to transform a memory safety vulnerability into a method of running arbitrary native code on a target device. This technique is prevalent because it provides the path of least resistance for attackers by enabling them to flexibly and uniformly stage each phase of their attack. For defenders, preventing arbitrary native code execution is desirable because it can substantially limit an attacker’s range of freedom without requiring prior knowledge of a vulnerability. To this end, Microsoft Edge in the Creators Update of Windows 10 leverages <strong>Code Integrity Guard</strong> (CIG) and <strong>Arbitrary Code Guard</strong> (ACG) to help break the most universal primitive found in modern web browser exploits: loading malicious code into memory.</p>
<h2>Hackers are developers, too</h2>
<p>A typical web browser exploit chain consists of three parts:</p>
<ol>
<li>An exploit for a <strong>remote code execution</strong> (RCE) vulnerability which is used to get native code running on the target device.</li>
<li>An exploit for <strong>elevation of privilege</strong> (EOP) vulnerability which is used to increase privileges and escape the sandbox.</li>
<li>A <strong>payload</strong> that leverages the obtained access to achieve the attacker’s objective (e.g. <a href="https://www.microsoft.com/en-us/security/portal/mmpc/shared/ransomware.aspx">ransomware</a>, implant, recon, etc).</li>
</ol>
<p>These parts naturally translate into a modular design for exploits which enables attackers to select different RCE, EOP, and payload combinations based on their target. As a consequence, modern exploits ubiquitously rely on executing arbitrary native code in order to run the 2<sup>nd</sup> and 3<sup>rd</sup> stages of their exploit. By breaking this critical link in the chain, we can influence the <a href="http://media.blackhat.com/bh-us-12/Briefings/M_Miller/BH_US_12_Miller_Exploit_Mitigation_Slides.pdf">exploit economics</a> by invalidating the attacker’s software design assumptions and forcing refactoring costs on them.</p>
<h2>Preventing the loading of malicious native code</h2>
<p>An application can directly load malicious native code into memory by either 1) loading a malicious DLL/EXE from disk or 2) dynamically generating/modifying code in memory. CIG prevents the first method by enabling DLL code signing requirements for Microsoft Edge. This ensures that only properly signed DLLs are allowed to load by a process. ACG then complements this by ensuring that signed code pages are immutable and that new unsigned code pages cannot be created.</p>
<h3>CIG: Only allow properly signed images to load</h3>
<p>CIG was first enabled for Microsoft Edge starting with the Windows 10 1511 update. In a <a href="https://blogs.windows.com/msedgedev/2015/11/17/microsoft-edge-module-code-integrity">previous blog post</a>, we explained how a kernel-enforced User Mode Code Integrity (UMCI) policy has been enabled for Microsoft Edge content processes that requires DLLs to be Microsoft, Windows Store, or <a href="https://msdn.microsoft.com/en-us/windows/hardware/gg463010.aspx">WHQL</a>-signed. With this policy in place, the kernel will fail attempts to load a DLL that is not properly signed. In practice, exploits do not typically rely on loading a DLL from disk, but it has been used by some exploits and it must be addressed to achieve our objective and to have a comprehensive solution. Since the Windows 10 1511 release, we’ve made additional improvements to help strengthen CIG:</p>
<ol>
<li><strong><strong>Preventing child process creation (Windows 10 1607): </strong></strong>As the UMCI policy is applied per-process, it is also important to prevent an attacker from spawning a new process with a weaker or non-existent UMCI policy. In Windows 10 1607, Microsoft Edge enabled the <em>no child process mitigation policy</em> for content processes which ensures that a child process cannot be created. This policy is currently enforced as a property of the token for a content process which ensures both direct (e.g. calling WinExec) and indirect (e.g. out-of-process COM server) process launches are blocked.</li>
</ol>
<ol start="2">
<li><strong><strong>Enabling the CIG policy sooner (Windows 10 Creators Update): </strong></strong>The enablement of the UMCI policy has been moved to process creation time rather than during process initialization. This was done to further improve reliability by eliminating a process launch time gap where local injection of improperly signed DLLs into a content process could occur. This was achieved by taking advantage of the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms686880(v=vs.85).aspx">UpdateProcThreadAttribute</a> API to specify the code signing policy for the process being launched.</li>
</ol>
<h3>ACG: Code cannot be dynamically generated or modified</h3>
<p>While CIG provides strong guarantees that only properly signed DLLs can be loaded from disk, it does not provide any guarantees about the state of image code pages after they are mapped into memory or dynamically generated code pages. This means an attacker can load malicious code by creating new code pages or modifying existing ones even when CIG is enabled. In practice, most modern web browser exploits eventually rely on invoking APIs like VirtualAlloc or VirtualProtect to do just this. Once an attacker has created new code pages, they then copy their native code payload into memory and execute it.</p>
<p>With ACG enabled, the Windows kernel prevents a content process from creating and modifying code pages in memory by enforcing the following policy:</p>
<ol>
<li><strong>Code pages are immutable</strong>. Existing code pages cannot be made writable and therefore always have their intended content. This is enforced with additional checks in the memory manager that prevent code pages from becoming writable or otherwise being modified by the process itself. For example, it is no longer possible to use VirtualProtect to make an image code page become PAGE_EXECUTE_READWRITE.</li>
</ol>
<ol start="2">
<li><strong>New, unsigned code pages cannot be created</strong>. For example, it is no longer possible to use VirtualAlloc to create a new PAGE_EXECUTE_READWRITE code page.</li>
</ol>
<p>When combined, the restrictions imposed by ACG and CIG ensure that a process can only directly map signed code pages into memory. Although this is great for security, ACG introduces a serious complication: modern web browsers rely on Just-in-Time (JIT) compilers for best performance. How can we satisfy both needs?</p>
<h3>Supporting Just-in-Time (JIT) Compilers</h3>
<p>Modern web browsers achieve great performance by transforming JavaScript and other higher-level languages into native code. As a result, they inherently rely on the ability to generate some amount of unsigned native code in a content process. Enabling JIT compilers to work with ACG enabled is a non-trivial engineering task, but it is an investment that we’ve made for Microsoft Edge in the Windows 10 Creators Update. To support this, we moved the JIT functionality of Chakra into a separate process that runs in its own isolated sandbox. The JIT process is responsible for compiling JavaScript to native code and mapping it into the requesting content process. In this way, the content process itself is never allowed to directly map or modify its own JIT code pages.</p>
<h2>Impact on attackers</h2>
<p>Together, CIG and ACG provide strong protection against a fundamental primitive that is ubiquitously used when exploiting web browser vulnerabilities. This means attackers must develop new methods for chaining the stages of their exploits.</p>
<p>In the Windows 10 Creators Update, CIG is enabled by default for Microsoft Edge, except for scenarios where certain incompatible extensions are present (such as IMEs) – in these scenarios, both CIG and ACG are currently disabled by default.</p>
<p>For compatibility reasons, ACG is currently only enforced on 64-bit desktop devices with a primary GPU running a WDDM 2.2 driver (the driver model released with the Windows 10 Anniversary Update), or when software rendering is use. For experimental purposes, software rendering can be forced via Control Panel -&gt;Internet Options -&gt; ”Advanced”. Current Microsoft devices (Surface Book, Surface Pro 4, and Surface Studio) as well as a few other existing desktop systems with GPU drivers known to be compatible with ACG are opted into ACG enforcement. We intend to improve the coverage and accuracy of the ACG GPU opt-in list as we evaluate the telemetry and feedback from customers.</p>
<p>One of the limitations of CIG and ACG is that they don’t prevent an attacker from leveraging valid signed code pages in an unintended way. For Example, this means attackers could still use well-known techniques like <em>return-oriented programming</em> (ROP) to construct a full payload that doesn’t rely on loading malicious code into memory. In order to help keep signed code “on the rails” as it executes, Microsoft Edge takes advantage of <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065(v=vs.85).aspx">Control Flow Guard</a> (CFG) which applies a <a href="https://www.microsoft.com/en-us/research/publication/control-flow-integrity/">control-flow integrity</a> policy to indirect calls. In the future, we hope to further mitigate control-flow hijacking such as by taking advantage of Intel’s <a href="https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf">Control-flow Enforcement Technology</a> (CET) to protect return addresses on the stack.</p>
<p>Finally, it should be noted that the use of CIG and ACG in Edge is not intended to fully prevent privileged code running on the system from injecting unsigned native code into a content process.  Rather, these features are intended to prevent the scenario of the content process itself attempting to load malicious native code.</p>
<h1>Up Next</h1>
<p>In an upcoming post, we’ll shift gears to focus on some of the major improvements that have been made to strengthen containment and isolation for Microsoft Edge in the Creators Update of Windows 10. These improvements provide the next line of defense in our efforts to help prevent web browser vulnerabilities from being used to compromise your device or personal data.</p>
<p>― <a href="https://twitter.com/epakskape">Matt Miller</a>, Principal Security Software Engineer, MSRC</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/">Mitigating arbitrary native code execution in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/feed/</wfw:commentRss>
<slash:comments>1</slash:comments>
</item>
<item>
<title>Introducing WebRTC 1.0 and interoperable real-time communications in Microsoft Edge</title>
<link>https://blogs.windows.com/msedgedev/2017/01/31/introducing-webrtc-microsoft-edge/</link>
<comments>https://blogs.windows.com/msedgedev/2017/01/31/introducing-webrtc-microsoft-edge/#respond</comments>
<pubDate>Tue, 31 Jan 2017 18:00:51 +0000</pubDate>
<dc:creator><![CDATA[Bernard Aboba and Shijun Sun]]></dc:creator>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Announcements]]></category>
<category><![CDATA[Interoperability]]></category>
<category><![CDATA[Media]]></category>
<category><![CDATA[New Platform Features]]></category>
<category><![CDATA[Object RTC]]></category>
<category><![CDATA[Real-time communications]]></category>
<category><![CDATA[VP8]]></category>
<category><![CDATA[WebRTC]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>We’re excited to announce the preview availability of the WebRTC 1.0 API, and support for the H.264/AVC and VP8 video codecs for RTC in Microsoft Edge, enabling plugin-free, interoperable video communications solutions across browsers and platforms. These features are enabled by default in Windows Insider Preview builds starting with last week’s release, 15019, and will [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/01/31/introducing-webrtc-microsoft-edge/">Introducing WebRTC 1.0 and interoperable real-time communications in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>We’re excited to announce the preview availability of the WebRTC 1.0 API, and support for the H.264/AVC and VP8 video codecs for RTC in Microsoft Edge, enabling plugin-free, interoperable video communications solutions across browsers and platforms.</p>
<p>These features are enabled by default in Windows Insider Preview builds starting with <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/changelog/desktop/15019/">last week’s release, 15019,</a> and will be in stable releases beginning with the <a href="https://www.microsoft.com/en-us/windows/upcoming-features">Windows 10 Creator’s Update</a>.</p>
<h1>Background and Object RTC</h1>
<p>Microsoft Edge <a href="https://blogs.windows.com/msedgedev/2015/09/18/ortc-api-is-now-available-in-microsoft-edge/#c7PYWL7bPCiLw41h.97">introduced support for ORTC beginning in EdgeHTML 13</a> (Windows 10 version 1511), providing the initial foundation for real-time communications in Edge. Our priority with the WebRTC 1.0 API support is to provide interoperability with legacy implementations on existing websites, which leverage the WebRTC API as previously deployed in other browsers.</p>
<p>Our WebRTC 1.0 API implementation provides support for peer-to-peer audio and video based on a subset of the W3C WebRTC-PC API circa 2015, prior to the addition of the WebRTC object model.  Because this implementation is focused on legacy interoperability (including mobile applications built from early versions of the WebRTC.org source code), we don’t plan to further update the native WebRTC 1.0 API beyond this release.</p>
<p>To utilize the most advanced features in the Microsoft Edge RTC stack, we recommend that considering the ORTC API, especially in situations where it is desirable to control individual transport, sender, and receiver objects directly, or to set up group audio and video calls. If you need support for objects or advanced features such as multi-stream and simulcast with the current WebRTC 1.0 API, we recommend <a href="https://github.com/webrtc/adapter">the adapter.js library</a>, which now supports Microsoft Edge.</p>
<h1>Codec interoperability</h1>
<p>The H.264/AVC and VP8 video codecs are supported in the Microsoft Edge RTC stack, which means video communications are now interoperable between Microsoft Edge and other major WebRTC browsers and RTC services. We have implemented the following congestion control and robustness mechanisms for both H.264/AVC and VP8 video codecs:</p>
<ul>
<li>Support for the <a href="https://webrtc.org/experiments/rtp-hdrext/abs-send-time/">absolute send time header extension</a> (abs-send-time)</li>
<li>Support for <a href="https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03">Google Receiver Estimated Maximum Bitrate</a>, &#8220;goog-remb&#8221;</li>
<li>Support for Picture Loss Indication (PLI) and Generic NACK feedback messages, per <a href="https://tools.ietf.org/html/rfc4585">RFC 4585</a></li>
<li>Support for RTP Retransmission, per <a href="https://tools.ietf.org/html/rfc4588">RFC 4588</a></li>
</ul>
<p>These features are available within both the ORTC API and native WebRTC 1.0 API, so you can make API and video codec decisions independently.</p>
<p>Note that while the Edge H.264/AVC implementation supports hardware offload within both the encoder and decoder, VP8 is implemented purely in software, and as a result may exhibit higher power consumption and CPU load.  If your application uses VP8, we recommend testing on lower-end devices to ensure acceptable performance.</p>
<h1>What’s next</h1>
<p>As we continue to chart our roadmap for real-time communications, our next priorities are adding support for the W3C Screen Capture specification, as well as improved support for enterprise scenarios. We look forward to sharing updates and preview builds as the work progresses.  Meanwhile, we look forward to your feedback on WebRTC and <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/status/?filter=f3f0000bf&amp;q=rtc">our current RTC roadmap</a>. You can try out WebRTC 1.0 <a href="https://insiders.windows.com">in preview builds today</a>, and if you encounter any bugs, share feedback on <a href="https://issues.microsoftedge.com">Microsoft Edge Platform Issues</a>, via <a href="https://twitter.com/msedgedev">Twitter at @MSEdgeDev</a>, or in the comments below.</p>
<p>― Shijun Sun, Principal Program Manager, Microsoft Edge<br />
― Bernard Aboba, Principal Architect, Microsoft Skype</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/01/31/introducing-webrtc-microsoft-edge/">Introducing WebRTC 1.0 and interoperable real-time communications in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/01/31/introducing-webrtc-microsoft-edge/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>ChakraCore’s first anniversary</title>
<link>https://blogs.windows.com/msedgedev/2017/01/13/chakracores-first-anniversary/</link>
<comments>https://blogs.windows.com/msedgedev/2017/01/13/chakracores-first-anniversary/#respond</comments>
<pubDate>Fri, 13 Jan 2017 18:00:34 +0000</pubDate>
<dc:creator><![CDATA[Brian Terlson, Gaurav Seth and Limin Zhu]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>Today marks the one year anniversary of open-sourcing ChakraCore – the core of the Chakra JavaScript engine that powers Microsoft Edge – under the MIT license. We wanted to take a moment to say thank you to everyone in the community who has contributed, helped and partnered with us! Your contributions and feedback help us [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/01/13/chakracores-first-anniversary/">ChakraCore&#8217;s first anniversary</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>Today marks the one year anniversary of <a href="https://blogs.windows.com/msedgedev/2016/01/13/chakracore-now-open/">open-sourcing ChakraCore</a> – the core of the Chakra JavaScript engine that powers Microsoft Edge – under the MIT license. We wanted to take a moment to say <strong>thank you</strong> to everyone in the community who has contributed, helped and partnered with us!</p>
<p>Your contributions and feedback help us improve and create a better product for the community. During this period, we’ve had over 70 contributors, both internal and external, directly contribute to the ChakraCore codebase and several other members of the JavaScript community engaged with us, both in individual capacity and as organizations. New products and services such as <a href="https://www.typescriptlang.org/">TypeScript</a>, <a href="https://blogs.windows.com/buildingapps/2016/04/05/open-translators-to-things-an-open-approach-for-accessing-similar-things/#Tz3IIj3IPl9EODDF.97">Open Translators to Things</a>, and <a href="https://github.com/Microsoft/HoloJS/blob/master/README.md">HoloJS</a> are now using ChakraCore. And it’s been great to see work outside of the core engine proving valuable to the community with things like ChakraCore&#8217;s <a href="https://twitter.com/AriyaHidayat/status/772303891035594753?cn=bWVudGlvbg%3D%3D&amp;refsrc=email">test suite landing in WebKit</a> and <a href="https://github.com/mozilla/spidernode/tree/master/deps/chakrashim">SpiderNode building on ChakraShim</a>.</p>
<p><a href="https://github.com/Microsoft/ChakraCore"><img class="aligncenter size-full wp-image-19553" src="https://winblogs.azureedge.net/win/2017/01/GitHub.png" alt="Screen capture showing the ChakraCore repository on GitHub." width="624" height="249" /></a></p>
<p>In the last year, we’ve talked about several capabilities that we shipped in ChakraCore including <a href="https://blogs.windows.com/msedgedev/2016/05/17/es6-modules-and-beyond/#JeWsx1O2M09mRp8Z.97">JavaScript language support</a> and <a href="https://blogs.windows.com/msedgedev/2016/10/31/webassembly-browser-preview/#hCCVUMsxwgS2AGMj.97">performance optimizations focused on real-world user experiences</a>. In addition, we’ve brought new technologies such as <a href="https://aka.ms/nodeTTD">Time Travel Debugging</a> and <a href="https://blogs.windows.com/msedgedev/2016/10/31/webassembly-browser-preview/">WebAssembly</a> to the engine. Today, we’d like to share a bit more about the progress that we’ve made taking ChakraCore cross-platform.</p>
<h1>The road to ChakraCore parity on Linux</h1>
<p>One of the key goals we set for ChakraCore when it went open source was to enable it to run on platforms other than Windows, starting with Linux, so that developers can use the engine for their needs regardless of the platform their apps or services run on. Last July, we shared our <a href="https://blogs.windows.com/msedgedev/2016/07/27/chakracore-on-linux-osx/#uoQs1PMbgsuKZXCG.97">first experimental implementation</a> of ChakraCore interpreter and runtime on x64 Linux (Ubuntu 16.04 LTS and Clang 3.8+) and macOS. This implementation enabled a high fidelity ChakraCore JavaScript interpreter to execute on the Linux platform.</p>
<p>While interpreters are often not great when it comes to throughput performance, they can be extremely useful in cases where the application or service has size or memory constraints, or the end user focus is on startup performance. This is because interpreters usually have low footprint and startup latency. They don’t need to keep copies of the JITed code that are created based on dynamic optimizations that are common across JavaScript JIT compilers. JITed functions are in general larger in size as compared to the compact bytecode. Also, interpreters can start executing code immediately, once it has been parsed.</p>
<p>For the scenarios where throughput performance matters, we landed the <a href="https://github.com/Microsoft/ChakraCore/wiki/Architecture-Overview#jit-compiler">ChakraCore JIT</a> in the master branch last December. However, the JIT compiler itself is not sufficient for higher throughput as performance quickly gets gated by the performance of the garbage collector, which is an inherent part of any modern JavaScript engine. Today, we are happy to share that we’ve also implemented the software-write-barrier support for Linux in the ChakraCore <a href="https://github.com/Microsoft/ChakraCore">master branch</a>, which is key to enabling ChakraCore&#8217;s <a href="https://github.com/Microsoft/ChakraCore/wiki/Architecture-Overview#garbage-collector">concurrent and partial garbage collector</a>.</p>
<p>With the JIT and the fully featured garbage collector landing in ChakraCore, all major <a href="https://github.com/Microsoft/ChakraCore/wiki/Architecture-Overview#jit-compiler">architectural pieces of ChakraCore</a> on Windows have now been ported to Linux. The team is now focused on adding the remaining few features such an Internationalization support, squashing the last set of bugs and optimizing the performance characteristics for ChakraCore on Linux to be on par with Windows.</p>
<h1><strong>What’s next</strong></h1>
<p>Our next steps for ChakraCore are always available on our <a href="https://github.com/Microsoft/ChakraCore/wiki/Roadmap">roadmap</a>. Today, we are intentionally not updating the roadmap significantly as the current items on the roadmap show our short-term focus &#8211; strengthening ChakraCore support on Linux and bring it to release quality, continuing our efforts within the Node.js community around coming up with <a href="https://github.com/nodejs/abi-stable-node">ABI stable Node APIs</a>, supporting more JavaScript and WebAssembly features, and improving performance for real-world usage patterns.</p>
<p>As we make further progress on the cross-platform related pieces in the upcoming months, you can expect a release of ChakraCore with better Linux support and performance. However, for those of you who’d like to try ChakraCore on Linux or macOS today and share your early feedback with us on the Beta quality support now available, here are the <a href="https://github.com/Microsoft/ChakraCore/wiki/Building-ChakraCore">instructions</a> for you to get started.</p>
<p>Once again, we are humbled as a team to work with the wonderful JavaScript community and would like to thank all of you who have contributed to the project and supported us. We look forward to further collaboration with the community and hope to see more developers <a href="https://github.com/Microsoft/ChakraCore/blob/master/CONTRIBUTING.md">contributing</a> to the project and <a href="https://github.com/Microsoft/ChakraCore/wiki/Embedding-ChakraCore">building</a> cool things with ChakraCore over time. We love to hear your experience, your feedback, and to learn what you are building – so keep sharing! You can always reach us on the <a href="https://github.com/Microsoft/ChakraCore">ChakraCore repo</a>, via <a href="https://gitter.im/Microsoft/ChakraCore">gitter</a> or send us a tweet via <a href="https://twitter.com/ChakraCore">@ChakraCore</a>.</p>
<p>&#8211; <a href="https://twitter.com/gauravseth">Gaurav Seth</a>, <a href="https://twitter.com/limin_z">Limin Zhu</a>, and <a href="https://twitter.com/bterlson">Brian Terlson</a>; Program Managers, Chakra</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/01/13/chakracores-first-anniversary/">ChakraCore&#8217;s first anniversary</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/01/13/chakracores-first-anniversary/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Introducing support for Content Security Policy Level 2</title>
<link>https://blogs.windows.com/msedgedev/2017/01/10/edge-csp-2/</link>
<comments>https://blogs.windows.com/msedgedev/2017/01/10/edge-csp-2/#respond</comments>
<pubDate>Tue, 10 Jan 2017 20:14:59 +0000</pubDate>
<dc:creator><![CDATA[Ted Dinklocker]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Announcements]]></category>
<category><![CDATA[Content Security Policy]]></category>
<category><![CDATA[Cross Site Scripting]]></category>
<category><![CDATA[CSP 2]]></category>
<category><![CDATA[New Platform Features]]></category>
<category><![CDATA[Security]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>We are happy to introduce support for Content Security Policy Level 2 (CSP2) in Microsoft Edge, another step in our ongoing commitment to make Microsoft Edge the safest and most secure browser for our customers. CSP2, when used correctly, is an effective defense-in-depth mechanism against cross site scripting and content injection attacks. This is available [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/01/10/edge-csp-2/">Introducing support for Content Security Policy Level 2</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>We are happy to introduce support for <a href="http://www.w3.org/TR/CSP11/">Content Security Policy Level 2</a> (CSP2) in Microsoft Edge, another step in our ongoing commitment to make Microsoft Edge the safest and most secure browser for our customers. CSP2, when used correctly, is an effective defense-in-depth mechanism against cross site scripting and content injection attacks. </p>
<p>This is available in the Insider Fast ring now starting with <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/changelog/desktop/15002">EdgeHTML 15.15002</a>, and will ship to stable builds with the Windows 10 Creators Update.<br />
<div id="attachment_19475" style="width: 256px" class="wp-caption aligncenter"><a href="https://winblogs.azureedge.net/win/2017/01/csp2.png"><img class="wp-image-19475 size-medium" src="https://winblogs.azureedge.net/win/2017/01/csp2-246x300.png" alt="Screen capture of the Content Security Policy Browser Test loaded in Edge, with CSP and CSP Level 2 both passing." width="246" height="300" /></a><p class="wp-caption-text">Microsoft Edge 15.15002 on the <a href="https://content-security-policy.com/browser-test/">CSP Browser Test</a></p></div></p>
<p><a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/security/content-security-policy/">Content Security Policy</a>, supported in all versions of Microsoft Edge, lets web developers lock down the resources that can be used by their web application, helping prevent <a href="https://en.wikipedia.org/wiki/Cross-site_scripting">cross-site scripting</a> attacks that remain a <a href="https://www.owasp.org/index.php/Top_10_2013-Top_10">common vulnerability</a> on the web. However, the first version of Content Security Policy was difficult to implement on websites with inline script elements that either pointed to script sources or that contained script directly. </p>
<p>CSP2 makes these scenarios easier by adding support for nonces and hashes for script and style resources. A nonce is a cryptographically strong random value generated on each page load that appears in both the CSP policy and in the script tags in the page. Using nonces can help to minimize maintaining a list of allowed source URL values, while also allowing trusted script declared in script elements to run.</p>
<p>In order to use a nonce in an existing template based web application a developer adds a nonce token for each of the trusted inline scripts:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script nonce=&quot;NonceToken&quot;&gt;alert(&quot;Allowed since NonceToken is declared&quot;)&lt;/script&gt;
&lt;script nonce=&quot;NonceToken&quot; src=&quot;https://trustedscriptsource.com.script&quot;&gt;&lt;/script&gt;
</pre>
<p>When the page is dynamically generated on load, the server generates a nonce value, inserts it into the NonceToken in the page and also declares it in the Content Security Policy HTTP header:</p>
<pre class="brush: xml; title: ; notranslate">
Content-Security-Policy: default-src 'self';
script-src 'self' https://example.com 'nonce-NonceToken'
</pre>
<p>This CSP configuration allows script to be downloaded and executed from the page’s own domain, or from <a href="https://example.com">https://example.com</a>. If a script source declaration in the page includes the correct nonce value, regardless of the source URL, that script can be downloaded and executed. </p>
<p>Script that does not meet these requirements would not even be downloaded by Microsoft Edge. In addition, any inline script that had the correct nonce value would be allowed to execute, but no other inline script would run.</p>
<p>CSP2 also adds support for the following:</p>
<ul>
<li>The new directives <code>base-uri</code>, <code>child-src</code>, <code>form-action</code>, <code>frame-ancestors</code> and <code>plugin-types</code> are now supported. <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/security/content-Security-Policy/#csp-directives">See supported CSP directives</a> for more.</li>
<li>Background worker scripts are governed by their own policy, separate from the policy of the document loading them. As with host documents, you can set the CSP for a worker in the response header.</li>
<li>A new event, <code>SecurityPolicyViolationEvent</code>, is now fired upon CSP violations. As well, several new fields have been added to the violation report object including <code>effectiveDirective</code> (the policy that was violated), <code>statusCode</code> (the HTTP response code), <code>sourceFile</code> (the URL of the offending resource), <code>lineNumber</code>, and <code>columnNumber</code>.</li>
</ul>
<p>We worked closely with Chrome and the <a href="https://github.com/w3c/web-platform-tests/tree/master/content-security-policy">W3C Web Platform Tests</a> to build an interoperable implementation, and continue to work closely with the W3C <a href="https://www.w3.org/2011/webappsec/">Web Application Security Working Group</a> on <a href="https://w3c.github.io/webappsec-csp/">Content Security Policy Level 3</a>.</p>
<h1>What’s next?</h1>
<p>CSP2 is an important step for Microsoft Edge to continue to improve the security stance and defense-in-depth capabilities of web application developers, but there’s plenty still to do. Next, we’ll focus on adding support for <a href="https://w3c.github.io/webappsec-csp/#strict-dynamic-usage">strict-dynamic</a> from the CSP3 spec to enable developers and site administrators to reduce their reliance on whitelists and tighten their CSP implementations.</p>
<p>Another CSP directive on our radar is <a href="http://www.w3.org/TR/upgrade-insecure-requests/"><code>upgrade-insecure-requests</code></a>. This directive is meant to make it even easier for a site administrator to move towards using all secure transports, while avoiding having to make massive updates to URL’s in their web applications.</p>
<p>The work for <code>strict-dynamic</code> and <code>upgrade-insecure-requests</code> is currently <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/status/?q=content%20security%20policy">under consideration for a future version of Microsoft Edge</a>.</p>
<p>A more secure web is better for developers, users, and browser vendors alike, and we would love to see more web applications taking advantage of the protections that CSP offers. A good resource for thinking through an implementation is <a href="https://hacks.mozilla.org/2016/02/implementing-content-security-policy/">Implementing Content Security Policy</a>. Give it a try and <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/">let us know</a> if you run into any issues in Microsoft Edge!</p>
<p>― Ted Dinklocker, Program Manager, Microsoft Edge</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2017/01/10/edge-csp-2/">Introducing support for Content Security Policy Level 2</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2017/01/10/edge-csp-2/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Introducing Brotli compression in Microsoft Edge</title>
<link>https://blogs.windows.com/msedgedev/2016/12/20/introducing-brotli-compression/</link>
<comments>https://blogs.windows.com/msedgedev/2016/12/20/introducing-brotli-compression/#comments</comments>
<pubDate>Tue, 20 Dec 2016 18:00:56 +0000</pubDate>
<dc:creator><![CDATA[Microsoft Edge Team]]></dc:creator>
<category><![CDATA[Mobile]]></category>
<category><![CDATA[PC]]></category>
<category><![CDATA[Tablet]]></category>
<category><![CDATA[Announcements]]></category>
<category><![CDATA[Brotli]]></category>
<category><![CDATA[Compression]]></category>
<category><![CDATA[EdgeHTML]]></category>
<category><![CDATA[New Platform Features]]></category>
<category><![CDATA[Performance]]></category>
<category><![CDATA[Windows Insiders]]></category>
<guid isPermaLink="false">http://blogs.windows.com/msedgedev/</guid>
<description><![CDATA[<p>Beginning with EdgeHTML 15.14986, Microsoft Edge supports Brotli as an HTTP content-encoding method. This change will be released to stable builds with the Windows 10 Creator’s Update early next year, but you can preview it now via the Windows Insider Program. With this release, Brotli will be broadly interoperable across browsers, with support in the [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2016/12/20/introducing-brotli-compression/">Introducing Brotli compression in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></description>
<content:encoded><![CDATA[<p>Beginning with <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/changelog/desktop/14986/">EdgeHTML 15.14986</a>, Microsoft Edge supports Brotli as an HTTP content-encoding method. This change will be released to stable builds with the Windows 10 Creator’s Update early next year, but you can preview it now via <a href="https://insider.microsoft.com">the Windows Insider Program</a>. With this release, Brotli will be broadly interoperable across browsers, with support in the latest versions of Microsoft Edge, Firefox, and Chrome.</p>
<p>Brotli is a compression format defined in <a href="https://www.ietf.org/rfc/rfc7932.txt">RFC 7932</a>, previously available as part of the <a href="https://blogs.windows.com/msedgedev/2016/05/03/woff2-fonts-in-microsoft-edge/">WOFF2 font format</a>. When used as an HTTP content-encoding method, Brotli achieves up to 20% better compression ratios with similar compression and decompression speeds (<a href="http://www.gstatic.com/b/brotlidocs/brotli-2015-09-22.pdf">PDF</a>). This ultimately results in substantially reduced page weight for users, improving load times without substantially impacting client-side CPU costs. As compared to existing algorithms, like Deflate, Brotli compression is more efficient in terms of file size and CPU time.</p>
<p>In the current preview release, Microsoft Edge supports Brotli on HTTPS and HTTP connections. In a future preview release, we will update this behavior to only advertise Brotli support on HTTPS connections. Like Chrome, we will continue to decode Brotli content on HTTP connections. Note that in the current preview release, there is a known issue which results in the F12 Developer Tools incorrectly not showing the accept encoding response header. This is tracked as <u>issue 9771399 on issues.microsoftedge.com</u>.</p>
<p>As always, we welcome your feedback on Brotli in Microsoft Edge! Let us know <a href="https://twitter.com/msedgedev">on Twitter</a> or in the comments below if you have any questions or issues. We’re very much looking forward to making the web just a little bit lighter with Brotli!</p>
<p>― Rob Trace, Senior Program Manager, Microsoft Edge</p>
<p>The post <a rel="nofollow" href="https://blogs.windows.com/msedgedev/2016/12/20/introducing-brotli-compression/">Introducing Brotli compression in Microsoft Edge</a> appeared first on <a rel="nofollow" href="https://blogs.windows.com/msedgedev">Microsoft Edge Dev Blog</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://blogs.windows.com/msedgedev/2016/12/20/introducing-brotli-compression/feed/</wfw:commentRss>
<slash:comments>5</slash:comments>
</item>
</channel>
</rss>
* Trying 107.154.117.106...
* TCP_NODELAY set
* Connected to blogs.windows.com (107.154.117.106) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: blogs.windows.com
* Server certificate: Microsoft IT SSL SHA2
* Server certificate: Baltimore CyberTrust Root
> GET /msedgedev/feed/ HTTP/1.1
> Host: blogs.windows.com
> User-Agent: curl/7.51.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Etag: "c5c7d8d3a2a384778202f242a27b8746"
< Last-Modified: Fri, 24 Mar 2017 16:06:25 GMT
< Content-Type: application/rss+xml; charset=UTF-8
< Content-Length: 182024
< Cache-Control: must-revalidate
< Date: Wed, 29 Mar 2017 21:44:29 GMT
< Set-Cookie: visid_incap_842129=S91GhTSwQtGN9fRf0bB7X70q3FgAAAAAQUIPAAAAAABhpm54P+PLpFETa0SigJ6t; expires=Thu, 29 Mar 2018 13:33:30 GMT; path=/; Domain=.windows.com
< Set-Cookie: incap_ses_287_842129=J/n7D2wsNTQ0Wr8sfaH7A70q3FgAAAAAQXGkni8JuC0+0gpZrJVrCA==; path=/; Domain=.windows.com
< Set-Cookie: ___utmvmLwumvyX=hugcZEYdAnB; path=/; Max-Age=900
< Set-Cookie: ___utmvaLwumvyX=jImosfV; path=/; Max-Age=900
< Set-Cookie: ___utmvbLwumvyX=aZt
< XKqOHalX: ntY; path=/; Max-Age=900
< X-Iinfo: 1-11458521-11454421 2VNN RT(1490823868389 138) q(0 0 0 -1) r(6 6)
< X-CDN: Incapsula
<
{ [1452 bytes data]
* Curl_http_done: called premature == 0
* Connection #0 to host blogs.windows.com left intact
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment