We baked in cross-site tracking prevention in all Safari browsing through our cookie policy, starting with Safari 1.0 in 2003. And we’ve increased privacy protections incrementally over the last 20 years. (Learn more by reading Tracking Prevention in Webkit.) Other popular browsers have not been as quick to follow our lead in tracking prevention but there is progress.
Apple believes that users should not be tracked across the web without their knowledge or their consent. Entering Private Browsing is a strong signal that the user wants the best possible protection against privacy invasions, while still being able to enjoy and utilize the web. Staying with the 2005 definition of private mode as only being ephemeral, such as Chrome’s Incognito Mode, simply doesn’t cut it anymore. Users expect and deserve more.
So, we decided to take Private Browsing further and add even more protection beyond the normal Safari experience. Last September, we added a whole new level of privacy protections to Private Browsing in Safari 17.0. And we enhanced it even further in Safari 17.2 and Safari 17.5. Plus, when a user enables them, all of the new safeguards are available in regular Safari browsing too.
With this work we’ve enhanced web privacy immensely and hope to set a new industry standard for what Private Browsing should be.
These are the protections and defenses added to Private Browsing in Safari 17.0:
In addition, we added these protections and defenses in all browsing modes:
We also expanded Web AdAttributionKit (formerly Private Click Measurement) as a replacement for tracking parameters in URL to help developers understand the performance of their marketing campaigns even under Private Browsing.
However, before we dive into these new and enhanced privacy protections, let’s first consider an important aspect of these changes: website compatibility risk.
There are many ideas for how to protect privacy on the web, but unfortunately many of them may break the user’s experience. Like security protections in real life, a balance must be struck. The new Private Browsing goes right up to the line, attempting to never break websites. But of course there is a risk that some parts of some sites won’t work. To solve this, we give users affordances to reduce privacy protections on a per-site basis. Such a change in privacy protections is only remembered while browsing within a site. This option is a last resort when a web page is not usable due to the privacy protections.
All of the new privacy protections in Private Browsing are also available in regular browsing. On iOS, iPadOS and visionOS go to Settings > Apps > Safari > Advanced > Advanced Tracking and Fingerprinting Protection and enable “All Browsing”. On macOS go to Safari > Settings > Advanced and enable “Use advanced tracking and fingerprinting protection”:
Let’s now walk through how these enhancements work.
Safari’s Private Browsing implements two new protections against tracking information in the destination URL when the user navigates between different websites. The specific parts of the URL covered are query parameters and the fragment. The goal of these protections is to make it more difficult for third-party scripts running on the destination site to correlate user activity across websites by reading the URL.
Let’s consider an example where the user clicks a link on clickSource.example
, which takes them to clickDestination.example.
The URL looks like this:
https://clickDestination.example/article?known_tracking_param=123&campaign=abc&click_val=456
Safari removes a subset of query parameters that have been identified as being used for pervasive cross-site tracking granular to users or clicks. This is done prior to navigation, such that these values are never propagated over the network. If known_tracking_param
above represents such a query parameter, the URL that’s used for navigation will be:
https://clickDestination.example/article?campaign=abc&click_val=456
As its name suggests, the campaign
above represents a parameter that’s only used for campaign attribution, as opposed to click or user-level tracking. Safari allows such parameters to pass through.
Finally, on the destination site after a cross-site navigation, all third-party scripts that attempt to read the full URL (e.g. using location.search
, location.href
, or document.URL
) will get a version of the URL that has no query parameters or fragment. In our example, this script-exposed value is simply:
https://clickDestination.example/article
In a similar vein, Safari also hides cross-site any document.referrer
from script access in Private Browsing.
Web AdAttributionKit (formerly Private Click Measurement) is a way for advertisers, websites, and apps to implement ad attribution and click measurement in a privacy-preserving way. You can read more about it here. Alongside the new suite of enhanced privacy protections in Private Browsing, Safari also brings a version of Web AdAttributionKit to Private Browsing. This allows click measurement and attribution to continue working in a privacy-preserving manner.
Web AdAttributionKit in Private Browsing works the same way as it does in normal browsing, but with some limits:
Safari 17.0 also comes with an automatically enabled content blocker in Private Browsing, which blocks network loads to known trackers. While Intelligent Tracking Prevention has long blocked all third party cookies, blocking trackers’ network requests from leaving the user’s device in the first place ensures that no personal information or tracking parameters are exfiltrated through the URL itself.
This automatically enabled content blocker is compiled using data from DuckDuckGo and from the EasyPrivacy filtering rules from EasyList. The requests flagged by this content blocker are only entries that are flagged as trackers by both DuckDuckGo and EasyPrivacy. In doing so, Safari intentionally allows most ads to continue loading even in Private Browsing.
Private Browsing also blocks cloaked network requests to known tracking domains. They otherwise have the ability to save third party cookies in a first-party context. This protection requires macOS Sonoma or iOS 17. By cloaked we mean subdomains mapped to a third-party server via CNAME cloaking or third-party IP address cloaking. See also the “Defending Against Cloaked First Party IP Addresses” section below.
When Safari blocks a network request to a known tracker, a console message of this form is logged, and can be viewed using Web Inspector:
`Blocked connection to known tracker: tracker.example`
Safari 15.0 started hiding IP addresses from known trackers by default. Private Browsing in Safari 17.0 adds the following protections for all users:
Additionally, for iCloud+ subscribers who have iCloud Private Relay turned on, Private Browsing takes privacy to the next level with these enhancements:
Safari 17.0 also boosts the privacy of Extensions in Private Browsing. Extensions that can access website data and browsing history are now off by default in Private Browsing. Users can still choose to allow an extension to run in Private Browsing and gain all of the extension’s utility. Extensions that don’t access webpage contents or browsing history, like Content Blockers, are turned on by default in Private Browsing when turned on in Safari.
With Safari and subsequently other browsers restricting stateful tracking (e.g. cross-site cookies), many trackers have turned to stateless tracking, often referred to as fingerprinting.
We distinguish these types of fingerprinting:
A challenge for any tracker trying to create a fingerprint is how stable the fingerprint will be over time. Software version fingerprinting changes with software updates, web extension fingerprinting changes with extension updates and enablement/disablement, user settings change when the user wants, multiple users of the same device means behavior fingerprints change, and roaming devices may change network and geographic position a lot.
Fingerprints can be used to track the user across websites. If successful, it defeats tracking preventions such as storage partitioning and link decoration filtering.
There are two types of solutions to this problem:
Less talked about is the fingerprinting problem of per-site user recall. Web browsers offer at least two ways for the user to reset their relationship with a website: Clear website data or use Private Browsing. Both make a subsequent navigation to a website start out fresh.
But fingerprinting defeats this and allows a website to remember the user even though they’ve opted to clear website data or use Private Browsing.
There are two types of solutions to this problem:
The ultimate anti fingerprinting challenge in our view is to address a specific user’s uniqueness when visiting a specific website. Here’s a simple example:
Having the locale setting to US/EN for American English may provide ample herd immunity in many cases. But what happens when a user with that setting visits an Icelandic government website or a Korean reading club website? They may find themselves in a very small “herd” on that particular website and combined with just a few more fingerprinting touch points they can be uniquely identified.
Addressing per-site visitor uniqueness is not possible in general by a browser unless it knows what the spread of visitors looks like for individual websites.
We view cross-site tracking and per-site user recall as privacy problems to be addressed by browsers.
Our approach:
Make the fingerprint unique per website, and generate a new unique fingerprint for every fresh start such as at website data removal.
Our tools:
Safari’s new advanced fingerprinting protections make it difficult for scripts to reliably extract high-entropy data through the use of several web APIs:
AudioBuffer
samples using WebAudio.Many modern web browsers use a computer’s graphics processing unit (GPU) to accelerate rendering graphics. The Web’s Canvas API (2D Canvas) and WebGL API give a web page the tools it needs for rendering arbitrary images and complex scenes using the GPU, and analyzing the result. These APIs are valuable for the web platform, but they allow the web page to learn unique details about the underlying hardware without asking for consent. With Safari’s advanced fingerprinting protections enabled, Safari applies tiny amounts of noise to pixels on the canvas that have been painted using drawing commands. These modifications reduce the value of a fingerprint when using these APIs without significantly impacting the rendered graphics.
It’s important to emphasize that:
This strategy helps mitigate many of the compatibility issues that arise from this kind of noise injection, while still maintaining robust fingerprinting mitigations.
In Safari 17.5, we’ve bolstered these protections by additionally injecting noise when reading back data from offscreen canvas in both service workers and shared workers.
Similarly, when reading samples using the WebAudio API — via AudioBuffer.getChannelData()
— a tiny amount of noise is applied to each sample to make it very difficult to reliably measure OS differences. In practice, these differences are already extremely minor. Typically due to slight differences in the order of operations when applying FFT or IFFT. As such, a relatively low amount of noise can make it substantially more difficult to obtain a stable fingerprint.
In Safari 17.5, we made audio noise injection more robust in the following ways:
AudioSourceNode
that contains a single high-entropy sample can’t be used to average out the injected noise and obtain the original value quickly.This noise injection also activates when using Audio Worklets (e.g. AudioWorkletNode
) to read back audio samples.
Lastly, for various web APIs that currently directly expose window and screen-related metrics, Safari takes a different approach: instead of the noise-injection-based mitigations described above, entropy is reduced by fixing the results to either hard-coded values, or values that match other APIs.
screen.width
/ screen.height
: The screen size is fixed to the values of innerWidth
and innerHeight
.screenX
/ screenY
: The screen position is fixed to (0, 0)
.outerWidth
/ outerHeight
: Like screen size, these values are fixed to innerWidth
and innerHeight
.These mitigations also apply when using media queries to indirectly observe the screen size.
We have worked for many years with the standards community on improving user privacy of the web platform. There are existing web APIs that are fingerprintable, such as Canvas, and reining in their fingerprintability is a long journey. Especially since we want to ensure existing websites can continue to work well.
It is key for the future privacy of the web to not compound the fingerprinting problem with new, fingerprintable APIs. There are cases where the tradeoff tells us that a rich web experience or enhanced accessibility motivates some level of fingerprintability. But in general, our position is that we should progress the web without increasing fingerprintability.
A recent example where we opposed a new proposal is the Topics API which is now shipping in the Chrome browser. We provided extensive critical feedback as part of the standards process and we’d like to highlight a few pieces here.
From the proposal:
// document.browsingTopics() returns an array of up to three topic objects in random order.
const topics = await document.browsingTopics();
Any JavaScript can call this function on a webpage. Yes, that includes tracker scripts, advertising scripts, and data broker scripts.
The topics come from a predefined list of hundreds of topics. It’s not the user who picks from these topics, but instead Chrome will record the user’s browsing history over time and deduce interests from it. The user doesn’t get told upfront which topics Chrome has tagged them with or which topics it exposes to which parties. It all happens in the background and by default.
The intent of the API is to help advertisers target users with ads based on each user’s interests even though the current website does not necessarily imply that they have those interests.
A new research paper by Yohan Beugin and Patrick McDaniel from University of Wisconsin-Madison goes into detail on Chrome’s actual implementation of the Topics API.
The authors use large scale real user browsing data (voluntarily donated) to show both how the 5% noise supposed to provide plausible deniability for users can be defeated, and how the Topics API can be used to fingerprint and re-identify users.
“We conclude that an important part of the users from this real dataset are re-identified across websites through only the observations of their topics of interest in our experiment. Thus, the real users from our dataset can be fingerprinted through the Topics API. Moreover, as can be seen, the information leakage and so, privacy violation worsen over time as more users are uniquely re-identified.” —Beugin and McDaniel, University of Wisconsin-Madison
The paper was published at the 2024 IEEE Security and Privacy Workshops (SPW) in May.
Re-identifying and tracking users is not the only privacy problem with the Topics API. There is also the profiling of users’ cross-site activity. Here’s an example using topics on Chrome’s predefined list.
Imagine in May 2024 you go to news.example
where you are a subscriber and have provided your email address. Embedded on the website, dataBroker.example
. The data broker has gleaned your email address from the login form and calls the Topics API to learn that you currently have these interests:
In May 2026 you go to news.example
where dataBroker.example
calls the Topics API and is told that you now have these interests:
Finally, in May 2029 you go to news.example
where dataBroker.example
calls the Topics API and is told that you have these interests:
You haven’t told any website with access to your email address anything that’s been going on in your family life. But the data broker has been able to read your shifting interests and store them in their permanent profile of you — while you were reading the news.
Now imagine what advanced machine learning and artificial intelligence can deduce about you based on various combinations of interest signals. What patterns will emerge when data brokers and trackers can compare and contrast across large portions of the population? Remember that they can combine the output of the Topics API with any other data points they have available, and it’s the analysis of all of it together that feeds the algorithms that try to draw conclusions about you.
We think the web should not expose such information across websites and we don’t think the browser, i.e. the user agent, should facilitate any such data collection or use.
Our defenses against cloaked third-party IP addresses and our partitioning of SessionStorage and blob URLs are enabled by default in both regular browsing and Private Browsing. Here’s how those protections work.
In 2020, Intelligent Tracking Prevention (ITP) gained the ability to cap the expiry of cookies set in third-party CNAME-cloaked HTTP responses to 7 days.
This defense did not mitigate cases where IP aliasing is used to cloak third party requests under first party subdomains. ITP now also applies a 7-day cap to the expiry of cookies in responses from cloaked third-party IP addresses. Detection of third-party IP addresses is heuristic, and may change in the future. Currently, two IP addresses are considered different parties if any of the following criteria are met:
Websites have many options for how they store information over longer time periods. Session Storage is a storage area in Safari that is scoped to the current tab. When a tab in Safari is closed, all of the session storage associated with it is destroyed. Beginning in Safari 16.1 cross-site Session Storage is partitioned by first-party web site.
Similarly, Blobs are a storage type that allow websites to store raw, file-like data in the browser. A blob can hold almost anything, from simple text to something larger and more complex like a video file. A unique URL can be created for a blob, and that URL can be used to gain access to the associated blob, as long as the blob still exists. These URLs are often referred to as Blob URLs, and a Blob URL’s lifetime is scoped to the document that creates it. Beginning in Safari 17.2, cross-site Blob URLs are partitioned by first-party web site, and first-party Blob URLs are not usable by third parties.
The additional privacy protections of Private Browsing in Safari 17.0, Safari 17.2 and Safari 17.5 set a new bar for user protection. We’re excited for all Safari users and the web itself to benefit from this work!
We love hearing from you! To share your thoughts on Private Browsing 2.0, find John Wilander on Mastodon at @wilander@mastodon.social or send a reply on X to @webkit. You can also follow WebKit on LinkedIn. If you run into any issues, we welcome your feedback on Safari UI (learn more about filing Feedback), or your WebKit bug report about web technologies or Web Inspector.
]]>This release includes WebKit changes between: 279855@main…280286@main.
:active-view-transition
pseudo-class. (280027@main) (129851076) [value]
as the first fallback step base. (280127@main) (107721910) browser.storage.set
with undefined
as a map value. (280265@main) (130282050) getTransformToElement
from SVGGraphicsElement (280208@main) (122435702) display: grid
container. (279986@main) (129366300) This release includes WebKit changes between: 279361@main…279854@main.
disclosure-open
and disclosure-closed
to point to the correct direction in right-to-left. (279404@main) (109014745) fractionalDigits
of Intl.DurationFormat
to be treated as at most 9 digits if it is omitted. (279632@main) (129145390) Fixed min-content
calculation for unstyled only-child
inlines elements. (273633@main) (128348427)
Fixed ellipsis rendering multiple times when position: relative
and top
are used. (279645@main) (128394449)
Fixed a bug for inline elements inserted in reverse order after a block in a continuation. (279422@main) (128826228)
Fixed the flash of a page background-colored bar in the footer when the window is resized. (279562@main) (128940179)
Fixed error handling for invalid filter primitive references. (279421@main) (104262208)
Fixed SVGLength
to sync with the WebIDL specification. (279659@main) (129169603)
Fixed Web Inspector to show nested workers. (279793@main) (108322385)
Fixed Accessibility inspector for switch controls to report “State: on/off” instead of “Checked: true/false”. (279772@main) (128952449)
OffscreenCanvas.transferToImageBuffer()
to clear the WebGL drawing buffer. (279434@main) (126738038) You can see how Safari in visionOS works by watching the Apple Vision Pro introduction at the WWDC23 Keynote or the session Meet Safari for spatial computing. If you don’t have your own Apple Vision Pro, and you want to experience what it’s like in person, you can book a free demo of Apple Vision Pro at your local Apple Store (in available regions).
Let’s take a look at how to use Safari’s suite of developer tools to test, inspect, and debug your site. First, you’ll learn how to use Safari developer tools with the visionOS simulator. Then, you’ll get a walkthrough of pairing Safari and Web Inspector on your Mac with Apple Vision Pro. These instructions work with for visionOS 1.2 and visionOS 2 so you can debug even if you do not have an Apple developer account.
The Mac is a powerful machine — powerful enough to run macOS, iOS, watchOS, tvOS, visionOS, and iPadOS at the same time. It’s here where app developers work on their apps, write code, and test their code in the appropriate Simulator.
You can test the website you are building in Safari inside Simulator on macOS. This lets you develop the site on your Mac, using your full development environment, with your favorite IDE, Terminal, and more. When you’re ready to test, use Web Inspector on Mac to inspect web pages running in its simulator.
At WWDC24, Apple announced visionOS 2 beta available now to developers with an Apple Developer Program membership. Xcode 16 beta includes the visionOS 2 beta simulator with Safari 18 beta. Or test in visionOS 1.2 with Safari 17.5 by downloading Xcode 15 and installing its simulator.
Here’s how to get started using the visionOS simulator:
Here’s how to get started using Safari’s developer tools on macOS:
Once you’ve completed this setup, you won’t need to repeat these steps again.
You can use Safari in visionOS to navigate to a web page, but it’s likely you already have the page open in Safari on macOS. So instead, use this tip to quickly send web pages from macOS to the visionOS simulator:
The visionOS simulator comes to the front, and the web page opens in Safari. This also works for any number of other simulators for iPhone and iPad, which you can always install later.
Learn more about using the visionOS simulator.
Web Inspector is instrumental when developing or troubleshooting web content in a simulator. To use it for a web page open in Safari in Apple Vision Pro Simulator. Click the Develop menu, select Apple Vision Pro (Simulator), and select the web page you want to inspect.
Web Inspector opens connected to the page loaded in Safari in the visionOS simulator. This brings all of the powerful inspection and debugging tools of Web Inspector to your web content loaded in Safari in any simulator. It also works for connecting to web pages loaded in Safari on iPhone, or iPad simulators.
Apple announced WebXR support with visionOS 2. If you’re using visionOS 1.2 in Apple Vision Pro or in the visionOS simulator on your Mac, you can still experience WebXR by turning on support for the testable version. You can also preview other new features like the <model>
element.
To enable support for WebXR or the <model>
element, from the the Home View, go to Settings > Apps > Safari > Advanced > Feature Flags and enable the feature flags for “HTML
Apple Vision Pro is a great place to work on a website. Use Mac Virtual Display to bring your Mac web development workflows into Apple Vision Pro. Test your site in Safari in visionOS, while debugging in Safari’s Web Inspector on macOS.
Use Apple Vision Pro as a private, portable 4K display for your Mac with Mac Virtual Display. Learn how in Use your Mac with Apple Vision Pro.
To get started connecting Safari in Apple Vision Pro with Web Inspector on macOS, you’ll need to go through a one-time set-up process that ensures only your Mac and your Apple Vision Pro have this kind of access to each other.
Now your devices are paired. You can reconnect anytime. In Safari on macOS, Apple Vision Pro will now appear in the Develop menu anytime your Apple Vision Pro is on and unlocked.
Alternatively, you can pair with Xcode.
Now you can inspect a web page that’s running in Safari in Apple Vision Pro using Web Inspector in Safari on macOS:
A Web Inspector window will open on macOS. Any changes you make will appear in Safari in visionOS.
For more information, read Inspecting visionOS.
Learn more about how to download Simulator, pair Apple Vision Pro with Mac, or use Web Inspector while creating content for visionOS by watching Rediscover Safari developer features or by reading Inspecting visionOS.
Now, we are pleased to announce WebKit for Safari 18 beta. It adds another 48 web platform features, as well as 18 deprecations and 174 bug fixes. Test it today on iOS 18 beta, iPadOS 18 beta, visionOS 2 beta, and macOS Sequoia beta.
Safari 18 for visionOS 2 beta adds support for immersive WebXR. Now you can create fully immersive experiences and deliver them on the web to people using Apple Vision Pro. Safari on visionOS 2 beta supports immersive-vr
sessions. WebXR scenes are displayed using hardware-accelerated graphics driven by WebGL.
Safari for visionOS 2 beta supports the new WebXR transient-pointer
input mode. It lets you make the most of natural input on visionOS, and allow your users to interact with a look and a pinch.
transient-pointer
in your WebXR experience to support interactions like this, where players use their hands to pinch and drag as they move chess pieces around.If you want to animate a 3D model of the user’s hands, Safari for visionOS 2 beta also includes support for WebXR hand tracking. To ensure privacy, permission to allow hand tracking will be requested from users at the start of their WebXR session.
Learn all about WebXR on visionOS 2 beta by watching Build immersive web experiences with WebXR at WWDC24, available Wednesday June 12. And learn more about transient-pointer
input mode by reading Introducing natural input for WebXR in Apple Vision Pro.
WebKit added support for the View Transitions API in Safari 18 beta. It provides an optimized browser API to animate elements from one state to another. Safari supports the CSS View Transitions Module Level 1 specification that adds new CSS properties and pseudo-elements for defining transition animations, along with a new browser API to start transition animations and react to different transition states. It works by capturing the current (old) state of the page and applying an animated transition to the new state. By default, the browser applies a cross-fade between the states.
Call the document.startViewTransition()
method to initiate the capture. You can pass a callback function as the first argument to make DOM state changes between the old and new captures. The method returns a ViewTransition object which contains promises that can be used to track when the view transition starts or ends.
Once the states are captured, a pseudo-element tree is built which can be targeted with CSS, allowing you to modify the CSS animations used for the transitions. The animations out of the old page state and into the new page state can be modified via the ::view-transition-new(*)
and ::view-transition-old(*)
selectors. You can also ask the browser to independently track state changes for a specific element by naming it with the CSS view-transition-name
property. You can then use the pseudo-element to customize animations for it.
.page-view {
view-transition-name: page-view;
}
::view-transition-old(page-view) {
animation: 500ms ease-in-out transition-out-animation;
}
::view-transition-new(page-view) {
animation: 500ms ease-in-out transition-in-animation;
}
The example below demonstrates state management with tabbed navigation. Each tab view has a custom transition animation out and a subtly different animation in, while the tabs themselves rely on the default page transition.
WebKit for Safari 18 beta adds support for Style Queries when testing CSS Custom Properties. Similar to how developers can use Sass mixins, Style Queries can be used to define a set of reusable styles that get applied as a group.
Here, if the --background
custom property is set to black, then certain styles will be applied — in this case to make the headline and paragraph text color white.
@container style(--background: black) {
h2, h3, p {
color: white;
}
}
Don’t forget to pay attention the HTML structure. By default, Style Queries reference the styles on the direct parent element. You can create a different reference through the use of Container Query names.
Support for Relative Color Syntax shipped in Safari 16.4. It lets you define colors in a more dynamic fashion, creating a new color from an existing color. The value lch(from var(--color) calc(L / 2) C H)
for instance uses the lch
color space to take the variable --color
and calculate a new color that’s half its lightness, calc(L / 2)
.
Now, starting in WebKit for Safari 18 beta, you can reference the currentcolor or a system color keyword as you define the new color. For example, this code will set the background color to be the same color as the text color, only 4 times lighter, as calculated in the oklch
color space.
section { background: oklch(from currentcolor calc(L * 4) C H); }
Being able to reference system color keywords opens up another world of options. System colors are like variables that represent the default colors established by the OS, browser, or user — defaults that change depending on whether the system is set to light mode, dark mode, high contrast mode, etc. For example, canvas
represents the current default background color of the HTML page, while fieldtext
matches the color of text inside form fields. Find the full list of system colors in CSS Color level 4.
Relative Color Syntax lets you define dynamic connections between colors in your CSS, lessening the need to control color through variables in a tightly-regimented design system. Learn more about Relative Color Syntax by watching this portion of What’s new in CSS from WWDC23.
WebKit for Safari 18 beta adds support for transition animation of the display
property.
Many developers are excited to use @starting-style
along with transition-behavior
and display: none
interpolation. WebKit for Safari 17.4 added general support for transition-behavior
, including transition-behavior: allow-discrete
. WebKit for Safari 17.5 added support for @starting-style
, letting you define starting values for transitioning an element as it’s created (or re-created). Now in WebKit for Safari 18 beta, you can use these features together to transition the display
property.
As a web developer, you’re very familiar with how link styling works on the web. For decades you’ve been able to use CSS to style text-decoration
, color
and more for :link
, :hover
, :active
, and :visited
states. You’ve also been able to adjust the size of the invisible tap target through use of padding.
Apple Vision Pro adds a new dimension to how links work — tap targets are visible on visionOS. Anytime a user looks at an interactive element, it’s highlighted to let them know that it can be tapped. And you as a designer or developer can intentionally design how an interaction region looks. You may want to add padding, for instance, or even a rounded corner to the otherwise invisible box.
Now in Safari in visionOS 2 beta, when you use CSS clip-path
to change the shape of tappable area of a link, the visible interaction region will change shape as well. Interactive UI elements built with SVG will also be highlighted with the proper shape. Learn more by watching Optimize for the spatial web at WWDC24, available Tuesday June 11.
Originally shipped in Safari 9.0, backdrop filter provides a way to apply graphics effects to the content behind a particular element. You can apply backdrop-filter
to a headline, for example, and everything behind the headline will be blurred, or have decreased saturation, or increased contrast. Any of the filter functions from SVG can be used — blur()
, brightness()
, contrast()
, drop-shadow()
, grayscale()
, hue-rotate()
, invert()
, opacity()
, saturate()
, and sepia()
.
For many years, backdrop filter only worked in Safari. It was available when you prefixed the property with -webkit-backdrop-filter
. Now, starting in Safari 18 beta, you don’t need the prefix. We also improved our implementation, fixing bugs and boosting interoperability.
This demo shows eight different filters and what you might do with each one alone. You can, of course, combine filters to create even more interesting results. With backdrop filter supported in Safari since 2015, Edge since 2018, Chrome since 2019, Samsung Internet since 2020, and Firefox since 2022, this is a great time to consider the kind of graphic design possibilities it enables.
WebKit for Safari 18 beta adds support for the safe
keyword for alignment in Flexbox. This provides a mechanism for refining how flex items overflow. Let’s look at an example of a simple navigation menu — a classic use of Flexbox.
<nav aria-label="main"><ul>
<li><a href="/us">U.S.</a></li>
<li><a href="/business">Business</a></li>
<li><a href="/investigations">Investigations</a></li>
<li><a href="/style">Style</a></li>
<li><a href="/tech">Tech</a></li>
<li><a href="/world">World</a></li>
</ul></nav>
The following CSS creates a simple layout that wraps when there’s not enough space on one line for the menu, while centering the items in the available space.
header nav {
display: flex;
flex-flow: wrap;
gap: 1.5rem;
justify-content: center; /* centers the items in the available space */
}
By default, justify-content: center
will always keep the items centered, even when the content is overflowing the containing box. You might prefer, however, that the content not be centered when it overflows — being centered cuts off both the beginning and end of the word, making the content harder to understand when the overflow is not visible.
justify-content: center
without and with the safe
keyword in this demo.The safe
keyword lets you change how alignment works when content overflows. The justify-content: safe center
rule will instead start align any item that is overflowing, while continuing to center the items that are not overflowing.
If you want to override the safe
keyword, you can use unsafe
. The justify-content: unsafe center
rule will do the same thing as justify-content: center
. The unsafe
keyword has been supported in WebKit for Safari for quite some time.
WebKit for Safari 18 beta adds support for content-visibility
. This property controls whether or not an element renders its contents in a fashion that’s useful for making performance optimizations. It lets you communicate to the browser that certain portions of the page will likely be initially offscreen, and suggest they be omitted from layout and rendering. This can make the page load faster.
Last year, we added support for web apps in macOS Sonoma. You can add any website to your dock — whether or not it was built with a Manifest file, Service Worker, or other technology to customize the web app experience. Go to the site in Safari, then File > Add to Dock… where you can customize the icon, change the name, and even clean up the URL. Then, just click on the web app icon in your Dock, and it will open as an app.
This year brings two improvements to web apps on Mac.
macOS Sequoia beta adds support for opening links directly in web apps. Now, when a user clicks a link, if it matches the scope
of a web app that the user has added to their Dock, that link will open in the web app instead of their default web browser.
For example, imagine you have added MDN Web Docs to the Dock. Then a colleague sends you a link to an MDN page in Messages, Mail, Slack, Discord, IRC, or any non-browser application on your Mac. Now when you click on that link, it will open in the MDN Web Docs web app instead of your default browser.
Clicking a link within a browser will maintain the current behavior. This feature only affects links opened elsewhere. (When a user is in Safari, clicking on a link that matches the scope
of a web app that is added to Dock, they will see an “Open in web app” banner, unless they have previously dismissed the banner.)
By default, this behavior applies when the link matches the host of the web page used to create the web app. As a developer, you can refine this experience by defining the range of URLs that should open in the web app with the scope
member in the web app manifest.
Now you can personalize web apps on Mac with Safari Web Extensions and Content Blockers. Navigate to the web app’s Settings menu to access all your installed Content Blockers and Web Extensions. Any enabled in Safari will be on by default in the web app. Each web app is uniquely customizable, just like Safari profiles.
Safari 18 beta also adds support for Mobile Device Management of extension enabled state, private browsing state, and website access on managed devices. This means schools and businesses that manage iOS, iPadOS, or macOS devices can now include the configuration of Safari App Extensions, Content Blockers, and Web Extensions in their management.
One of the amazing experiences you can have on Apple Vision Pro is looking at spatial photos and panoramas. When you open the Photos app in visionOS, you see a montage of your photos. Tap an image, it appears alone in a floating frame in front of you, while the rest of the app disappears.
A spatial photo appears at just the right height and viewing angle to make it feel like you’ve gone back to a moment in time. A second tap of the UI breaks it out of the frame, as it grows and becomes even more immersive. Similarly, a panorama floats in a frame on first tap. Then on second tap of the UI, it expands to wrap all around you, creating a fully immersive experience.
Now in Safari 18 for visionOS 2 beta, you can use the Fullscreen API to create the same experience on the web. You can embed the photo in a web page, and provide the ability to tap. The photo will pop into a floating frame as the Safari window disappears. Then when the user taps on the spatial photo or panorama UI that visionOS provides, the photo will further expand to create a fully immersive experience. When they exit the image, the Safari window will return.
Let’s walk through how to support experiencing a spatial photo or panorama on the web using Fullscreen API. First, include the image on your web page using any of the techniques we’ve used on the web for years. Here, we can embed a flattened panoramic photo into the web page using simple HTML.
<img src="panorama.jpeg" class="go-fullscreen" alt="[description]">
Then using JavaScript, we’ll trigger .requestFullscreen()
on tap. Perhaps like this.
document.querySelectorAll('.go-fullscreen').forEach(element => {
element.addEventListener('click', async () => {
await element.requestFullscreen();
});
});
You could, of course, create your own UI for the user to tap, rather than making the entire photo the tap target.
Spatial images work just the same, although it’s likely we want to provide fallbacks for browsers that do not support HEIC files. We can do so with the picture
element.
<picture>
<source srcset="spatial.heic" type="image/heic">
<source srcset="fallback.avif" type="image/avif">
<img src="fallback.jpg" class="go-fullscreen" alt="[description]" >
</picture>
Spatial images are stereoscopic, with both a left and right channel. In Safari, when the image is embedded in the web page, the browser will show the left channel. And there’s no need to worry about providing a fallback of any sort for Safari on macOS, iOS, or iPadOS — the stereoscopic HEIC file works great.
This technique will also cause images to go fullscreen in any browser that supports Fullscreen API. Learn more about adding panorama and spatial photos to your websites by watching Optimize for the spatial web at WWDC24, available Tuesday June 11.
At last year’s WWDC, Apple unveiled inline predictive text on iOS, iPadOS, macOS and more. It helps users input text faster by predicting what they might be typing and finishing the word, phrase or even a whole sentence when the user taps the space bar. Now, WebKit for Safari 18 beta on iOS, iPadOS, visionOS, macOS Sequoia and macOS Sonoma brings inline predictive text to the web.
While inline predictive text makes for a fantastic, personalized user experience, there might be specific situations on the web where it’s better to not have predictions. WebKit for Safari 18 beta on iOS, iPadOS, visionOS, macOS Sequoia and macOS Sonoma gives web developers the opportunity to disable inline predictions through the writingsuggestions
attribute. By default, writing suggestions is set to true. You can turn off the capability by including the writingsuggestions="false"
attribute on any type of text input field.
writingsuggestions
.
WebKit for Safari on iOS 18 beta adds haptic feedback for <input type=checkbox switch>
. This means, now when a user taps a switch control on iPhone, a single tap is felt — just like how toggling a switch feels in Settings app on iOS. Try this demo to see what it’s like.
WebKit for Safari 18 beta on macOS improves accessibility support for date and time input field types. Now <input type="date">
, <input type="datetime-local">
, and <input type="time">
elements work properly with VoiceOver.
Usually elements have the labels they need, but sometimes there is no text label for a particular button or UI. In this situation, ARIA can be used to provide an accessible label. The aria-label
attribute provides names of labels while aria-roledescription
provides the description for the role of an element.
On very rare occasions, you may need to override aria-label
or aria-roledescription
to provide different names or descriptions specifically for braille. The aria-braillelabel
and aria-brailleroledescription
attributes provide such an ability. They exist to solve very specific needs, including educational contexts where the site needs to render the specific braille table dot pattern. If you do use braille-related ARIA attributes, be sure to test them using a braille reader. If in doubt, relying on the accessible name from content or aria-label
/ aria-roledescription
is almost always the better user experience. WebKit has supported these ARIA attributes for years.
Now, WebKit for Safari 18 beta adds support for the ariaBrailleLabel
and ariaBrailleRoleDescription
element reflection properties. These make it possible to get and set the aria-braillelabel
and aria-brailleroledescription
ARIA attributes on DOM elements directly via JavaScript APIs, rather than by using setAttribute
and getAttribute
.
Watch video without distractions in Viewer for Safari 18 beta on macOS.
When you play in Viewer, the video fills the Safari window, while providing full access to system playback controls. Then it automatically enters picture-in-picture anytime you switch tabs, close the window, or occlude the web page with another window. Look for Video Viewer in the new page menu in Safari whenever you are on a web page with a prominent video element.
Safari for visionOS 2 beta adds support for docking fullscreen videos into the current Environment. Anytime a user is watching a video fullscreen, they can tap to enter a fully immersive experience. Turning the Digital Crown adjusts the immersion. Light emitted from the video reflects off of the Environment, while audio is rendered on a large soundstage.
WebKit for Safari 18 beta adds Workers support for both Managed Media Source (MMS) and Media Source Extensions (MSE). This can be especially helpful on complex websites that want to ensure continuous and smooth video playback even when other site activity (such as live commenting) causes a very busy main thread. You can see the performance difference in this demo.
WebKit for Safari 18 beta adds support for the WebRTC HEVC RFC 7789 RTP Payload Format. Previously, the WebRTC HEVC used generic packetization instead of RFC 7789 packetization. This payload format provides a new option for improving videoconferencing, video streaming, and delivering high-bitrate movies and TV shows.
WebKit for Safari 18 beta adds support for MediaStreamTrack processing in a dedicated worker. And it adds support for missing WebRTC stats.
Two years ago at WWDC22, we announced support for passkeys — a groundbreaking industry-standard way to login to websites and app services. Passkeys provide people with an extremely easy user experience, while delivering a profound increase in security. To learn more, watch Meet Passkeys or read Supporting passkeys.
WebKit for Safari 18 beta adds support for three new features as we continue to improve passkeys. First, Safari 18 beta adds support for using mediation=conditional
for web authentication credential creation. This allows websites to automatically upgrade existing password-based accounts to use passkeys. Learn more by watching Streamline sign-in with passkey upgrades and credential managers at WWDC24, available on Tuesday, June 11.
Second, WebKit for Safari 18 beta adds support for using passkeys across related origins. This lets websites use the same passkey across a limited number of domains which share a credential backend.
And third, WebKit for Safari 18 beta adds support for the WebAuthn prf
extension. It allows for retrieving a symmetric key from a passkey to use for the encryption of user data.
WebKit for Safari 18 beta adds support for secure HTTPS for all images, video, and audio by upgrading passive subresource requests in mixed content settings. This means that if some files for a website are served using HTTPS and some are served using HTTP (known as “mixed content”), all images and media will now be auto-upgraded to HTTPS, in adherence with Mixed Content Level 2.
WebKit for Safari 18 beta adds support for Unicode 15.1.0 characters in RegExp. Unicode 15.1 added 627 characters, bringing the total of characters to 149,813. Now, these new characters can be used in regular expressions.
WebKit for Safari 18 beta also adds support for the v
flag with RegExp.prototype[Symbol.matchAll]
. providing more powerful ways to match Unicode characters, as specified in the ECMAScript 2024 standard.
For example, you can now specify to only match on Latin characters, while avoiding matching on Cyrillic script characters.
const regex = /\p{sc=Latin}/v;
console.log(regex.test('A')); // true, 'A' is a Latin script character
console.log(regex.test('А')); // false, 'А' is a Cyrillic script character
Or split a string matching on Emojis.
"a 🥰 b 🥰".split(/[\p{Emoji}--\p{ASCII}]/v)// ["a ", " b ", ""]
WebKit for Safari 18 beta adds support for URL.parse()
, a way to parse URLs which returns null rather than an exception when parsing fails.
// Before
let url = null;
try {
url = new URL(input, base);
} catch(e) { }
// Now
const url = URL.parse(input, base);
WebKit for Safari 18 beta expands Declarative Shadow tree support by adding the shadowRootDelegatesFocus
and shadowRootClonable
IDL attributes to the <template>
element. It also adds the shadowRootSerializable
attribute and shadowRootSerializable
IDL attribute to the <template>
element, enabling those using Declarative Shadow roots to opt into making them serializable. Serializing can be done through the new getHTML()
method that has been added at the same time.
WebKit for Safari 18 beta adds support for PopStateEvent
’s hasUAVisualTransition
, indicating whether the user agent has a visual transition in place for the fragment navigation.
WebKit for Safari 18 beta adds support for subresource integrity in imported module scripts, which gives cryptographic assurances about the integrity of contents of externally-hosted module scripts.
WebKit for Safari 18 beta adds support for the bytes()
method to the Request,
Response
, Blob
, and PushMessageData
objects. This replaces the need for web developers to call arrayBuffer()
, which can be difficult to use, and wraps the result in a Uint8Array
. Calling bytes()
is now the recommended way going forward when you need to access the underlying bytes of the data these objects represent.
WebKit for Safari 18 beta adds support for feature detecting text fragments by exposing document.fragmentDirective
. Note that the returned object (a FragmentDirective
) doesn’t provide any functionality, but it’s helpful if you need to know if Fragment Directives are supported by the browser.
WebKit for Safari 18 beta adds support for the willReadFrequently
context attribute for the getContext()
method. It indicates whether or not a lot of read-back operations are planned. It forces the use of a software accelerated 2D or offscreen canvas, instead of hardware accelerated. This can improve performance when calling getImageData()
frequently.
WebKit for Safari 18 beta extends 2D canvas support for currentcolor
. It can now be used inside color-mix()
or Relative Color Syntax. Here currentcolor
will default to the computed color
property value on the canvas
element.
WebKit for Safari 18 beta adds support for six new WebGL extensions:
EXT_texture_mirror_clamp_to_edge
WEBGL_render_shared_exponent
WEBGL_stencil_texturing
EXT_render_snorm
OES_sample_variables
OES_shader_multisample_interpolation
WebKit for Safari 18 beta adds support for fuzzy search code completion in the Web Inspector’s CSS source editor.
WebKit for iOS 18 beta, iPadOS 18 beta, visionOS 2 beta, and macOS Sequoia beta adds support for two new API — the Writing Tools API and an API to control adaptive image glyph insertion. Learn more about these API by watching Get started with Writing Tools and Bring expression to your app with Genmoji at WWDC24, both available Tuesday June 11.
WebKit for Safari 18 beta adds support for Apple Pay funds transfer.
While it’s rare to deprecate older technology from the web, there are occasions when it makes sense. We’ve been busy removing -webkit
prefixed properties that were never standardized, aging media formats that were never supported in other browsers, and more. This helps align browser engines, improve interoperability, and prevent compatibility problems by reducing the possibility that a website depends on something that’s not a web standard.
WebKit for Safari 18 beta removes support for OffscreenCanvasRenderingContext2D
’s commit()
method.
WebKit for Safari 18 beta deprecates support for a number of rarely used -webkit
prefixed CSS pseudo-classes and properties — and even one -khtml
prefixed property.
-webkit-alt
and alt
properties:-webkit-animating-full-screen-transition
pseudo-class:-webkit-full-screen-ancestor
pseudo-class:-webkit-full-screen-controls-hidden
pseudo-class:-webkit-full-page-media
pseudo-class:-webkit-full-screen-document
pseudo-class:-khtml-drag
pseudo-classWebKit for Safari 18 beta also deprecates support for the resize: auto
rule. Support for the resize
property remains, just as it’s been since Safari 4. The values Safari continues to support include: none
, both
, horizontal
, vertical
, block
, inline
, plus the global values. Early versions of CSS Basic User Interface Module Level 3 defined auto
, but it was later written out of the web standard.
WebKit for Safari 18 beta also deprecates support for non-standardize WEBKIT_KEYFRAMES_RULE
and WEBKIT_KEYFRAME_RULE
API in CSSRule.
WebKit for Safari 18 beta removes support for the JPEG2000 image format. Safari was the only browser to ever provide support.
If you’ve been serving JPEG2000 files using best practices, then your site is using the picture
element to offer multiple file format options to every browser. Safari 18 beta will simply no longer choose JPEG2000, and instead use a file compressed in JPEG XL, AVIF, WebP, HEIC, JPG/JPEG, PNG, or Gif — choosing the file that’s best for each user. Only one image will be downloaded when you use <picture>
, and the browser does all the heavy lifting.
We have noticed that some Content Deliver Networks (CDN) use User Agent sniffing to provide one file to each UA, offering only JPEG2000 images to Safari — especially on iPhone and iPad. If you expect this might be happening with your site, we recommend testing in Safari 18 beta on both macOS Sequoia and iOS or iPadOS 18. If you see problems, contact your SaaS provider or change your image delivery settings to ensure your website provides fallback images using industry best practices.
If you notice a broken site, please file an issue at webcompat.com.
WebKit for Safari 18 beta removes support for non-standard VTTRegion.prototype.track
.
WebKit for Safari 18 beta removes the last bits of support for AppCache.
When AppCache first appeared in 2009, in Safari 4, it held a lot of promise as a tool for caching web pages for use offline. It was imagined as “HTML5 Application Cache” back when HTML itself was being further expanded to handle more use cases for web applications. A developer could create a simple cache manifest file with a list of files to be cached. Its simplicity looked elegant, but there was no mechanism for cache busting, and that made both developing a site and evolving the site over time quite frustrating. AppCache also had security challenges. So new web standards were created to replace it. Today, developers use Service Workers and Cache Storage instead.
WebKit deprecated AppCache with a warning to the Console in Safari 11.0. Then in 2021, we removed support for AppCache from Safari 15.0, with a few exceptions for third-party users of WKWebView. Now we are removing those exceptions. This change to WebKit will only affect the rare web content loaded in older third-party apps that have JavaScript code which relies on the existence of AppCache related interfaces.
WebKit for Safari 18 beta removes the SVGAnimateColorElement interface.
WebKit for Safari 18 beta removes support for four non-standard Web APIs:
KeyboardEvent.altGraphKey
KeyboardEvent.prototype.keyLocation
HashChangeEvent
’s non-standard initHashChangeEvent()
methodIn addition to all the new features, WebKit for Safari 18 beta includes work to polish existing features.
<header>
inside <main>
and sectioning elements.aria-hidden
on a slot not hiding the slot’s assigned nodes.aria-hidden=true
to be ignored on the <body>
and <html>
elements. datetime
values being exposed to assistive technologies in the wrong timezone. datetime
value being exposed to assistive technologies for datetime-local
inputs. dd
, details
, dt
, em
, hgroup
, option
, s
, and strong
. aria-labelledby
to expose their entire subtree text, not just their direct child text. visibility: visible
inside a container with visibility: hidden
. aria-describedby
text after the targeted element changes its subtree.transition
property to produce the shortest serialization. animation
property to produce the shortest serialization. navigator.credentials.create()
rejects with “NotAllowedError: Operation Failed” after a conditional UI request is aborted.response
attribute to data
. drawImage(detachedOffscreenCanvas)
to throw an exception.drawImage
to not alter the input source or the destination rectangles. clearRect()
. drawImage()
API to throw an exception when the image is in broken state. white-space
to a non-default value dynamically on a whitespace or a new line.text-spacing
properties into font
properties. disclosure-open
and disclosure-closed
to point to the correct direction in right-to-left. backface-visibility
to create a stacking context and containing block. getComputedStyle()
to work with functional pseudo-elements like ::highlight()
. :-webkit-full-screen
pseudo-class to :fullscreen
. :-webkit-any-link
to :any-link
and :matches()
to :is()
. getComputedStyle()
pseudo-element parsing to support the full range of CSS syntax. @supports
to correctly handle support for some -webkit
prefixed pseudo-elements that were incorrectly treated as unsupported. light-dark()
. font-variant-caps: all-small-caps
with font-synthesis
. :empty
selector to work with animations. gap
as-is in serialized and computed values. @starting-style
incorrectly invoking with a null element. -apple-pay-button
from applying to any element that supports appearance: auto
and is not a button. hsl()
and hsla()
implementation to match the latest spec changes. rgb()
and rgba()
to match the latest spec. hwb()
implementation to match the latest spec.mask-mode
.datalist
dropdown to sync its options
elements after a DOM update. <select multiple>
scrollbars to match the used color scheme. <option>
from a <datalist>
element. input
element with type="email"
and the multiple
attribute. <input type=checkbox switch>
. History
to throw a SecurityError when not in a fully active Document.document.referrer
initialization.RegExp.prototype.@@split
to update the following legacy RegExp static properties: RegExp.input
, RegExp.lastMatch
, RegExp.lastParen
, RegExp.leftContext
, RegExp.rightContext
, and RegExp.$1, ... RegExp.$9
. String.prototype.replace
to not take the fast path if the pattern is RegExp Object and the lastIndex
is not numeric. (return
in async generators to correctly await
its value.Symbol.species
getters to not share a single JS Function. RangeError
if Set
methods are called on an object with negative size
property.eval()
function from another realm to not cause a direct eval
call. eval()
call with ...spread
syntaxt to be a direct call.[[Construct]]
of derived class.eval()
in a default value expression inside a rest parameter creates a variable in the environment of the function rather than the separate one of the parameters;eval()
, or a closure created in a default value expression of a preceding parameter, but only if there is a var
binding by the same name;var
bindings.false
. emitReturn()
to load this
value from arrow function lexical environment prior to the TDZ check. instanceof
to not get RHS prototype when LHS is primitive.Object.groupBy
and Map.groupBy
to work for non-objects. Array.fromAsync
to not call the Array constructor twice. Function.prototype.toString
for accessor properties. Set#symmetricDifference
to call this.has
in each iteration. ArrayBuffer
and SharedArrayBuffer
constructor to check length before creating an instance. fractionalDigits
of Intl.DurationFormat
to be treated as at most 9 digits if it is omitted. navigator.cookieEnabled
to return false
when cookies are blocked. currentTime
to be further than the gap’s start time. sampleRate
and numberOfChanges
to be required and non-zero in a valid AudioEncoderConfig.Sec-Fetch-Site
value for navigation of a nested document. Timing-Allow-Origin
to not apply to an HTTP 302 response. <textarea>
element with 1rem
padding.backdrop-filter
to apply to the border area of an element with a border-radius
.height: 100%
is applied on nested content.break-word
with a float discarding text.min-content
calculation for unstyled only-child
inlines elements.position: relative
and top
are used. <switch>
element.display: none
as the default UA style rule. cursor: pointer
matching standards. stop-color
if it is not rendered in the page. SVGLength
to sync with the WebIDL specification. width
and height
are animated.transform
property while that property is animated with an implicit keyframe. color-mix
. cssText
setter to change the style
attribute when the serialization differs.history.pushState()
and history.replaceState()
to ignore the title
argument. showPicker()
method to trigger suggestions from a datalist
. lang
attribute in no namespace to only apply to HTML and SVG elements.getGamepads()
to no longer trigger an insecure contexts warning.<picture>
element displaying the same image twice. toJSON()
method.toJSON()
method.CustomEvent.target
when dispatching an event. navigator.language
only returning the system language in iOS 17.4. width
attribute for <hr>
. www.
sub-domain for Associated Domains for all web apps. !important
not getting overridden when using the interactive editing controls. text-indent
property suggesting prefixed properties instead of each-line
or hanging
.background
autocompletion suggestion to include repeating-conic-gradient
.overflow: scroll
elements to scroll as expected when highlighting an element from the DOM tree. You can test Safari 18 beta by installing the beta of macOS 15, iOS 18, or iPadOS 18. Or, if you’d like, you can try out Safari 18 beta on macOS Sonoma or macOS Ventura by downloading the Safari 18 beta, once it’s available. (Sign in using a free Apple ID to download. Installing Safari 18 beta on macOS Sonoma or macOS Ventura will replace your existing version of Safari with no way to revert to an earlier version.) You can also help test many of these features in Safari Technology Preview.
We love hearing from you. To share your thoughts on Safari 18 beta, find us on Mastodon at @jensimmons@front-end.social and @jondavis@mastodon.social. Or send a reply on X to @webkit. You can also follow WebKit on LinkedIn. If you run into any issues, we welcome your feedback on Safari UI (learn more about filing Feedback), or your WebKit bug report about web technologies or Web Inspector. If you notice a website that seems broken in Safari, but not in other browsers, please file a report at webcompat.com. Filing issues really does make a difference.
Download the latest Safari Technology Preview on macOS to stay at the forefront of the web platform and to use the latest Web Inspector features.
You can also find this information in the Safari 18 beta release notes.
]]>Three sessions at WWDC24 dive into the spatial web, passkey upgrades, and WebXR.
Discover how to make the most of visionOS capabilities on the web. Explore recent updates like improvements to selection highlighting, and the ability to present spatial photos and panorama images in fullscreen. Learn to take advantage of existing web standards for dictation and text-to-speech with WebSpeech, spatial soundscapes with WebAudio, and immersive experiences with WebXR.
Coming Tuesday, June 11.
Learn how to automatically upgrade existing password-based accounts to use passkeys. We’ll share why and how to improve account security and ease of sign-in, information about new features available for credential manager apps, and how to make your app information shine in the new Passwords app.
Coming Tuesday, June 11.
Discover how WebXR empowers you to add fully immersive experiences to your website in visionOS. Find out how to build WebXR experiences that take full advantage of the input capabilities of visionOS, and learn how you can use Simulator to test WebXR experiences on macOS.
Coming Wednesday, June 12.
]]>After digging in further, I learned about Web Platform Tests (WPT), a cross-browser test suite essential to executing Interop Accessibility’s ambitious vision. WPT enables anyone to write a single automated test that runs in all major browser engines (i.e., Chromium, Gecko, and WebKit), thereby ensuring that web technologies such as HTML or ARIA (Accessible Rich Internet Applications) work as expected. It’s never been possible before this to write an accessibility test that runs in all browsers, on any system. Despite some limitations around mobile testing and operating system coverage, WPT holds great promise as a tool for realizing a more accessible and inclusive web!
As an example, the following hypothetical test asserts that the accessibility role of an <img>
element is “image
”:
<img data-expectedrole="image" ...>
For an inclusive user experience, it’s imperative that roles are accurately computed by the browser and in turn, properly exposed by platform accessibility APIs (HTML Accessibility API Mappings). Roles enable assistive technology users to understand the purpose of user interface elements (e.g., button
, link
, dialog
) and with WPT, we can easily verify browser-calculated roles.
You may observe that our fictitious <img>
example is missing a text alternative even though it’s required for accessibility. I can add this to test that the <img>
’s textual description, supplied via the alt
attribute, is properly exposed as its accessibility label:
<img alt="stack of fluffy pancakes"
data-expectedlabel="stack of fluffy pancakes"
data-expectedrole="image"
...
>
In terms of the screen reader experience, we expect that this particular UI properly announces as “stack of fluffy pancakes, image”. Another hypothetical example showcasing label calculation for an image button:
<button data-expectedlabel="Order!" ...>
<img alt="Order!" ...>
</button>
Here, the button’s nested content (the <img>
’s alt
specifically) provides the accessibility label for the button itself and the resulting announcement would be “Order!, button”. These examples demonstrate the simplicity and power of WPT: with a couple lines of markup, we’re able to quickly ascertain how web browsers expose the accessibility of any DOM element.
Note: for those interested in seeing more complex, real WPT examples: resolving ambiguity in label calculation that involves hidden nodes, investigating display: contents
and accessible name calculation for aria-label
.
Under the hood, when I run the above <img>
test for example, a JavaScript Promise function asserts that the image’s accessibility role and label are calculated correctly by the browser. To this end, WPT uses testharness.js, a JavaScript framework for writing test cases, and WebDriver for obtaining browser-calculated accessibility metadata about DOM elements (at present, either an element’s programmatic label or role). Most WPT accessibility tests are also written with HTML markup and some data-*
attributes (e.g., data-testname
, data-expectedrole
) that provide hooks for WPT test execution and reporting.
Tests can be run locally using CLI commands that invoke browser automation. One of the slicker aspects of WPT is its robust continuous integration (CI) infrastructure that runs tests in the WPT repo across latest versions of all major browser engines on a daily basis (and for pull requests)! Test results are stored in the WPT interop dashboard for easy viewing and to help browser engineers improve interoperability. A special thank you is definitely in order to all the people that keep the WPT CI servers running; their hard work provides a well-maintained, reliable, and stable WPT infrastructure.
I hope that the utility of these WPT accessibility tests is abundantly clear: when accessibility semantics (e.g., role) and labels work interoperably across browsers, and in accordance with developer intent, this is a victory for both web developers and users. Thinking more broadly, what if we could regularly test the accessibility behavior of any and all web platform features on the latest browsers in an automated fashion? How much time and effort could this save?
This is why WPT is so compelling: using a powerful, scaleable testing framework, we can produce easy-to-write tests that:
For the reasons above, it’s difficult to overstate the utility of interoperability and the ultimate benefit of WPT: it gets everyone collectively closer to the shared goal and vision of a reliable and inclusive web!
The value of writing WPT accessibility tests isn’t limited to ensuring correct cross-browser behavior or gauging browser conformance to accessibility specifications. WPT tests can also positively influence the very criteria they are written to test. For example, a colleague recently wrote a WPT test for accessible name node traversal and after investigation, we observed that all major browsers failed in an identical manner (which is unusual). We identified multiple specification ambiguities from this work which motivated fixes across browsers. The issue also spawned fruitful discussion on several related topics all in the pursuit of great web accessibility and a best-in-class user experience. Awesome stuff!
In addition to the value of WPT testing for web developers, further benefits include:
It’s incredible to see the WPT accessibility testing grow over time with our efforts continually bolstered by more efficient infrastructure, broader testing coverage, and strong partnerships. While Apple has taken a lead role, it’s highly collaborative across partners such as Adobe, Hilton, Mozilla, Google, Igalia, Bocoup, etc. I’m amazed by the degree of diligence, technical knowledge and passion that is demonstrated in all aspects of this project. From both inside and outside of Apple, the deep focus and unwavering commitment towards the mission of web accessibility is infectious. To everyone involved: kudos and keep up the great work!
I’m excited for a future that includes greater WebDriver capabilities in inspecting browser-generated accessibility metadata, in addition to dwindling accessibility gaps across web browsers as a result of productive collaboration. I invite you, dear reader, to contribute to this future of a more interoperable, reliable, and accessible web by writing WPT tests. Please join us!
]]>This release includes WebKit changes between: 278844@main…279360@main.
Fixed toggling the visibility on a canvas parent undoing the effect of clearRect()
. (279302@main) (128226178)
Fixed the Canvas drawImage()
API to throw an exception when the image is in broken state. (279319@main) (128588063)
font-variant-caps: all-small-caps
with font-synthesis
. (279183@main) (121314557) bytes()
to Blob and PushMessageData. (279263@main) (128418858) getUserMedia
promise resolution. (278851@main) (128112002) This release includes WebKit changes between: 278097@main…278429@main.
Fixed updating table accessibility text when its caption dynamically changes. (278164@main) (127263464)
Fixed updating aria-describedby
text after the targeted element changes its subtree. (278318@main) (127390465)
Fixed pseudo-elements not getting captured for View Transitions. (278123@main) (126964779)
Fixed View Transition rendering when the root element is not captured in the new snapshot. (278120@main) (127217265)
Fixed an issue where the Web Inspector viewport might appear cut off. (278208@main) (117272735)
Fixed overflow: scroll
elements to scroll as expected when highlighting an element from the DOM tree. (278614@main) (124554999)
There are several exciting new CSS features in Safari 17.5, including text-wrap: balance
, the light-dark()
color function, and @starting-style
, plus the ability to use feature queries with @import
rules. Let’s look at how you can put each one to use.
On the web, with its flexible container widths, inconsistent lengths of content, and variation between browsers, it can feel impossible to avoid having text wrap in such a way that too few words end up all by themselves on a very short last line.
When type was set by hand, typographers would painstakingly avoid this undesirable result by manually moving content around. Over the decades, web developers have tried a series of different tricks to avoid orphans in CSS, in HTML, in JavaScript, and in content management systems. None work very well. The attempts usually feel hacky, laborious, and fragile.
To solve this and other frustrations, the CSS Working Group has defined three new options that you can use to change how text will wrap. You can switch from default wrapping to another style with text-wrap
. WebKit for Safari 17.5 adds support for the first of these new options — balancing.
The text-wrap: balance
rule asks the browser to “balance” the lines of text and make them all about the same length.
You can see how now the text no longer fills the containing block — there’s a large amount of space on the right of the words. This is expected, and something you’ll want to think about as you decide when to use text-wrap: balance
.
Where exactly each line of text will break when using text-wrap: balance
may be slightly different in each browser. The CSS Text level 4 web standard leaves it up to each browser engine team to decide which algorithm they want to use in determining how exactly to wrap balanced text.
It can be computationally expensive for the browser to count characters and balance multiple lines of text, so the standard allows browsers to limit the number of lines that are balanced. Chromium browsers balance 6 or fewer lines, Firefox balances 10 or fewer, while Safari/WebKit balances an unlimited numbers of lines.
For now, Safari does not balance text if it’s surrounding a float or initial letter. And Safari disables the balancer if the content contains preserved tabs or soft hyphens.
The text-wrap
property is actually a shorthand for two longhand properties: text-wrap-style
and text-wrap-mode
.
The text-wrap-mode
property provides a mechanism for expressing whether or not text should wrap.
text-wrap-mode: wrap; /* initial value */
text-wrap-mode: nowrap;
The wrap
value turns it on, and the nowrap
value turns it off, just like the values for white-space
. (In fact, text-wrap-mode
is the newly introduced longhand of white-space
.) WebKit added support for text-wrap-mode: wrap
and nowrap
in Safari 17.4.
The text-wrap-style
property selects how to wrap. The initial value is auto
— asking text to wrap in the way it has for decades. Or, you can choose a value to switch to another “style” of wrapping.
WebKit for Safari 17.5 adds support for text-wrap-style: balance
, stable
, and auto
.
text-wrap-style: auto; /* initial value */
text-wrap-style: balance;
text-wrap-style: stable;
Of course, the text-wrap
shorthand is a way to combine text-wrap-mode
and text-wrap-style
and declare them together. If you write text-wrap: balance
it’s the same as text-wrap: wrap balance
, meaning: “yes, please wrap, and when you do, please balance the text”.
Full support will eventually include three properties and six values. No browser supports everything yet, so be sure to look up support for the text-wrap
, text-wrap-mode
, and text-wrap-style
properties, as well as the balance
, pretty
, stable
, auto
, wrap, and nowrap
values.
The balance
, pretty
, and stable
values will simply fall back to auto
in browsers without support, so progressive enhancement is easy. You can use these values today, no matter how many of your users don’t yet have a browser with support. They will simply get auto
-wrapped text, just like they would if you didn’t use text-wrap
. Meanwhile, those users with support will get an extra boost of polish.
light-dark()
color functionMore and more, users expect websites and web apps to support dark mode. Since Safari 12.1, the prefers-color-scheme
media query has given you the ability to write code like this:
body {
background: white;
color: black;
}
@media (prefers-color-scheme: dark) {
body {
background: darkslategray;
color: white;
}
}
Or perhaps you’ve used variables to define colors for both light and dark mode at once, making it easier to use them everywhere.
:root {
--background: white;
--text: black;
}
@media (prefers-color-scheme: dark) {
:root {
--background: darkslategray;
--text: white;
}
}
body {
background: var(--background);
color: var(--text);
}
Well, now there’s a new option — the light-dark()
function. It makes defining colors for dark mode even easier.
First, inform the browser you are providing a design for both light and dark modes with the color-scheme
property. This prompts the browser to switch the default user agent styles when in dark mode, ensuring the form controls appear in dark mode, for example. It’s also required for light-dark()
to work correctly.
:root {
color-scheme: light dark;
}
Then, any time you define a color, you can use the light-dark()
function to define the first color for light mode, and the second color for dark mode.
color: light-dark(black, white);
background-color: light-dark(white, darkslategray);
You can still use variables, if you’d like. Perhaps you want to structure your code like this.
:root {
color-scheme: light dark;
--background: light-dark(black, white);
--text: light-dark(white, darkslategray);
}
body {
background: var(--background);
color: var(--text);
}
An often-asked question when learning about light-dark()
is “does this only work for colors?” Yes, this function only works for colors. Use the prefers-color-scheme
media query to define the rest of your color-scheme dependent styles.
WebKit for Safari 17.5 adds support for @starting-style
. It lets you define starting values for a particular element. This is needed to enable a transition when the element’s box is created (or re-created).
.alert {
transition: background-color 2s;
background-color: green;
@starting-style {
background-color: transparent;
}
}
In the above example, the background-color
will transition from transparent to green when the element is added to the document.
Many developers are excited to use @starting-style
along with display: none
interpolation. To do so, WebKit also needs to support animation of the display
property, which has not yet shipped in Safari. You can test this use case today in Safari Technology Preview.
WebKit for Safari 17.5 adds the supports()
syntax to @import
rules. Now you can conditionally import CSS files based on whether or not there’s support for a certain feature.
@import <url> supports(<feature>);
For example, you could load different stylesheets based on whether or not CSS Nesting is supported.
@import "nested-styles.css" supports(selector(&));
@import "unnested-styles.css" supports(not selector(&));
Or you could load certain CSS files when a browser does not have support for Cascade Layers. (Note that any @import
rules with layer()
will automatically be ignored in a browser without layer support.)
@import url("reset.css") layer(reset);
@import url("framework.css") layer(framework);
@import url("custom.css") layer(custom);
@import url("unlayered-fallback-styles.css") supports(not at-rule(@layer));
Or simply test for a feature. Here, these layout styles will only be loaded if Subgrid is supported.
@import url("layout.css") supports(grid-template-columns: subgrid);
WebKit for Safari 17.5 adds support for AV1 to WebCodecs when an AV1 hardware decoder is available.
WebKit for Safari 17.5 adds WebGL support for EXT_conservative_depth
and NV_shader_noperspective_interpolation
.
WKWebView adds support for logging MarketplaceKit errors to the JavaScript console. This will make errors easier to debug.
In addition to these new features, WebKit for Safari 17.5 includes work polishing existing features.
excludeCredentials
property being ignored during a passkey registration request. (124405037) @scope
. (124640124) @scope
limit making the element out of scope. (124956673) <select>
rendering in dark mode. (123845293) pointer-events: none
is placed over it. (118936715) <audio>
playback to continue to the next media activity when in the background. (121268089) (FB13551577) loadeddata
events for <audio>
and <video>
on page load. (124079735) (FB13675360) mousemove
events in an iframe
when the mouse is clicked from outside the iframe
and then moves into it while the button is held down. (120540148) (FB13517196) Safari 17.5 is available on iOS 17.5, iPadOS 17.5, macOS Sonoma 14.5, macOS Ventura, macOS Monterey and in visionOS 1.2.
If you are running macOS Ventura or macOS Monterey, you can update Safari by itself, without updating macOS. On macOS Ventura, go to > System Settings > General > Software Update and click “More info…” under Updates Available.
To get the latest version of Safari on iPhone, iPad, or Apple Vision Pro, go to Settings > General > Software Update, and tap to update.
We love hearing from you. To share your thoughts on Safari 17.5, find us on Mastodon at @jensimmons@front-end.social and @jondavis@mastodon.social. Or send a reply on X to @webkit. You can also follow WebKit on LinkedIn. If you run into any issues, we welcome your feedback on Safari UI, or your WebKit bug report about web technologies or Web Inspector. Filing issues really does make a difference.
Download the latest Safari Technology Preview on macOS to stay at the forefront of the web platform and to use the latest Web Inspector features.
You can also find this information in the Safari 17.5 release notes.
]]>