Safari 26.5 is here, delivering the :open pseudo-class, the element-scoped keyword for random(), color-interpolation for SVG gradients, the ToggleEvent.source property for popovers, and the Origin API.
Alongside new features, this release continues our ongoing efforts to greatly improve the quality of WebKit. There are 63 bug fixes in total — making this the biggest May release of WebKit yet. The improvements span SVG, WebRTC, networking, editing, and more. Scroll-driven animations and Anchor Positioning both get multiple fixes. Rendering at different zoom levels works better. And work continues improving the handling layout whenever a block-level element lives inside an inline element.
The new :open pseudo-class in CSS provides a clean way to style the open state of elements like <details>, <dialog>, <select>, and <input>.
Previously, you might have used the [open] attribute selector for <details> and <dialog>. It works on those elements, but doesn’t work on <select> or <input>. Plus, it’s an attribute selector doing the job better handled by a pseudo-class. Now :open provides a single, consistent pattern that works across all of these element types.
For <dialog>, it now matches when the dialog is showing — whether opened with showModal() or show(). And for <input>, it applies when an associated picker is displayed, like a date or color picker.
For <select>, :open matches when the drop-down is expanded.
select:open {
border: 1px solid skyblue;
}
This is a practical improvement to everyday CSS. The progressive enhancement is straightforward — browsers that don’t yet support :open simply won’t apply those rules, and the underlying elements still function normally.
We were proud to be the first browser to ship the new CSS random() function last December, in Safari 26.2. Since then, the CSS Working Group adjusted how named random values work. Using a named value in the syntax, like random(--size, 100px, 200px), now creates a global result, instead of something scoped to each individual element. Safari 26.5 implements these changes, including a new element-scoped keyword for when you need per-element behavior.
For example, imagine you have eight instances of <div class="box"> and apply the following CSS.
.box {
width: random(100px, 200px);
height: random(100px, 200px);
border: 2px solid black;
}
You get eight completely differently sized rectangles. This is because each time the random function is used, it generates a brand new number, in this case between 100px and 200px. This is how random() has worked since Safari 26.2.
If, instead, you want all eight boxes to be the same size with the same randomly generated height and width, you can write:
.box {
width: random(--w, 100px, 200px);
height: random(--h, 100px, 200px);
}
This chooses a random number, names it (as --w or separately --h), and reuses the named number on each box. (Before Safari 26.5, a cache name was scoped to the individual element, each single box. Now it is global.)
If you want all eight boxes to be square, you can use:
.box {
width: random(--s, 100px, 200px);
height: random(--s, 100px, 200px);
}
The --s ties the two sizes together. The height and width is random, but it’s the same number. Before Safari 26.5, this would give you eight differently-sized squares. Now it will give you a single random size for all eight squares.
If you want eight differently sized squares, you can now use the element-scoped keyword to scope the name to the element, like this:
.box {
width: random(--s element-scoped, 100px, 200px);
height: random(--s element-scoped, 100px, 200px);
}
Now the name applies only to a single element. You can put element-scoped before or after the name, meaning this works too: random(element-scoped --s, 100px, 200px). Lastly, the element-shared keyword has been removed from Safari 26.5, since the new default behavior covers this use case and the CSS Working Group removed it from the specification.
CSS anchor positioning continues to mature in this release, with several fixes addressing real-world usage patterns.
anchor() fallback values did not accept unitless zero. (173554237)display: contents did not establish an anchor scope when using anchor-scope. (173718365)This release includes two fixes for hanging-punctuation.
hanging-punctuation to correctly treat U+0027 (apostrophe) and U+0022 (quotation mark) as hangable quote characters. (172668971)hanging-punctuation: first. (172669250)Scroll-driven animations are a powerful recent addition to CSS, and this release includes four fixes that improve their reliability.
scroll animation timeline range name in scroll-driven animations. (171630023)animation-play-state was dynamically set to paused. (171630127)Work continues on the layout engine rewrite for block-in-inline contexts, with several fixes in this release.
getClientRects() could return rects with zero width and height for spans in multi-column layouts. (171101490)<span> with decoration was incorrectly positioned when a sibling block margin was present inside a block-in-inline context. (171101555)<br> element was incorrectly positioned inside a block-in-inline context when a block margin was present. (171101748)display: grid subgrid inside a grid-lanes container incorrectly contributed its items’ intrinsic sizes to the parent’s track sizing algorithm. (171230544)rowspan cell was incorrectly applied across the full length of the spanning cell’s border. (171634786)column-count: 1 could fail to display text. (172306151)This release includes a focused quality pass on rendering behavior at different zoom levels.
lh and rlh units resolved with double-zoom when line-height is a number. (173515568)rlh unit was double-zoomed when resolving with evaluation-time zoom for unzoomed properties. (173518838)aspect-ratio was not honored correctly when the page was zoomed in. (174498486)@font-face rules with different styles could incorrectly fall back to glyphs from other faces in the same family, rather than proceeding to the next family as specified by the font matching algorithm. (172390840):has(:empty) was not invalidated when the content of a child element changed from empty to non-empty. (174501418)WebKit for Safari 26.5 adds support for the color-interpolation attribute on SVG gradients, enabling linearRGB color space interpolation.
<linearGradient color-interpolation="linearRGB">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
By default, SVG gradients interpolate colors in the sRGB color space. Setting color-interpolation="linearRGB" on a gradient element now produces more perceptually even color transitions, especially noticeable in gradients between saturated colors, where sRGB interpolation can produce a darker or muddier midpoint than expected.
The work continues making significant improvements to SVG.
removeAttribute for width or height on an SVG root element did not reset to the initial default values. (172132798)onbegin, onend, and onrepeat on SVGAnimationElement and added the missing onend event handler. (172581017)<image> element was not repainted when its href attribute was removed. (172875166)cursor: url() appeared blurry on high DPI displays. (173950927)Safari 26.5 adds support for the source property on ToggleEvent. Now, when a popover or other toggleable element is toggled, the event includes a reference to the element that triggered the action, such as the invoker button that opened a popover. This makes it straightforward to coordinate behavior between a trigger and its target without manually tracking that relationship in your own code.
popover.addEventListener("toggle", (e) => {
if (e.newState === "open") {
console.log("Opened by:", e.source);
}
});
Safari 26.5 also adds support for the Origin API, which exposes origin information as a structured Origin object rather than requiring string parsing. This also enables you to perform same-site comparisons between origins without having to pull in the Public Suffix List. Origin.from(value) allows you to construct an Origin object from a string or built-in object, such as MessageEvent. When the origins from built-in objects are opaque, you can still compare them. This wasn’t possible before as you only had access to the serialized origin, which is “null” for opaque origins.
const messageOrigin = Origin.from(messageEvent);
const localOrigin = Origin.from("https://social.example");
if (messageOrigin.isSameSite(localOrigin))
grantAccess();
DecompressionStream discarded valid decompressed output when extra trailing bytes were present after the compressed stream, instead of enqueuing the output before throwing. (171020155)preventDefault() on pointerdown events did not prevent page scrolling when only passive touch event listeners are installed. (173988278)In addition to all the fixes described above, WebKit for Safari 26.5 also includes the following improvements:
contenteditable region could place the cursor in the wrong position. (171850465)readonly date <input> could still be edited via keyboard using the date picker. (171535893)datalist suggestions were presented directly over the associated input, obscuring it. (174264299)dragenter and dragleave events to include relatedTarget in the event object. (172048448)srcset and sizes attributes containing calc() expressions with division by zero were not displayed. (173954748)TypedArray.prototype.sort() failing when the comparison function accesses the .buffer property of the typed array. (172516044)MediaCapabilities.decodingInfo() always returned false for spatialRendering. (172689752)Content-Type header. (173705083)Content-Type header. (173945210)document.hasStorageAccess() could return a Promise that never resolves. (172424614)manifest.json failed to load in Safari. (172120877)NaN and infinity values. (166699074)RTCIceCandidate.toJSON() to include the usernameFragment property in its serialized output. (172689343)RTCRtpSender to allow a maxFramerate value of 0. (172689374)RTCRtpSynchronizationSource.timestamp to use the correct time base. (172689387)RTCRtpTransceiver.setCodecPreferences() to accept codecs with case-insensitive mimeType matching. (172689477)Safari 26.5 is available on iOS 26.5, iPadOS 26.5, visionOS 26.5, macOS Tahoe 26.5, plus macOS Sequoia, and macOS Sonoma. On iOS, iPadOS, and visionOS, you can update to Safari 26.5 as part of the OS update in Settings > General > Software Update. On macOS, Safari updates are delivered through System Settings > General > Software Update.
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 bug report. Filing issues really does make a difference.
You can also find this information in the Safari release notes.