December 19, 2025

Release Notes for Safari Technology Preview 234

Surfin’ Safari

Safari Technology Preview Release 234 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 303092@main…304071@main.

Accessibility

Resolved Issues

  • Fixed missing aria-label on the button added by <img controls> to improve accessibility for screen readers. (304013@main) (164651880)

Animations

New Features

  • Added support for Threaded Scroll-driven Animations. With Threaded Scroll-driven Animations, eligible scroll-driven animations are updated as their associated timeline’s source element is scrolled instead of when the page rendering is updated, yielding smoother animations on devices with Pro Motion displays. Additionally, since scrolling is performed in a separate process, those animations update as scrolling occurs no matter the load on the main thread. Eligible animations are any scroll-driven animations animating the opacity, transform, translate, scale, rotate, filter, backdrop-filter or any of the Motion Path properties. (303997@main) (165924545)

CSS

New Features

  • Added support for CSS display: grid-lanes. (303114@main) (164860495)
  • Added support for an automatic initial value for grid-auto-flow in CSS Grid Level 3 to switch flow orientation based on grid-template-rows and grid-template-columns for grid lane layouts. (303634@main) (164791817)
  • Added support for item-tolerance in CSS Masonry layouts to improve flexible grid item placement. (303096@main) (164043151)

Resolved Issues

  • Fixed an issue where max-width was not correctly applied to tables with fixed widths. (303644@main) (96554687)
  • Fixed incorrect sizing and fragment URL handling for SVG images used in -webkit-cross-fade(). (303593@main) (106633417)
  • Fixed table layout so that fixed horizontal margins on <caption> elements now contribute to the table’s minimum preferred logical width, preventing captions from causing narrower than expected tables. (303642@main) (120990942)
  • Fixed incorrect width calculation for positioned elements using box-sizing: border-box with an aspect-ratio, ensuring borders and padding are not double-counted. (303834@main) (121500004)
  • Fixed the UA style sheet to use :focus-visible instead of :focus for outline properties. (303643@main) (123155364)
  • Fixed HighlightRegistry to remove its non-standard constructor and updated tests to use CSS.highlights while ensuring Map.prototype is properly restored after tampering. (303858@main) (125529396)
  • Fixed handling of @property registration so that the initial-value descriptor can be optional. (303757@main) (131288198)
  • Fixed devicePixelRatio so that page zoom now affects the main frame consistently with iframes, keeping their values synchronized. (303397@main) (163857955)
  • Fixed line-height to correctly scale font-relative units when text zoom is applied. (304012@main) (165073337)
  • Fixed element.clientWidth and element.clientHeight to correctly include padding for content-box tables. (303641@main) (165515755)
  • Fixed: Refactored the handling of block-level boxes inside inline boxes. (303985@main) (165523565)
  • Fixed an issue where text-decoration: underline appeared higher than expected when text-box-trim was applied to the root inline box. (303710@main) (165614136)
  • Fixed auto-placement cursor handling for spanning items in grid-lanes layouts to correctly wrap within the valid range. (303815@main) (165701659)
  • Fixed an issue with grid lanes masonry layout where items with negative margins were incorrectly positioned too low by always taking the maximum running position. (303813@main) (165718130)

HTML

Resolved Issues

  • Fixed shadowrootcustomelementregistry attribute serialization to correctly compare ShadowRoot and document registries. (303841@main) (165476421)

JavaScript

Resolved Issues

  • Fixed Date constructor overflow handling so that invalid day values now return NaN. (303582@main) (155776209)
  • Fixed Intl.Locale.prototype.getWeekInfo() to remove the minimalDays property for compliance with the specification. (303287@main) (165083619)
  • Fixed Intl.NumberFormat to properly apply minimumFractionDigits and maximumFractionDigits to ensure currency and compact notations behave correctly. (303943@main) (165875014)

MathML

Resolved Issues

  • Fixed default MathML rule thickness to use the font’s underlineThickness metric with a zero fallback. (303108@main). (164693673)
  • Fixed painting empty <msqrt> radical operator in MathML by removing an incorrect check. (303134@main) (164776629)
  • Fixed MathML <mpadded>, <mfrac>, <munderover>, <mover> and <mspace> elements not updating layout when attributes like width, height, depth, lspace, and voffset etc. changed. (303508@main) (164797996)
  • Fixed MathML boolean attributes so they are now compared ASCII case-insensitively. (303107@main) (164819048)

Media

Resolved Issues

  • Fixed an issue where Video Viewer UI elements overlapped or exited unexpectedly. (303256@main) (164051864)
  • Fixed an issue where WebM with VP9/Vorbis fallback would not play. (303100@main) (164053503)
  • Fixed an issue where empty <track> elements prevented media from advancing its readyState and blocked play() calls. (303314@main) (164125914)
  • Fixed MediaStreamTrackProcessor to respect track.enabled = false. (303389@main) (165199900)
  • Fixed an issue where the ended event for Media Source Extensions might never fire by ensuring buffered ranges update correctly and playback gaps are observed even when the video does not start at time zero. (303596@main) (165430052)
  • Fixed an issue where caption previews were not shown in the default media controls. (304070@main) (165931046)

SVG

Resolved Issues

  • Fixed SVG intrinsic sizing and preferredAspectRatio() to correctly transpose dimensions for vertical writing modes. (303578@main) (103262534)
  • Fixed SVGLength parsing to correctly return the initial value when encountering parser errors or invalid values. (303577@main) (136102554)
  • Fixed an issue where SVGImage did not respect system dark mode changes. (303920@main) (140661763)
  • Fixed SVGLength.prototype.valueAsString to throw a SyntaxError when assigned an empty string. (303594@main) (165429393)
  • Fixed an issue where lengths with leading or trailing whitespace failed to be parsed. (303951@main) (165501190)

Web API

New Features

  • Added support for ReadableStream.getIterator() and the [@@asyncIterator] methods to enable iteration over streams. (303970@main). (96318671)
  • Added support for the Keyboard Lock API. (303093@main) (161422221)
  • Added support for using readable byte streams as fetch request and response bodies and enabling synchronous start behavior. (303115@main) (162107262)
  • Added support for ReadableByteStream. (303239@main) (164877711)
  • Added support for upgrading elements in CustomElementRegistry.prototype.initialize. (303250@main) (165045530)
  • Added support for the customelementregistry content attribute and handling of null customElementRegistry values in document.createElement, document.createElementNS, and element.attachShadow. (303300@main) (165096267)
  • Expose MediaDeviceInfo interface in SecureContext only as per web specification. (303512@main) (165318702)

Resolved Issues

  • Fixed an issue where scroll-margin from IntersectionObserver incorrectly applied to scrollers inside cross-origin iframes. (303367@main) (164994009)
  • Fixed ReadableStream and WritableStream to correctly pass abort and cancel reasons and improving WebTransport stream handling. (303738@main) (165474756)

Web Authentication

New Features

  • Added support for the WebAuthn PRF extension that maps to the CTAP hmac-secret extension, enabling credential-bound cryptographic secrets for both credential creation and authentication flows. (303406@main) (113572812)

Resolved Issues

  • Fixed an issue where the excludeCredentials list was not sent to CTAP when its size was 1. (303120@main) (164546088)

Web Inspector

New Features

  • Added support for starting and stopping <canvas> recordings from the console within a Worker using console.record() and console.recordEnd(). (303230@main) (98223237)
  • Added support in the Web Inspector Timelines Heap view to display the dominator object, if any, when viewing the shortest GC path. (303368@main) (165177746)
  • Added support for auto-completion of sideways-lr and sideways-rl values for the writing-mode CSS property. (303884@main) (165777054)
  • Added support for auto-completion of grid-lanes and inline-grid-lanes values for the display CSS property. (304001@main) (165873256)

Resolved Issues

  • Fixed incorrect breakpoint and search result positions in the Web Inspector after pretty-printing inline scripts containing multi-line template literals. (303680@main) (29417859)
  • Fixed an issue where the Console tab search bar in Web Inspector would disappear when the window was too narrow. (304057@main) (50922509)
  • Fixed an issue where breakpoints and search results in Web Inspector could point to the wrong location after a previously formatted source file was reopened in an unformatted state. (303327@main) (165059693)

WebRTC

New Features

  • Added support for capturing audio from multiple microphones on macOS with getUserMedia while managing echo cancellation and dynamically migrating existing captures to non-VPIO units. (303113@main) (163945062)

December 19, 2025 08:43 PM

Introducing CSS Grid Lanes

Surfin’ Safari

It’s here, the future of masonry layouts on the web! After the groundwork laid by Mozilla, years of effort by Apple’s WebKit team, and many rounds debate at the CSS Working Group with all the browsers, it’s now clear how it works.

Introducing CSS Grid Lanes.

.container {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
}

Try it today in Safari Technology Preview 234.

How Grid Lanes work

Let’s break down exactly how to create this classic layout.

Classic masonry-style layout of photos of various aspect ratios, all the same width, aligned in six columns
You can try out this demo of photo gallery layouts today in Safari Technology Preview.

First, the HTML.

<main class="container">
  <figure><img src="photo-1.jpg"></figure>
  <figure><img src="photo-2.jpg"></figure>
  <figure><img src="photo-3.jpg"></figure>
  <!-- etc -->
</main>

Let’s start by applying display: grid-lanes to the main element to create a Grid container ready to make this kind of layout. Then we use grid-template-columns to create the “lanes” with the full power of CSS Grid.

In this case, we’ll use repeat(auto-fill, minmax(250px, 1fr)) to create flexible columns at least 250 pixels wide. The browser will decide how many columns to make, filling all available space.

And then, gap: 16px gives us 16 pixel gaps between the lanes, and 16 pixel gaps between items within the lanes.

.container {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
}

That’s it! In three lines of CSS, with zero media queries or container queries, we created a flexible layout that works on all screen sizes.

Think of it like a highway of cars in bumper-to-bumper traffic.

Cartoon drawing of a highway from above. Nine cars fill four lanes of traffic, bumper to bumper. Each car has a number labeling it, showing the order these would be in HTML.

Just like the classic Masonry library, as the browser decides where to put each item, the next one is placed in whichever column gets it closest to the top of the window. Like traffic, each car “changes lanes” to end up in the lane that gets them “the furthest ahead”.

This layout makes it possible for users to tab across the lanes to all currently-visible content, (not down the first column below the fold to the very bottom, and then back to the top of the second column). It also makes it possible for you to build a site that keeps loading more content as the user scrolls, infinitely, without needing JavaScript to handle the layout.

The power of Grid

Varying lane sizes

Because Grid Lanes uses the full power of CSS Grid to define lanes using grid-template-*, it’s easy to create creative design variations.

For example, we can create a flexible layout with alternating narrow and wide columns — where both the first and last columns are always narrow, even as the number of columns changes with the viewport size. This is accomplished with grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr).

Demo layout of photos, where the 1st, 3rd, 5th, and 7th column are narrow, while the 2nd, 4th and 6th columns are twice as wide.
Try out the demo of photo gallery layouts today in Safari Technology Preview.

There’s a whole world of possibilities using grid-template-* syntax.

Spanning items

Since we have the full power of Grid layout, we can also span lanes, of course.

A complex layout of titles with teaser text for over two dozen articles — telling people what they'll experience if they open the article. The first teaser has a very large headline with text, and spans four columns. Five more teasers are medium-sized, bowl and next to the hero. The rest of the space available is filled in with small teasers. None of the teasers have the same amount of content as the rest. The heights of each box are random, and the layout tucks each box up against the one above it.
Try out the demo of newspaper article layout today in Safari Technology Preview.
main {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(20ch, 1fr));
  gap: 2lh;
}
article { 
  grid-column: span 1; 
}
@media (1250px < width) {
  article:nth-child(1) { 
    grid-column: span 4;             
  }
  article:nth-child(2), article:nth-child(3), article:nth-child(4), article:nth-child(5), article:nth-child(6), article:nth-child(7), article:nth-child(8) { 
    grid-column: span 2; 
  }
}

All the article teasers are first set to span 1 column. Then the 1st item is specifically told to span 4 columns, while the 2nd – 8th to span 2 columns. This creates a far more dynamic graphic design than the typical symmetrical, everything the same-width, everything the same-height layout that’s dominated over the last decade.

Placing items

We can also explicitly place items while using Grid Lanes. Here, the header is always placed in the last column, no matter how many columns exist.

A layout of paintings — each has a bit of text below the painting: title, etc. The paintings are laid out in 8 columns. Over on the right, spanning across two columns is the header of the website.
Try out the demo of a museum website layout today in Safari Technology Preview.
main {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(24ch, 1fr));
}
header {
  grid-column: -3 / -1;
}

Changing directions

Yes, lanes can go either direction! All of the examples above happen to create a “waterfall” shape, where the content is laid out in columns. But Grid Lanes can be used to create a layout in the other direction, in a “brick” layout shape.

Contrasting cartoon drawings: on the left, waterfall layout with boxes lined up in columns, falling down the page. And "brick" layout, with boxes flowing left to right, stacked like bricks in rows.

The browser automatically creates a waterfall layout when you define columns with grid-template-columns, like this:

.container {
  display: grid-lanes;
  grid-template-columns: 1fr 1fr 1fr 1fr;
}

If you want a brick layout in the other direction, instead define the rows with grid-template-rows:

.container {
  display: grid-lanes;
  grid-template-rows: 1fr 1fr 1fr;
}

This works automatically thanks to a new default forgrid-auto-flow, the normal value. It figures out whether to create columns or rows based on whether you defined the lanes using grid-template-columns or grid-template-rows.

The CSS Working Group is still discussing which property will explicitly control the flow orientation, and what its syntax will be. The debate is over whether to reuse grid-auto-flow or create new properties like grid-lanes-direction. If you’re interested in reading about the options being considered or chime in with your thoughts, see this discussion.

However, since normal will be the initial value either way, you don’t have to wait for this decision to learn Grid Lanes. When you define only one direction — grid-template-rows or grid-template-columns — it will Just Work™. (If it doesn’t, check if grid-auto-flow is set to a conflicting value. You canunset it if needed.)

Placement sensitivity

“Tolerance” is a new concept created for Grid Lanes. It lets you adjust just how picky the layout algorithm is when deciding where to place items.

Look at the next drawing. Notice that Car 4 is a tiny bit shorter than Car 1. When the “tolerance” is zero, Car 6 ends up in the right-most lane, while Car 7 is on the left. Car 6 ends up behind Car 4 on the right because that gets it a tiny bit closer “down the road” (closer to the top of the Grid container). Car 7 then takes the next-closest-to-the-top slot, and ends up behind Car 1 on the left. The end result? The first horizontal grouping of content is ordered 1, 2, 3, 4, and the next is 7, 5, 6.

Same cartoon drawing of the highway of bumper to bumper traffic from above.

But the difference in length between Car 1 and Car 4 is tiny. Car 6 isn’t meaningfully closer to the top of the page. And having item 6 on the right, with item 7 on the left is likely an unexpected experience — especially for users who are tabbing through content, or when the content order is somehow labeled.

These tiny differences in size don’t matter in any practical sense. Instead, the browser should consider item sizes like Car 1 and Car 4 to be a tie. That’s why the default for flow-tolerance is 1em — which means only differences in content length greater than 1 em will matter when figuring out where the next item goes.

If you’d like the layout of items to shuffle around less, you can set a higher value for flow-tolerance. In the next digram, the tolerance is set to half-a-car, causing the cars to lay out basically from left to right and only moving to another lane to avoid the extra-long limo. Now, the horizontal groupings of content are 1, 2, 3, 4, and 5, 6, 7.

Now the highway has the cars ordered in a fashion that's less chaotic.

Think of tolerance as how chill you want the car drivers to be. Will they change lanes to get just a few inches ahead? Or will they only move if there’s a lot of space in the other lane? The amount of space you want them to care about is the amount you set in flow-tolerance.

Remember that people tabbing through the page will see each item highlighted as it comes into focus, and may be experiencing the page through a screenreader. An item tolerance that’s set too high can create an awkward experience jumping up and down the layout. An item tolerance that’s too low can result in jumping back and forth across the layout more than necessary. Adjust flow-tolerance to something appropriate for the sizes and size variations of your content.

[Note, when this article was first published, this property was named item-tolerance in the specification and in Safari Technology Preview 234. On January 7, 2026 the CSS Working Group resolved to change the name to flow-tolerance.]

Try it out

Try out Grid Lanes in Safari Technology Preview 234! All of the demos at webkit.org/demos/grid3 have been updated with the new syntax, including other use cases for Grid Lanes. It’s not just for images! For example, a mega menu footer full of links suddenly becomes easy to layout.

A layout of 15 groups of links. Each has between two and nine links in the group — so they are all very different heights from each other. The layout has five columns of these groups, where each group just comes right after the group above it. Without any regard for rows.
Try out the mega menu demo today in Safari Technology Preview.
.container {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(max-content, 24ch));
  column-gap: 4lh;
}

What’s next?

There are a few last decisions for the CSS Working Group to make. But overall, the feature as described in this article is ready to go. It’s time to try it out. And it’s finally safe to commit the basic syntax to memory!

We’d love for you to make some demos! Demonstrate what new use cases you can imagine. And let us know about any bugs or possible improvements you discover. Ping Jen Simmons on Bluesky or Mastodon with links, comments and ideas.

Our team has been working on this since mid-2022, implementing in WebKit and writing the web standard. We can’t wait to see what you will do with it.

December 19, 2025 09:00 AM

December 12, 2025

WebKit Features for Safari 26.2

Surfin’ Safari

Safari 26.2 is a big release. Packed with 62 new features, this release aims to make your life as a web developer easier by replacing long-standing frustrations with elegant solutions. You’ll find simpler ways to create common UI patterns with just a few lines of HTML or CSS, and no JavaScript — like auto-growing text fields with CSS field-sizing, and buttons that open/close dialogs and popovers with command and commandfor HTML attributes. Navigation API makes building single-page apps more straightforward. Full width numbers are normalized, and text shaping across element boxes is supported for languages like Arabic. Anchor Positioning expands with the position-visibility property and much more. The cursor property works on pseudo-elements. Improvements to Initial Letter make it easier to create drop-caps. CHIPS brings back partitioned cookies, this time opt-in. WebXR on visionOS now supports WebGPU. And much, much more. Plus, this release resolves 165 bugs. It’s a release that makes the web more dependable, letting you spend less time working around browser inconsistencies and more time accomplishing your goals.

HTML

HTML is 35 years old, yet keeps evolving to make web development easier. Recent years have brought many small but powerful HTML innovations that simplify building dynamic user interfaces — letting you solve common use cases with HTML and CSS alone, “paving the cowpaths”, and reducing the need for JavaScript or third-party frameworks. Safari 26.2 delivers several more such features.

Button commands

Before, using a button on a web page to trigger a client-side action required JavaScript. Now, you can use command and commandfor attributes in HTML to control popovers and dialogs.

Use the commandfor attribute to tie the button to the id of the element it affects. And use the command attribute to tell the browser which action to take. There are six predefined values for the command attribute. These map to existing JavaScript methods. Fordialogelements: show-modal, close, and request-close. And for any HTML element with thepopover attribute: show-popover, hide-popover, and toggle-popover.

You can also observe custom commands in JavaScript through events. Custom commands are named using --foobar syntax, and used declaratively in HTML as command="--foobar".

Finding content

Safari 26.2 adds support for auto-expanding the details element. Now, anytime someone uses “Find” in Safari to search the page, if the search result is hidden inside a closed details element, the element will automatically expand to reveal the text. Also, if the user navigates to a URL that contains a Text Fragment and the targeted fragment is inside a closed details, it will automatically expand.

Similarly, Safari 26.2 adds support for the hidden=until-found attribute. You can apply this to any element in HTML, causing the content to not be rendered as part of the page, until a user searches for it. Then it appears.

<div hidden="until-found">
  <p>This content is hidden, but will be found by search!</p>
</div>

Thebeforematch event fires on an element with hidden=until-found just before it’s revealed by a find-in-page search. This allows you to run JavaScript to prepare the content, update analytics, or perform other actions before the hidden content becomes visible to the user.

Off-screen radio buttons now automatically scroll into view when focused. This is especially helpful when users navigate with keyboard shortcuts or screen readers, improving accessibility.

ARIA Index Text attributes

Safari 26.2 adds support for thearia-colindextext andaria-rowindextext attributes, which provide human-readable alternatives to aria-colindex and aria-rowindex.

The previously-supported options use numeric values to indicate a cell’s position within a table or grid. Now aria-colindextext and aria-rowindextext let you provide more meaningful labels. This is particularly valuable when columns use letters (like A, B, C in a spreadsheet) or when rows represent time periods, categories, or other non-numeric sequences. When both attributes are present, assistive technologies announce the human-readable text instead of the number, giving users better context as they navigate complex tables and grids.

Full width number normalization

Full-width characters are commonly used in Japanese, Chinese, and Korean text input. Safari 26.2 converts certain full-width characters into normalized equivalents for <input type="number"> fields. Now full-width digits (0123) become standard digits (0123); full-width minus signs (-) become standard minus signs (-); and full-width dots (.) become standard periods (.) This normalization lets users type numbers naturally in their language while ensuring the input works correctly as a number value. Also, disallowed characters are now immediately rejected.

And more

You might remember that HTML5 was originally intended to provide an outlining algorithm — where a website could use multiple h1 headlines on a page, and the browser would assign levels to each headline based on the overall DOM structure of elements. In practical terms, this idea didn’t work out and it was never widely implemented in browsers. Developers simply use h2, h3, h4, etc to convey levels of headline. To go with the intended original behavior in HTML5, the default UA styling for h1 elements was specified to visually change the headline when it was a child of article, aside, nav, or section — making the font-size and margin smaller and smaller each time it was nested. In Safari 26.2, following a recent HTML standard change, those UA styles are being removed.

When viewing web content in a Mac Catalyst app on macOS 26.2, elements with a title attribute will now display the tooltip when a user hovers.

CSS

Shrink wrapping form fields

Safari 26.2 adds support for the field-sizing property. Applying field-sizing: content causes the input and textarea form fields to shrink-wrap their content and grow as more text is entered. This eliminates the need for JavaScript to resize form fields dynamically. You can use min-height, min-width, max-height, and max-width to keep the field within the range you desire.

CSS Calc functions

In recent years, CSS has gained many powerful mathematical abilities, adding to its maturity as a programming language. Safari 26.2 brings three new functions — random(), sibling-index() and sibling-count().

The random() function lets you include a randomly generated value from a specified range in your calculations. For example, random(0, 100, 2) will choose an even number between 0 and 100, while random(0turn, 1turn) will be a fraction of a turn — basically, any decimal between 0 and 360 degrees. Learn all about what the CSS random function can do in our article, Rolling the dice with CSS random().

The sibling-count() function counts up the number of elements that are siblings of the current element, and returns a number, while sibling-index() will tell you which numbered item this one is — the 4th item for example. They make it incredibly easy to do things you’ve probably wished you could do for years.

For example, today, CSS Grid makes it trivial to proportion space in a layout with fr units — but in the days of float-based responsive layouts, this code would have been incredibly helpful (and still is today):

.gallery-item {
  width: calc(100% / sibling-count());
}

It calculates a width for an item by dividing the total width available by the total number of sibling items in the DOM. When there’s four items, the width of each is 25%. When there’s five items, each is 20%.

CSS has had nth-child() for a long time, letting you target a specific numbered item. The sibling-index() function is similar, telling you which number item a particular one is in the order.

This demo uses random() to generate the random rotation distance and sibling-index() to generate the angle for each of the wheel items.

Text shaping across inline boxes

Safari 26.2 adds support for text shaping across inline boxes. This is especially impactful for scripts like Arabic, N’Ko and many others where the letters join together and change appearance as text is rendered. The word “مرحبا” in Arabic (which means “hello” or “welcome”) is spelled using these letters: م ر ح ب ا — which then change their shapes and work together to create مرحبا. Before Safari 26.2, such letters would not combine if they were wrapped in separate elements. Of course, it’s not common to wrap an individual letter in the middle of a word with a span or other inline element, but there are good use cases for this — especially, perhaps, when wanting to change the color of the letters in teaching how the writing system works, like this:

There’s still more work to do in this space to support the full range of different behaviors of the many kinds of text shaping around the world.

Initial letter improvements

Initial letter was originally created by folks at Apple and implemented over a decade ago in Safari 9. It was created behind a -webkit- prefix, as was best practice at that time. Since then, the CSS web standard has matured to handle more complex use-cases. Safari 26.2 updates our implementation, adding support for decimal values in the initial-letter property. This can be especially helpful if you need to make a slight adjustment to better fit your font. Also, support for web fonts was added in March 2024 with Safari 18.4. The -webkit- prefix is still required, but these updates make it very usable in the meantime.

Anchor positioning improvements

Safari 26.2 adds several refinements to Anchor Positioning, which originally shipped in Safari 26.0. First, Safari 26.2 supports for flip-x and flip-y options in position-try-fallback. These keywords allow an anchored element to flip along the x- or y-axis when it would otherwise overflow its container.

The new position-visibility property lets you control when anchor-positioned elements are visible. For example, use no-overflow to hide an element when it overflows its container. Other values include always, anchors-visible, inherit, initial, revert, revert-layer, and unset.

The position-try property now works on pseudo-elements like ::before, ::after, and ::backdrop, which were previously unaffected. This means pseudo-elements can be repositioned using fallback strategies just like regular elements.

There are also many updates to the WebKit implementation of Anchor Positioning, listed in Bug Fixes below.

Color improvements

After being the first browser to ship new color spaces to CSS, color-mix(), relative color syntax, and contrast-color(), we’re excited to bring even more improvements in Safari 26.2.

The color-mix() function blends two color values and returns the result. Previously, developers were required to list a color space as the first argument of the function, like this: color-mix(in srgb, magenta, pink). Since many developers used srgb out of habit, the results were often sub-optimal. Starting with Safari 26.2, you can use color-mix() without listing a color space — and get oklab as the default. You can just say color-mix(magenta, pink)
and you’ll get the same result as if you’d written color-mix(in oklab, magenta, pink). The Oklab color space is an especially good choice when blending colors, since the mathematical model is designed to make adjustments based on how humans perceive color, rather than pure numbers. Learn more about wide-gamut P3 color on the web in this video from WWDC.

Safari 26.2 also adds support for thescrollbar-color property. It takes two values — one for the color of the scrollbar thumb (the part that moves) and the second for the scrollbar track (the background). Note in all browsers, the track background color only has an effect according to how that particular operating system works, and is dependent on how the user has their personal settings for scrollbars configured. Along with scrollbar-width and scrollbar-gutter, the scrollbar-color property completes the set of modern properties for styling scrollbars, making it a good time to stop using the original ::-webkit-scrollbar pseudo elements.

Safari 26.2 also adds display-p3-linear to the predefined set of color spaces available for use, alongside of display-p3, srgb and others.

P3 is still a better color space to use in most cases, but having support for P3 Linear provides an easy way to use linear color math while optimizing performance compared to other options like rec2100-linear.

accent-color legibility

The accent-color property allows for the customization of form controls with native appearance, but certain color choices could make text or indicators within the control hard to read. Safari 26.2 fixes these issues in both light and dark mode while maintaining a consistently-displayed color across all form controls. To achieve this, the following behaviors are performed:

For elements with a light color scheme, if the luminance of the accent color is greater than 0.5, the displayed accent color is clamped back down to 0.5 while preserving the hue.

For elements with a dark color scheme, if the luminance of the accent color is less than 0.5, the displayed accent color is clamped back down to 0.5 while preserving the hue. If the luminance of the accent color is greater than 0.5, then the following controls adapt in order to remain legible:

  • checkboxes display with a dark check
  • radio buttons display with a dark indicator
  • submit buttons display with dark text by default
  • switch controls display with an increased drop shadow for the thumb in the on-state

Text decoration improvements

In Safari 26.2, the text-decoration property is a proper shorthand for all four of the longhand properties: text-decoration-line, text-decoration-color, text-decoration-style and text-decoration-thickness. This means you can combine separate underline qualities for underlines, overlines and sidelines into one CSS rule like this: text-decoration: green wavy underline 3px. This turned out to be a large project, requiring significant refactoring of decades-old code to untangle the interaction between text-decoration and editing code.

The text-decoration-line property now supports the new spelling-error and grammar-error values, which let you emulate the respective native error markers. For example, this code will take the browser’s default styling for spelling errors (whatever that might be) and apply it to the span of text:

.span {
  text-decoration-line: spelling-error;
}

(If you want to override the browser’s default styling for spelling or grammar errors, you can target it with ::spelling-error or ::grammar-error and apply styling as desired — a feature that shipped in Safari 17.4 and is supported in Chromium browsers.)

Finally, Safari 26.2 provides bug fixes for text decoration. The text-decoration-thickness and text-underline-offset have been fixed to properly work in vertical writing modes. And the default computed value for text-emphasis-style: filled|open has been corrected to be filled|open circle instead of filled|open dot in horizontal typographic modes.

@scope

The @scope rule now correctly handles implicit scoping roots when used with constructed and adopted stylesheets in shadow DOM contexts. Previously, styles defined in constructed stylesheets might not have properly respected the shadow boundary as an implicit scope.

This improvement ensures that when you create a CSSStyleSheet programmatically and adopt it into a shadow root, any @scope rules without an explicit root will correctly treat the shadow root as the implicit scoping boundary:

const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  @scope {    .item { padding: 1em; }  }`);
shadowRoot.adoptedStyleSheets = [sheet];

This is particularly important for developers building design systems and component libraries using the Constructable Stylesheets API, which is a common pattern in modern Web Components.

WebKit for Safari 26.2 supports using :host as the scoping root in @scope rules. This allows you to create scoped styles that target the shadow host element, making it easier to write encapsulated component styles.

@scope(:host) {
  /* Styles scoped to elements within the shadow host */
  .component {
    color: blue;
  }
}

This feature enhances the ability to write modular, component-based styles while maintaining proper encapsulation boundaries in Web Components.

Safari 26.2 adds support for using the :scope pseudo-class when the scoping root matches the :visited pseudo-class. This allows you to create sophisticated scoping patterns that take link visitation state into account.

@scope (a:visited) {
  :scope {
    color: green;
  }
}

MathML

A new value forfont-family is now available in Safari 26.2, named math. This moves a previously directly-coded stack of fonts intended for use with mathematical expressions from being defining in the UA style sheet for just the <math> element to a new rule that can be called anywhere with font-family: math. Math fonts include specialized data for equation layout — things like stylistic variants for stretching glyphs, proper handling of superscripts and subscripts, brackets that span multiple lines, and double-struck characters.

The newmath-shift CSS property gives you the ability to create a more tightly compacted rendering of formulas by using math-shift: compact to reduce the vertical shift of superscripts.

More CSS

Safari 26.2 adds support for cross-origin() and referrer-policy() CSS URL modifiers. These let you control CORS and referrer behavior directly in CSS when loading resources like images or fonts, without needing HTML attributes or server headers. You can now specify these policies inline with your url() functions for more granular control over resource fetching.

The cursor property now works on pseudo-elements like ::before and ::after. Previously, you couldn’t change the cursor when hovering over content generated by pseudo-elements — now you can style them just like regular elements, giving you more control over the user experience and visual feedback throughout your interface.

Positioned boxes in scrollable containing blocks can now overflow in the scrollable direction. Previously, positioned elements might be clipped or behave unexpectedly when they extended beyond their scrollable container. This fix ensures that positioned content can properly overflow in the direction the container scrolls, making it easier to create complex layouts with scrollable regions and absolutely or fixed positioned elements.

Web API

Navigation API

Safari 26.2 adds support for the Navigation API. A modern replacement for the History API, it’s designed to give you better control over browser navigation. For years, web developers have relied on the History API (pushState, replaceState, and the popstate event) to build single-page applications, but it had significant limitations — you couldn’t intercept link clicks or form submissions, the popstate event only fired for back-forward navigation, and managing navigation state was cumbersome. The Navigation API solves these problems with a cleaner, more powerful interface.

The key feature is the navigate event, which fires for all types of navigation — link clicks, form submissions, back-forward buttons, and programmatic changes. You can intercept these navigations and handle them client-side, making it much easier to build SPAs without routing libraries. The API is also promise-based, so you can easily coordinate async operations like data fetching with navigation changes, and it includes built-in state management for each navigation entry. Here’s a simple example of client-side routing:

navigation.addEventListener('navigate', (event) => {
  // Only intercept same-origin navigations
  if (!event.canIntercept) return;

  event.intercept({
    async handler() {
      // Fetch and display new content
      const response = await fetch(event.destination.url);
      const html = await response.text();
      document.querySelector('main').innerHTML = html;
    }
  });
});

With this code, all link clicks and navigation within your site are automatically intercepted and handled client-side, turning your multi-page site into a single-page application with just a few lines of code.

Scrollend

Safari 26.2 adds support for the scrollend event, which fires once when scrolling definitively completes. Whether triggered by user gestures, keyboard navigation, smooth scrolling, or JavaScript, this event gives you a reliable signal that scrolling has finished. Previously, developers had to debounce the scroll event with timers to detect when scrolling stopped, which was imprecise and required guessing at appropriate delay values.

The scrollend event is useful for tasks that should only happen after scrolling is done, like lazy-loading content, updating UI based on final scroll position, or saving scroll state. Instead of firing dozens of times during a scroll, you get one clean event when it’s actually over.

document.addEventListener('scrollend', () => {
  // Scrolling has completely finished
  const scrollPosition = window.scrollY;
  localStorage.setItem('scrollPosition', scrollPosition);

  // Or lazy-load images now in view
  loadVisibleImages();
});

This fires once when scrolling stops, giving you a clean, reliable way to respond to the final scroll position without any timer-based guesswork.

View Transitions

Safari 26.2 adds support for document.activeViewTransition, which exposes the currently active View Transition. This gives you direct access to the transition object while it’s running, allowing you to check its state, wait for specific phases to complete, or programmatically control the transition. You can use this to coordinate other animations or UI updates with your View Transitions, or to handle cases where you need to know if a transition is already in progress before starting a new one.

Text Interaction

WebKit for Safari 26.2 adds support for document.caretPositionFromPoint(). This method is useful whenever you want to convert screen coordinates (x, y) into a text position in the document, giving you character-level precision for sophisticated text interaction (like building text editors, annotation tools, or custom selection interfaces).

Pointer and Touch Events

Safari 26.2 adds support for fractional coordinates in PointerEvent and TouchEvent properties like clientX, clientY, pageX, pageY, offsetX, offsetY, and screenX/screenY. Previously, these values were rounded to whole numbers, but they now include sub-pixel precision as decimal values (like 150.7 instead of 151). This gives you more accurate position data for touch and pointer interactions, which is useful for precise drawing applications, gesture recognition, or smooth animation tracking. Note that MouseEvent coordinates remain whole numbers, so if you’re handling multiple input types, you may see different precision levels depending on the event type.

As part of Interop 2025, Safari 26.2 continues to improve the interoperability of Pointer and Mouse Events. Early implementations of these events predated any official web standard, leading to inconsistencies across browsers. In 2022, the Interop Project took on Pointer and Mouse Events as an investigation to sort out the complexities and chart a path forward. The official web standard for Pointer Events was first published in November 2024, and WebKit now further aligns with that maturing specification.

Service Workers

Safari 26.2 improves asynchronous URL error handling in Service Workers. Invalid or malformed URLs now properly throw catchable errors in async operations, allowing you to handle URL errors gracefully with try/catch blocks.

Cookie Store

Safari 26.2 adds support in the Cookie Store API for handling cookieStore.set() calls with an empty string path. Previously, passing an empty string for the path parameter could cause issues or unexpected behavior. Now you can explicitly set a cookie with an empty path string, and the API will handle it correctly, giving you more flexibility in how you manage cookie paths programmatically.

The CookieStore API originally shipped in Safari 18.4. Now, with Safari 26.2, it enforces stricter validation for special cookie name prefixes to prevent misuse. Cookies with certain prefixes have special security meanings: the __Host- prefix indicates an extra-secure cookie (must be secure, no domain, path must be /), and the __Secure- prefix signals it must be sent over HTTPS only. Cookies with invalid names like __Host-Http- and __Http- are now rejected.

And more

Safari 26.2 removes support for the overflowchanged event, which was never standardized. This event fired when an element’s overflow state changed, but modern alternatives like ResizeObserver offer more robust ways to detect layout changes.

Performance API

Safari 26.2 adds support for two tools that measure the performance of web applications, Event Timing API and Largest Contentful Paint.

The Event Timing API lets you measure how long it takes for your site to respond to user interactions. When someone clicks a button, types in a field, or taps on a link, the API tracks the full timeline — from the initial input through your event handlers and any DOM updates, all the way to when the browser paints the result on screen. This gives you insight into whether your site feels responsive or sluggish to users. The API reports performance entries for interactions that take longer than a certain threshold, so you can identify which specific events are causing delays. It makes measuring “Interaction to Next Paint” (INP) possible.

Largest Contentful Paint (LCP) measures how long it takes for the largest visible element to appear in the viewport during page load. This is typically your main image, a hero section, or a large block of text — whatever dominates the initial view. LCP gives you a clear signal about when your page feels loaded to users, even if other resources are still downloading in the background.

Web Inspector

Web Inspector now shows Largest Contentful Paint entries in the Timelines tab, both in the Layout & Rendering timeline and in the events list. This makes it easier to see exactly when your page’s largest visible element rendered, and to correlate that timing with other layout and rendering work happening on the page.

Web Animations API

Safari 26.2 adds support for theoverallProgress property on the Animation interface. It gives you a number between 0 and 1 that represents how far the animation has progressed toward completion. Unlike tracking individual iterations, this tells you the progress across the entire animation — so if you have an animation set to run three times, overallProgress tracks the journey from start to finish across all three iterations.

The Animation.commitStyles() method now works with completed animations, letting you persist their final state as inline styles. You can run an animation to completion, lock in the result, and remove the animation itself — keeping the visual effect while freeing up resources.

JavaScript

Safari 26.2 adds support for Math.sumPrecise(), which sums multiple numbers with better floating-point accuracy. Regular addition accumulates rounding errors with each operation — adding 12 numbers means 11 separate additions, each losing a bit of precision. Math.sumPrecise() performs the entire sum as a single operation, eliminating accumulated error.

Safari 26.2 adds support for Map.prototype.getOrInsert() and WeakMap.prototype.getOrInsert(), letting you retrieve a value or insert a default if the key doesn’t exist — all in one operation. This simplifies the common check-then-set pattern, making code that builds up data structures cleaner and more efficiently.

WebAssembly

WebKit for Safari 26.2 adds support for Wasm Memory resizable buffer APIs. They give you more control over how WebAssembly memory is allocated and managed, allowing code in both Wasm and JavaScript to directly access the same memory space for efficient communication.

JS String Builtins now let Wasm modules import string constants without substantial glue code, reducing memory usage for some Wasm applications. They also enable working directly with JavaScript strings without calling imported JavaScript functions, avoiding the overhead of Wasm-to-JavaScript calls.

Safari 26.2 also adds two resizable ArrayBuffer methods to WebAssembly to allow conversion between fixed-length and resizable memory buffers. The WebAssembly.Memory.prototype.toResizableBuffer() method converts a WebAssembly memory instance to use a resizable ArrayBuffer, whose maximum size is determined by the memory’s maximum property. The WebAssembly.Memory.prototype.toFixedLengthBuffer() method converts a WebAssembly memory instance to use a fixed-length ArrayBuffer, which is the traditional WebAssembly memory behavior.

Back in September 2025, Safari 26.0 added support for WebAssembly.JSTag to bridge exception handling between JavaScript and WebAssembly. When JavaScript throws an exception into Wasm, the exception is wrapped with a JSTag so WebAssembly can catch and handle it appropriately.

WebGPU

Support for WebXR first shipped in Safari 18.0 in visionOS 2 in September 2024. It relied on WebGL for rendering 3D graphics. In September 2025, Safari 26.0 added support for WebGPU for use cases outside of WebXR. WebGPU is similar to WebGL in its capabilities, but it’s designed to better match how modern GPUs work, resulting in better performance and more flexibility. Now with Safari 26.2 on visionOS, WebXR supports WebGPU. This means you can build experiences in WebXR with the full power of WebGPU.

Safari 26.2 also adds support for using GPUTexture objects as depth-stencil attachments in rendering operations and resolve attachments in WebGPU render passes. Depth-stencil attachments are special textures used during 3D render. Depth tracks how far away each pixel is from the camera, while stencil creates masks and templates that control which pixels get rendered. This change simply updates to the very latest specification now allowing texture in JavaScript anyplace you would have used texture.createView() in the past. Now, both are supported.

SVG

Safari 26.2 brings many improvements to SVG. First, the <a> element now supports the type attribute, which lets you specify the MIME type of the linked resource. For instance:

<svg>
  <a href="destination.svg" type="image/svg+xml">
    <text x="10" y="20">Click me</text>
  </a>
</svg>

The repeatEvent in SVG animations is an event that fires each time an SVG animation element repeats its iteration, now supported to better align with the SMIL specification and match other browsers. Safari 26.2 also supports the onbegin event handler property defined in the SVGAnimationElement IDL (Interface Definition Language) that fires when an SVG animation starts.

The async attribute in SVGScriptElement controls whether a script should be executed asynchronously, matching the behavior of HTMLScriptElement.

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="200">
  <script href="external-script.js" async="true"/>
  <!-- or -->
  <script href="another-script.js" async="async"/>
</svg>

Safari 26.2 supports the hreflang attribute on SVGAElement. It specifies the language of the linked resource, matching the functionality of HTMLAnchorElement to improve SVG link handling.

And see the list of bug fixes below for the full picture of the improvements to SVG.

WebRTC

Safari 26.2 adds support for the encrypted field to RTCRtpHeaderExtensionParameters. This gives you as a developer more fine-grained control over which metadata is visible to network intermediaries versus what remains private end-to-end. The RTCRtpHeaderExtensionParameters WebRTC API interface describes Real-time Transport Protocol header extensions used in media streams. Additional metadata alongside the already-encrypted media payload, might include audio levels, video orientation, timing information and custom application data.

Canvas

WebKit for Safari 26.2 removes the non-standard legacy drawImageFromRect. Created in the earliest days of Canvas API, it was originally intended to be an intuitive way to draw a rectangular portion of an image, but it never became part of the official Canvas specification. Instead the standard drawImage() method provides this functionality, supported since Safari 2.

Web Compatibility

Safari 26.2 ships support for CHIPS (Cookies Having Independent Partitioned State) once again. Originally shipped in Safari 18.4 in March 2025, CHIPS was temporarily removed in Safari 18.5 for further refinement.

Beginning with Intelligent Tracking Prevention 1.0 in 2017, we began unconditionally partitioning cookies. Over the next two year, WebKit’s implementation evolved based on feedback, until in 2019 we stopped partitioning cookies. Based on this experience, CHIPS was designed as a way to give site owners control over whether their cookies are partitioned.

Now, partitioned cookies let third-party content — like embedded chat widgets, payment processors, or SaaS tools in iframes — opt-in to using cookies on a specific site without enabling cross-site tracking. Safari blocks setting and accessing cross-site cookies when partitioning was not requested.

If siteB.example is embedded in an iframe on siteA.example and sets a partitioned cookie, that cookie is only accessible when siteB.example appears on siteA.example — not on other sites.

To create a partitioned cookie, add the Partitioned attribute along with SameSite=None and Secure:

Set-Cookie: TestCookie=12345; SameSite=None; Secure; Partitioned

Or in JavaScript:

document.cookie = "TestCookie=12345; SameSite=None; Secure; Partitioned";

Safari partitions cookies by site (not origin), matching other browsers. This means news.siteA.example and mail.siteA.example share the same partition since they’re subdomains of siteA.example.

If you need access to unpartitioned third-party cookies, continue using the Storage Access API with document.requestStorageAccess().

WebDriver

WebDriver in Safari 26.2 makes it easy to write automated tests that exercise different user scenarios involving the Storage Access API. Using the new Set Storage Access WebDriver command, a test can validate what happens when cross-site storage access is granted or denied (i.e., when calling document.requestStorageAccess()). The Set Permissions WebDriver command has been extended to support the storage-access key. This allows a test to validate website behavior when the user has configured permissions to always accept or reject such storage-access requests.

WebKit API

Now in iOS 26.2, iPadOS 26.2, macOS 26.2, watchOS 26.2 and visionOS 26.2, WebKit supports exporting more types of WebPage content using SwiftUI Transferable APIs — now including .png, .flatRTFD, .rtf, and .utf8PlainText.

Web Extensions

Safari 26.2 brings some much-requested APIs for developers of extensions. These enhancements make it easier than ever for you to help your users get started using a Safari Web Extension.

First, from your native iOS, iPadOS, and visionOS application, it’s now possible to determine if your Safari Web Extension has been turned on by the user. To do so, call SFSafariExtensionManager.stateOfExtension(withIdentifier identifier: String) async throws -> SFSafariExtensionState. The SFSafariExtensionState result has an isEnabled boolean property that lets your app know if the extension has been turned on.

Once you’ve determined the state of your extension, you may want to help your user understand where to turn it on. With one function call, you can deep link into Safari Extension Settings directly into the view for your extension. To do so, call
SFSafariSettings.openExtensionsSettings(forIdentifiers: [``String``]) async throws and pass in an array of the composed identifiers for your extension(s) as the extensionIdentifiers argument. If you pass a single identifier, the user will be deep linked directly into settings for that extension. If you pass multiple identifiers, the user will be deep linked into Safari Extension Settings and see the list of all installed extension, highlighting the rows of the extensions whose identifiers you passed in.

Finally, if you’re currently shipping a Safari App Extension, Safari 26.2 on macOS introduces improvements to the migration path for your users. Previously, it’s been possible to associate your web extension with an app extension and replace it during an upgrade. By making this association, it would automatically turn the web extension on and hide the app extension. In Safari 26.2 and later, if the Safari web extension replaces a single Safari app extension, Safari also migrates web permissions and the setting that indicates whether the user allows the extension in Private Browsing. Safari only migrates website permissions if the Safari web extension does not require more website access than the Safari app extension.

Also introduced browser.runtime.getVersion() as a simplified synchronous method to retrieve the installed extension version, replacing the common pattern of runtime.getManifest().version.

Bug fixes and more

Along with the new features, WebKit for Safari 26.2 includes additional improvements to existing features.

Accessibility

  • Fixed Voice Control number and name overlays not labeling content inside iframe elements. (118252216)
  • Fixed incorrect accessibility bounds of SVG roots, ensuring assistive technologies have access to the correct geometry. (153782363)
  • Fixed an issue where <label> elements targeted by aria-labelledby stopped providing accessibility text to assistive technologies after dynamic page changes. (158906980)

Animations

  • Fixed inheritance of additional animation properties (animation-timing-function, animation-play-state, animation-iteration-count, and animation-direction) in ::view-transition pseudo-elements to improve style consistency. (156131284)
  • Fixed animation-name resolution to correctly find matching @keyframes within tree-scoped and shadow DOM contexts. (156484228)
  • Fixed a bug where extremely large animation-duration values could cause the page to become unresponsive. (158775366)
  • Fixed Animation.commitStyles() so that custom properties are properly committed to the target element. (158919736)
  • Fixed Animation.commitStyles() to correctly commit logical properties as their corresponding physical properties. (158920529)

Browser

  • Fixed: Safari now reports a frozen OS version in its user agent string on iOS 26 and iPadOS 26, showing the last version released before iOS 26. (156170132)

CSS

  • Fixed -webkit-user-select: none disabling find-in-page in Safari. (8081660)
  • Fixed incorrect z-ordering for position: sticky elements. (90572595)
  • Fixed getComputedStyle to correctly ignore ::first-letter and ::first-line styles on flex containers, to reflect used style. (94163778)
  • Fixed style invalidation so that :scope selectors always match even when the scoping root is unavailable. (135907710)
  • Fixed propagation of the body element’s writing-mode to the document element to match the CSS Writing Modes Level 4 specification. (149475070)
  • Fixed @position-try so that revert-layer correctly only reverts the position-try origin instead of affecting other cascade origins. (154355428)
  • Fixed positioned boxes in scrollable containing blocks to overflow in scrollable direction. (155625030)
  • Fixed anchor-center so that when an anchored element has no anchor in the same containing block, it correctly falls back to behaving like center as specified. (155768216)
  • Fixed anchor() positioning in CSS Grid to correctly account for grid-area. (155823420)
  • Fixed the default computed value for text-emphasis-style: filled|open to be filled|open circle not filled|open dot in horizontal typographic modes. (155911820)
  • Fixed the text-decoration shorthand to cover all four longhand properties. (156011594)
  • Fixed an issue where @namespace rules that failed insertion could still affect the namespace node. (156651404)
  • Fixed incorrect handling of auto inline margins on grid items during track sizing that caused excessive vertical spacing in subgrids. (157638931)
  • Fixed automatic min-size handling for flex and grid items to correctly treat overflow: clip as non-scrollable, aligning with the CSS specifications. (158215991)
  • Fixed incorrect baseline alignment for <button> elements when contain: layout is applied by using the content box as the baseline. (159007878)
  • Fixed out-of-flow box with no sibling ignoring align-content. (159097576)
  • Fixed CSS anchor positioning to remember the last successful position option at ResizeObserver delivery time, aligning with the spec. (159225250)
  • Fixed handling of the ::first-line pseudo-element when floats prevent the initial line from containing inline content, ensuring correct styling is applied to the actual first formatted line. (159613287)
  • Fixed an issue where collapsed table rows subtracted border-spacing twice. (160542118)
  • Fixed ::view-transition pseudo-element to use position: absolute instead of fixed to align with the updated specification. (160622000)
  • Fixed container queries to allow container-name matching across the full flat tree, making container names tree-scoped in line with the CSS Conditional 5 specification. (160696378)
  • Fixed handling of ::first-letter pseudo-elements to always force inline display unless floated.(160710650)
  • Fixed the behavior of the nesting selector & directly inside @scope to correctly act like :where(:scope) for proper specificity handling. (160769736)
  • Fixed position-try-fallback resolution by treating names as tree-scoped references to properly search shadow DOM host scopes. (161081231)
  • Fixed an issue where a <select> element with long <option> text caused horizontal scrolling when nested inside a flex item. (161563289)
  • Fixed getComputedStyle to return numeric values for orphans and widows instead of the internal auto value, ensuring the computed values correctly reflect the CSS specification. (161566631)
  • Fixed column-count: 1 so that it now correctly creates a multi-column container per the CSS Multi-column Layout specification. (161611444)
  • Fixed the calculation of anchor positions in vertical-rl multi-column layouts by correctly flipping coordinates in fragmented flows. (161616545)
  • Fixed the order to try anchor position fallback options, such that the last successful position option is tried first, followed by the original style, and then the remaining options. (161714637)
  • Fixed position-area handling to include the in-flow scrollable area of the initial containing block. (161741583)
  • Fixed position-visibility: no-overflow to respond correctly to scrolling. (162173481)
  • Fixed: Renamed position-area keywords from x-self-start, x-self-end, y-self-start, and y-self-end to self-x-start, self-x-end, self-y-start, and self-y-end respectively to align with updated CSSWG specifications.(162214793)
  • Fixed auto margins by converting them to zero when position-area or anchor-center is applied in CSS Anchor Positioning. (162809291)
  • Fixed FontFace.family so that font family names with spaces are treated as plain strings without parsing or serializing aligning with other browsers. (163047573)
  • Fixed flex and grid layout to correctly handle padding and margins in all writing modes. (163048874)
  • Fixed an issue where underlines using text-underline-position: right appeared on top of the text in horizontal writing modes instead of under the line. (163506701)
  • Fixed an infinite style resolution loop when a position-try box was inside a display: none tree. (163691875)
  • Fixed position-area alignment so that when only one inset is set to auto, the element now aligns toward the opposite non-auto inset. (163691905)
  • Fixed text-decoration-thickness and text-underline-offset not working in vertical writing modes. (163727749)
  • Fixed an issue where scrollRectToVisible() did not scroll pages to bring fixed anchor-positioned boxes into view when navigating with the keyboard. (163764088)
  • Fixed an issue where anchor-positioned elements transitioning from display: block to display: none can not anchor themselves to the anchor. (163861918)
  • Fixed incorrect underline positioning for text-decoration when inline box sides are trimmed. (163909909)

DOM

  • Fixed an issue where command-clicking to open a link in a new tab navigates the current tab. (57216935)

Editing

  • Fixed jumbled text when copy/pasting bidirectional text starting with left-to-right. (152236717)
  • Fixed paste performance in textarea by skipping unnecessary layout calls and only removing unrendered text nodes in richly editable fields. (157813510)

Events

  • Fixed boundary pointer and mouse events not firing when the hit test target changed under a stationary pointer. (160147423)

Forms

  • Fixed an issue where some websites may sometimes fail to reveal the focused element when the keyboard appears. (50384887)
  • Fixed form controls to preserve legibility when using accent-color in both light and dark modes by adjusting luminance thresholds and updating submit button text handling. (99018889)
  • Fixed input fields with field-sizing: content so that larger placeholder text now correctly expands the height of the field by including the placeholder’s computed height. (123125836)
  • Fixed <select> element with long <option> text causing horizontal scrolling in grid or flex containers. (141633685)
  • Fixed an issue on iOS where backing out of the “Take a photo/video” file upload flow caused the upload button to stop working. (157789623)
  • Fixed painting for <input type="range"> sliders in right-to-left vertical block writing modes. (158567821)
  • Fixed an issue where tainted scripts were blocked from reading values of form fields they created, now allowing access if the field was not modified by user input. (163299988)

HTML

  • Fixed an issue where navigating to :~:text fragments on dynamically generated pages did not highlight or scroll to the fragment. (150880542)

Home Screen Web Apps

  • Fixed an issue where an audio element failed to play when re-opening a Home Screen Web App. (155336513)

Images

  • Fixed HDR images in CSS backgrounds, CSS borders and inside SVG images so they are now properly decoded and rendered in HDR mode. (158076668)

JavaScript

  • Fixed non-standard new Date(2024-12-3) yielding to an “Invalid Date” error. (141044926)
  • Fixed “text/json/json+json” to be considered an invalid JSON MIME type. (154912716)
  • Fixed compatibility issues with the timezone option in the Intl.DateTimeFormat constructor. (156148700)
  • Fixed Intl.Local#language to return "und" if the language subtag is "und". (156248659)
  • Fixed Intl to support non-continental timezones to align with the specification. (156424446)
  • Fixed exception check errors by adding a missing exception check for Array#flat. (157525399)
  • Fixed an issue where the module loader would incorrectly attempt to refetch a module after a failed fetch. (158084942)
  • Fixed Iterator.prototype.flatMap to properly handle iterators without a return method. (158783404)
  • Fixed poor error messages for destructing null or undefined values. (159340067)
  • Fixed TypeError messages to be clearer in for-of loops. (159814766)
  • Fixed TypeError messages when calling class or function constructors without new to include the constructor name. (161152354)

MathML

  • Fixed rendering of unknown MathML elements so they now behave like mrow as required by the MathML Core specification. (148593275)
  • Fixed mfenced elements to render like mrow. (161416576)

Media

  • Fixed western Arabic numbers being displayed in the video viewer instead of eastern Arabic numbers. (141281469)
  • Fixed WebVTT line-height to be normal by default, not 1. (156633220)
  • Fixed handling of null media accessibility caption profile. (159134245)
  • Fixed hiding and resuming a webm video that sometimes causes a decoding error. (159508950)
  • Fixed MediaRecorder to no longer fire erroneous error events when stopped immediately after track changes, aligning behavior with Chrome and closer to Firefox. (161124260)
  • Fixed an issue where custom WebVTT caption text size settings did not propagate to cue child elements by moving the font-size definition into the cue’s shared <style> block. (162547969)

Networking

  • Fixed an issue where rel=preload link headers with a nonce could trigger erroneous Content-Security-Policy-Report-Only violations due to the nonce not being copied into the fetch options. (75060055)
  • Fixed an issue where apps that are mistakenly calling the WKWebView API loadRequest from a background thread may end up crashing. (162070925)

PDF

  • Fixed an issue where the active PDF annotation hover effect would remain visible after moving the pointer away. (162951528)

Rendering

  • Fixed incorrect clipping of position: fixed and position: sticky content during view transitions. (154886047)
  • Fixed computing static position to correctly size and locate an inset modified containing block. (155650719)
  • Fixed alignment candidate to consider both first and last baseline item position. (155806707)
  • Fixed the cross axis direction in flexbox to properly consider text directionality when the cross axis aligns with the inline axis to handle direction property and flex-wrap: wrap-reverse interactions. (156540996)
  • Fixed <button> elements to use the last line as their baseline instead of the first line to ensure consistent alignment with <br> in the text. (157955703)
  • Fixed orthogonal table cells so their writing-mode is no longer forced to match the table, allowing proper vertical layout. (158221827)
  • Fixed an issue where exiting fullscreen could scroll to unscrollable areas. (158351089)
  • Fixed an issue where the padding end incorrectly contributed to scrollable overflow when the inline direction was flipped. (158529814)
  • Fixed word breaking so that a hyphen followed by a Latin-1 Supplement character (U+00C0–U+00FF) correctly allows line breaks. (158942361)
  • Fixed large inset box shadows to render correctly. (159888287)
  • Fixed an issue where sticky elements at the edge of the viewport could disappear during rubber band scrolling. (160385933)
  • Fixed an issue where selecting table cells could cause overlapping selections in flex and grid layouts. (160805174)
  • Fixed flickering of elements with slow-painting content during view transitions. (160886647)
  • Fixed an issue where elements with both opacity and CSS filter effects could render incorrectly. (161130683)
  • Fixed an issue where elements with background images were not counted as contentful for Paint Timing. (161456094)
  • Fixed scroll-to-text fragment highlights to automatically choose a contrasting foreground and background color to keep text readable on dark pages, while respecting custom ::target-text styles. (163166782)
  • Fixed an issue where fullscreen dialog backdrops did not properly extend below the address bar by extending the backdrop’s background into obscured inset areas. (163535684)
  • Fixed an issue where slotted text nodes could become hidden when adjacent elements in a flex container changed their display property. (163571747)

SVG

  • Fixed an issue where a dynamic change in a CSS property of an SVG element does not get reflected in the instances of the SVGElement. (98577657)
  • Fixed an issue where stop-color incorrectly accepted hashless hex color values like 1234 by treating them as invalid to follow the spec. (119166640)
  • Fixed SVGMarkerElement to correctly support the SVG_MARKER_ORIENT_AUTO_START_REVERSE value, aligning behavior with the spec and other browsers. (123453058)
  • Fixed absolutely positioned SVG elements to correctly account for the containing block’s padding. (127608838)
  • Fixed handling of word-spacing so that leading white space in SVG text correctly applies spacing at the start of a text box. (134941299)
  • Fixed an issue where SVGs with a 0px intrinsic width were ignored but now correctly respect degenerate aspect ratios and fall back to the viewBox aspect ratio. (156339128)
  • Fixed handling semicolons at end of a keySplines value. (156511711)
  • Fixed unnecessary rounding of viewportLocation in 'foreignObject' layout. (156740732)
  • Fixed <svg> elements to correctly calculate their intrinsic aspect ratio using currentViewBoxRect() when a <view> is referenced. (157445966)
  • Fixed SVGFETurbulenceElement to correctly fallback numOctaves to 1 for invalid or negative values, aligning with the specification and other browsers. (158988528)
  • Fixed an issue where SVG pattern tileImage could appear blurred or pixelated when zooming or printing. (159202567)
  • Fixed SVGStyleElement so that its type and media attributes now use pure attribute reflection, matching HTMLStyleElement. (159358585)
  • Fixed an issue where <view> element was not applied to the root element. (159705519)
  • Fixed SVGAElement so that its rel and relList attributes now affect navigation behavior, including proper handling of noopener, noreferrer, and the new opener value, aligning SVG links with HTMLAnchorElement behavior. (160724516)

Security

  • Fixed parsing of require-trusted-types-for in CSP to ensure 'script' is only valid when followed by whitespace or end of buffer. (147760089)

Service Worker

  • Fixed an issue where service worker downloads are not being saved to Downloads folder. (154501503)

Storage

  • Fixed WebSockets to correctly inherit storage access from the frame that created them. (147949918)
  • Fixed requestStorageAccess() should always grant access when called from a same-site iframe. (156545395)
  • Fixed Storage Access API to not be usable in insecure contexts. (157337423)
  • Fixed requestStorageAccess() to reject with a NotAllowedError. (157446015)
  • Fixed an issue where cross-origin navigations incorrectly preserved storage access. (158446697)
  • Fixed an issue where dedicated workers could inherit storage access from their parent document, preventing them from sending cross-site requests with cookies. (158814068)

Tables

  • Fixed collapsed table rows retaining nonzero height. (158276634)

Web API

  • Fixed an issue where the first pointerdown event was lost after triggering a context menu by right-clicking. (84787733)
  • Fixed window.opener being incorrectly set to null when a site-isolated iframe navigated to a new site, ensuring opener relationships persist across frame migrations. (117269418)
  • Fixed the ability to delete a cookie through Cookie Store API that was set through document.cookie. (142339417)
  • Fixed Trusted Types to only verify event handler attributes for elements in the XHTML, SVG, and MathML namespaces, preventing incorrect checks on other namespaces. (147763139)
  • Fixed reading the mutable field from the outer object instead of as a child of notification. (157475553)
  • Fixed location.protocol setter to be restricted to HTTP(S) schemes. (157607342)
  • Fixed scroll and scrollend events so they correctly fire on <input type="text"> elements instead of their inner elements. (157880733)
  • Fixed CookieStore methods to strip tabs and spaces from the names and values passed in. (157907393)
  • Fixed JSON modules to fetch with an application/json Accept header. (158176845)
  • Fixed an issue where click and auxclick event targeting does not follow pointer capture target override. (159477637)
  • Fixed the order of pointerup and boundary events so that pointerout and pointerover fire before pointerup when a child element is attached under the cursor. (160913756)
  • Fixed element.scrollTo and element.scrollBy so they correctly scroll text input fields by forwarding scroll operations to the inner text element. (160963921)
  • Fixed EventCounts interface was not maplike. Enables use of methods such as .forEach(), keys(), and entries(). (160968888)
  • Fixed an issue where mousemove events were still dispatched to removed mouseover targets instead of their parent element when the target was deleted. (161203639)
  • Fixed missing pointerenter and mouseenter events when a child element moved under the mouse. (161362257)
  • Fixed an issue where only one CSP violation report was sent for multiple enforced require-trusted-types-for directives. (161740298)
  • Fixed Trusted Types incorrectly treating null or undefined policy return values as null instead of empty strings during createHTML, createScript, and createScriptURL operations. (161837641)
  • Fixed attachShadow() to default to using the global custom element registry instead of the host’s registry when customElementRegistry is null. (161949419)
  • Fixed attachShadow() to use the global custom element registry by default when customElementRegistry is null, aligning with the specification. (161949493)

Web Extensions

  • Fixed an issue where onInstalled getting called after every launch of Safari when opening a profile window. (147491513)
  • Fixed sender.origin parameter to match window.location.origin. (155884667)
  • Fixed an issue where Safari extension popups could open scrolled down and some websites could flicker during scrolling. (155965298)
  • Fixed an issue that caused the web page to crash when navigating to certain URLs with an extension enabled. (158180410)

Web Inspector

  • Fixed syntax highlighting for JavaScript features like template literals, private class elements, optional chaining, and others. (107619553)
  • Fixed an issue where the Console truncated long string outputs. (124629101)
  • Fixed an issue where DOM elements represented in the Console could not be selected. (157015598)
  • Fixed an issue where newlines and indentation in HTML markup would show up in DOM node previews in the Console. (157225532)
  • Fixed an issue that prevented scrolling of the Media details sidebar from the Elements tab. (157768497)
  • Fixed an issue where accepting a completion suggestion for a shorthand property value would malform the combined value. (159107788)
  • Fixed an issue where navigating the DOM tree using the keyboard would get stuck in a loop within certain subtrees. (159841729)
  • Fixed an issue where the Sources tab won’t show contents of a script that contains a for statement with optional chaining in the test condition. (160617913)
  • Fixed an issue where adding DOM attributes or node siblings did not work correctly when using the actions from the context menu. (161577627)

WebDriver

  • Fixed the navigate endpoint in WebDriver to properly validate URLs against the current browsing context and set the default readiness state to Interactive to align with the specification. (157031091)
  • Fixed an issue where element references nested inside Array or Object arguments were not properly extracted when executing scripts. (162571946)

WebRTC

  • Fixed camera indicator staying enabled even after ending a meeting or removing access to the camera. (152962650)

Feedback

We love hearing from you. To share your thoughts, find us online: Jen Simmons on Bluesky / Mastodon, Saron Yitbarek on BlueSky / Mastodon, and Jon Davis on Bluesky / Mastodon. You can 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 run into a website that isn’t working as expected, please file a report at webcompat.com or refresh the page and then select Report a Website Issue from Safari Page Menu to share feedback directly with Apple. Filing issues really does make a difference.

You can also find this information in the Safari release notes.

December 12, 2025 06:30 PM

December 08, 2025

Release Notes for Safari Technology Preview 233

Surfin’ Safari

Safari Technology Preview Release 233 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 302450@main…303091@main.

Animations

Resolved Issues

  • Fixed incorrect overlap calculations for transform animations including translate, scale, and rotate properties. (303045@main) (88383253)

HTML

New Features

  • Added support for enhanced HTML select parsing to allow <select> elements to include <optgroup>, <option>, and <hr> at deeper nesting levels. (302480@main) (163927485)

MathML

New Features

  • Added support for the MathML scriptlevel attribute, mapping it to CSS math-depth as a presentational hint. (302841@main) (164469677)

Resolved Issues

  • Fixed mpadded elements in RTL (dir="rtl") to respect lspace. (303070@main) (164740784)

Rendering

Resolved Issues

  • Fixed an issue where fixed positioned elements were not rendered correctly in right-to-left pages using the vertical-rl writing mode. (302542@main) (161712734)

Web API

New Features

  • Added support for reading Blob.stream() with a BYOB (getReader({mode:'byob'})) reader. ( 302787@main ) (164307723)

Resolved Issues

  • Fixed Trusted Types to correctly send CSP violation reports when a default policy returns an invalid javascript: URL or throws an exception. (302543@main) (160960418)
  • Fixed NavigateEvent to correctly fire an AbortSignal when a navigation is aborted. (302591@main) (163957784)
  • Fixed NavigateEvent.sourceElement to correctly reference elements from different browsing contexts. (302504@main) (163962362)

Web Inspector

New Features

  • Added support for capturing console.screenshot images within a Worker, including handling of ImageData, ImageBitmap, OffscreenCanvas, various CanvasRenderingContext types, and valid base64 data: URLs. (302778@main) (98223234)

December 08, 2025 10:21 PM

December 04, 2025

::target-text: An easy way to style text fragments

Surfin’ Safari

You’re reading a great blog post. You want to share it with your friend but instead of getting them to read the whole thing, you really just want to highlight a few key sentences and have them go directly to that section of the page. That’s what text fragments are for.

As a user, you can highlight any section of text on a page and right click to make it a text fragment. In Safari, that means right clicking and selecting “Copy Link with Highlight” from the menu and getting a url that will highlight the text fragment when the page loads.

The default highlighting gives you a pale yellow highlight under the fragment text, like this:

Lorem ipsum blog post with pale yellow highlight for text fragment.

You can click on this link to see for yourself how it works.

That’s the user experience. But what about the developer experience? Is there something we developers can do to customize that experience for our users a bit more? Actually, there is! We’ll use the ::target-text pseudo-element to help us style our text fragment.

In your CSS file, use the ::target-text pseudo-element and style the text with whatever properties you wish, like this:

::target-text {
  background-color: blue;
  color: white;
}

That’ll get you this result:

Lorem ipsum blog post with white text on blue highlight for text fragment.

So if you want to decide how a text fragment looks to your users, take advantage of ::target-text and own the user’s text fragment experience. It’s fully supported in all browsers.

If you enjoyed this kind of bite-size content, let me know. You can reach me, Saron Yitbarek, on BlueSky, or reach out to our other evangelists — Jon Davis, on Bluesky / Mastodon, and Jen Simmons, on Bluesky / Mastodon. You can also follow WebKit on LinkedIn. If you find a bug or problem, please file a WebKit bug report.

December 04, 2025 07:21 PM

November 21, 2025

Grid: how grid-template-areas offer a visual solution for your code

Surfin’ Safari

Using grid lines is a flexible and powerful way to place your elements on a grid, but, when looking at the code, it might be a bit hard to visualize. So Grid gives you another way to place your elements that might be easier to see called grid areas. There’s a bit more upfront work involved, but the pay off might be worth it.

The idea behind grid areas is that we name each element we want to place on our grid and then use a certain syntax to place them visually where we want them to go. To illustrate, let’s start with my product page.

Here’s the html I’m starting with:

<div class="card">
  <h1>Product 1</h1>
  <h2>$99</h2>
  <p>This is a description of the first option.</p>
  <ul><!-- product details here --></ul>
</div>

<div class="card">
  <h1>Product 2</h1>
  <h2>$99</h2>
  <p>This is a description of the first option.</p>
  <ul><!-- product details here --></ul>
</div>

<div class="card">
  <h1>Add-ons</h1>
  <h2>$149</h2>
  <p>This is another description.</p>
  <ul><!-- product details here --></ul>
</div>

<div class="card">
  <h1>Testimonial</h1>
  <h2>$299</h2>
  <p>This is a third description.</p>
  <ul><!-- product details here --></ul>
</div>

And here’s the CSS I’m starting with:

.pricing-options {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2em;
}
.card {
  border: 1px solid black;
  padding: 2em 5em;
  font-family: sans-serif;
  border-radius: 1em;
}

That will give me this result:

Four cards three on one row and the last on the second left spot.

We want our page to follow this design:

Black and white mockup of two products, add-ons on the right spanning two rows, and testimonial spanning two columns.

This means we want our Add-ons to span two rows and our Testimonial to span two columns. Here’s how we can accomplish that with grid-template-areas.

First, we need to label each element by assigning a value to the grid-area property. To do that, let’s give our elements classes to reference in our CSS.

<div class="card product-1">
  <h1>Product 1</h1>
  <!-- product details here -->
</div>

<div class="card product-2">
  <h1>Product 2</h1>
  <!-- product details here -->
</div>

<div class="card add-ons">
  <h1>Add-ons</h1>
  <!-- product details here -->
</div>

<div class="card testimonial">
  <h1>Testimonial</h1>
  <!-- product details here -->
</div>

Now let’s add those grid-area property values. You can name them anything you want, but since my class names are pretty descriptive, I’m going to name the grid-areas the same as my class names.

.product-1 {
  grid-area: product-1;
}
.product-2 {
  grid-area: product-2;
}
.add-ons {
  grid-area: add-ons;
}
.testimonial {
  grid-area: testimonial;
}

Now comes the visual part. In our CSS, we’re going to go back up to where our grid is defined and we’re going to assign a new property called grid-template-areas. I’m now going to visually assign each cell of my grid to an element in my html.

My grid is three columns across and an unspecified number of rows, which means it’ll be as many rows as needed. I’m going to assign product-1 to that first top cell and product-2 in my second top cell. Then my third top cell is going to be taken up by my add-ons element. And because my add-ons element is going to span two rows, the cell right beneath that is going to be assigned to add-ons too. And finally, we have the bottom left cell assigned to testimonial and because that element is taking up two columns across, the cell right next to it will be assigned to testimonial as well.

Here’s what the final code looks like:

.pricing-options {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2em;
  grid-template-areas:
    "product-1 product-2 add-ons"
    "testimonial testimonial add-ons";
}

The beauty of grid-template-areas is that all of the decisions about where to place what element happen in a single property. You still have to do the upfront work of naming your elements, but once you’ve done that, you can visually see where everything is in relation to each other in a single place. Changing it is simpler too — just move the element name to a different “cell” and you’re done.

Using grid-template-areas , we get our desired layout.

Final layout of site with two products, add-ons on the right spanning two rows and testimonial at the bottom spanning two columns.

If you have any other questions about Grid and would like to see more content on this topic, let us know. You can share your feedback with me, Saron Yitbarek, on BlueSky, or reach out to our other evangelists — Jon Davis, on Bluesky / Mastodon, and Jen Simmons, on Bluesky / Mastodon. You can also follow WebKit on LinkedIn. If you find a bug or problem, please file a WebKit bug report.

November 21, 2025 01:00 AM

November 12, 2025

Release Notes for Safari Technology Preview 232

Surfin’ Safari

Safari Technology Preview Release 232 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 301766@main…302449@main.

CSS

New Features

  • Added support for allowing positioned boxes in scrollable containing blocks to overflow along scrollable directions. (302259@main) (162722820)
  • Added support for flip-x and flip-y options in position-try-fallback for CSS Anchor Positioning. (302057@main) (163282036)

Resolved Issues

  • Fixed handling of padding and margins for flex and grid layouts across all writing modes. (301814@main) (71046552)
  • Fixed getComputedStyle("top") to correctly resolve percentage values for absolutely positioned elements inside inline containers. (302090@main) (161390162)
  • Fixed an infinite style resolution loop when a position-try box was inside a display: none subtree. (302254@main) (161570947)
  • Fixed width, height, min-width, min-height, max-width and max-height to apply CSS zoom at used-value time. (302241@main) (161848512)
  • Fixed CSS zoom to scale <iframe> element contents. (302097@main) (162314059)
  • Fixed getBoundingClientRect and getClientRects to return scaled lengths according to CSS zoom instead of unscaled values, aligning with the CSS Viewport specification. (301806@main). (162325730)
  • Fixed scrolling behavior so that scrollRectToVisible() can bring fixed anchor-positioned boxes outside the viewport into view, improving keyboard navigation. (302368@main) (162378346)
  • Fixed an issue where @font-face and FontFace.family failed when the font family name contained spaces, ensuring the family name is now treated as a plain string instead of being parsed. (301793@main) (162637501)
  • Fixed top, left, right, and bottom to apply CSS zoom at used-value time (302102@main) (162663056)
  • Fixed margin to apply CSS zoom at used-value time. (301965@main) (162907254)
  • Fixed evaluation of calc() expressions to correctly apply the used zoom factor to length values, ensuring properties like line-height and box dimensions scale properly. (301968@main) (163141549)
  • Fixed an issue where calc(em) values for unzoomed properties were incorrectly adjusted. (302041@main) (163267333)
  • Fixed position-area normal alignment to correctly align toward the non-auto inset when only one inset is auto. (302299@main) (163317238)
  • Fixed incorrect underline positioning for text-decoration when inline box sides are trimmed. (302435@main) (163858721)

JavaScript

Resolved Issues

  • Fixed Intl.DateTimeFormat to throw a RangeError for legacy non-IANA timezones, aligning behavior with TC39 standards. (302447@main) (156857252)

Media

Resolved Issues

  • Fixed: Aligned with other browsers by dispatching enter and exit events on TextTrackCue and VTTCue with no track. (301836@main) (160195643)
  • Fixed an issue where the mute button disappeared in macOS inline videos with adjustable sizes. (301896@main) (162897286)

Rendering

Resolved Issues

  • Fixed over-aggressive clipping of child layers in multicolumn layouts to prevent visual overflow issues with position: relative elements and transform:scale() text. (302249@main) (126413036)
  • Fixed unreadable Scroll-to-Text-Fragment highlights on dark pages. (301930@main) (126539910)
  • Fixed an issue where positioned, transformed, or opacity-altered <img> elements with HDR JPEG gainmaps would incorrectly render in SDR. (302200@main) (156858374)

SVG

Resolved Issues

  • Fixed animation of the stop-color attribute on <stop> elements.(302163@main) (109823555)

Storage

Resolved Issues

  • Fixed an issue where IndexedDB databases might have mismatched metadata version and database name encoding format. (302055@main) (163219457)

Web API

Resolved Issues

  • Fixed event ordering and committed promise timing for intercepted Navigation API traverse navigations. (302418@main) (161445256)
  • Fixed the processing order of Trusted Types for DOM attribute setting. (302272@main) (162143148)
  • Fixed NavigateEvent to correctly fire an AbortSignal when a navigation is aborted. (302591@main) (163957784)
  • Fixed NavigateEvent.sourceElement to correctly reference elements from different browsing contexts. (302504@main) (163962362)

Web Inspector

Resolved Issues

  • Fixed an issue where CSS properties added to new rules were not applied and were marked as invalid. (302301@main) (103548968)
  • Fixed an issue in the Console where the count of identical consecutive messages could be wrong. (301917@main) (162612099)

November 12, 2025 10:23 PM

November 03, 2025

WebKit Features for Safari 26.1

Surfin’ Safari

Today, Safari 26.1 is available with iOS 26.1, iPadOS 26.1, macOS Sequoia 26.1 and visionOS 26.1, as well as for macOS Sequoia and macOS Sonoma. It contains 2 new features and 36 improvements to existing features.

Relative units in SVG

As part of our most recent efforts on quality, WebKit for Safari 26.1 refactors the way the rendering engine handles CSS Units. This results in giving the SVG engine easier access to relative units, adding support for certain units inside SVG files for the first time. These units include rem; viewport units: vh, vw, vmin, vmax; typography-relative units: rlh, ic, cap, and container query units: cqw, cqi, cqmin, cqmax.

Anchor Positioning improvements

Safari 26.1 includes a dozen improvements to CSS Anchor Positioning. Now WebKit remembers the last successful position-try fallback in CSS anchor positioning to reduce layout jumps when styles change. See below for the full list of changes to Anchor Positioning.

Bug fixes and more

Along with the new features, WebKit for Safari 26.1 includes improvements to existing features.

Accessibility

  • Fixed hit testing for scrolled iframe content by adjusting for the frame’s scroll position, ensuring accurate element detection across assistive technologies. (158233884)
  • Fixed an issue where VoiceOver reports the wrong radio count with a dynamically inserted radio option. (159937173)
  • Fixed exposing content within dynamically expanded details elements in the accessibility tree. (159937257)
  • Fixed the target of aria-labelledby not updating its accessibility label after dynamic innerHTML change in the label. (160691619)

CSS Anchor Positioning

  • Fixed anchor positioning to handle fragmented multicolumn flows. (156958568)
  • Fixed anchor positioning fallbacks to respond to scrolling. (158451016)
  • Fixed an issue where container queries doesn’t work with position-try element. (158880410)
  • Fixed anchor positioning to account for a left-hand scrollbar in right-to-left and vertical-rl containing blocks. (160723993)
  • Fixed handling inline containing blocks for CSS Anchor Positioning. (160892829)
  • Fixed an issue where anchor-positioned elements failed to update their position when the default anchor changed. (160892850)
  • Fixed an issue where transitioning an element to display: none with transition-behavior: allow-discrete and CSS Anchor Positioning would repeatedly restart the transition. (161421046)
  • Fixed position-area for the initial containing block to include the in-flow scrollable area, improving alignment for typical overflow cases. (161997622)
  • Fixed position-visibility: anchors-visible visibility heuristic when anchor is clipped by an ancestor container. (160060564)

CSS

  • Fixed @media print styles to work when used inside a nested rule. (158608834)
  • Fixed: Improved the performance of :has(> .changed) .subject selectors. (159257003)
  • Fixed pseudo-class invalidation performance by creating separate RuleSets for attribute selectors like :has([attr=value]) to avoid using universal invalidation. (159257022)
  • Fixed an issue where changing the ruby-overhang property did not trigger a layout update, ensuring proper rendering when overhang values change. (159573050)
  • Fixed offsetParent to return the fixed-position element’s containing block when it is not the viewport, such as a transformed element. (160892685)
  • Fixed <select> fallback styling by removing the outdated background and updating the dropdown arrow. (161104364)

Forms

  • Fixed native text inputs so that their background colors update when autofilled. (159014135)
  • Fixed checkboxes and radio buttons missing borders in the filled state when “Increased Contrast” is enabled on macOS. (159379948)

PDF

  • Fixed VoiceOver not recognizing the password form in encrypted documents. (159240531)

Rendering

  • Fixed a bottom gap appearing on layouts with viewport-sized fixed containers on iOS. (158055568)
  • Fixed an issue on iOS where Safari extension popups and some websites could scroll or flicker unexpectedly. (160216319)
  • Fixed list markers overlapping text in certain situations. (160892820)
  • Fixed an issue that caused cropped flexbox elements to render incorrectly. (161218029)
  • Fixed string search freezing when subject has large number (>1000). (161421015)

SVG

  • Fixed absolutely positioned SVGs so that their size correctly accounts for the padding of the containing block when the SVG root is out-of-flow. (160727702)

Security

  • Fixed Safari ignoring the style-src-elem Content Security Policy directive ensuring it is checked before falling back to style-src, in line with CSP3 specifications. (157298407)

Web API

  • Fixed an issue on iOS 26 where pressing the B button on a gamepad could make a page appear to lose gamepad focus by bypassing the system’s automatic navigation behavior. (159125095)

Web Inspector

  • Fixed issue where searching on certain text fails to find matches. (159897282)

WebGPU

  • Fixed an issue where GPUQueue.copyExternalImageToTexture could not handle SVG images. (158442476)
  • Fixed an issue where video playback using the WebGPU renderer in WebCodecs could display a black screen. (158442539)
  • Fixed an issue where WebGPU video textures failed to load in Three.js panoramas. (159918934)

WebKit API

  • Fixed a crash when an app uses WKWebView::loadRequest API on background threads. (162225842)

WebRTC

  • Fixed getUserMedia() on iOS incorrectly firing devicechange events when there was no actual change to available microphones or default devices. (157693528)

Feedback

We love hearing from you. To share your thoughts, find our web evangelists online: Jen Simmons on Bluesky / Mastodon, Saron Yitbarek on Bluesky / Mastodon, and Jon Davis on Bluesky / Mastodon. You can 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 run into a website that isn’t working as expected, please file a report at webcompat.com. Filing issues really does make a difference.

You can also find this information in the Safari release notes.

November 03, 2025 09:00 AM

October 30, 2025

Release Notes for Safari Technology Preview 231

Surfin’ Safari

Safari Technology Preview Release 231 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 300987@main…301765@main.

CSS

New Features

  • Added support for the safe keyword with anchor-center in CSS Anchor Positioning. (301301@main) (155767796)
  • Added support for flip-x and flip-y options in position-try-fallback for CSS Anchor Positioning. (302057@main) (163282036)

Resolved Issues

  • Fixed handling of padding and margins for flex and grid layouts across all writing modes. (301814@main) (71046552)
  • Fixed position-visibility: no-overflow to respond correctly to scrolling. (301211@main) (162173481)
  • Fixed: Renamed position-area keywords from x-self-start, x-self-end, y-self-start, and y-self-end to self-x-start, self-x-end, self-y-start, and self-y-end respectively to align with updated CSSWG specifications.(301226@main) (162214793)
  • Fixed <iframe> elements so their content correctly respects the page’s usedZoom(). (302097@main) (162314059)
  • Fixed auto margins by converting them to zero when position-area or anchor-center is applied in CSS Anchor Positioning. (301662@main) (162809291)

JavaScript

Resolved Issues

  • Fixed TypeError messages when calling class or function constructors without new to include the constructor name. (301023@main) (161152354)

Media

Resolved Issues

  • Fixed an issue where custom WebVTT caption text size settings did not propagate to cue child elements by moving the font-size definition into the cue’s shared <style> block. (301681@main) (162547969)

Rendering

New Features

  • Added support for text shaping across inline boxes. (301354@main) (162430932)

Resolved Issues

  • Fixed an issue where selecting table cells could cause overlapping selections in flex and grid layouts. (294464@main) (160805174)
  • Fixed a performance issue on layouts with long pre blocks and word-break: break-all by including whitespace in overflow width calculations. (301657@main) (162695099)
  • Fixed Largest Contentful Paint to optimize text paints by performing an early area comparison when an element has only one text box. (301895@main) (163067611)
  • Fixed Largest Contentful Paint to skip tracking loadTime for data URI images. (301988@main) (163213487)
  • Fixed how Largest Contentful Paint performs area checks for text nodes, optimizing calculations when all rects are collected and ancestor transforms are absent. (302072@main) (163285757)

Web API

Resolved Issues

  • Fixed Navigation API WPT tests failing due to a WebDriver error. (161199777)
  • Fixed PerformanceEventTiming so that keydown and pointerdown entries no longer wait for their corresponding keyup or pointerup events before assigning a duration, preventing durations from appearing too long. (302107@main) (161911473)
  • Fixed attachShadow() to use the global custom element registry by default when customElementRegistry is null, aligning with the WHATWG DOM specification (300996@main). (161949493)
  • Fixed navigate() with { history: "replace" } to correctly update the current History item instead of adding a new one during same-document navigations. (302130@main) (163323288)

Web Inspector

Resolved Issues

  • Fixed an issue where the Sources tab won’t show contents of a script that contains a for statement with optional chaining in the test condition. (301197@main) (160617913)

WebDriver

Resolved Issues

  • Fixed an issue where element references nested inside Array or Object arguments were not properly extracted when executing scripts. (301445@main) (162571946)

October 30, 2025 07:19 PM

October 15, 2025

Release Notes for Safari Technology Preview 230

Surfin’ Safari

Safari Technology Preview Release 230 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 300291@main…300986@main.

Animations

Resolved Issues

  • Fixed animation-name resolution to correctly find matching @keyframes within tree-scoped and shadow DOM contexts. (300706@main) (156484228)

CSS

Resolved Issues

  • Fixed incorrect handling of auto inline margins on grid items during track sizing that caused excessive vertical spacing in subgrids. (300422@main) (157638931)
  • Fixed CSS anchor positioning to remember the last successful position option at ResizeObserver delivery time, aligning with the spec. (300890@main) (159225250)
  • Fixed an issue where transitioning an element to display: none with transition-behavior: allow-discrete and CSS Anchor Positioning would repeatedly restart the transition. (300519@main) (160421419)
  • Fixed the acceptable anchor algorithm in CSS Anchor Positioning to correctly consider inline elements as containing blocks. (300614@main) (160917762)
  • Fixed CSS nesting to inline parent selectors when possible instead of always wrapping them in :is() to improve selector performance. (300297@main) (160927950)
  • Fixed position-try-fallback resolution by treating names as tree-scoped references to properly search shadow DOM host scopes. (300333@main) (161081231)
  • Fixed an issue where a <select> element with long <option> text caused horizontal scrolling when nested inside a flex item. (300684@main) (161563289)
  • Fixed getComputedStyle to return numeric values (2) for orphans and widows instead of the internal auto value, ensuring the computed values correctly reflect the CSS specification. (300690@main) (161566631)
  • Fixed column-count: 1 so that it now correctly creates a multi-column container per the CSS Multi-column Layout specification. (300787@main) (161611444)
  • Fixed the calculation of anchor positions in vertical-rl multi-column layouts by correctly flipping coordinates in fragmented flows. (300807@main) (161616545)
  • Fixed the order to try anchor position fallback options, such that the last successful position option is tried first, followed by the original style, and then the remaining options. (300909@main) (161714637)
  • Fixed position-area handling to include the in-flow scrollable area of the initial containing block. (300921@main) (161741583)
  • Fixed position-visibility: no-overflow to respond correctly to scrolling. (301211@main) (162173481)
  • Fixed: Renamed position-area keywords from x-self-start, x-self-end, y-self-start, and y-self-end to self-x-start, self-x-end, self-y-start, and self-y-end respectively to align with updated CSSWG specifications.(301226@main) (162214793)

HTML

Resolved Issues

  • Fixed an issue where navigating to :~:text fragments on dynamically generated pages did not highlight or scroll to the fragment. (300918@main) (150880542)

MathML

Resolved Issues

  • Fixed rendering of unknown MathML elements so they now behave like mrow as required by the MathML Core specification. (300580@main) (148593275)

Media

Resolved Issues

  • Fixed MediaRecorder to no longer fire erroneous error events when stopped immediately after track changes, aligning behavior with Chrome and closer to Firefox. (300682@main) (161124260)

Rendering

Resolved Issues

  • Fixed incorrect clipping of position:fixed/sticky content during view transitions. (300561@main) (154886047)
  • Fixed an issue that caused cropped flexbox elements to render incorrectly. (300433@main) (159638640)
  • Fixed an issue where sticky elements at the edge of the viewport could disappear during rubber band scrolling. (300544@main) (160385933)
  • Fixed flickering of elements with slow-painting content during view transitions. (300902@main) (160886647)
  • Fixed an issue where elements with both opacity and CSS filter effects could render incorrectly. (300549@main) (161130683)
  • Fixed an issue where elements with background images were not counted as contentful for Paint Timing. (300667@main) (161456094)

SVG

Resolved Issues

  • Fixed an issue where stop-color incorrectly accepted hashless hex color values like 1234 by treating them as invalid to follow the spec. (300296@main) (119166640)
  • Fixed an issue where SVG pattern tileImage could appear blurred or pixelated when zooming or printing. (300357@main) (159202567)
  • Fixed SVGAElement so that its rel and relList attributes now affect navigation behavior, including proper handling of noopener, noreferrer, and the new opener value, aligning SVG links with HTMLAnchorElement behavior. (300462@main) (160724516)

Security

Resolved Issues

  • Fixed parsing of require-trusted-types-for in CSP to ensure 'script' is only valid when followed by whitespace or end of buffer. (300770@main) (147760089)

Web API

New Features

  • Added support for Largest Contentful Paint. (300834@main) (161705604)

Resolved Issues

  • Fixed an issue where the first pointerdown event was lost after triggering a context menu by right-clicking. (300696@main) (84787733)
  • Fixed Trusted Types to only verify event handler attributes for elements in the XHTML, SVG, and MathML namespaces, preventing incorrect checks on other namespaces. (300783@main) (147763139)
  • Fixed an issue where navigate.back in the main frame would fail after a navigate.back in a child frame by properly clearing the provisional history item to allow correct back navigation. (301092@main) (158259024)
  • Fixed NavigateEvent.sourceElement to correctly reference the submitting HTMLFormElement instead of null when a form is submitted. (301252@main) (160391355)
  • Fixed EventCounts interface was not maplike. Enables use of methods such as .forEach(), keys(), and entries(). (300830@main) (160968888)
  • Fixed an issue where mousemove events were still dispatched to removed mouseover targets instead of their parent element when the target was deleted. (300522@main) (161203639)
  • Fixed missing pointerenter and mouseenter events when a child element moved under the mouse. (300564@main) (161362257)
  • Fixed an issue where only one CSP violation report was sent for multiple enforced require-trusted-types-for directives. (300832@main) (161740298)
  • Fixed Trusted Types incorrectly treating null or undefined policy return values as null instead of empty strings during createHTML, createScript, and createScriptURL operations. (300892@main) (161837641)

Web Extension

New Features

  • Added support for browser.runtime.getVersion() to retrieve the extension version from its manifest. (300972@main) (161742137)

Web Inspector

Resolved Issues

  • Fixed syntax highlighting for JavaScript features like template literals, private class elements, optional chaining, and others. (300332@main) (107619553)
  • Fixed an issue where navigating the DOM tree using the keyboard would get stuck in a loop within certain subtrees. (300471@main) (159841729)
  • Fixed an issue where adding DOM attributes or node siblings did not work correctly when using the actions from the context menu. (300752@main) (161577627)

October 15, 2025 09:15 PM