Chrome 69 Beta: CSS tricks, and more

By Google

Unless otherwise noted, changes described below apply to the newest Chrome Beta channel release for Android, Chrome OS, Linux, macOS, and Windows. View a complete list of the features in Chrome 69 on ChromeStatus.com. Chrome 69 is beta as of August 2.
Chrome has added several new CSS features.
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%
}

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 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 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" />

<style>
  #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);
  }
</style> 

<div id=box></div>

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 = ev.data;
  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;
    requestAnimationFrame(draw);
  };
  draw(0);
}

Main page:

const worker = new Worker("worker.js");
const offscreenCanvas =
    document.getElementById("canvas").transferControlToOffscreen();
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().
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 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.
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.
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).
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:


Selection in a ligature in English.

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.
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.
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 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.
Chrome sometimes deprecates, removes, or changes features to increase interoperability with other browsers. This version of Chrome includes the following such changes.
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.
The document.createTouchList() method was removed
in favor of the Touch() constructor which has been supported since Chrome 48.
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.