Bringing Chrome to ARM64 Linux Devices

We’re excited to announce that Google will launch Chrome for ARM64 Linux devices in Q2 2026, following the successful expansion of Chrome to Arm-powered macOS devices in 2020 and Arm-powered Windows devices in 2024.

Launching Chrome for ARM64 Linux devices allows more users to enjoy the seamless integration of Google’s most helpful services into their browser. This move addresses the growing demand for a browsing experience that combines the benefits of the open-source Chromium project with the Google ecosystem of apps and features.

This release represents a significant undertaking to ensure that ARM64 Linux users receive the same secure, stable, and rich Chrome experience found on other platforms.

Get the best of the Google ecosystem

With Chrome, you are able to leverage the full power of the Google ecosystem, providing a more cohesive and feature-rich environment designed for convenience and cross-device continuity. By signing into a Google Account, your bookmarks, browsing history, and open tabs follow you across devices. You can easily access the best extensions the Chrome Web Store has to offer, without needing to use specialized tools or alter developer settings. And you can effortlessly translate webpages with a single click.

Use the browser that is secure by design

Chrome also offers the added benefit of Google’s strongest security protections. Enabling Enhanced Protection in Safe Browsing offers real-time protection against phishing and malware by leveraging AI alongside Google’s list of known threats. With the Google Pay integration you can easily and securely manage your payments, using Chrome autofill for an added level of convenience. And the Google Password Manager lets you securely store, generate, and sync complex passwords across all your devices, eliminating the need to memorize multiple logins. It goes beyond simple storage by actively monitoring your credentials for data breaches and providing "Password Checkup" alerts if any of your accounts are compromised.

Partnering with the industry

Last year, NVIDIA introduced the DGX Spark, an AI supercomputing device that packs its Grace Blackwell architecture into a compact, 1-liter form factor. Google is partnering with NVIDIA to make it easier for DGX Spark users to install Chrome. Users with other Linux distributions can also install the ARM64 version of Chrome by visiting chrome.com/download.

This launch marks a major milestone in our commitment to the Linux community and the Arm ecosystem. We look forward to seeing how developers and power-users leverage Chrome on this next generation of high-performance devices.

Android Sets New Record for Mobile Web Performance

A core part of the Android experience is the web. Whether you are browsing in Chrome or using one of the >90% of Android apps that utilize WebView, the speed of the web defines the speed of your phone. Today, we are proud to celebrate a major milestone: Android is now the fastest mobile platform for web browsing.

Through deep vertical integration across hardware, the Android OS, and the Chrome engine, the latest flagship Android devices are setting new performance records, outperforming all other mobile competitors in the key web performance benchmarks Speedometer and LoadLine and providing a level of responsiveness previously unseen on mobile.

Android flagship phones reach new high-scores in
web performance benchmarks (Chrome 146, March 2026)

Why web performance matters

Web performance isn't just about high scores—it’s about how your device feels every day. On Android, web content and its performance is central to the user experience.

Whether searching for information, catching up on the latest news, or online-shopping, Android users spend a significant portion of their daily screen time interacting with web content. Chrome is one of the most popular Android apps in the US and worldwide. Furthermore, this usage increases sharply on tablets and foldables, where productivity use cases are key.

While the web is clearly important, a great web experience necessitates a fast browser and device: Modern websites are highly complex, with more than 200 million active sites serving everything from blog posts with dynamic ad auctions to desktop-class productivity tools. This complexity makes for a demanding workload that can stress even powerful devices.

To ensure a high-quality user experience, we focus on two critical pillars when evaluating web performance: responsiveness and page load speed.

Speedometer: Measuring web responsiveness

Speedometer is the collaborative industry standard used by all major browser engine developers to measure web app responsiveness. It simulates real-world user actions—like adding items to a to-do list—to measure interaction latency.

While synthetic, Speedometer's workloads offer high consistency and are built using relevant, state-of-the-art web frameworks, such as React, Angular or jQuery, and include to-do apps, text editors, chart rendering, and a mock news portal.

Speedometer scores have a strong correlation (-0.8) with 99th-percentile interaction latency (INP) in the field. Thus, a higher Speedometer score directly translates to a more fluid, snappy feeling when you tap, scroll, or type on a website.

LoadLine: Measuring the complete page load

While interaction responsiveness is vital, it’s only half of the story. Users also care about how fast a page appears after they click a link. To measure this, Chrome and Android teams worked with Android SoC and OEM partners to develop LoadLine, an emerging end-to-end benchmark that simulates the complete process of loading a website.

Where traditional benchmarks often focus on synthetic tasks, LoadLine uses recorded, stable versions of select real-world websites. This includes simpler and more complex sites with varied characteristics, reflecting the most important types of mobile web content, such as shopping, search, and news portals.

LoadLine has proven that Android's page load performance is world-class: Top tier Android phones score up to 47% higher than non-Android competitors. And this matters: LoadLine scores also correlate well (-0.8) with median and high-percentile page load latency in the field.

Speedometer (left) and examples of LoadLine workloads (right)

Success through vertical optimization

Android’s current lead is the result of a concerted effort to tune the entire "stack"—from silicon to software.

We encouraged our Android partners to evaluate and tune their devices against Speedometer and LoadLine. While advances in SoCs' core performance build the foundation for fast web experiences, tuning of the OS and browser software stack are critical to utilize the hardware effectively. Collaborating with select SoC and OEM partners, we utilized Speedometer and LoadLine to optimize Chrome and kernel scheduler policies.

As a result of these improvements, some Android flagship phones improved their Speedometer and LoadLine scores by 20-60% year-over-year, compared to their respective predecessor models. And these improvements translate to faster real-world web performance: Today, page loads are 4-6% faster and high-percentile interactions 6-9% faster on these newer models, for real users in the field.

We invite all developers and hardware partners to join us in using these benchmarks to push the boundaries of what’s possible on the mobile web.

JetStream 3: A modern benchmark for high-performance, compute-intensive Web applications

We’re incredibly excited to announce the release of JetStream 3, built in close collaboration with Apple, Mozilla, and other partners in the web ecosystem!

While we’ve covered the high-level details of this release in our shared announcement blog post, we wanted to take a moment here to dive a little deeper. In this post, we’ll pull back the curtain on the benchmark itself, explore the methodology behind our choices, and share the motivations driving these major updates.


Why Do We Benchmark, Anyway?

Before we get into the "what," it helps to talk about the "why." Why do browser engineers care so much about benchmarks?

At its core, benchmarking serves as a critical safety net for catching performance regressions before they ever reach users. But beyond that, benchmarks act as a powerful motivation function—a sort of "gamification" for browser engineers. Having a clear target helps us prioritize our efforts and decide exactly which optimizations deserve our focus. It also drives healthy competitiveness between different browser engines, which ultimately lifts the entire web ecosystem.

Of course, the ultimate goal isn't just to make a number on a chart go up; it's to meaningfully improve user experience and real-world performance.

Driven by Open Governance

Just like Speedometer 3, JetStream 3 is the result of a massive collaborative effort across all major browser engines, including Apple, Mozilla, and Google.

We adopted a strict consensus model for this release. This means we only added new workloads when everyone agreed they were valuable and representative. This open governance model has led to an incredibly productive collaboration with buy-in from multiple parties, ensuring the benchmark serves the best interests of the overall Web ecosystem.

Ripe for an Update

The last major release, JetStream 2, came out in 2019. In the technology space—and especially on the Web—six years is an eternity.

There's a well-known concept in economics called Goodhart's Law, which states that when a measure becomes a target, it ceases to be a good measure. Over time, engines naturally optimize for the specific patterns of a benchmark, and the metrics slowly lose their correlation with real-world performance. Speedometer recently received a massive update to account for this, and it only makes sense that JetStream is next in line.

JetStream vs. Other Benchmarks

You might be wondering: with the recent release of Speedometer 3, why do we need another benchmark?

While Speedometer is fantastic for measuring UI rendering and DOM manipulation, JetStream has a different focus: the computationally intensive parts of Web applications. We're talking about use cases like browser-based games, physics simulations, framework cores, cryptography, and complex algorithms.

There are also practical engineering considerations. JetStream is designed so that it can run in engine shells—like d8, the standalone shell for V8. For engine developers, this is a massive advantage. Building a shell is significantly quicker than compiling a full browser like Chrome, allowing engineers to iterate faster. Because d8 is single-process, it also produces far less background noise, leading to more stable testing. This shell-compatibility also makes JetStream highly valuable for hardware and device vendors running simulators. It is a trade-off—a shell is slightly further removed from a full, real-world browser environment—but the engineering velocity it unlocks is well worth it.

How We Select Workloads

Building a benchmark requires a delicate balance between microbenchmarks and real applications.

Microbenchmarks are great engineering tools; they have a high signal-to-noise ratio and make it easy to see the effects of one specific optimization. While they make sense for early improvements of new features, they also often encourage overfitting in the long run. Engines might optimize heavily for a tiny loop that looks great on the benchmark but does absolutely nothing to help real users.

Because of this, a primary criterion for inclusion in JetStream 3 is that a workload should represent a real, end-to-end use case (or at least a highly abstracted form of one).

We also heavily prioritized diversity. We don’t want workloads that all exercise the exact same hot loop. We want coverage across different frameworks, varied libraries, diverse source languages, and distinct toolchains.

Finally, we had to lay down some practical ground rules:

  • Time: The full benchmark suite needs to complete in a few minutes.
  • Memory: It shouldn't consume so much RAM that it crashes low-end devices.
  • Network: It shouldn't require massive payload transfers.
  • Consistency: Results should be deterministic and repeatable from one run to the next.

Rethinking WebAssembly

One of the most significant shifts in JetStream 3 is an increased focus and major update with regards to WebAssembly (Wasm).

When JetStream 2 was created, Wasm was still in its infancy. Fast forward to today, and Wasm is significantly more widespread.

Because the language has evolved so rapidly, JetStream 2 became outdated quickly. It only tested the Wasm MVP (Minimum Viable Product). Today, the Wasm spec includes powerful features like SIMD (single instruction, multiple data), WasmGC, and Exception Handling—none of which were being properly benchmarked.

The ecosystem of tools has also completely transformed. The old workloads relied almost entirely on ancient versions of Emscripten compiling C/C++, often utilizing the deprecated asm.js backend via asm2wasm. Furthermore, some of the old microbenchmarks mis-incentivized the wrong optimizations. For example, the old HashSet-wasm workload rewarded aggressive inlining that actually hurt performance in real-world user scenarios.

The New WebAssembly Workloads

To fix this, we sought out entirely new Wasm workloads, introducing 12 in total.

We expanded our toolchain coverage from just C++ to include five new toolchains: J2CL, Dart2wasm, Kotlin/Wasm, Rust, and .NET. This means we are now actively benchmarking Wasm generated from Java, Dart, Kotlin, Rust, and C#!

These workloads represent actual end-to-end tasks, including:

  • argon2: A cryptographic password hashing function.
  • Transformers.js: Client-side machine learning heavily utilizing SIMD.
  • Cross-platform UI: Dart and Kotlin workloads utilizing WasmGC.
  • SQLite3: The ubiquitous database, replacing old WebSQL patterns.
  • .NET: As an example of full interpreters and language runtimes built on top of Wasm.

These aren't tiny, kilobyte-sized modules anymore. These are multi-megabyte applications that produce diverse, complex flamegraphs, pushing engines to their limits. Reflecting its heightened importance on the modern web, Wasm now makes up 15-20% of the overall benchmark suite, up from just 7% in JetStream 2. Beyond new workloads, JetStream 3 also overhauls scoring to ensure that runtime performance—not just instantiation—is accurately reflected in the total score.

The New and Updated JavaScript Workloads

We have many new larger JavaScript workloads that better represent how JS is used in the wild. Additionally to just measuring the pure execution speed we have "startup" workloads that include parsing and frameworks setup code – more closely matching what happens on initial page load.

  • babylonjs: Startup and execution of the JavaScript core of the Babylon.js 3D engine.
  • bigint-noble-ed25519: BigInt stress-test that calculates an elliptic curve.
  • doxbee: Async code patterns using promises and async functions.
  • js-tokens js-tokenizer performance over JavaScript and JSX sources.
  • jsdom-d3-startup: D3 running in a JavaScript-only DOM implementation frequently used in unittests.
  • lazy-collections: JavaScript generators stress-test.
  • mobx-startup: Startup performance of the MobX state management library.
  • prismjs: Startup performance of a syntax highlighting library on various source files.
  • proxies: Two new workloads that stress tests proxy functionality using different libraries.
  • raytrace classes: Stress testing private and public fields with ES6 classes.
  • sync-fs: A mock file system, testing DataView, Promises, and synchronous generators / iterators.
  • threejs: A 3D particle system implemented with Three.js.
  • typescript-lib: Typescript v5.9 compilation speed.
  • validatorjs: String validation and sanitization with validator.js.
  • web-ssr: Server-side rendering (SSR) using React.

Updated JavaScript Workloads

  • WTB: Updated version of the web-tooling benchmark measuring performance of various developer tools.
  • Sunspider: All separate workloads have been combined into a single item to reduce its weight.
  • Various older workloads were fixed to fix benchmark bugs and counter-act non real-world improvements.

Conclusion

With JetStream 3, the browser benchmarking space has made another big step forward and brought a new tool for browsers to improve performance for their valued users. Alongside Speedometer and MotionMark, these benchmarks give a clear view not only to browser vendors but also to users about various engine’s performance.

If you’d like to contribute to the benchmark with your own workloads or have suggestions for how we can make it better, feel free to join the repository on GitHub. We’re continually iterating on these benchmarks and will have more updates on each in the future as well.

Gemini 1.5 Pro Now Available in 180+ Countries; With Native Audio Understanding, System Instructions, JSON Mode and More

Posted by Jaclyn Konzelmann and Megan Li - Google Labs

Achieving privacy compliance with your CI/CD: A guide for compliance teams

Posted by Fergus Hurley – Co-Founder & GM, Checks, and Evan Otero – Product Manager, Checks

Introducing new AI tools on Google for Developers

Posted by Chris Demeke – Senior Product Manager

Celebrating 5 years of Jetpack Compose

Posted by Rebecca Franks, Developer Relations Engineer, Nick Butcher, Product Manager, Loryn Hairston, Product Marketing Manager, Android


Today, we officially celebrate five years since the release of Jetpack Compose 1.0. From version 1.0, announced on July 28th, 2021, to our latest 1.11 release, we’ve seen the APIs evolve significantly over the years, and we’re taking a moment to celebrate.

When we officially announced the 1.0 release, we promised a simpler, faster, and more intuitive way to build native interfaces on Android. Looking back, it's safe to say that Compose didn’t just deliver on that promise, but also completely changed the Android ecosystem, with more than 68% of the top 1,000 apps using it in production today.

History

Over the last five years, Compose has grown steadily. In the early days, we explored showing you how to build layouts with the basic Box, Row, and Column. Today, we’ve expanded Compose to work not just on mobile devices, but to other form factors such as Compose for TV, WearOS, Glance for Widgets, and even display glasses with Jetpack Compose Glimmer.



We recorded an Android Developers Backstage episode with Clara Bayarri, Engineering Lead for Jetpack, and two former leads of the team, Romain Guy and Chet Haase, along with Tor Norbye, Senior Engineering Director. In this episode, they discuss the history of Compose and the early days of development.




Compose highlights over the years

Looking back

The beginnings of Compose were very different from what you know today. Two projects were happening in parallel inside the Android team.

At the time, the Views toolkit team was thinking of unbundling the UI Toolkit into a library to help with development speed, and make it easier for developers to adopt and control updates. Meanwhile, a team was working on a novel idea to build declarative layouts by embedding XML inside Kotlin, which looked something like this:



Those two efforts merged to produce what you know today - a fully declarative UI Toolkit that utilizes the power of a compiler plugin, runtime, and Kotlin:

@Composable
fun Newsfeed(stories: List<Story>) {
    LazyColumn {
        items(stories) { story ->
            Card {
                val author = story.author
                Image(painterResource(author.profilePhoto),
                    contentDescription = author.name)
                Text(author.name)
                Text(story.content)
                if (story.hasCommentsEnabled()) {
                    for(comment in story.comments) {
                        Text(comment.mainContent)
                    }
                }
            }
        }
    }
}

And you, the community, helped us very early on! Before 2021, Compose had a pre-alpha phase, which helped ensure Compose was fit to solve the problems of our developers.

One of our favorite memories is the Android Dev Challenge. We challenged the community to build four different tasks with Compose, filling our feeds with Puppy apps, clocks, and weather apps, and giving us a ton of direct feedback that helped shape the 1.0 release.

Compose has continued to evolve, from launching with a set of Material 2 components to now supporting Material 3 Expressive.

Material 2 in Compose

Material 3 Expressive in Compose

Looking ahead

As of today, Compose 1.11 is the latest version with 1.12 coming soon, offering so much more than 1.0, 5 years ago. This year, we introduced more adaptive APIs, such as FlexBox, Grid, MediaQuery, and Styles. These APIs let you advance to the next level of premium, adaptive UI development with Compose.

At Google I/O 2026, we announced that we are now Compose-first, meaning that all future UI development will happen only in Compose, while the Views toolkit enters maintenance mode. Material Design is also shifting focus entirely to Compose, signaling an end to the findViewById era.

Community is at the heart of Compose 

Over the years, you’ve inspired us with creative examples of how you’ve used Compose, and we’d love to highlight a few more examples of where we’ve seen exciting work. JetBrains has been a great partner for Google with Compose, expanding Compose to work across platforms with Compose Multiplatform and enabling desktop, iOS, and web developers to also enjoy the benefits of Compose.

We’ve really enjoyed following our most beloved newsletters from JetpackCompose.app’s Dispatch, AndroidWeekly, to jetc - helping Android Developers stay up-to-date with the latest in the world of Compose and Android.

Another standout contributor is sinasamaki. They’ve created many delightful experiences using Compose, such as this fun ribbon modifier and the glitchy effect:


Saket Narayan has also always been an inspiration when it comes to creating useful tools for Compose, such as telephoto, a library featuring support for pan and zoom gestures and automatic sub-sampling of large images, or the latest library, Touch Robot, which allows you to easily test interaction animations:

paparazzi.gif(end = 3_000) {
  DebitCard(
    Modifier.testTag("card")
  )

  val touchRobot = rememberTouchRobot()
  LaunchedEffect(Unit) {
    touchRobot.onNode(hasTestTag("card")).performGesture {
      draw(
        path = createAndroidHeadPath(),
        duration = 3.seconds,
      )
    }
  }
}

/** A path drawing the Android head. */
fun createAndroidHeadPath(bounds: Rect): Path = TODO()

Jake Wharton, who has used Compose in innovative ways (like molecule, and even building UI with Compose for the terminal with mosaic). Chris Banes, who has built many Compose libraries over the years, with our most recent favourite - Haze for background blurring, and many of the Android Google Developer Experts like Akshay Chordiya, Huyen Tue Dao, and Katie Barnett, who’ve contributed to the success of Compose. But this is not about selecting individuals - there have been so many great contributors to the Compose codebase, and many of you continue to inspire us with your fun examples, libraries, and in-depth talks. Without the community, Jetpack Compose wouldn’t be as successful as it is today.

Cheers to the next 5 years, and more! 

Jetpack Compose has grown from an experimental idea into the standard for Android UI Development. Thank you to the entire Toolkit team at Google, and to the incredible global developer community that wrote libraries, filed bugs, and pushed the boundaries of what declarative UI can do.

This week, we’ll be celebrating with some in-person birthday parties across the globe, and a live “Birthday party” on the Android Developers YouTube channel on July 30th at 13:00 UTC. During this time, we’ll hang out and discuss Compose and answer your questions!

Cheers to the next 5 years, and happy composing!

Delivering safer, age-appropriate experiences on Google Play

Posted by Paul Feng, VP of Product Management, Google Play




Providing a safe online experience and protecting users from harm is a top priority at Google Play. We take this responsibility seriously and have been investing continuously to offer baseline protections on our platform while also empowering parents with the tools they need to make decisions for their families. Importantly, we also want to empower Play developers with the capabilities to deliver age-appropriate experiences based on their app's content.

To support this, today, we are taking another big step in our ongoing partnership with parents and developers by announcing the expansion of the Google Play Age Signals API to all Play developers globally. Building on current availability in Brazil, we will expand this experience first to users in Australia and Canada by mid-August, with a full global rollout to all users later this year.

Empowering developers to create age-appropriate experiences

The Play Age Signals API is a privacy-preserving tool that puts parents in the driver's seat allowing them to share their child's age range (e.g. 16-17) directly with apps. It also enables adults to easily share their age when prompted by the app developer. In turn, developers receive the signals they need to tailor their own in-app safety experiences and content for users in an age-appropriate way.

We want to give developers the ability to choose the right protections for the nature of their app. A weather app, for example, shouldn't need the same safety settings as entertainment or media apps. Rather than enforcing one-size-fits-all rules, we give developers the flexibility to choose how they integrate safety signals. With this reliable signal, you retain complete agency to tailor your app's content, features, and settings to match your audience.

Users have a choice to share their age range in a privacy-friendly way

Simplifying controls for parents

Parents shouldn't have to manage complex safety settings across dozens of different apps to keep their children safe. The Play Age Signals API simplifies this by putting age-sharing controls in one place, directly inside the Google Family Link app. Parents have a choice to share their child’s age range, and if they choose to share, all Play apps that use Play Age Signals API can receive age signals. This lets children jump straight into age-appropriate content without parents having to manually configure settings inside these apps. Age ranges are never shared by default, and parents can update or turn off these settings at any time.

Centralized and easy way to manage age sharing settings for parents via Family Link App

Building on our broader safety tools

The Play Age Signals API builds upon a strong foundation of established safety features and strict policies we have long enforced on Google Play. Today, we already mandate that apps designed for families meet rigorous safety standards, and we continuously review and scan applications to ensure they are safe for children. For developers, we also offer built-in tools like Restrict Minor Access in the Play Console to help them manage who can discover their apps. For parents, Google Family Link remains a trusted, central dashboard where they can manage screen-time limits, PIN-based content filters, and app download approvals.

Expanding the Play Age Signals API globally adds a powerful new tool to our existing safety suite, helping parents and developers work together to make Google Play an even safer, more trustworthy place for families.


Inside Android Skills - Built for deprecation

Posted by Jose Alcérreca, Developer Relations Engineer, Android Developer Relations

We released the official Android Skills in April, and the response surpassed all our expectations. In this blog post, I'll address some of the feedback we received, explaining the philosophy and methodology behind the project. Hopefully, this will also help you understand what happens behind the scenes when you install and use skills, allowing you to make better use of tokens and your own time.

Why are there so few official skills?

Currently, we only consider new skills when there's a verifiable knowledge gap in state-of-the-art (SOTA) models. Put simply: you don't need to teach the model what it already knows. (Though there are a few exceptions—read on!)

We’ve released around 20 official skills so far, and they intentionally target highly specific, fast-moving areas that standard models aren't fully grounded on yet—things like AGP 9, Navigation 3, advanced Camera APIs, and Perfetto SQL.

What about core, more general, skills? Every installed skill injects 100–200 tokens into the baseline context of every task you start. If that skill actually activates, that count can quickly jump into the thousands. In most cases, hoarding basic skills is both counterproductive and expensive. Before installing a skill for writing basic Kotlin or Compose, consider if your LLM of choice really needs it, or if it knows those topics well enough already.

Evaluating skills

Before their release, each skill is tested against a comprehensive set of evals that prove that the skill delivers clear value. These evals should pass when the skill is active, and fail otherwise. Evals are to skills what integration tests are to code.

timeout_s: 1200
repository:
  url: [redacted - internal git repo]
  working_dir: wear_compose_m3_empty_app
category_ids:
  - wear
prompt: |-
  Add a horizontal pager to MainActivity.kt. Have three pages in the pager. Each page should contain
  the text "Page 1", "Page 2", and "Page 3" respectively in the center of the screen.
commands:
  build:
    - ./gradlew assembleDebug
acceptance_criteria:
  project_builds: true
  llm_diff_judge:
    - Must use `HorizontalPagerScaffold`.
    - Each page should use `AnimatedPage` to wrap a `ScreenScaffold`.

Example eval that checks the correct implementation of a horizontal pager on a wear app

At a minimum, we test the skill in Android Studio using the latest Gemini Flash model. Depending on the skill, we also ensure compatibility with other models such as Gemini Pro and other agents such as Antigravity, and third-party systems.

All of the evals run with access to the Knowledge Base, so if the information is in the documentation, and models decide to search for it, we don't publish a skill for it.

Using the Android Knowledge Base (Android Studio or Android CLI)

If you develop Android apps, you should always use the Android Knowledge Base to have access to the official documentation. If you use the agent in Android Studio, it's already available as a tool, but if you use another agent, install Android CLI. Among other things, it contains the docs command, which gives your agent access to the official Android documentation. Having a single tool is much more efficient than installing hundreds of skills.

If your model is acting overconfident, and you want it to consult the documentation more often, a very common way to motivate it is to add "Always consult the official Android documentation when dealing with Android APIs" to your AGENTS.md file or equivalent. Of course, you can also force this by asking the agent to check the documentation directly in your prompts.

Why are pull requests disabled?

Because our evaluation framework depends on internal infrastructure that cannot be open-sourced, we are unable to accept direct pull requests for new skills—without this infrastructure, we would have no way to re-evaluate incoming PR changes. However, we actively monitor community feedback. If you want to report a bug, suggest an optimization, or request a new official skill, please file an issue!

When do core or basic skills make sense?

While SOTA models generally don't need basic skills, there are some scenarios where enabling core or community-built skills adds real value. For example:

  • You're using vague prompts: Skills amplify your intent. If you give a loose prompt like "add animations to this screen," a specific Compose animation skill can inspire the model, pushing it toward modern APIs or screenshot testing patterns it might not have otherwise considered.
  • You want to use smaller, cheaper models: Frontier LLMs are expensive. If you are offloading routine tasks to smaller open-weight models like Gemma 4, enabling basic skills fills the knowledge gaps that smaller parameters miss.
  • You're refactoring or reviewing legacy code: Models excel at generating code that works, but when editing old codebases, they often prioritize staying consistent with the surrounding legacy patterns over rewriting things with modern accuracy. A specialized reviewer agent equipped with core skills can help break that habit.
  • You deviate from the norm: LLMs love the standard "Google way" of architecting Android apps. If your team uses a highly customized view-layer architecture, the model will struggle to stay aligned. A custom skill explicitly describing your architecture goes a long way.

Where can I find core skills?

The Android community has your back. Chris Banes has a comprehensive collection of skills for Compose and Kotlin, Ivan Morgillo published a skill that audits Compose projects, and Jaewoong Eum created two on testing and performance.

Always download skills from reputable sources! I personally wouldn't trust repositories containing dozens or hundreds of Android skills as they're probably AI-generated and untested, and they could even contain malicious or biased instructions. Also, don't install general software engineering skills blindly; a lot of them are tailored for web development.

Goal: deprecation

Loosely paraphrasing Karpathy: Skills of today will be in the models of tomorrow. As SOTA models keep improving, we expect skills to be obsolete, especially those built around new APIs. To figure out when to retire them, we run our evals when new models drop. If they pass, we'll keep them around for a few months until most users have transitioned over.

Chrome 86: Improved Focus Highlighting, WebHID, and More

Unless otherwise noted, changes described below apply to the newest Chrome beta channel release for Android, Chrome OS, Linux, macOS, and Windows. Learn more about the features listed here through the provided links or from the list on ChromeStatus.com. Chrome 86 is beta as of September 3, 2020.

CSS Pseudo-Class: focus-visible and the Quick Focus Highlight

For users who rely on a keyboard or similar assistive technology to navigate the web, the focus indicator is a crucial visual affordance. To improve both the user and developer experience of working with focus, Chrome 86 is introducing two features.

The first is a CSS selector, :focus-visible, which lets a developer opt-in to the same heuristic the browser uses when it's deciding whether to display a default focus indicator.

The second is a user setting called Quick Focus Highlight. When enabled, this setting causes an additional focus indicator to appear over the active element. Importantly, this indicator will be visible even if the page has disabled focus styles with CSS and it causes any :focus or :focus-visible styles to always be displayed. For details, see Giving users and developers more control over focus.

An animation of the quick focus highlight showing how it temporarily highlights a link in a line of text and then fades out to not obscure the text content.

WebHID API

Note: The origin trial for this feature was originally announced as starting in Chrome 85. That timeline changed.

There is a long tail of human interface devices (HIDs) that are too new, too old, or too uncommon to be accessible by systems' device drivers. The WebHID API solves this by providing a way to implement device-specific logic in JavaScript.

An HID is one that takes input from or provides output to humans. Examples of devices include keyboards, pointing devices (mice, touchscreens, etc.), and gamepads.

The inability to access uncommon or unusual HID devices is particularly painful when it comes to gamepad support. Gamepad inputs and outputs are not well standardized and web browsers often require custom logic for specific devices. This is unsustainable and results in poor support for the long tail of older and uncommon devices.

We're working on an article to show you how to use the new API. In the meantime, we've found some demos from a few eager engineers that you can use to try the new API. To see those demos, check out Human interface devices on the web: a few quick examples. The Origin Trials section has information on signing up and a list of other origin trials starting in this release. This origin trial is expected to run through Chrome 87 in January 2021.

Origin Trials

This version of Chrome introduces the origin trials described below. Origin trials allow you to try new features and give feedback on usability, practicality, and effectiveness to the web standards community. To register for any of the origin trials currently supported in Chrome, including the ones described below, visit the Origin Trials dashboard. To learn more about origin trials themselves, visit the Origin Trials Guide for Web Developers.

New Origin Trials

Cross-Screen Window Placement

Adds new screen information APIs and makes incremental improvements to existing window placement APIs, allowing web applications to offer compelling multi-screen experiences.

The existing window.screen property offers a limited view of available screen space, while window placement functions are generally restricted to the current screen. This feature unlocks modern multi-screen capabilities for web applications.

battery-savings Meta Tag

Adds a meta tag allowing a site to recommend measures for the user agent to apply in order to save battery life and optimize CPU usage. Websites that are known to have high CPU or battery costs may want to request that the UA optimize for CPU or battery, even if the user has not requested it. Most modern operating systems also have battery saving features that activate either when the battery is low or the user wishes to save battery. Ideally web sites should be able to respect these settings. Sites may wish to advise the user agent on which strategies work best for the site in these situations.

Secure Payment Confirmation

Secure payment confirmation augments the payment authentication experience on the web with the help of the Web Authentication API. The feature adds a new PaymentCredential credential type to the Credential Management API, which allows a relying party such as a bank to create a PublicKeyCredential that can be queried by any merchant origin as part of an online checkout via the Payment Request API using the proposed secure-payment-confirmation payment method.

This feature enables a consistent, low friction, strong authentication experience using platform authenticators. Strong authentication with the user's bank is becoming a requirement for online payments in many regions, including the European Union. The new feature provides a better user experience and stronger security than existing solutions.

Cross-Origin-Opener-Policy Reporting API

Adds a reporting API to help developers deploy cross-origin opener policy (COOP) on their websites. In addition to reporting breakages when COOP is enforced, it proves a report-only mode that reports potential breakages that would have happened had COOP been enforced. To register for the origin trial, follow the link above. For more information, see Making your website "cross-origin isolated" using COOP and COEP.

Completed Origin Trials

The following features, previously in a Chrome origin trial, are now enabled by default.

Native File System

The new Native File System API enables developers to build powerful web apps that interact with files on the user's local device such as IDEs, photo and video editors, text editors, and more. After a user grants access, this API allows web apps to read or save changes directly to files and folders on the user's device. It does all this by invoking the platform's own open and save dialog boxes. The image below shows a web page invoked using the open dialog box on Mac.

To learn more, see sample code, and a text editor demonstration app, see The Native File System API: Simplifying access to local files for details.

Note: The API surface is changed considerably from what was available in the origin trial. Differences are explained in detail in the spec repo. In the coming weeks, watch the web.dev article listed above for a full explanation of how to use the production version of the API.

Other Features in This Release

Altitude and Azimuth for PointerEvents v3

Adds Altitude and Azimuth angles to PointerEvents. Adds tiltX and tiltY to altitude and azimuth transformation and altitude and azimuth to tiltX and tiltY transformation depending on which pair is available from the device. These angles are those commonly measured by devices. Altitude and azimuth can be calculated using trigonometry from tiltX, tiltY. From a hardware perspective it is easier and less expensive to measure tiltX and tiltY.

From a stylus app perspective altitude and azimuth makes more sense and is more intuitive for users. Using tiltX and tiltY requires a developer to visualize the intersection angle between two imaginary planes, while azimuth and altitude are easier to visualize just by looking at the pen and the screen surface.

Adding azimuth and altitude makes the API more intuitive. Providing conversion between tiltX and tiltY and altitude and azimuth and vice versa allows for backwards compatibility with apps using tiltX and tiltY (even if newer devices might only return altitude and azimuth).

A Well-Known URL for Changing Passwords

Websites can set a well-known URL for changing passwords (for example, /.well-known/change-password). This URL's purpose is to redirect users to the change password page in order for them to modify their passwords quickly. Chrome leverages this URL to help users change their passwords when it detects a saved, compromised password. For more information, see Help users change passwords easily by adding a well-known URL for changing passwords.

Change Encoding of Space Character when URLs are Computed by Custom Protocol Handlers

The navigator.registerProtocolHandler() handler now replaces spaces with "%20" instead of "+". This makes Chrome consistent with other browsers such as Firefox.

CSS ::marker Pseudo-Element

Adds a pseudo-element for customizing numbers and bullets for <ul> and <ol> elements. This change lets developers control the color, size, bullet shape, and number type.

Document-Policy Header

Document Policy restricts the surface area of the web platform on a per-document basis, similar to iframe sandboxing, but more flexibly. It can do things like:

  • Restrict the use of poorly-performing images.
  • Disable slow synchronous JavaScript APIs.
  • Configure iframe, image, or script loading styles.
  • Restrict overall document sizes or network usage.
  • Restrict patterns which cause page re-layout.

Additionally, the header allows sites to opt out of fragment and text-fragment scrolling on load as a privacy mitigation for the scroll-to-text-fragment feature. This is the first part of the Document Policy API to ship.

EME persistent-usage-record Session

Adds a new MediaKeySessionType named "persistent-usage-record session", for which the license and keys are not persisted and for which a record of key usage is persisted when the keys available within the session are destroyed. This feature may help content providers understand how decryption keys are used for purposes like fraud detection.

FetchEvent.handled

A FetchEvent dispatched to a service worker is in a loading pipeline, which is performance sensitive. The new FetchEvent.handled property returns a promise that resolves when a response is returned from a service worker to its client. This enables a service worker to delay tasks that can only run after responses are complete.

HTMLMediaElement.preservesPitch

Adds a property to determine whether the pitch of an audio or video element should be preserved when adjusting the playback rate. This feature is wanted for creative purposes (for example, pitch-shifting in "DJ deck" style applications). It also prevents the introduction of artifacts from pitch-preserving algorithms at playback speeds very close to 1.00. It is already supported by Safari and Firefox.

Imperative Shadow DOM Distribution API

Web developers can now explicitly set the assigned nodes for a slot element. This solves two problems with Shadow DOM v1:

  • Web developers must specify a slot attribute for every one of a shadow host's children (except for elements for the default slot).
  • Component creators can't change the slotting behavior based on conditions.

For information on how the new API solves these issues, see the Imperative Shadow DOM Distribution API explainer.

Move window.location.fragmentDirective

The window.location.fragmentDirective property has been moved to document.fragmentDirective. This is a change to the text fragments feature.

New Display Values for the <fieldset> Element

The <fieldset> element now supports 'inline-grid', 'grid', 'inline-flex', and 'flex' keywords for the CSS 'display' property.

ParentNode.replaceChildren() Method

Adds a method to replace all children of the ParentNode with the passed-in nodes. Previously, there are a couple different ways to replace a node's children with a new set of nodes including:

  • Using node.innerHTML and node.append() to clear and replace all child nodes.
  • Using node.removeChild() and node.append() in a loop.

Safelist Distributed Web Schemes for registerProtocolHandler()

Chrome has extended the list of URL schemes that can be overridden via registerProtocolHandler() to include cabal, dat, did, dweb, ethereum, hyper, ipfs, ipns, and ssb. Extending the list to include decentralized web protocols allows resolution of links to generic entities independently of the website or gateway that's providing access to it. For more information, see Programmable Custom Protocol Handlers at are we distributed yet?

text/html Support for the Asynchronous Clipboard API

The Asynchronous Clipboard API currently does not support the text/html format. Chrome 86 adds support for copying and pasting HTML from the clipboard. The HTML is sanitized when it is read and written to the clipboard. The purpose of this change is to allow use cases such as:

  • Web editors, to copy and paste rich text with images and links.
  • Remote desktop applications, to synchronize text/html payloads across devices.

This is also intended to help the replacement of document.execCommand() for copy and paste functionality.

VP9 for macOS Big Sur

The VP9 video codec is now available on macOS Big Sur whenever it's supported in the underlying hardware. If developers use the Media Capabilities API to detect playback smoothness and power efficiency, the logic in their player should automatically start preferring VP9 at higher resolutions without any action on their part. To take full advantage of this feature, developers should encode their VP9 files in multiple resolutions to accommodate varying user bandwidths and connections.

WebRTC Insertable Streams

Enables the insertion of user-defined processing steps in the encoding and decoding of a WebRTC MediaStreamTrack. This allows applications to insert custom data processing. An important use case this supports is end-to-end encryption of the encoded data transferred between RTCPeerConnections via an intermediate server.

Deprecations, and Removals

This version of Chrome introduces the deprecations and removals listed below. Visit ChromeStatus.com for lists of current deprecations and previous removals.

Remove WebComponents v0 from WebView

Web Components v0 was removed from desktop and Android in Chrome 80. Chromium 86 removes them from WebView. This removal includes Custom Elements v0, Shadow DOM v0, and HTML Imports.

Deprecate FTP Support

Chrome is deprecating and removing support for FTP URLs. The current FTP implementation in Google Chrome has no support for encrypted connections (FTPS), or proxies. Usage of FTP in the browser is sufficiently low that it is no longer viable to invest in improving the existing FTP client. In addition, more capable FTP clients are available on all affected platforms.

Chrome 72 and later removed support for fetching document subresources over FTP and rendering of top level FTP resources. Currently navigating to FTP URLs results in showing a directory listing or a download depending on the type of resource. A bug in Google Chrome 74 and later resulted in dropping support for accessing FTP URLs over HTTP proxies. Proxy support for FTP was removed entirely in Google Chrome 76.

The remaining capabilities of Google Chrome's FTP implementation are restricted to either displaying a directory listing or downloading a resource over unencrypted connections.

Deprecation of support will follow this timeline:

Chrome 86

FTP is still enabled by default for most users, but turned off for pre-release channels (Canary and Beta) and will be experimentally turned off for one percent of stable users. In this version you can re-enable it from the command line using either the --enable-ftp command line flag or the --enable-features=FtpProtocol flag.

Chrome 87

FTP support will be disabled by default for fifty percent of users but can be enabled using the flags listed above.

Chrome 88

FTP support will be disabled.

Chrome Beta for Android Update

 Hi everyone! We've just released Chrome Beta 86 (86.0.4240.16) for Android: it's now available on Google Play.

You can see a partial list of the changes in the Git log. For details on new features, check out the Chromium blog, and for details on web platform updates, check here.

If you find a new issue, please let us know by filing a bug.

Ben Mason
Google Chrome

Beta Channel Update for Desktop

The Chrome team is excited to announce the promotion of Chrome 86 to the beta channel for Windows, Mac and Linux. Chrome 86.0.4240.22 contains our usual under-the-hood performance and stability tweaks, but there are also some cool new features to explore - please head to the Chromium blog to learn more!



A full list of changes in this build is available in the log. Interested in switching release channels?  Find out how here. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.



Google Chrome
Prudhvikumar Bommana

Giving users and developers more control over focus

Chrome 86 introduces two new features that improve both the user and developer experience when it comes to working with focus.


The :focus-visible pseudo-class is a CSS selector that lets developers opt-in to the same heuristic the browser uses when it's deciding whether to show a default focus indicator. This makes styling focus more predictable.


The Quick Focus Highlight is a user preference that causes the currently focused element to display an indicator for two seconds. The Quick Focus Highlight will always display, even if a page has disabled focus styles using CSS. It will also cause all CSS focus styles to match regardless of the input device that is interacting with the page.


An animation of the quick focus highlight showing how it temporarily highlights a link in a line of text and then fades out to not obscure the text content.

What is focus?

When a user interacts with an element the browser will often show an indicator to signal that the element has "focus". This is sometimes referred to as the "focus ring" because browsers typically put a solid or dashed ring around the focused element.


A button with a default blue focus ring


The focus ring signals to the user which element will receive keyboard events. If a user is tabbing through a form, the focus ring indicates which text field they can type into, or if they've focused a submit button they will know that pressing Enter or Spacebar will activate that button.

Problems with focus

For users who rely on a keyboard or other assistive technology to access the page, the focus ring acts as their mouse pointer - it's how they know what they are interacting with.


Unfortunately, many websites hide the focus ring using CSS. Oftentimes they do this because the underlying behavior of focus can be difficult to understand, and styling focus can have surprising consequences.


For example, a custom dropdown menu should use the tabindex attribute to make itself keyboard operable. But adding a tabindex to an element causes all browsers to show a focus ring on that element if it is clicked with a mouse. If a developer is surprised to see the focus ring when they click the menu, they might use the following CSS to hide it:


.custom-dropdown-menu:focus {
  outline: none;
}

This "fixes" their issue, insofar as they no longer see the focus ring when they click the menu. However, they have unknowingly broken the experience for users relying on a keyboard to access the page. As mentioned earlier, for users who rely on a keyboard to access the page, the focus ring acts as their mouse pointer. Therefore, CSS that removes the focus ring (without providing an alternative) is akin to hiding the mouse pointer.


To improve on this situation, developers need a better way to style focus - one that matches their expectations of how focus should work, and doesn't run the risk of breaking the experience for users. At the same time, users need to have the final say in the experience and should be able to choose when and how they see focus. This is where :focus-visible and the Quick Focus Highlight come in.

:focus-visible

Whenever you click on an element, browsers use an internal heuristic to determine whether they should display a default focus indicator. This is why in Chrome tabbing to a <button> shows a focus ring, but clicking it with a mouse does not. 


When you use :focus to style an element, it tells the browser to ignore its heuristic and to always show your focus style. For some situations this can break the user's expectation and lead to a confusing experience.


:focus-visible, on the other hand, will invoke the same heuristic that the browser uses when it's deciding whether to show the default focus indicator. This allows focus styles to feel more intuitive. In Chrome 86 and beyond, this should be all you need to style focus:


/* Focusing the button with a keyboard will show a dashed black line. */
button:focus-visible {
  outline: 4px dashed black;
}

By combining :focus-visible with :focus you can take things a step further and provide different focus styles depending on the user's input device. This can be helpful if you want the focus indicator to depend  on the precision of the input device:


/* Focusing the button with a keyboard will show a dashed black line. */
button:focus-visible {
  outline: 4px dashed black;
}
  
/* Focusing the button with a mouse, touch, or stylus will show a subtle drop shadow. */
button:focus:not(:focus-visible) {
  outline: none;
  box-shadow: 1px 1px 5px rgba(1, 1, 0, .7);
}

The snippet above says that if the browser would normally show a focus indicator, then it should do so using a 4px dashed black outline. Additionally, the example relies on the existing :focus behavior and says that if an element has focus, but the browser would not normally show a default focus ring, then it should show a drop shadow. 


Since the browser doesn't usually show a default focus ring when a user clicks on  a button, the :focus:not(:focus-visible) pattern can be an easy way to specifically target mouse/touch focus.


Note that not all browsers set focus in the same way, so the above snippet will work in Chromium based browsers, but may not work in others.

The :focus-visible heuristic

Understanding the browsers’ heuristics for focus indicators will help you understand when to use :focus-visible. Unfortunately, the heuristic has never been specified, so the behavior is subtly different in every browser. The :focus-visible specification suggests one possible heuristic based on the behavior browsers currently demonstrate. Here's a quick breakdown:


Has the user expressed a preference to always see a focus indicator?

If the user has indicated that they always want to see a focus indicator, then :focus-visible will always match on the focused element, just like :focus does.


Does the element require text input?

:focus-visible will always match when an element which requires text input (for example, <input type="text">) is focused.


A quick way to know if an element is likely to require text input is to ask yourself "If I were to tap on this element using a mobile device, would I expect to see a virtual keyboard?" If the answer is "yes" then the element will match :focus-visible.


What input device is being used?

If the user is using a keyboard to navigate the page, then :focus-visible will match on any interactive element (including any element with tabindex) which becomes focused. If they're using a mouse or touch screen, then it will only match if the focused element requires text input. 


Was focus moved programmatically?

If focus is moved programmatically by calling focus(), the newly focused element will only match :focus-visible if the previously focused element matched it as well. 


For example, if a user presses a physical key, and the event handler opens a menu and moves focus to the first menu item, :focus-visible will still match and the menu item will have a focus style.


Because mouse users may frequently use keyboard shortcuts, Chrome's implementation will bypass "keyboard mode" if a meta key (such as command, control, etc.) is pressed. For example, if a user who was previously using a mouse pressed a keyboard shortcut which shows a settings dialog, :focus-visible would not match on the focused element in the settings dialog.

Support and polyfill

Currently, :focus-visible is only supported in Chrome 86 and other Chromium-based browsers, though there's work underway to add support to Firefox. Refer to the MDN browser compatibility table to keep track of current support.


If you'd like to use :focus-visible today you can do so with the help of the :focus-visible polyfill. Once the polyfill is loaded, you can use the .focus-visible class instead of :focus-visible to achieve similar results:


/* Define mouse/touch focus indicators. */
.js-focus-visible :focus:not(.focus-visible) {
  …
}
  
/* Define keyboard focus indicators. */
.js-focus-visible .focus-visible {
  …
}

Note that the MDN support table shows Firefox supports a similar selector known as :-moz-focusring which :focus-visible is based on; however the behavior between the two selectors is quite different and it's recommended to use the :focus-visible polyfill if you need cross-browser support.


Quick Focus Highlight

:focus-visible makes it easier for developers to selectively style focus and avoids pitfalls with the existing :focus selector. While this is a great addition to the developer toolbox, for a subset of users, particularly those with cognitive impairments, it can be helpful to always see a focus indicator, and they may find it distressing when the focus indicator appears less often due to selective styling with :focus-visible.


For these users, Chrome 86 adds a setting called Quick Focus Highlight.


Quick Focus Highlight temporarily highlights the currently focused element, and causes :focus-visible to always match.


To enable Quick Focus Highlight:


  1. Go to Chrome's settings menu (or type chrome://settings into the address bar).

  2. Click Advanced then Accessibility.

  3. Enable the toggle switch to Show a quick highlight on the focused object.


Once Quick Focus Highlight is enabled, focused elements will show a white-blue outline with a blue glow. (See the image below.). The Highlight uses these alternating colors to ensure that it has proper contrast on any background.


The quick focus highlight on a white, black, and blue background. The rings are visible in all scenarios.


The Highlight is outset from the focused element to avoid interfering with that element's existing focus styles or drop shadows. The Highlight will fade out after two seconds to avoid obscuring page content, such as text.


FAQ

User-input can be multi-modal, for example some 2-in-1 laptops support mouse, keyboard, touch, and stylus. How does :focus-visible work with these devices?

Because :focus-visible uses the same heuristic as a default focus indicator, the experience should match what users expect on these platforms when they interact with unstyled HTML elements.


In other words, if developers use :focus-visible as their primary means to style focus, then the experience should be more consistent for all users regardless of their input device.

Does :focus-visible expose sensitive information?

Most of the time, :focus-visible matching only indicates that a user is using the keyboard, or has focused an element which takes text input.


:focus-visible could potentially be used to detect that a user has enabled a preference to always show a focus indicator, by tracking mouse and keyboard events and checking matches(":focus-visible") on elements which were focused when the keyboard is not being used. Since the precise details of when :focus-visible should match are left up to the browser's implementation, this would not be a completely reliable method.

What's the impact on users with low vision or cognitive impairments?

:focus-visible and the Quick Focus Highlight were designed to work together to help these users.


:focus-visible aims to address the common anti-pattern of developers removing the focus indicator from all of their controls. Using the browser's focus heuristic helps by creating fewer surprises for developers when the focus ring appears, meaning fewer reasons to use CSS to hide the ring.


For some users the browser's default behavior may still be insufficient. They may want to see a focus ring regardless of the type of control they're interacting with, or the input device they're using. That's where the Quick Focus Highlight can help.


The Quick Focus Highlight lets users increase the visibility of the focus indicator, and makes it so :focus-visible always matches, regardless of their input device. This combination of effects should make the currently focused element much easier to identify.


Why not have an "alway on" focus indicator?

The Quick Focus Highlight does not currently support an "always on" mode because it's difficult to design a universal focus overlay that does not obscure page content. As a result, the Highlight will fade out after two seconds, and rely on either the browser's default focus indicator, or the page author's :focus and :focus-visible styles.


Because the Highlight is a user preference its behavior can be changed in the future if users would prefer that it always stay on.

Should we also add :focus-visible-within?

There has been discussion around adding :focus-visible-within, but a proposal will require additional use cases. If you feel like you have a good use case for :focus-visible-within please add it to the discussion issue.


We welcome your feedback!

:focus-visible and the Quick Focus Highlight are the product of years of work and feedback from developers in the :focus-visible WICG repo and the standards bodies. We'd like to say thank you to everyone who helped shape these features.


Give :focus-visible and the new Highlight a shot, and tell us what you think.

If you've found an issue with the Quick Focus Highlight, attach a screenshot and send it to our support tracker.

If you've found an issue with :focus-visible, use this template to file a chromium bug.