New CSS tricks

Chrome has added several new CSS features.

Conic gradients

CSS conic (angular/sweep) gradients allow color transitions around a center rather than radiating from it. This allows, for example, creating a hue wheel using only two CSS properties as shown below. More examples are available.

div {
  background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
  border-radius: 50%

New margin, padding, and border properties

Logical margin, padding, and border properties now use standard names, specifically margin-{block,inline}-{start,end}, padding-{block,inline}-{start,end} and border-{block,inline}-{start,end}-{width,style,color}. These capabilities were previously supported through -webkit prefixes and non-standard names. Shorthand properties are only added for border-{block,inline}-{start,end}.

CSS scroll snap

CSS scroll snap positions are offsets in a scroll container’s visual viewport where scrolling will stop after each scrolling operation. This improves the user experience by allowing scrollable zones to easily stop at predefined points. This also enables common UX scroll patterns without the need for JavaScript. One such pattern is a horizontal image carousel accomplished with the declarations below. The article Well-Controlled Scrolling with CSS Scroll Snap provides more depth.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;

#gallery img {
   scroll-snap-align: center;

Display cutouts

Display cutouts are now supported in Chrome through the new CSS env() function (environment variables) and the viewport-fit meta tag. This allows developers to take advantage of the entire screen on devices that have a display cutout.

For example, to tell the browser to expand into the display cutout area the site should set the viewport-fit property in the viewport meta tag to cover. The site can then use the safe area inset CSS environment variables to layout their content without being covered by the cutout. This is shown below. The explainer and the spec provide more information.

<meta name="viewport" content="viewport-fit: cover" />

  #box {
    margin-top: env(safe-area-inset-top);
    margin-left: env(safe-area-inset-left);
    margin-bottom: env(safe-area-inset-bottom);
    margin-right: env(safe-area-inset-right);

<div id=box></div>

Other features in this release


OffscreenCanvas is a new interface that allows 2D and WebGL canvas rendering contexts to be used in Workers. This increases parallelism in web applications and improves performance on multi-core systems.

Chrome now also supports DedicatedWorker.requestAnimationFrame(), allowing animation-like events to be triggered the same on dedicated workers as they are in Window. For example:

const offscreenCanvas = new OffscreenCanvas(100, 100);
const ctx = offscreenCanvas.getContext("2d");
ctx.fillRect(0, 0, 10, 10);

Or together with canvas:

const canvasElement = document.getElementById("mycanvas")
const offscreenCanvas = canvasElement.transferControlToOffscreen();
const ctx = offscreenCanvas.getContext("2d");
ctx.fillRect(0, 0, 10, 10);

Inside a worker:

self.onmessage = function(ev) {
  const offscreenCanvas =;
  const ctx = offscreenCanvas.getContext("2d");
  let x = 0;
  const draw = function() {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.fillRect(x, 0, 10, 10);
    x = (x + 1) % ctx.canvas.width;

Main page:

const worker = new Worker("worker.js");
const offscreenCanvas =
worker.postMessage(offscreenCanvas, [offscreenCanvas]);


A new method named Element.toggleAttribute() allows toggling the existence of an element’s attribute in a way similar to Element.classList.toggle. An optional force parameter forces addition or deletion of the attribute depending on the value of force. This makes managing boolean attributes much simpler as the interface doesn’t use strings as does Element.setAttribute().

Fetch API: Request.isHistoryNavigation

A boolean property has been added to request objects to indicate whether a particular request is a history navigation. This allows a service worker to know whether a request was due to a back/forward navigation. An example of how this might be used is that a service worker could respond to such a navigation with a cached response.

JavaScript APIs

JavaScript has several new APIs:

  • The ReportingObserver API provides a JavaScript callback function invoked in response to deprecations and browser interventions. The report can be saved, sent to the server, or or handled using arbitrary JavaScript. This feature is designed to give developers greater insight into the operation of their sites on real-world devices.
  • JavaScript arrays are getting two new methods. Array.prototype.flat() returns a new array with all sub-array elements concatenated into it recursively up to the specified depth. The sub-array elements become members of the new array. Array.prototype.flatMap() first maps each element using a mapping function, then flattens the result into a new array. This method is functionally equivalent to a map followed by calling flat() with a depth of 1.

Keyboard Map API

Some applications such as games assign specific functions to specific physical keys. When the interface references these keys it needs to show either the character displayed on the key, which varies by locale, or the character assigned to the key by an alternate keyboard layout that may have been installed by the user. Because of these layout variations it’s sometimes possible for the character shown in the interface to not reference the intended physical key.
This new API provides a way to translate KeyboardEvent.code values representing physical keys into correct strings for display to the user. You can find details and examples of this new API in the specification and the explainer.


Support for the rtt“, “downlink“, and “ect” client hint values and HTTP request headers have been added to Chrome to convey a device’s network connection speed to servers. For example, the rtt client hint provides the server with the estimated effective round-trip time of the current connection, rounded to the nearest multiple of 25 milliseconds.The server could use this serve a downsampled image if the connection speed is slower than expected. These network quality hints provide to the server the same values as provided to a web page by the Network Information APIs navigator.connection.rtt, navigator.connection.downlink, and navigator.connection.effectiveType.

Media: Querying encryption scheme support through EME

Some platforms or key systems only support AES-128 in CTR mode, while others only support CBCS mode. Still others are able to support both. A new method allows web developers to query whether a specific encryption scheme is supported by Encrypted Media Extensions (EME).

Mid-ligature text selection

Chrome now allows for text to be selected inside ligatures. (A ligature is a combination of two or more letters in a single symbol.) This includes both mouse selection as well as cursor selection in input and textarea elements. We have also changed slightly the way we render text selection to support this change. Parts of text that happen to lie outside the selection area are now rendered with the original style:

Chrome 69
Selection in a ligature in English.
Chrome 69
Selection in a ligature in Arabic.


To avoid leaking information between frames, performance.memory values are currently heavily quantized, and delayed by 20 minutes.
If the renderer process is locked to documents from a single site (as in the case of Site Isolation on desktop), we can expose this information with fewer concerns about leaking information between frames. In these cases, we’ll not return quantized memory consumption information, delayed by 30 seconds. This allows developers to detect performance regressions from user data more easily because the memory measurements will be more accurate and can be taken more frequently.


Service workers have two improvements:

  • ServiceWorkerRegistration.update() previously resolved with undefined. Now it resolves to the registration object as required by the specification.
  • Because of a technical limitation, navigator.serviceWorker previously threw a SecurityError when accessed on an insecure context. After this change, navigator.serviceWorker returns undefined

. This aligns with the specification.

Update behavior of CSS Grid Layout percentage row tracks and gutters

In a future release there will be a change to how percentage row tracks and gutters are resolved on grid containers with indefinite height. Currently they behave similar to percentage heights in regular blocks, but going forward they will behave the same as for columns, making them symmetric.
Percentages will be ignored when computing intrinsic height (like it happens now) and resolved afterwards against that height. That way both column and row axes will have a symmetric behavior in order to resolve tracks and gutters specified by percentages.
In Chrome 69 you’ll get a warning in the JavaScript console about this change. If you want to keep the current behavior in Chrome 70 you need to replace your percentage row tracks and gutters in indefinite height grid containers by “auto” and “0px” respectively.

Web Locks API

The Web Locks API allows scripts running in one tab to asynchronously acquire a lock, hold it while work is performed, then release it. While held, no other script executing in the same origin can acquire the same lock. A lock represents some potentially shared resource, identified by a name chosen by the web app. For example, if a web app running in multiple tabs wants to ensure that only one tab is syncing to the network, each tab could try to acquire a my_net_sync lock, but only one tab will succeed.
An example is shown below. It shows a function called when a lock for my_resource is acquired.

await navigator.locks.request('my_resource', async lock => {
  const url = await look_up_in_database();
  const response = await fetch(url);
  const body = await response.text();
  await store_body_in_database(body);

For more details about the API methods and options, see the explainer and draft specification.

Web Authentication now supports CTAP2 FIDO devices

Web Authentication adds support for CTAP2 devices, which provide advanced security capabilities such as biometric authentication and resident keys (keys stored on the device). The WebAuthentication API formerly only supported Universal 2nd Factor (U2F) devices at the transport layer. This change doesn’t alter the API surface itself, but enables richer device interactions via the existing Web Authentication API.


WebRTC has two improvements:

  • Chrome now supports the RTCRtpParameters.headerExtensions dictionary entry which is returned by RTCRtpSender.getParameters(). This is a read-only field that allows inspection of the parameters that are set on a PeerConnection after negotiation.
  • The RTCRtpSender and RTCRtpReceiver interfaces now provide the getCapabilities() method

which returns the most optimistic view of the capabilities of the system for sending media of the given kind. It does not reserve any resources, ports, or other state but is meant to provide a way to discover the types of capabilities of the browser including which codecs or RTP extensions may be supported.

Deprecations and Interoperability Improvements

Chrome sometimes deprecates, removes, or changes features to increase interoperability with other browsers. This version of Chrome includes the following such changes.

Removal of ‘stalled’ event from HTMLMediaElements that use Media Source Extensions

Previously, the HTMLMediaElement.stalled event fired when media download has failed to progress for at least 3 seconds. In Media Source Extensions, the web app manages the download and the media element is not aware of its progress. Since some apps append media data in chunks larger than 3 seconds, stalled was being fired at inappropriate times. To solve this, stalled has been removed for Media Source Extensions.

Removal of document.createTouchList

The document.createTouchList() method was removed
in favor of the Touch() constructor which has been supported since Chrome 48.

The window.confirm() method no longer activates its parent tab

If a document in a background tab calls window.confirm(), it returns immediately with false, and no dialog is shown to the user. If the tab is active, then the call shows a dialog as normal. Specifically, this removes the ability to use window.confirm() to bring a tab to the front because this is rarely what the user wants.


Please enter your comment!
Please enter your name here