<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Blog – WebKit</title>
	<atom:link href="https://webkit.org/blog/feed/" rel="self" type="application/rss+xml"/>
	<link>https://webkit.org</link>
	<description>Open Source Web Browser Engine</description>
	<lastBuildDate>Thu, 23 Apr 2026 20:04:50 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<itunes:explicit>no</itunes:explicit><itunes:subtitle>Open Source Web Browser Engine</itunes:subtitle><item>
		<title>Release Notes for Safari Technology Preview 242</title>
		<link>https://webkit.org/blog/17934/release-notes-for-safari-technology-preview-242/</link>
		
		<dc:creator/>
		<pubDate>Thu, 23 Apr 2026 20:04:50 +0000</pubDate>
				<category><![CDATA[Safari Technology Preview]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17934</guid>

					<description><![CDATA[Safari Technology Preview Release 242 is now available for download for macOS Tahoe and macOS Sequoia.]]></description>
										<content:encoded><![CDATA[<p><a href="https://webkit.org/blog/6017/introducing-safari-technology-preview/">Safari Technology Preview</a> Release 242 is now <a href="https://developer.apple.com/safari/resources/">available for download</a> 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.</p>
<p>This release includes WebKit changes between: <a href="https://github.com/WebKit/WebKit/compare/f91abd9528154fcf24a3ea90d43fdde378d9793b...b53493b67d659fd4026d0a21d03b63620daf704e">310187@main&#8230;310599@main</a>.</p>
<h3>Accessibility</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where VoiceOver read text within images that have <code>role="presentation"</code>. (<a href="https://commits.webkit.org/310483@main">310483@main</a>)  (159304061)</li>
<li>Fixed macOS accessibility support for customizable <code>&lt;select&gt;</code> elements using <code>appearance: base-select</code>. (<a href="https://commits.webkit.org/310441@main">310441@main</a>)  (173696010)</li>
</ul>
<h3>CSS</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the CSS <code>attr()</code> function from CSS Values Level 5. (<a href="https://commits.webkit.org/310246@main">310246@main</a>)  (173700363)</li>
<li>Added support for the <code>oblique-only</code> value for <code>font-synthesis-style</code> as defined in CSS Fonts Level 4. (<a href="https://commits.webkit.org/310409@main">310409@main</a>)  (173730766)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>@media (prefers-color-scheme: dark)</code> inside an iframe did not match when the iframe&#8217;s <code>color-scheme</code> was set to <code>dark</code>. (<a href="https://commits.webkit.org/310465@main">310465@main</a>)  (142072593)</li>
<li>Fixed <code>position-try-order</code> to interpret logical axis values using the containing block&#8217;s writing mode instead of the element&#8217;s own writing mode. (<a href="https://commits.webkit.org/310277@main">310277@main</a>)  (169501069)</li>
<li>Fixed an issue where percent-height replaced elements computed stale preferred widths in shrink-to-fit containers. (<a href="https://commits.webkit.org/310194@main">310194@main</a>)  (171184282)</li>
<li>Fixed an issue where the table cell <code>nowrap</code> minimum width calculation quirk was applied outside of quirks mode. (<a href="https://commits.webkit.org/310195@main">310195@main</a>)  (171410252)</li>
<li>Fixed an issue where checkbox outlines appeared misaligned. (<a href="https://commits.webkit.org/310323@main">310323@main</a>)  (172742551)</li>
<li>Fixed an issue where anchor-positioned elements anchored to children of sticky-positioned boxes did not stick correctly. (<a href="https://commits.webkit.org/310255@main">310255@main</a>)  (172884148)</li>
<li>Fixed an issue where pseudo-elements were not sorted correctly when sorting anchor elements by tree order. (<a href="https://commits.webkit.org/310407@main">310407@main</a>)  (173032203)</li>
<li>Fixed an issue where ligatures caused a non-zero layout width for text with <code>font-size: 0</code>. (<a href="https://commits.webkit.org/310394@main">310394@main</a>)  (173840866)</li>
<li>Fixed <code>:in-range</code> and <code>:out-of-range</code> pseudo-classes to correctly update when the <code>readonly</code> attribute changes. (<a href="https://commits.webkit.org/310484@main">310484@main</a>)  (173978657)</li>
<li>Fixed an issue where <code>view-timeline-inset</code> serialization failed to coalesce identical values. (<a href="https://commits.webkit.org/310590@main">310590@main</a>)  (174096313)</li>
</ul>
<h3>Forms</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>&lt;select multiple&gt;</code> did not always fire <code>onchange</code> when the mouse button was released far outside the element. (<a href="https://commits.webkit.org/310482@main">310482@main</a>)  (173882861)</li>
</ul>
<h3>HTML</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>closedby</code> attribute on <code>&lt;dialog&gt;</code> elements. (<a href="https://commits.webkit.org/310487@main">310487@main</a>)  (173974767)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed the HTML parser fast path to correctly process escaped attribute values longer than one character. (<a href="https://commits.webkit.org/310209@main">310209@main</a>)  (173673581)</li>
<li>Fixed the HTML parser fast path to correctly detect nested <code>&lt;li&gt;</code> elements. (<a href="https://commits.webkit.org/310492@main">310492@main</a>)  (173983892)</li>
<li>Fixed the HTML parser fast path to use the adjusted current node for MathML and SVG integration point checks. (<a href="https://commits.webkit.org/310593@main">310593@main</a>)  (174096305)</li>
</ul>
<h3>Images</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where inserting an image with a <code>srcset</code> attribute into a dynamically created iframe resulted in an invisible image. (<a href="https://commits.webkit.org/310446@main">310446@main</a>)  (66849050)</li>
</ul>
<h3>JavaScript</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where class instance field initializers did not have the correct evaluation context when used inside arrow functions and nested scopes. (<a href="https://commits.webkit.org/310594@main">310594@main</a>)  (173296563)</li>
<li>Fixed <code>%ArrayIteratorPrototype%.next()</code> to return <code>{ done: true }</code> instead of throwing a <code>TypeError</code> when the source TypedArray is detached and the iterator has already completed. (<a href="https://commits.webkit.org/310292@main">310292@main</a>)  (173759106)</li>
<li>Fixed an issue where a fixed-count mixed-width character class in a regular expression did not correctly restore the index on backtrack. (<a href="https://commits.webkit.org/310477@main">310477@main</a>)  (173972458)</li>
</ul>
<h3>Media</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where scrubbing a video in full-screen mode could cause it to exit full-screen. (<a href="https://commits.webkit.org/310415@main">310415@main</a>)  (172682230)</li>
<li>Fixed an issue where <code>HTMLMediaElement.preservesPitch = true</code> did not work when the element was connected to an <code>AudioContext</code>. (<a href="https://commits.webkit.org/310521@main">310521@main</a>)  (173727365)</li>
</ul>
<h3>Networking</h3>
<h4>New Features</h4>
<ul>
<li>Added support for secure cookies on loopback hosts. (<a href="https://commits.webkit.org/310542@main">310542@main</a>)  (137604100)</li>
</ul>
<h3>Rendering</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed a regression where nested column flexboxes could cause content to render at the wrong size. (<a href="https://commits.webkit.org/310253@main">310253@main</a>)  (173321492)</li>
<li>Fixed a regression where nested empty inline boxes accumulated an incorrect vertical offset, causing inline elements to stack as block-level elements. (<a href="https://commits.webkit.org/310313@main">310313@main</a>)  (173723162)</li>
<li>Fixed an issue where pseudo-elements were incorrectly included in outline rect collection. (<a href="https://commits.webkit.org/310531@main">310531@main</a>)  (174033087)</li>
</ul>
<h3>SVG</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>lang</code> and <code>xml:lang</code> attribute in SVG. (<a href="https://commits.webkit.org/310495@main">310495@main</a>)  (143751056)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where SMIL animations of <code>href</code> or <code>xlink:href</code> on SVG <code>&lt;image&gt;</code> elements had no visual effect. (<a href="https://commits.webkit.org/310236@main">310236@main</a>)  (96316808)</li>
<li>Fixed an issue where SVG gradient animations did not work unless <code>y1</code> and <code>y2</code> attributes were explicitly specified. (<a href="https://commits.webkit.org/310257@main">310257@main</a>)  (123457088)</li>
<li>Fixed an SVG <code>&lt;tspan&gt;</code> positioning bug with <code>xml:space="preserve"</code> that caused multi-line text to render incorrectly. (<a href="https://commits.webkit.org/310347@main">310347@main</a>)  (143722975)</li>
<li>Fixed an issue where URL fragments were not percent-decoded before being used for SVG references. (<a href="https://commits.webkit.org/310443@main">310443@main</a>)  (169582378)</li>
</ul>
<h3>Scrolling</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where sticky-positioned elements could flicker rapidly after scrolling. (<a href="https://commits.webkit.org/310545@main">310545@main</a>)  (173680821)</li>
<li>Fixed an issue where scroll anchoring could cause a page to scroll to the top or bottom automatically. (<a href="https://commits.webkit.org/310574@main">310574@main</a>)  (173885027)</li>
</ul>
<h3>Tables</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue with a collapsed border color mismatch when the table cell has a different writing-mode. (<a href="https://commits.webkit.org/310303@main">310303@main</a>)  (173655092)</li>
</ul>
<h3>Web API</h3>
<h4>New Features</h4>
<ul>
<li>Added support for <code>getAllRecords()</code> and <code>IDBGetAllOptions</code> in the IndexedDB API. (<a href="https://commits.webkit.org/310462@main">310462@main</a>)  (173881825)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>document.open()</code> incorrectly aliased the caller&#8217;s security origin. (<a href="https://commits.webkit.org/310543@main">310543@main</a>)  (173369038)</li>
<li>Fixed an issue where <code>Object.prototype</code> could not be serialized by <code>structuredClone()</code>. (<a href="https://commits.webkit.org/310363@main">310363@main</a>)  (173728983)</li>
<li>Fixed an issue where backslashes were not handled correctly in non-special URLs. (<a href="https://commits.webkit.org/310290@main">310290@main</a>)  (173757759)</li>
<li>Fixed a URL parsing bug in the special relative or authority state. (<a href="https://commits.webkit.org/310300@main">310300@main</a>)  (173772241)</li>
<li>Fixed an issue where event listener <code>once</code> and <code>passive</code> flags were not preserved when copying listeners between elements. (<a href="https://commits.webkit.org/310355@main">310355@main</a>)  (173834642)</li>
<li>Fixed `Preserve existing listener options (such as passive defaulting) when overwriting event handler attributes. (<a href="https://commits.webkit.org/310362@main">310362@main</a>)  (173842822)</li>
</ul>
<h3>WebRTC</h3>
<h4>New Features</h4>
<ul>
<li>Added support for <code>RTCRtpReceiver.jitterBufferTarget</code>. (<a href="https://commits.webkit.org/310285@main">310285@main</a>)  (173676035)</li>
<li>Added support for video source <code>width</code> and <code>height</code> in RTC stats. (<a href="https://commits.webkit.org/310295@main">310295@main</a>)  (173677615)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where I420 BT709 <code>VideoFrame</code> was encoded in an incorrect color space when encoding to VP9. (<a href="https://commits.webkit.org/310306@main">310306@main</a>)  (169425608)</li>
<li>Fixed an issue where <code>RTCRtpSender.setParameters</code> did not clear parameters that were unset by the web application. (<a href="https://commits.webkit.org/310286@main">310286@main</a>)  (173678165)</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Release Notes for Safari Technology Preview 241</title>
		<link>https://webkit.org/blog/17917/release-notes-for-safari-technology-preview-241/</link>
		
		<dc:creator/>
		<pubDate>Wed, 08 Apr 2026 21:21:17 +0000</pubDate>
				<category><![CDATA[Safari Technology Preview]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17917</guid>

					<description><![CDATA[Safari Technology Preview Release 241 is now available for download for macOS Tahoe and macOS Sequoia.]]></description>
										<content:encoded><![CDATA[<p><a href="https://webkit.org/blog/6017/introducing-safari-technology-preview/">Safari Technology Preview</a> Release 241 is now <a href="https://developer.apple.com/safari/resources/">available for download</a> 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.</p>
<p>This release includes WebKit changes between: <a href="https://github.com/WebKit/WebKit/compare/f4d9aee8564bd69af3b62913cf0dc558055e460b...0432220790bcd2f3133408195256b93866db0315">309287@main&#8230;310186@main</a>.</p>
<h3>Accessibility</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where calling <code>speechSynthesis.cancel()</code> removed utterances queued by subsequent <code>speechSynthesis.speak()</code> calls. (<a href="https://commits.webkit.org/309349@main">309349@main</a>)  (46151521)</li>
<li>Fixed an issue where incorrect bounding boxes were computed for MathML table rows and cells. (<a href="https://commits.webkit.org/309640@main">309640@main</a>)  (172851295)</li>
<li>Fixed an issue where comboboxes did not forward focus to their <code>aria-activedescendant</code>, preventing assistive technologies from interacting with list items. (<a href="https://commits.webkit.org/309641@main">309641@main</a>)  (172931277)</li>
<li>Fixed an issue where <code>aria-owns</code> was not respected when computing the accessible name from element content. (<a href="https://commits.webkit.org/310020@main">310020@main</a>)  (173249317)</li>
</ul>
<h3>Animations</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>animation-fill-mode</code> did not correctly apply viewport-based units after the viewport was resized. (<a href="https://commits.webkit.org/310007@main">310007@main</a>)  (80075191)</li>
</ul>
<h3>CSS</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>stretch</code> keyword in box sizing properties. (<a href="https://commits.webkit.org/309405@main">309405@main</a>)  (132539604)</li>
<li>Added stable support for CSS scroll anchoring. (<a href="https://commits.webkit.org/310113@main">310113@main</a>)  (171840378)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where U+2028 LINE SEPARATOR was not rendered as a forced line break per the CSS specification. (<a href="https://commits.webkit.org/309701@main">309701@main</a>)  (88470339)</li>
<li>Fixed an issue where <code>outline-offset</code> was inflated for <code>outline: auto</code> on macOS. (<a href="https://commits.webkit.org/309812@main">309812@main</a>)  (94116168)</li>
<li>Fixed <code>font-family</code> serialization to preserve quotes around family names that match CSS-wide keywords or generic families. (<a href="https://commits.webkit.org/309959@main">309959@main</a>)  (125334960)</li>
<li>Fixed an issue where a font was downloaded despite no characters in the document falling within its <code>unicode-range</code>. (<a href="https://commits.webkit.org/309360@main">309360@main</a>)  (140674753)</li>
<li>Fixed an issue where a flex item containing a percentage-height image did not shrink correctly around the image. (<a href="https://commits.webkit.org/309544@main">309544@main</a>)  (156902823)</li>
<li>Fixed an issue where View Transition snapshots were incorrectly stored in sRGB, causing rendering issues with non-sRGB colors. (<a href="https://commits.webkit.org/310012@main">310012@main</a>)  (167634138)</li>
<li>Fixed a performance issue where <code>contain: layout</code> caused significantly slower forced layouts when all siblings created their own formatting context. (<a href="https://commits.webkit.org/310173@main">310173@main</a>)  (171545381)</li>
<li>Fixed an issue where underlines were split when a ruby base was expanded due to long ruby text. (<a href="https://commits.webkit.org/309356@main">309356@main</a>)  (171653095)</li>
<li>Fixed an issue where changing <code>color-scheme</code> did not repaint the background of composited iframes. (<a href="https://commits.webkit.org/309567@main">309567@main</a>)  (171658244)</li>
<li>Fixed an issue where nested children of a popover element failed to render when using <code>position: absolute</code>. (<a href="https://commits.webkit.org/310019@main">310019@main</a>)  (171735933)</li>
<li>Fixed an issue where <code>color: initial</code> resolved to the wrong color in dark appearance mode. (<a href="https://commits.webkit.org/309430@main">309430@main</a>)  (172320282)</li>
<li>Fixed an issue where an element with <code>display: contents</code> did not establish an anchor scope when using <code>anchor-scope</code>. (<a href="https://commits.webkit.org/309946@main">309946@main</a>)  (172355302)</li>
<li>Fixed a regression where media queries could fail to resolve correctly in the presence of viewport units and anchors, causing styles to not update on viewport changes. (<a href="https://commits.webkit.org/309470@main">309470@main</a>)  (172385594)</li>
<li>Fixed a regression where absolutely positioned elements with intrinsic height incorrectly resolved percentage heights, causing content to not render on some sites. (<a href="https://commits.webkit.org/309513@main">309513@main</a>)  (172513516)</li>
<li>Fixed <code>&lt;general-enclosed&gt;</code> in media queries to reject content with unmatched close brackets per the <code>&lt;any-value&gt;</code> grammar. (<a href="https://commits.webkit.org/309497@main">309497@main</a>)  (172575115)</li>
<li>Fixed an issue where a right-floated table could overlap another table. (<a href="https://commits.webkit.org/309316@main">309316@main</a>)  (172655655)</li>
<li>Fixed an issue where grid containers failed to avoid float boxes. (<a href="https://commits.webkit.org/309317@main">309317@main</a>)  (172655720)</li>
<li>Fixed an issue where checkboxes could overlap with adjacent text. (<a href="https://commits.webkit.org/310015@main">310015@main</a>)  (172741572)</li>
<li>Fixed an issue where the <code>rlh</code> unit was double-zoomed with evaluation-time CSS zoom. (<a href="https://commits.webkit.org/309654@main">309654@main</a>)  (172798163)</li>
<li>Fixed <code>outline: auto</code> to correctly respect zoom. (<a href="https://commits.webkit.org/309926@main">309926@main</a>)  (173068660)</li>
<li>Fixed <code>:active</code>, <code>:focus-within</code>, and <code>:hover</code> pseudo-classes to correctly account for elements in the top layer. (<a href="https://commits.webkit.org/309755@main">309755@main</a>)  (173145294)</li>
<li>Fixed the <code>shape()</code> function to omit default control point anchors in computed value serialization per the CSS Shapes specification. (<a href="https://commits.webkit.org/309851@main">309851@main</a>)  (173233716)</li>
<li>Fixed: Updated SVG and MathML user agent style sheets to use <code>:focus-visible</code> instead of <code>:focus</code>. (<a href="https://commits.webkit.org/309912@main">309912@main</a>)  (173321368)</li>
<li>Fixed an issue where view transition snapshots could capture stale transform values for accelerated CSS transform animations. (<a href="https://commits.webkit.org/309982@main">309982@main</a>)  (173323193)</li>
<li>Fixed an issue where <code>lh</code> and <code>rlh</code> units resolved with double-zoom when <code>line-height</code> was a number value. (<a href="https://commits.webkit.org/310043@main">310043@main</a>)  (173448638)</li>
<li>Fixed <code>outline-width</code> to be ignored when <code>outline-style</code> is <code>auto</code>, matching the specification. (<a href="https://commits.webkit.org/310145@main">310145@main</a>)  (173567890)</li>
<li>Fixed <code>:in-range</code> and <code>:out-of-range</code> pseudo-classes for time inputs with reversed ranges. (<a href="https://commits.webkit.org/310156@main">310156@main</a>)  (173589851)</li>
</ul>
<h3>Canvas</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where a 2D canvas element unnecessarily forced a compositing layer. (<a href="https://commits.webkit.org/309599@main">309599@main</a>)  (172864747)</li>
</ul>
<h3>Forms</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where keyboard commands such as paste did not work in form fields that restrict input to numbers. (<a href="https://commits.webkit.org/309300@main">309300@main</a>)  (4360235)</li>
<li>Fixed: Made the <code>&lt;input type="checkbox" switch&gt;</code> control behave more like other controls with regards to native appearance CSS properties. (<a href="https://commits.webkit.org/310143@main">310143@main</a>)  (173487610)</li>
</ul>
<h3>HTML</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>auto</code> keyword in the <code>sizes</code> attribute on <code>&lt;img&gt;</code> elements, enabling automatic size calculation based on the rendered layout width. (<a href="https://commits.webkit.org/309476@main">309476@main</a>)  (172827205)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where an HTML <code>map</code> element without a <code>name</code> attribute did not match its associated image using the <code>id</code> attribute. (<a href="https://commits.webkit.org/309490@main">309490@main</a>)  (12359382)</li>
<li>Fixed an issue where <code>replaceWith()</code> stopped processing remaining nodes if a script in the replacement removed a sibling. (<a href="https://commits.webkit.org/309411@main">309411@main</a>)  (172753019)</li>
<li>Fixed an issue where HEIC images were incorrectly converted to JPEG when uploaded via drag-and-drop. (<a href="https://commits.webkit.org/309872@main">309872@main</a>)  (173206598)</li>
<li>Fixed an issue where setting the <code>rel</code> attribute on an <code>&lt;a&gt;</code> element multiple times did not clear prior link relations. (<a href="https://commits.webkit.org/310144@main">310144@main</a>)  (173567839)</li>
</ul>
<h3>Images</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where adopting a standalone <code>img</code> element did not update its image data. (<a href="https://commits.webkit.org/309523@main">309523@main</a>)  (172856773)</li>
</ul>
<h3>JavaScript</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>Array.prototype.concat</code> to correctly handle arrays with indexed accessors, preventing getter reentry from bypassing <code>Symbol.isConcatSpreadable</code> checks. (<a href="https://commits.webkit.org/309423@main">309423@main</a>)  (172237596)</li>
<li>Fixed an issue where a greedy or non-greedy non-BMP character class in a regular expression could advance the index past the end of input. (<a href="https://commits.webkit.org/309968@main">309968@main</a>)  (172978772)</li>
<li>Fixed TypedArray <code>[[Set]]</code> to check the receiver before writing to the typed array. (<a href="https://commits.webkit.org/309967@main">309967@main</a>)  (173386404)</li>
</ul>
<h3>MathML</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where symmetric non-stretchy large operators were not centered around the math axis. (<a href="https://commits.webkit.org/309778@main">309778@main</a>)  (170905663)</li>
<li>Fixed an issue where <code>minsize</code> and <code>maxsize</code> defaults and percentages did not use the unstretched size as specified. (<a href="https://commits.webkit.org/309764@main">309764@main</a>)  (170908253)</li>
</ul>
<h3>Media</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>preservesPitch</code> and <code>playbackRate</code> were not correctly handled on an <code>HTMLMediaElement</code> connected to an <code>AudioContext</code> via <code>createMediaElementSource</code>. (<a href="https://commits.webkit.org/310098@main">310098@main</a>)  (93275149)</li>
<li>Fixed an issue where video captions could be hidden behind other elements during inline playback. (<a href="https://commits.webkit.org/309505@main">309505@main</a>)  (171023402)</li>
<li>Fixed an issue where seeking in a WebM video did not work correctly while content was still loading. (<a href="https://commits.webkit.org/309373@main">309373@main</a>)  (172473039)</li>
<li>Fixed an issue where media playback could not move to the next item in a playlist when the tab was in the background. (<a href="https://commits.webkit.org/309879@main">309879@main</a>)  (172676372)</li>
<li>Fixed an issue where HDR video content appeared washed out due to colorspace information being lost during processing. (<a href="https://commits.webkit.org/309502@main">309502@main</a>)  (172721079)</li>
</ul>
<h3>Networking</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed a regression where the referrer could be missing after a process-swap navigation. (<a href="https://commits.webkit.org/309382@main">309382@main</a>)  (169006635)</li>
</ul>
<h3>Printing</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where animations were not rendered during print, causing missing content on animated pages. (<a href="https://commits.webkit.org/309488@main">309488@main</a>)  (36901701)</li>
<li>Fixed an issue where printing light text on a dark background with backgrounds disabled could result in invisible text. (<a href="https://commits.webkit.org/309604@main">309604@main</a>)  (170070133)</li>
</ul>
<h3>Rendering</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where the document background color did not align with the CSS specification, causing incorrect background colors when pinch-zooming out. (<a href="https://commits.webkit.org/309332@main">309332@main</a>)  (23607800)</li>
<li>Fixed an issue where <code>WidthIterator</code> consumed the first character twice, potentially causing incorrect text measurement. (<a href="https://commits.webkit.org/309437@main">309437@main</a>)  (128492167)</li>
<li>Fixed a regression where hovering over elements could leave repaint artifacts on the page. (<a href="https://commits.webkit.org/309861@main">309861@main</a>)  (169112402)</li>
<li>Fixed an issue where Find in Page scrolled to the wrong location when matching text inside elements with <code>user-select: none</code>. (<a href="https://commits.webkit.org/309923@main">309923@main</a>)  (170477571)</li>
<li>Fixed an issue where remote snapshotting could flip part of the page. (<a href="https://commits.webkit.org/309441@main">309441@main</a>)  (170868383)</li>
<li>Fixed an issue where an anonymous block created for list markers was not properly collapsed when block content prevented line-box parenting. (<a href="https://commits.webkit.org/309466@main">309466@main</a>)  (172686060)</li>
<li>Fixed an issue where elements flickered when scrolling. (<a href="https://commits.webkit.org/309493@main">309493@main</a>)  (172701438)</li>
<li>Fixed an issue where U+2029 PARAGRAPH SEPARATOR was not treated as a forced line break. (<a href="https://commits.webkit.org/309706@main">309706@main</a>)  (173106856)</li>
<li>Fixed an issue where tiles were missing after navigating back in history. (<a href="https://commits.webkit.org/309966@main">309966@main</a>)  (173288233)</li>
</ul>
<h3>SVG</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where SVG animation did not clear the animated CSS property when <code>attributeName</code> was dynamically changed. (<a href="https://commits.webkit.org/309621@main">309621@main</a>)  (97097883)</li>
<li>Fixed an issue where a CSS filter referencing an SVG filter via <code>url(#id)</code> was not invalidated when the filter content changed. (<a href="https://commits.webkit.org/309495@main">309495@main</a>)  (101870430)</li>
<li>Fixed an issue where invalid SVG filter effects were rendered instead of being suppressed. (<a href="https://commits.webkit.org/309463@main">309463@main</a>)  (130951885)</li>
<li>Fixed an issue where <code>getScreenCTM()</code> did not include CSS transforms and zoom contributions in the legacy SVG rendering path. (<a href="https://commits.webkit.org/309354@main">309354@main</a>)  (171525696)</li>
<li>Fixed an issue where an SVG <code>&lt;image&gt;</code> element was not repainted when the <code>href</code> attribute was removed. (<a href="https://commits.webkit.org/309397@main">309397@main</a>)  (172530834)</li>
<li>Fixed an issue where an invalid attribute type in one SVG animation group prevented all subsequent animation groups from running. (<a href="https://commits.webkit.org/309436@main">309436@main</a>)  (172593109)</li>
<li>Fixed a regression where wheel events were not dispatched to an empty <code>&lt;svg&gt;</code> root element. (<a href="https://commits.webkit.org/310013@main">310013@main</a>)  (172909441)</li>
<li>Fixed an issue where SMIL <code>parseClockValue</code> did not reject out-of-range minutes and seconds values per the SMIL timing specification. (<a href="https://commits.webkit.org/310184@main">310184@main</a>)  (173577212)</li>
</ul>
<h4>Deprecations</h4>
<ul>
<li>Removed the <code>SVGLocatable</code> and <code>SVGTransformable</code> interfaces to align with the SVG2 specification. (<a href="https://commits.webkit.org/309396@main">309396@main</a>)  (104668934)</li>
<li>Removed the <code>viewTarget</code> property from <code>SVGViewSpec</code> to align with the SVG2 specification. (<a href="https://commits.webkit.org/309424@main">309424@main</a>)  (172590438)</li>
</ul>
<h3>Storage</h3>
<h4>New Features</h4>
<ul>
<li>Added support for setting <code>maxAge</code> in the Cookie Store API via <code>cookieStore.set()</code>. (<a href="https://commits.webkit.org/309738@main">309738@main</a>)  (166301541)</li>
</ul>
<h3>Web API</h3>
<h4>New Features</h4>
<ul>
<li>Added support for fractional coordinates in <code>PointerEvent</code> and <code>TouchEvent</code> properties such as <code>clientX/clientY</code>, <code>pageX/pageY</code>, <code>offsetX/offsetY</code>, and <code>screenX/screenY</code>, while <code>MouseEvent</code> values remain whole. (<a href="https://commits.webkit.org/298383@main">298383@main</a>)  (9564176)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>NavigateEvent.navigationType</code> to return <code>"replace"</code> when navigating to a URL that matches the active document&#8217;s URL. (<a href="https://commits.webkit.org/309871@main">309871@main</a>)  (169999046)</li>
<li>Fixed an issue where <code>navigation.currentEntry.key</code> did not change in private browsing windows after calling history.pushState(). (<a href="https://commits.webkit.org/309489@main">309489@main</a>)  (171147417)</li>
<li>Fixed a performance issue where <code>ResizeObserver</code> callbacks became increasingly sluggish over time. (<a href="https://commits.webkit.org/309376@main">309376@main</a>)  (172718139)</li>
<li>Fixed an issue where <code>IntersectionObserver</code> could get sluggish over time due to O(n^2) iteration when observing many elements. (<a href="https://commits.webkit.org/309387@main">309387@main</a>)  (172727210)</li>
<li>Fixed an issue where <code>navigation.currentEntry.id</code> did not change in private browsing windows after calling <code>history.replaceState()</code>. (<a href="https://commits.webkit.org/309560@main">309560@main</a>)  (172897962)</li>
</ul>
<h3>Web Inspector</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where an active recording in the Timelines tab would stop when navigating or reloading the current page even when the setting to stop recording once the page loads was turned off. (<a href="https://commits.webkit.org/309566@main">309566@main</a>)  (169732727)</li>
<li>Fixed an issue where clicking the resource type selectors in the Network and Sources tabs did not show any options and just used the previously selected option. (<a href="https://commits.webkit.org/310437@main">310437@main</a>)  (173857179)</li>
</ul>
<h3>WebRTC</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>RTCRtpCodec</code> dictionary and related constructs. (<a href="https://commits.webkit.org/309610@main">309610@main</a>)  (172745579)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>RTCDataChannel</code> did not check the SCTP buffered amount synchronously. (<a href="https://commits.webkit.org/309322@main">309322@main</a>)  (172386678)</li>
<li>Fixed an issue where <code>MediaStreamTrack</code> could have incorrect settings if the source settings changed while the track was being transferred. (<a href="https://commits.webkit.org/309458@main">309458@main</a>)  (172657570)</li>
<li>Fixed an issue where a remote WebRTC track was not unmuted when the first packet was received. (<a href="https://commits.webkit.org/309987@main">309987@main</a>)  (172904930)</li>
<li>Fixed validation of RTC send encodings to better align with the specification. (<a href="https://commits.webkit.org/310055@main">310055@main</a>)  (172997814)</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Introducing the JetStream 3 Benchmark Suite</title>
		<link>https://webkit.org/blog/17899/introducing-the-jetstream-3-benchmark-suite/</link>
		
		<dc:creator/>
		<pubDate>Tue, 31 Mar 2026 18:30:06 +0000</pubDate>
				<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17899</guid>

					<description><![CDATA[Today, alongside our colleagues at Google and Mozilla, we announced JetStream 3.0, a major update to the cross-browser benchmark suite.]]></description>
										<content:encoded><![CDATA[<p>Today, alongside our colleagues at Google and Mozilla, we announced JetStream 3.0, a major update to the cross-browser benchmark suite. While the <a href="http://browserbench.org/announcements/jetstream3/">shared announcement</a> covers the breadth of the suite and the collaborative effort behind it, we wanted to take a moment to dive deeper into how the WebKit team approached these challenges and the engineering work in JavaScriptCore behind our improvements.</p>
<p>Benchmarks are among the best tools browser engine developers use to drive performance. The web is ever evolving though, and any benchmark will get out of date with new best practices. Moreover, when the most accessible optimizations have been addressed in a benchmark, subsequent optimizations tend to become less and less general and more specific to that exact workload. JetStream 3 represents both a refresh and a fundamental shift in how we measure performance, particularly regarding WebAssembly and the scale of modern web applications.</p>
<h2>The Evolution of WebAssembly Benchmarking</h2>
<p>One of the most significant changes in JetStream 3 is how we measure WebAssembly (Wasm) workloads. To understand why we changed it, we have to look back at where Wasm started. When JetStream 2 was released, WebAssembly was in its infancy. The earliest adopters of Wasm were large C/C++ projects that previously compiled to an earlier technology, asm.js. We anticipated large C/C++ applications (like video games) where users would be more willing to tolerate a long, one-time startup cost in exchange for high-throughput performance afterward. Consequently, JetStream 2 scored Wasm in two distinct phases: Startup and Runtime.</p>
<h3>An <code>Infinity</code> Problem</h3>
<p>Over the years, browser engines have become remarkably efficient at instantiating WebAssembly modules. As startup times improved, the incentive to pursue even micro-optimizations actually compounded. Shaving 0.1 ms off a 100 ms workload is indistinguishable from noise; however, once engines successfully reduced that instantiation time to just 2 ms, that same 0.1 ms improvement suddenly represented a 5% performance gain. In WebKit, for instance, we optimized the startup path so aggressively that for certain smaller workloads, our startup time effectively reached zero seconds. In JetStream 2, each iteration’s time was computed with <code>Date.now()</code>, which rounds down so any sub-1 ms time becomes 0 ms.</p>
<p>This created a unique challenge for the benchmark. The scoring formula was Score = 5000 / Time. Thus, when the time hit zero, the score became infinity. We eventually had to patch the benchmark harness in JetStream 2.2, clamping the score to 5000, so that a 0 ms sub-score didn’t obsolete all other scores.</p>
<p>While getting an infinite score sounds like a victory, it was a clear sign that browser engines had outgrown JetStream 2’s Wasm subtests. On the modern web, Wasm is in the critical path for many page loads. It is used in libraries, image decoders, and UI frameworks. A &#8220;zero&#8221; startup time in a microbenchmark doesn&#8217;t account for how well the code runs immediately after instantiation, which got lost in the long, single Runtime score. JavaScript benchmarks in JetStream 2 measured the full execution lifecycle, so we concluded that WebAssembly scoring should work the same way.</p>
<p>In JetStream 3, we retired the separate, single iteration, Startup/Runtime scoring for Wasm. Instead, we have adopted the same scoring methodology used for JavaScript benchmarks; Running the same code for many iterations and extracting:</p>
<ul>
<li>First Iteration: Captures compilation and initial setup (the &#8220;startup&#8221; cost before).</li>
<li>Worst Case Iterations: Captures &#8220;jank&#8221; and garbage collection or tiering pauses.</li>
<li>Average Case Iterations: Captures sustained throughput.</li>
</ul>
<p>These scores are then geometrically averaged to compute the subtest&#8217;s overall score, which in turn feeds into the geometric mean of the full benchmark score. This shift forces engines to optimize the entire lifecycle of a WebAssembly instance, ensuring that Wasm integrates smoothly into the interactive web.</p>
<h3>Escaping the Microbenchmark Trap</h3>
<p>Another major goal for JetStream 3 was to move away from small workloads. In the early days of browser competition, small, tight loops, typically called “Microbenchmarks”, were often used to prove one engine was faster than another. While useful for regression testing, microbenchmarks are dangerous for long-term optimization. They encourage engines to over-fit to specific patterns, creating overly specialized optimizations for a specific hot loop or function that might not translate to (or worse, even harm) general performance.</p>
<p>JetStream 3 focuses on larger, longer-running workloads. By increasing the code size and complexity, we dilute the impact of any single &#8220;hot&#8221; function. This forces the engine to be generally efficient across a variety of optimizations not only in the JIT compilers, but also in standard library functionality.</p>
<p>These new workloads also ensure we are optimizing for the features developers are actually using today:</p>
<ul>
<li>JavaScript: Private/public class fields, Promises/async functions, and modern RegExp features.</li>
<li>WebAssembly: <a href="https://github.com/WebAssembly/gc/blob/main/proposals/gc/Overview.md">WasmGC</a> (Garbage Collection), <a href="https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md">SIMD</a> (Single Instruction, Multiple Data), and <a href="https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md">Exception Handling</a>.</li>
</ul>
<h2>Optimizing JavaScriptCore for JetStream 3</h2>
<p>With the new benchmark in place, we turned to the engineering work needed to perform well on it. To that end, the WebKit team has made significant architectural improvements to JavaScriptCore over the last year.</p>
<h3>WebAssembly GC</h3>
<p>JetStream 3 includes WasmGC workloads compiled from Dart, Java, and Kotlin. These languages exercise different allocation patterns and usage strategies, which stress-tests the engine&#8217;s GC implementation broadly.</p>
<h4>Inlining GC allocations</h4>
<p>When a WasmGC program creates a struct or an array, the browser&#8217;s engine needs to allocate memory for that object on the garbage collected heap. In our initial implementation, every allocation went through a general-purpose C++ function call. This is similar to how calling <code>malloc</code> works in C: the program jumps to a shared allocation routine, which finds available memory, sets it up, and returns a pointer. While correct, this overhead adds up quickly in WasmGC workloads that create millions of small objects, which is typical of languages like Dart and Kotlin that compile to WasmGC.</p>
<p>We optimized this in two phases. First, we changed the memory layout of GC objects. Originally, each struct and array had a separate, out-of-line backing store for its fields. This meant that creating a struct required two allocations: one for the object header and one for the field data. It also meant that every field access required following an extra pointer. We changed both structs (<a href="https://commits.webkit.org/291579@main">291579@main</a>) and arrays (<a href="https://commits.webkit.org/291760@main">291760@main</a>) to store their field data directly after the object header in a single contiguous allocation, eliminating the second allocation and the pointer indirection. This single change was a roughly 40% improvement on the WasmGC subtests.</p>
<p>Second, we inlined the allocation fast path directly into the generated machine code. Rather than calling out to a C++ function for every allocation, the compiler now emits a short sequence of instructions that bumps a pointer, writes the object header, and returns, all without leaving the generated code. The slow path (when the current memory block is full and a new one needs to be obtained) still calls into C++, but the fast path handles the vast majority of allocations. We added this optimization to both of our WebAssembly compiler tiers: the Build Bytecode Quickly (BBQ) baseline compiler (<a href="https://commits.webkit.org/292808@main">292808@main</a>, <a href="https://commits.webkit.org/292925@main">292925@main</a>) and the Optimized Machine-code Generator (OMG) optimizing compiler (<a href="https://commits.webkit.org/298551@main">298551@main</a>). We also embedded runtime type information directly into each GC object (<a href="https://commits.webkit.org/306226@main">306226@main</a>), so that type checks (such as checking whether a cast is valid) can be done with a simple pointer comparison rather than looking up type metadata through a separate table.</p>
<h4>GC Type Reference Counting</h4>
<p>In WebAssembly, every function and GC object has a concrete type defined in the module&#8217;s type section. The engine needs to keep these type definitions alive for as long as any object or function references them. Wasm type definitions may be shared across Workers, while JSC&#8217;s garbage collector is per-Worker and not global across the process. To solve this mismatch, we use reference counting. In our initial version of WasmGC, each object held a reference to its type definition, and when the object was destroyed, the reference was released.</p>
<p>One of the performance problems we saw initially was that every time the garbage collector destroyed a WasmGC object, it had to decrement the reference count on the object&#8217;s type. For workloads that create and destroy large numbers of short-lived objects (which is often common in garbage-collected languages), this meant that garbage collection was spending a large fraction of its time just updating these reference counts. On top of that, looking up type information required acquiring a global lock and searching a hash table; this created contention when multiple threads were compiling or running WebAssembly code simultaneously.</p>
<p>We attacked this from several angles. The most impactful change was eliminating the need for GC objects to have destructors at all (<a href="https://commits.webkit.org/292257@main">292257@main</a>). Previously, each GC object had a destructor that released its type reference. By restructuring how type information is stored, so that the garbage collector can find type definitions through the object&#8217;s Structure (discussed in more detail in a <a href="https://webkit.org/blog/6756/es6-feature-complete/">previous blog post</a>) rather than reference counting them per-object, we removed the destructor entirely. This was a roughly 40% improvement on the Dart-flute-wasm subtest, because the garbage collector could now sweep dead GC objects without doing any per-object cleanup work. Finally, we also moved type references directly into the type definition records themselves (<a href="https://commits.webkit.org/300159@main">300159@main</a>), removing the need for global locks and hash table lookups when accessing a type&#8217;s runtime type information (e.g. for casting).</p>
<h4>GC Type Checks</h4>
<p>Languages that compile to Wasm with Wasm GC features rely heavily on type checks. Operations like downcasting an object to a more specific type (<code>ref.cast</code>), testing whether an object is an instance of a type (<code>ref.test</code>), and verifying function signatures at indirect call sites (<code>call_indirect</code>) all require the engine to determine at runtime whether one type is a subtype of another. In our initial implementation, each of these checks was a call into a C++ runtime function that walked the type hierarchy, which was expensive for workloads that perform millions of casts per second.</p>
<p>We addressed this by inlining the type checks directly into the generated machine code using a technique known as <a href="https://dl.acm.org/doi/10.1145/115372.115297">Cohen&#8217;s type display</a> algorithm. The idea is that each type stores a fixed-size array, called a display, containing pointers to all of its ancestor types. To check whether object A is a subtype of type B, the engine only needs to look up a single entry in A&#8217;s display at B&#8217;s inheritance depth (i.e. the number of superclasses B has) and compare pointers, rather than walking a chain of parent pointers. We first inlined this into our optimizing compiler, OMG (<a href="https://commits.webkit.org/298798@main">298798@main</a>), and then into our baseline compiler, BBQ (<a href="https://commits.webkit.org/298842@main">298842@main</a>), so that even code that has not yet been fully optimized benefits. To make the display lookup as fast as possible, we embedded the first six display entries directly into each type&#8217;s runtime type information record (<a href="https://commits.webkit.org/299056@main">299056@main</a>), so that the common case of shallow type hierarchies requires no extra pointer indirection and stays within a single cache line.</p>
<p>We also found that many type checks could be eliminated entirely. The Wasm type system carries static type information through the wasm binary, and in many cases the engine can prove at compile time that a value already satisfies the required type, in particular, when inlining a generic leaf function. We propagated this static type information from the parser through to code generation (<a href="https://commits.webkit.org/298875@main">298875@main</a>), so that when the compiler can prove a value is already a GC object, it skips the runtime cell and object checks that would otherwise be emitted (<a href="https://commits.webkit.org/298961@main">298961@main</a>). Together, these changes ensure that type checking overhead is minimal across all execution tiers.</p>
<h4>Better Inlining Heuristics with Callsite Feedback</h4>
<p>When a compiler inlines a function, it replaces a function call with the body of the called function. This avoids the overhead of the call itself and, more importantly, gives the compiler the opportunity to optimize the caller and callee together. For example, if the caller always passes a constant to a parameter, the inlined body can be specialized for that constant.</p>
<p>However, inlining has a cost: it makes the compiled code larger. If the compiler inlines too aggressively, the generated code may end up duplicating the same logic repeatedly, which is worse for the CPU’s instruction cache. Secondly, the more code inlined, the longer compilations take, which in a JIT can have a significant performance impact. This means the compiler needs good heuristics to decide which call sites are worth inlining and which are not.</p>
<p>Our initial Wasm inlining implementation made these decisions one call site at a time. Each call was evaluated independently: if the callee was small enough and the call was hot enough, it would be inlined. The problem is that this local, greedy approach does not consider the overall picture. It might inline several less-important calls and then run out of its code size budget before reaching a call that would have been far more beneficial to inline.</p>
<p>We replaced this with a non-local inlining decision system (<a href="https://commits.webkit.org/302215@main">302215@main</a>) that considers all the call sites in a function simultaneously. The algorithm assigns a priority to each candidate call site based on how frequently it is executed, how large the callee is, and how much optimization opportunity inlining would unlock. It then inlines call sites in priority order until the code size budget is exhausted. This is particularly important for WasmGC workloads, where source-language compilers for Dart, Kotlin, and Java tend to emit many small functions in order to keep download sizes small, expecting the browser&#8217;s compiler to inline the important ones.</p>
<h4>Polymorphic Indirect Call Inlining</h4>
<p>Languages that compile to WasmGC, such as Dart and Kotlin, rely heavily on virtual method dispatch. When you call a method on an object in these languages, the actual function that gets called depends on the runtime type of the object. In the generated WebAssembly, this is represented as an indirect call: instead of calling a specific function, the code loads a function pointer from a table and calls through it. Indirect calls are significantly more expensive than direct calls because the processor cannot predict where the call will go, and the compiler cannot inline a function if it does not know which function will be called.</p>
<p>To address this, we added profiling to our baseline compiler, BBQ, that records which function is actually called at each indirect call site as the program runs (<a href="https://commits.webkit.org/299870@main">299870@main</a>). When our optimizing compiler, OMG, later recompiles the function, it uses this profile data. If a call site always calls the same function (monomorphic), OMG can generate a guard that checks &#8220;is the target still the expected function?&#8221; and then either takes a fast path that calls (or inlines) the known function directly, or falls back to the slow indirect call path. This guard-and-inline pattern turns what was an unpredictable indirect call into a predictable direct call in the common case.</p>
<p>We extended this approach to handle call sites that call a small number of different functions (<a href="https://commits.webkit.org/301972@main">301972@main</a>). Rather than giving up when a call site has more than one target, we now profile up to three distinct callees. The optimizing compiler can then generate a sequence of checks, one for each known target, each followed by an inlined copy of that target&#8217;s code, with a final fallback for any unknown callee. The fallback is annotated as rare (<a href="https://commits.webkit.org/308557@main">308557@main</a>), which tells later compiler passes to optimize for the expected case where one of the known targets matches. This optimization is not something a source language compiler can do statically, since it does not know which concrete types will appear at a given call site until the program actually runs.</p>
<h4>Abstract Heaps</h4>
<p>We introduced a concept called &#8220;Abstract Heaps&#8221; to our Wasm compiler pipeline, which we already had in the JS pipeline (<a href="https://commits.webkit.org/300394@main">300394@main</a>, <a href="https://commits.webkit.org/300472@main">300472@main</a>, <a href="https://commits.webkit.org/300499@main">300499@main</a>, <a href="https://commits.webkit.org/305726@main">305726@main</a>). Abstract Heaps allow the compiler to reason about the side effects of Wasm instructions more precisely based on types. This enables type-based-alias-analysis (TBAA), which can describe the abstract heap access of each operation. By understanding which parts of the heap are affected by specific operations, we can eliminate redundant loads and stores in Wasm. This is particularly useful in combination with inlining, which can reveal more information about the objects being allocated. While the source language compiler can do some of this before sending the code to the browser, not all do for a number of reasons. For example, code size is very important so a source language compiler may choose not to inline in order to reduce the time to launch of an application. Additionally, as mentioned above, JavaScriptCore profiles indirect function calls and potentially inlines them, which isn’t feasible statically.</p>
<h4>Register Allocator Improvements</h4>
<p>A register allocator is the part of a compiler that decides which program values live in CPU registers (fast) and which must be &#8220;spilled&#8221; to memory (slow). It is one of the most performance-critical compiler passes because nearly every instruction in the generated code is affected by its decisions. It is also one of the most compilation-time-critical passes, especially for WebAssembly where compilation speed directly impacts page load time.</p>
<p>We replaced our previous register allocator, which dynamically switched between a graph coloring algorithm (<a href="https://www.cs.cmu.edu/afs/cs/academic/class/15745-s16/www/lectures/L23-Register-Coalescing.pdf">iterated register coalescing</a>) and a linear scan algorithm, with a new greedy register allocator. The greedy algorithm works by processing each program value&#8217;s &#8220;live range&#8221; (the span of instructions during which the value is needed) in priority order. For each value, it attempts to assign a register. If no register is available, it considers whether evicting a lower-priority value from its register would be beneficial. In our measurements, greedy allocation produces similar code quality to graph coloring, while running much faster. It also produces better code than linear scan because it can make more globally informed decisions about which values deserve registers the most.</p>
<p>The core data structure that tracks which registers are in use at which points in time was originally built on a balanced binary tree (std::set), which required many pointer-chasing operations across different cache lines. We replaced it with a B+ tree specifically designed for interval queries (<a href="https://commits.webkit.org/299207@main">299207@main</a>), where each tree node is sized to fit in one or two cache lines. This made the register allocation phase nearly 2x faster for large functions, which matters because WebAssembly functions generated from languages like Dart and Kotlin can contain tens of thousands of values.</p>
<p>Beyond the core algorithm, we added several important features. Live range splitting (<a href="https://commits.webkit.org/304261@main">304261@main</a>) allows the allocator to keep a spilled value in a register for the portion of code where it is most heavily used, even if it cannot stay in a register for its entire lifetime. Coalescing with pinned registers (<a href="https://commits.webkit.org/304889@main">304889@main</a>) eliminates unnecessary copy instructions when WebAssembly runtime values, such as the pointer to the current instance, are already in a known register. Proactive spill slot coalescing (<a href="https://commits.webkit.org/306945@main">306945@main</a>) reduces the size of the stack frame by sharing memory between spilled values that are never alive at the same time. And for values that are simple constants, the allocator can now rematerialize them (recompute them from scratch) at each use point rather than loading them from the stack (<a href="https://commits.webkit.org/292654@main">292654@main</a>, <a href="https://commits.webkit.org/302864@main">302864@main</a>), which frees up a register for other values.</p>
<p>The improved compilation speed of the greedy allocator also had an indirect benefit: it allowed us to raise the maximum function size that our optimizing compiler will attempt to compile (<a href="https://commits.webkit.org/292197@main">292197@main</a>). Previously, very large functions were left in the baseline tier because the optimizing compiler took too long. With the greedy allocator, we can now fully optimize larger functions without unacceptable compilation pauses. Once the greedy allocator had proven itself across all configurations, we removed the old linear scan allocator entirely (<a href="https://commits.webkit.org/305981@main">305981@main</a>).</p>
<h4>IPInt support for SIMD</h4>
<p>JavaScriptCore has three execution tiers for WebAssembly: BBQ and OMG are the JIT tiers, as described above, but there is also an interpreter tier, IPInt. IPInt executes WebAssembly bytecode directly without any compilation, taking inspiration from the <a href="https://github.com/titzer/wizard-engine">Wizard engine</a>. This means IPInt can begin running code nearly instantly, only requiring a small amount of metadata. BBQ and OMG, being JIT compilers, take longer to generate code than IPInt and have a larger memory footprint but have higher throughput.</p>
<p>In JetStream 3, there are several workloads (transformersjs-bert-wasm and dotnet-aot-wasm) that use SIMD instructions. Previously, as IPInt did not support SIMD instructions, when a WebAssembly module used SIMD, the engine had to synchronously compile the function with BBQ before it could execute. This meant that any module using SIMD lost the near instant-start benefit of the interpreter tier and paid a mandatory compilation cost up front. It also meant that SIMD could not be used at all in JIT-less configurations, which is a requirement in some contexts for security reasons (e.g. when <a href="https://support.apple.com/en-us/105120">Lockdown Mode</a> is enabled).</p>
<p>We implemented full SIMD support in IPInt, covering all of the standard WebAssembly SIMD instructions on both ARM64 and x86_64. Beyond the instructions themselves, we needed to teach the rest of the interpreter about the 128-bit <code>v128</code> type: local and global variable access, function calls and tail calls, on-stack replacement to BBQ, exception handling, and WasmGC struct and array fields. We also ensured that SIMD works correctly when the JIT is completely disabled. With all of this in place, we enabled IPInt SIMD by default (<a href="https://commits.webkit.org/301576@main">301576@main</a>), giving WebAssembly SIMD code the same near instant-start execution that non-SIMD code has always had.</p>
<h3>JavaScript improvements</h3>
<p>JetStream 3 includes workloads that exercise modern JavaScript features that were not yet standardized or widely adopted when JetStream 2 was released, including BigInt arithmetic, async/await-heavy control flow, and Promise combinators. Optimizing for these workloads led to improvements across several subsystems in JavaScriptCore.</p>
<h4>BigInt Improvements</h4>
<p>BigInt is a JavaScript feature that allows programs to work with arbitrarily large integers. Unlike regular JavaScript numbers, which are 64-bit floating point values and lose precision for integers beyond 2^53, BigInts can represent integers of any size. JetStream 3 includes workloads that exercise BigInt arithmetic heavily, which exposed several areas where our implementation could be improved.</p>
<p>We made improvements on two fronts: the algorithms used for arithmetic and the memory representation of BigInt values.</p>
<p>For multiplication, we implemented the Comba algorithm (<a href="https://commits.webkit.org/304184@main">304184@main</a>), which is significantly faster for multiplying small, same-sized BigInts. The traditional &#8220;schoolbook&#8221; multiplication algorithm processes one digit at a time, writing partial results and carrying. Comba&#8217;s algorithm instead accumulates all the partial products for each column of the result at once, which allows the processor to pipeline the multiply-and-add operations more efficiently. We also added a fast path for single-digit multipliers (<a href="https://commits.webkit.org/303956@main">303956@main</a>), which is the common case for operations like doubling a value.</p>
<p>For division, we imported and adapted a modern division algorithm implementation (<a href="https://commits.webkit.org/304114@main">304114@main</a>), and then further optimized it with the <a href="https://gmplib.org/~tege/division-paper.pdf">DIV2BY1 technique</a> (<a href="https://commits.webkit.org/304278@main">304278@main</a>). DIV2BY1 works by pre-computing the multiplicative inverse of the divisor. Then, instead of dividing, each step of the algorithm multiplies by this inverse, which is faster on modern CPUs where multiplication is much cheaper than division. This is especially effective when dividing repeatedly by the same divisor, which is common in operations like converting a BigInt to a decimal string. We also added a cache for remainder computation (<a href="https://commits.webkit.org/308930@main">308930@main</a>) that remembers the inverse, so that repeated modulo operations with the same divisor avoid recomputing it.</p>
<p>On the memory representation side, BigInts in JavaScriptCore were historically stored as a small header object with a pointer to a separate heap-allocated array of digits. This meant every BigInt operation required following a pointer to get to the actual digit data, and creating a BigInt required two allocations. We changed this so that the digits are stored directly after the object header in a single contiguous allocation (<a href="https://commits.webkit.org/307016@main">307016@main</a>), similar to how we improved WasmGC struct layout. We also shrank the minimum BigInt object size to just 16 bytes (<a href="https://commits.webkit.org/308026@main">308026@main</a>) by storing the sign bit in an existing, unused per-object bitfield rather than using a dedicated byte for it. For arithmetic operations that need temporary working space, we switched from allocating temporary BigInt objects on the garbage-collected heap to using stack-allocated vectors (<a href="https://commits.webkit.org/304337@main">304337@main</a>), which avoids triggering garbage collection during intermediate computation steps. Lastly, we improved how our JIT compilers speculate on BigInt types (<a href="https://commits.webkit.org/308054@main">308054@main</a>), allowing the optimizing compiler to generate more efficient code when it can prove that a value is a BigInt.</p>
<h4>MicrotaskQueue and Async function improvements</h4>
<p>The microtask queue is the mechanism that JavaScript engines use to schedule small units of deferred work. Every time a Promise resolves, the callbacks attached to it are placed on the microtask queue. Every time an async function hits an <code>await</code>, the continuation of that function is scheduled as a microtask. In heavily asynchronous code, such as the doxbee-async benchmark in JetStream 3 that models a chain of database operations, the microtask queue processes millions of tasks per second. This made it a critical performance target.</p>
<p>Our microtask queue was originally implemented in WebCore, WebKit&#8217;s web platform layer, and JavaScriptCore called into it through a virtual function interface. Every time the engine needed to schedule or run a microtask, it crossed this boundary, which involved virtual dispatch, redundant safety checks, and prevented the compiler from optimizing across the boundary. We completely rewrote the microtask queue, first extracting it into its own subsystem (<a href="https://commits.webkit.org/291566@main">291566@main</a>), then moving it into JavaScriptCore (<a href="https://commits.webkit.org/291649@main">291649@main</a>), and finally moving the last remaining WebCore enqueue code into JSC as well (<a href="https://commits.webkit.org/308483@main">308483@main</a>). The new implementation uses specialized entry points for calling microtask functions (<a href="https://commits.webkit.org/305407@main">305407@main</a>) that skip setup work that is redundant when the engine is already running, and uses lightweight tagging techniques (<a href="https://commits.webkit.org/308140@main">308140@main</a>) to dispatch microtasks without needing to read type metadata from memory.</p>
<p>Alongside the microtask queue rewrite, we systematically moved all of our Promise implementation from JavaScript builtins to C++. In JavaScriptCore, &#8220;builtins&#8221; are internal functions implemented in JavaScript that ship with the engine and implement parts of the standard library. While convenient to write, they have significant startup costs because they need to be parsed and compiled, and the JIT compilers have limited ability to optimize across the boundary between builtin JavaScript code and the engine&#8217;s C++ internals. We rewrote Promise.all (<a href="https://commits.webkit.org/304039@main">304039@main</a>), Promise.race (<a href="https://commits.webkit.org/303893@main">303893@main</a>), Promise.allSettled (<a href="https://commits.webkit.org/304081@main">304081@main</a>), Promise.any (<a href="https://commits.webkit.org/304084@main">304084@main</a>), Promise.prototype.finally (<a href="https://commits.webkit.org/305248@main">305248@main</a>), and Promise.resolve/reject (<a href="https://commits.webkit.org/301423@main">301423@main</a>) in C++. This eliminated the parsing and compilation overhead and allowed us to hand-optimize the hot paths. We also added support in our optimizing JIT compilers for <code>Promise.prototype.then</code> (<a href="https://commits.webkit.org/308636@main">308636@main</a>), so that when the compiler can prove the promise is a standard Promise (not a subclass with overridden behavior), it can generate the then operation inline without any function call overhead.</p>
<p>For async functions specifically, we made three significant improvements. First, we changed how async functions are resumed after an <code>await</code>. Previously, awaiting a value would create a promise reaction (a callback) that, when triggered, would schedule a microtask to resume the function. This double-dispatch meant each <code>await</code> required two trips through the microtask queue. We changed this so that the microtask queue drives async function resumption directly (<a href="https://commits.webkit.org/303208@main">303208@main</a>), cutting the overhead in half. Second, for async functions that contain no <code>await</code> (which is more common than it might sound, since conditional code paths may not always reach an <code>await</code>), we inline the entire function body so that it executes synchronously without any generator or microtask overhead at all (<a href="https://commits.webkit.org/304987@main">304987@main</a>). Third, after each <code>await</code>, the engine must check whether the awaited value is a &#8220;thenable&#8221; (an object with a <code>then</code> method), because thenables are treated specially by the Promise resolution algorithm. We optimized this check by tracking whether the <code>then</code> property has ever been added to common object types (<a href="https://commits.webkit.org/304952@main">304952@main</a>), so that for plain objects and iterator results that do not have a <code>then</code> property, the check can be skipped entirely (<a href="https://commits.webkit.org/304355@main">304355@main</a>).</p>
<h2>Performance Results</h2>
<p>The combination of these architectural changes resulted in roughly a 10% improvement from Safari 26.0 to Safari 26.4. Because JetStream 3 scores the full lifecycle of each workload, this improvement reflects gains that users experience directly: faster initial page loads from quicker WebAssembly compilation, and smoother interactions from more efficient JavaScript execution and reduced garbage collection pauses.</p>
<figure class="mattewhite widescreen"><img fetchpriority="high" decoding="async" src="https://webkit.org/wp-content/uploads/JS3-benchmark.png" alt="Horizontal bar chart titled 'JetStream 3 (M4 MacBook Air)' comparing JavaScript benchmark scores between two macOS versions. macOS Tahoe 26.0 scored 359, macOS Tahoe 26.4 scored 395, approximately a 10% performance improvement. The x-axis ranges from 0 to 400, and the legend notes that higher scores are better. Bars are light blue." width="2272" height="1380" class="wp-image-17914" srcset="https://webkit.org/wp-content/uploads/JS3-benchmark.png 2272w, https://webkit.org/wp-content/uploads/JS3-benchmark-300x182.png 300w, https://webkit.org/wp-content/uploads/JS3-benchmark-1024x622.png 1024w, https://webkit.org/wp-content/uploads/JS3-benchmark-768x466.png 768w, https://webkit.org/wp-content/uploads/JS3-benchmark-1536x933.png 1536w, https://webkit.org/wp-content/uploads/JS3-benchmark-2048x1244.png 2048w" sizes="(max-width: 2272px) 100vw, 2272px" /></figure>
<h2>Conclusion</h2>
<p>JetStream 3 reflects a shift in how we think about browser benchmarking: scoring the full lifecycle rather than isolated phases, measuring real-world workloads rather than microbenchmarks, and developing the suite collaboratively across browsers. Building it pushed us to make meaningful architectural improvements to JavaScriptCore, from WasmGC allocation and inlining to BigInt arithmetic and async function execution. We’re excited about the opportunities provided by the JetStream 3 benchmark to further improve the performance of applications on the web. As always, we will continue our efforts to make the fastest, most secure browser for Safari users.</p>
]]></content:encoded>
					
		
		
			<enclosure length="689875" type="application/pdf" url="https://www.cs.cmu.edu/afs/cs/academic/class/15745-s16/www/lectures/L23-Register-Coalescing.pdf"/><itunes:explicit/><itunes:subtitle>Today, alongside our colleagues at Google and Mozilla, we announced JetStream 3.0, a major update to the cross-browser benchmark suite.</itunes:subtitle><itunes:summary>Today, alongside our colleagues at Google and Mozilla, we announced JetStream 3.0, a major update to the cross-browser benchmark suite.</itunes:summary><itunes:keywords>Performance</itunes:keywords></item>
		<item>
		<title>Release Notes for Safari Technology Preview 240</title>
		<link>https://webkit.org/blog/17896/release-notes-for-safari-technology-preview-240/</link>
		
		<dc:creator/>
		<pubDate>Thu, 26 Mar 2026 23:15:35 +0000</pubDate>
				<category><![CDATA[Safari Technology Preview]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17896</guid>

					<description><![CDATA[Safari Technology Preview Release 240 is now available for download for macOS Tahoe and macOS Sequoia.]]></description>
										<content:encoded><![CDATA[<p><a href="https://webkit.org/blog/6017/introducing-safari-technology-preview/">Safari Technology Preview</a> Release 240 is now <a href="https://developer.apple.com/safari/resources/">available for download</a> 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.</p>
<p>This release includes WebKit changes between: <a href="https://github.com/WebKit/WebKit/compare/92d46f7506c61bfcdb73d36c2f5dffc87844eeea...4d96716c8dc8eb15bea579d6097eba53ec4d3ed4">308418@main&#8230;309286@main</a>.</p>
<h3>CSS</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>revert-rule</code> CSS keyword, which rolls back the cascade to behave as if the current style rule had not been present. (<a href="https://commits.webkit.org/308733@main">308733@main</a>)  (171132753)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue on macOS where custom CSS scrollbars could be cut off and the scrollbar corner rect was sized incorrectly. (<a href="https://commits.webkit.org/309119@main">309119@main</a>)  (168566468)</li>
<li>Fixed <code>hanging-punctuation</code> to support U+0027 (apostrophe) and U+0022 (quotation mark) as hangable quotes. (<a href="https://commits.webkit.org/308597@main">308597@main</a>)  (171672576)</li>
<li>Fixed <code>hanging-punctuation</code> to allow ideographic space (U+3000) to hang when used with the <code>first</code> value. (<a href="https://commits.webkit.org/308605@main">308605@main</a>)  (171679311)</li>
</ul>
<h3>Editing</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where the Font Picker style selection became unusable after changing fonts when editing multiple lines of text. (<a href="https://commits.webkit.org/308562@main">308562@main</a>)  (110651645)</li>
<li>Fixed an issue where emoji images were not preserved correctly when copying and pasting content across different websites. (<a href="https://commits.webkit.org/309176@main">309176@main</a>)  (162708499)</li>
<li>Fixed an issue where text selection would jump unexpectedly when selecting absolutely-positioned content inside an element with <code>user-select: none</code>. (<a href="https://commits.webkit.org/308451@main">308451@main</a>)  (170475401)</li>
</ul>
<h3>Forms</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where keyboard tabbing position was lost when a focused button became disabled, causing focus to jump to the beginning of the page. (<a href="https://commits.webkit.org/308991@main">308991@main</a>)  (120676409)</li>
</ul>
<h3>HTML</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed viewport <code>&lt;meta&gt;</code> parsing to correctly treat form feed as ASCII whitespace per the HTML specification. (<a href="https://commits.webkit.org/309044@main">309044@main</a>)  (108440799)</li>
<li>Fixed incorrect parsing of pixel-length margin attributes on <code>&lt;body&gt;</code>, <code>&lt;iframe&gt;</code>, and <code>&lt;frame&gt;</code> elements. (<a href="https://commits.webkit.org/308526@main">308526@main</a>)  (171240848)</li>
</ul>
<h3>Media</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where decoding WebM audio files with more than two channels would fail. (<a href="https://commits.webkit.org/308749@main">308749@main</a>)  (82160691)</li>
<li>Fixed <code>MediaCapabilities.decodingInfo()</code> incorrectly reporting VP8 in WebM as not supported. (<a href="https://commits.webkit.org/308789@main">308789@main</a>)  (127339546)</li>
<li>Fixed an issue where MP4 files containing Opus audio tracks could not be decoded with <code>decodeAudioData</code>. (<a href="https://commits.webkit.org/309140@main">309140@main</a>)  (170196423)</li>
<li>Fixed an issue where Live Text selection was unavailable on paused fullscreen videos. (<a href="https://commits.webkit.org/308498@main">308498@main</a>)  (170817667)</li>
<li>Fixed an issue where FairPlay-protected VP9 content failed to play via <code>MediaSource</code>. (<a href="https://commits.webkit.org/308622@main">308622@main</a>)  (171210968)</li>
<li>Fixed an issue where autoplay would proceed before default text tracks finished loading. (<a href="https://commits.webkit.org/308796@main">308796@main</a>)  (171699293)</li>
<li>Fixed the <code>currentTime</code> getter to return <code>defaultPlaybackStartPosition</code> when no media player exists. (<a href="https://commits.webkit.org/308654@main">308654@main</a>)  (171722368)</li>
<li>Fixed <code>HTMLMediaElement</code> to fire a <code>timeupdate</code> event when resetting the playback position during media load as required by the specification. (<a href="https://commits.webkit.org/308695@main">308695@main</a>)  (171785463)</li>
<li>Fixed an issue where the media player <code>preload</code> attribute was not properly updated when the <code>autoplay</code> attribute was set. (<a href="https://commits.webkit.org/308815@main">308815@main</a>)  (171883159)</li>
</ul>
<h3>PDF</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where panning a zoomed-in PDF on iOS would frequently rubber band back to the starting position. (<a href="https://commits.webkit.org/309264@main">309264@main</a>)  (156854435)</li>
</ul>
<h3>Rendering</h3>
<h4>New Features</h4>
<ul>
<li>Added support for subpixel inline layout, enabling more precise text and inline element positioning. (<a href="https://commits.webkit.org/309251@main">309251@main</a>)  (171835370)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where table cells with <code>rowspan</code> values exceeding the actual number of rows were incorrectly computing heights. (<a href="https://commits.webkit.org/309153@main">309153@main</a>)  (3209126)</li>
<li>Fixed an issue where replaced elements with intrinsic content size keywords like <code>fit-content</code> were not properly accounting for aspect ratio constraints. (<a href="https://commits.webkit.org/308995@main">308995@main</a>)  (168264069)</li>
<li>Fixed an issue where table sections with explicit heights did not properly constrain and distribute space among contained rows. (<a href="https://commits.webkit.org/308540@main">308540@main</a>)  (169235210)</li>
<li>Fixed an issue where auto table layout did not honor <code>max-width</code> on table cells when distributing width between them. (<a href="https://commits.webkit.org/308934@main">308934@main</a>)  (171459245)</li>
<li>Fixed an issue where <code>border-spacing</code> incorrectly included collapsed columns in auto table layout calculations. (<a href="https://commits.webkit.org/308549@main">308549@main</a>)  (171468102)</li>
<li>Fixed an issue where percentage-height children of table cells with unresolvable percentage heights were not sized intrinsically. (<a href="https://commits.webkit.org/308547@main">308547@main</a>)  (171469500)</li>
<li>Fixed an issue where MathML token elements ignored <code>-webkit-text-fill-color</code> when painting math variant glyphs. (<a href="https://commits.webkit.org/308911@main">308911@main</a>)  (172020318)</li>
<li>Fixed an issue where cell backgrounds in collapsed-border tables extended into adjacent cells&#8217; border space at table edges. (<a href="https://commits.webkit.org/308969@main">308969@main</a>)  (172068907)</li>
<li>Fixed an issue where list item margins were computed incorrectly when the page was zoomed in or out. (<a href="https://commits.webkit.org/309152@main">309152@main</a>)  (172312498)</li>
<li>Fixed an issue where <code>about:blank</code> iframes did not always have a transparent background. (<a href="https://commits.webkit.org/309212@main">309212@main</a>)  (172400258)</li>
</ul>
<h3>SVG</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where the XML document parser did not defer inline script execution until pending stylesheets had loaded. (<a href="https://commits.webkit.org/308980@main">308980@main</a>)  (122574381)</li>
<li>Fixed an issue where SVG elements referencing non-existent filter IDs were not rendered. (<a href="https://commits.webkit.org/308809@main">308809@main</a>)  (164046592)</li>
<li>Fixed an issue where <code>removeAttribute</code> for <code>width</code> or <code>height</code> on an SVG root element did not reset to the default 300&#215;150 dimensions. (<a href="https://commits.webkit.org/308906@main">308906@main</a>)  (170233990)</li>
<li>Fixed an issue where UI events such as wheel failed to fire for inner SVG elements. (<a href="https://commits.webkit.org/309010@main">309010@main</a>)  (171703966)</li>
<li>Fixed <code>onbegin</code>, <code>onend</code>, and <code>onrepeat</code> event handler attributes on <code>SVGAnimationElement</code> to properly map to their corresponding event types. (<a href="https://commits.webkit.org/309273@main">309273@main</a>)  (172533070)</li>
</ul>
<h4>Deprecations</h4>
<ul>
<li>Removed the non-standard <code>nearestViewportElement</code> and <code>farthestViewportElement</code> properties from <code>SVGGraphicsElement</code>, aligning with the SVG2 specification. (<a href="https://commits.webkit.org/308436@main">308436@main</a>)  (171262197)</li>
</ul>
<h3>Scrolling</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed a scroll snap issue where navigating between items could incorrectly snap back when layout changes occurred. (<a href="https://commits.webkit.org/308420@main">308420@main</a>)  (166596210)</li>
<li>Fixed an issue where pages using the Navigation API could have offset hit test locations, making elements unclickable. (<a href="https://commits.webkit.org/308976@main">308976@main</a>)  (171752650)</li>
</ul>
<h3>Web API</h3>
<h4>New Features</h4>
<ul>
<li>Added support for a wider range of characters in DOM element and attribute names, aligning with the updated WHATWG specification. (<a href="https://commits.webkit.org/308884@main">308884@main</a>)  (95205349)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>location.ancestorOrigins</code> returning stale origins after an iframe is removed from the document. (<a href="https://commits.webkit.org/309126@main">309126@main</a>)  (169097730)</li>
</ul>
<h3>Web Extensions</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where extensions with a trailing comma in <code>manifest.json</code> failed to load in Safari. (<a href="https://commits.webkit.org/308935@main">308935@main</a>)  (171749937)</li>
</ul>
<h3>Web Inspector</h3>
<h4>New Features</h4>
<ul>
<li>Added support for showing contrast information in the Color Picker when editing background color properties. (<a href="https://commits.webkit.org/308653@main">308653@main</a>)  (171332734)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where previewing resources in the Network tab displayed an error upon navigating away and Preserve Log was enabled. (<a href="https://commits.webkit.org/308559@main">308559@main</a>)  (171216835)</li>
<li>Fixed an issue where selected DOM node keys in a Map in the Scope Chain sidebar had unreadable white text on a light background. (<a href="https://commits.webkit.org/309006@main">309006@main</a>)  (171840122)</li>
</ul>
<h3>WebAssembly</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>WebAssembly.compileStreaming</code> and <code>WebAssembly.instantiateStreaming</code> to correctly accept <code>compileOptions</code> for JS string builtins. (<a href="https://commits.webkit.org/308234@main">308234@main</a>, <a href="https://commits.webkit.org/308419@main">308419@main</a>)  (170989896)</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WebKit Features for Safari 26.4</title>
		<link>https://webkit.org/blog/17862/webkit-features-for-safari-26-4/</link>
		
		<dc:creator/>
		<pubDate>Tue, 24 Mar 2026 17:00:30 +0000</pubDate>
				<category><![CDATA[News]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17862</guid>

					<description><![CDATA[March has a way of bringing a lot of new things to WebKit — and this year is no exception.]]></description>
										<content:encoded><![CDATA[<p>March has a way of bringing a lot of new things to WebKit — and this year is no exception. With 44 features, 191 fixes and one deprecation, Safari 26.4 is a release packed with web technology.</p>
<p>What’s most exciting? CSS Grid Lanes brings masonry-style layouts to the web platform — a long-awaited solution for building rich visual galleries and much more. WebTransport provides a modern alternative to WebSocket, opening the door to low-latency experiences like multiplayer games, live collaboration tools, and improved video conferencing. And Keyboard Lock API gives web apps better control over keyboard shortcuts.</p>
<p>Beyond the headliners, the heart of this release is focused on what web developers ask for most. We hear you loud and clear. Results from 2025 developer surveys made it clear you want time to catch up with new features, not be swamped with more. You want existing features to work consistently across every browser. You asked for browser engineers working on WebKit to help you by squashing bugs and closing gaps in spec coverage. That’s what this release aims to do.</p>
<p>Most of the features listed in the <a href="https://developer.apple.com/documentation/safari-release-notes/safari-26_4-release-notes">Safari 26.4 release notes</a> are not entirely new. Many update features where the behavior didn’t quite match the latest web standard. Others make specific combinations of existing features work better together. Here’s one example — we shipped support for the CSS <code>min()</code> and <code>max()</code> functions in 2018, almost two years before any other browser. And we shipped the HTML <code>sizes</code> attribute for responsive images even longer ago, back in 2014. But until now, you couldn’t use <code>min()</code>, <code>max()</code>, or <code>clamp()</code> inside of the <code>sizes</code> attribute in WebKit. In Safari 26.4, you can.</p>
<p>And then there are the bug fixes — hundreds of them across the platform. WebKit engineers went deep to improve specific areas like SVG, Tables, MathML, and CSS Zoom. And we’re continuing our multi-year rewrite of the layout engine. Blocks-in-inline layout is complete in Safari 26.4, work on Flexbox continues, and we’ve now begun rewriting CSS Grid.</p>
<p>As we continue this work, we greatly value your input. If something has been bothering you, it’s worth testing in Safari 26.4 to see if it’s been fixed. If the bug is still there, please file it at <a href="https://bugs.webkit.org/">bugs.webkit.org</a>. Or if it’s already filed, add additional comments to the existing issue describing your experience and why fixing it matters for you. When multiple websites signal that something needs fixing, that helps. The more concrete you can be — a brief story about why this hurts your users, a link to a real website affected, a snippet of code or reduced test case — the better equipped we are to prioritize and fix what matters most. We are paying attention, even if our response shows up as a shipped fix rather than a reply in the issue.</p>
<p>We care deeply about the experience people have when using Safari. And we care about the experience people have when using any of the millions of iOS, iPadOS, macOS, visionOS, and watchOS apps that are built using WebKit and JavaScriptCore. When our customers open a news app, a shopping app, a travel app, a banking app — there’s a good chance the interface they’re interacting with is powered by the same HTML, CSS, and JavaScript you write every day when making web apps and websites that live at a URL. Every rendering fix, every improved feature, every performance gain we ship benefits everything touched by the web platform.</p>
<p>We are passionate about making experiences our customers love, no matter how they use their device. Web designers and developers are central to those experiences. You are our partners. We truly hope this release makes a real difference in your success.</p>
<h2><a name="css"></a>CSS</h2>
<h3><a name="grid-lanes"></a>Grid Lanes</h3>
<figure class=""><picture><source srcset="https://webkit.org/wp-content/uploads/gridlanes-for264-dark.webp" type="image/png" media="(prefers-color-scheme: dark)"><img decoding="async" src="https://webkit.org/wp-content/uploads/gridlanes-for264-light.webp" alt="Safari window showing photo gallery laid out with Grid Lanes, alternating narrow and wide columns, with photos of all sorts of aspect ratios neatly aligned in columns" width="2000" height="1330" class="aligncenter size-full wp-image-17877" srcset="https://webkit.org/wp-content/uploads/gridlanes-for264-light.webp 2000w, https://webkit.org/wp-content/uploads/gridlanes-for264-light-300x200.webp 300w, https://webkit.org/wp-content/uploads/gridlanes-for264-light-1024x681.webp 1024w, https://webkit.org/wp-content/uploads/gridlanes-for264-light-768x511.webp 768w, https://webkit.org/wp-content/uploads/gridlanes-for264-light-1536x1021.webp 1536w" sizes="(max-width: 2000px) 100vw, 2000px" /></picture></figure>
<p>Safari 26.4 adds support for <a href="https://webkit.org/blog/17660/introducing-css-grid-lanes/">Grid Lanes</a>. It’s a new layout system that extends CSS Grid with powerful capabilities for creating flexible, flowing layouts. You might be familiar with the patterns it can create. Often called “masonry” or “waterfall” layouts, they were made popular like sites like Pinterest and attainable with Javascript libraries like <a href="https://masonry.desandro.com/">masonry.js</a>. Now this capability is available in CSS with  <code>display: grid-lanes</code>.</p>
<p>And it can do much more than just the classic layout. At its root, Grid Lanes provides a way to pack content of different aspect ratios into either columns or rows. And does so in a way where users can tab through all the visible content, and where new content can be lazy-loaded at the end.</p>
<p>Grid Lanes builds on the foundation of CSS Grid, giving it powerful track sizing and explicit placement capabilities.</p>
<pre><code class="css"><span class="keyword builtin">.container</span> {
  <span class="attribute">display</span>: <span class="identifier">grid-lanes</span>;
  <span class="attribute">grid-template-columns</span>: <span class="identifier">repeat</span>(<span class="identifier">auto-fill</span>, <span class="identifier">minmax</span>(<span class="number">200px</span>, <span class="number">1</span><span class="identifier">fr</span>));
}
</code></pre>
<p>Safari 26.4 supports the recently-finalized core syntax for Grid Lanes (see <a href="https://webkit.org/blog/17660/introducing-css-grid-lanes/"><em>Introducing CSS Grid Lanes</em></a>), including support for <code>flow-tolerance</code>, which gives you control over how aggressively each item tries to “change lanes” to be closest to the start. This affects how much the placement of consecutive items shifts back and forth across the page — a particularly important consideration for accessibility. Try tuning the value, and see how it affects item placement and keyboard navigation across items.</p>
<p>Grid Lanes opens up new possibilities for layouts that have been difficult to achieve with existing CSS. In addition to the Pinterest-style masonry layouts, you can use it to create dynamic arrangements of content in either columns or rows. Check out our <a href="https://webkit.org/demos/grid3/">Grid Lanes demos</a> for more ideas. Learn about browser support &amp; progressive enhancement strategies in <a href="https://webkit.org/blog/17758/when-will-css-grid-lanes-arrive-how-long-until-we-can-use-it/"><em>When will CSS Grid Lanes arrive? How long until we can use it?</em></a></p>
<p>We also added support for Grid Lanes to Web Inspector.</p>
<figure class=""><picture><source srcset="https://webkit.org/wp-content/uploads/gridlanes-inspector-dark-scaled.webp" type="image/png" media="(prefers-color-scheme: dark)"><img decoding="async" src="https://webkit.org/wp-content/uploads/gridlanes-inspector-light-scaled.webp" alt="Same example of Grid Lanes layout, a gallery of photos. This time, with the Web Inspector open to the Grid layout tooling, with item numbers marked on the screen." width="2560" height="1505" class="aligncenter size-full wp-image-17880" srcset="https://webkit.org/wp-content/uploads/gridlanes-inspector-light-scaled.webp 2560w, https://webkit.org/wp-content/uploads/gridlanes-inspector-light-300x176.webp 300w, https://webkit.org/wp-content/uploads/gridlanes-inspector-light-1024x602.webp 1024w, https://webkit.org/wp-content/uploads/gridlanes-inspector-light-768x452.webp 768w, https://webkit.org/wp-content/uploads/gridlanes-inspector-light-1536x903.webp 1536w, https://webkit.org/wp-content/uploads/gridlanes-inspector-light-2048x1204.webp 2048w" sizes="(max-width: 2560px) 100vw, 2560px" /></picture></figure>
<p>The Grid Inspector now supports CSS Grid Lanes with order number overlays that show the placement sequence of grid items. You can toggle order number visibility in the settings and visualize gaps between items arranged by Grid Lanes. Auto-completion for <code>grid-lanes</code> and <code>inline-grid-lanes</code> values in the <code>display</code> property makes it easier to experiment with these new layout options. Learn more in <a href="https://webkit.org/blog/17746/new-safari-developer-tools-provide-insight-into-css-grid-lanes/"><em>New Safari developer tools provide insight into CSS Grid Lanes</em></a>.</p>
<h3><a name="name-only-container-queries"></a>Name-Only Container Queries</h3>
<p>Safari 26.4 adds support for name-only <code>@container</code> queries, allowing you to target named containers without specifying any size conditions. Previously, container queries required both a container name and a condition — like <code>@container sidebar (min-width: 300px)</code>. Now you can query just the container name:</p>
<pre><code class="css"><span class="keyword">@container</span> <span class="keyword">sidebar</span> {
  .<span class="attribute">card</span> {
    <span class="attribute">padding</span>: <span class="number">1</span><span class="identifier">rem</span>;
  }
}
</code></pre>
<p>This is useful when you want to apply styles based on which container an element is inside, regardless of that container’s size. It’s particularly handy for component variants or when you’re using container queries more for scoping styles than for responsive behavior. You still define the container name the same way:</p>
<pre><code class="css"><span class="keyword builtin">.sidebar</span> {
  <span class="attribute">container-name</span>: <span class="identifier">sidebar</span>;
  <span class="attribute">container-type</span>: <span class="identifier">inline-size</span>;
}
</code></pre>
<p>Now you can target elements inside that container without worrying about size breakpoints, giving you more flexibility in how you structure your component styles.</p>
<h3><a name="custom-cursors-on-marker"></a>Custom Cursors on ::marker</h3>
<p>Safari 26.4 adds support for the <code>cursor</code> property on the <code>::marker</code> pseudo-element, letting you customize pointer behavior for list markers.</p>
<pre><code class="css"><span class="keyword">li</span>::<span class="keyword">marker</span> {
  <span class="attribute">cursor</span>: <span class="identifier">pointer</span>;
}
</code></pre>
<p>This is one step toward making <code>::marker</code> more flexible.</p>
<h3><a name="math-typography"></a>Math Typography</h3>
<p>Safari 26.4 adds several improvements for mathematical typography, making it easier to display and style mathematical notation on the web.</p>
<p>The <code>math-depth</code> property gives you control over the sizing of nested mathematical expressions. In complex formulas with fractions, superscripts, and subscripts, <code>math-depth</code> automatically scales nested elements appropriately, ensuring readability while maintaining proper mathematical hierarchy.</p>
<p>Safari 26.4 also adds support for <code>font-size: math</code>, which applies proper scaling logic for mathematical content. This works together with <code>math-depth</code> to ensure formulas render at the right size relative to surrounding text.</p>
<p class="codepen" data-height="640" data-pen-title="math demo" data-default-tab="result" data-slug-hash="myrMpWJ" data-editable="true" data-user="jensimmons" style="height: 640px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
<p><script async src="https://public.codepenassets.com/embed/index.js"></script></p>
<p>For layout performance, you can now use CSS size containment with MathML elements via <code>contain-intrinsic-inline-size</code> and <code>contain-intrinsic-block-size</code>. This helps the browser optimize rendering of complex mathematical expressions, particularly when they’re off-screen or being dynamically loaded.</p>
<p>Finally, <code>math-style</code> and <code>math-shift</code> now animate as discrete values, allowing you to create transitions between different mathematical presentation styles.</p>
<p>These additions make MathML more powerful and performant, particularly for educational content, scientific publications, and any site that needs to display mathematical notation.</p>
<p>Along with these new features, a number of  MathML bugs were fixed:</p>
<ul>
<li>Fixed default MathML rule thickness to use the font’s <code>underlineThickness</code> metric with a zero fallback. (164693673)</li>
<li>Fixed <code>mpadded</code> elements in RTL (<code>dir="rtl"</code>) to respect <code>lspace</code>. (164740784)</li>
<li>Fixed an issue where empty <code>&lt;msqrt&gt;</code> radical operators in MathML were not painted correctly. (164776629)</li>
<li>Fixed MathML <code>&lt;mpadded&gt;</code>, <code>&lt;mfrac&gt;</code>, <code>&lt;munderover&gt;</code>, <code>&lt;mover&gt;</code> and <code>&lt;mspace&gt;</code> elements not updating layout when attributes like <code>width</code>, <code>height</code>, <code>depth</code>, <code>lspace</code>, and <code>voffset</code> etc. changed. (164797996)</li>
<li>Fixed MathML boolean attributes so they are now compared ASCII case-insensitively. (164819048)</li>
<li>Fixed incorrect positioning of <code>mpadded</code> content in right-to-left mode. (166045517)</li>
<li>Fixed an issue where <code>&lt;msqrt&gt;</code> or <code>&lt;mroot&gt;</code> elements did not update their radical operators when children were dynamically added or removed. (166556627)</li>
<li>Fixed <code>&lt;mpadded&gt;</code> so that percentage values for <code>width</code>, <code>height</code>, and <code>depth</code> attributes are treated as absent and use content dimensions as defaults, matching the MathML Core specification. (167350169)</li>
</ul>
<h3><a name="zoom"></a>Zoom</h3>
<p>Safari 26.4 includes a significant set of CSS Zoom fixes. The <code>zoom</code> property in CSS scales an element and its contents. While <code>transform: scale()</code> does something similar, <code>zoom</code> is handy because it affects layout, causing surrounding content to respond to the change in size.</p>
<p>CSS <code>zoom</code> is separate from browser zoom, (the kind triggered by ⌘+ and ⌘−), but the two can compound. An element with <code>zoom: 2</code> on a page that’s been zoomed in to 150% gets scaled by both factors. Getting everything to calculate correctly in that situation is genuinely tricky, and a lot of the fixes in this release are about getting that right. Properties like <code>width</code>, <code>height</code>, <code>margin</code>, and positional values now correctly apply zoom at used-value time. CSS <code>calc()</code> expressions correctly account for the zoom factor. And <code>getBoundingClientRect()</code> and <code>getClientRects()</code> in JavaScript now return properly scaled values.</p>
<p>Here’s the full list:</p>
<ul>
<li>Fixed <code>width</code>, <code>height</code>, <code>min-width</code>, <code>min-height</code>, <code>max-width</code> and <code>max-height</code> to apply CSS zoom at used-value time. (161848512)</li>
<li>Fixed CSS zoom to scale <code>&lt;iframe&gt;</code> element contents. (162314059)</li>
<li>Fixed <code>getBoundingClientRect</code> and <code>getClientRects</code> to return scaled lengths according to CSS zoom instead of unscaled values, aligning with the CSS Viewport specification. (162325730)</li>
<li>Fixed <code>top</code>, <code>left</code>, <code>right</code>, and <code>bottom</code> to apply CSS zoom at used-value time (162663056)</li>
<li>Fixed <code>margin</code> to apply CSS zoom at used-value time. (162907254)</li>
<li>Fixed evaluation of <code>calc()</code> expressions to correctly apply the used <code>zoom</code> factor to length values, ensuring properties like <code>line-height</code> and box dimensions scale properly. (163141549)</li>
<li>Fixed an issue where <code>calc(em)</code> values for unzoomed properties were incorrectly adjusted. (163267333)</li>
<li>Fixed an issue where <code>calc()</code> incorrectly treated margins as present. (163605539)</li>
<li>Fixed <code>devicePixelRatio</code> so that page zoom now affects the main frame consistently with iframes, keeping their values synchronized. (163857955)</li>
<li>Fixed <code>line-height</code> to correctly scale font-relative units when text zoom is applied. (165073337)</li>
<li>Fixed performance and correctness issues with inheritance in the modern CSS Zoom implementation. (167715972)</li>
<li>Fixed an issue where <code>&lt;video&gt;</code> poster images were incorrectly double-scaled when <code>zoom</code> was applied by using the cached intrinsic poster size without reapplying zoom. (150976146)</li>
</ul>
<h3><a name="threaded-scroll-driven-animations"></a>Threaded Scroll-driven Animations</h3>
<p>Safari 26.4 adds support for threaded Scroll-driven Animations. Now, the animations driven by scroll position run on the compositor thread, separate from the main thread. You don’t need do anything to get this benefit. When you use <code>animation-timeline: scroll()</code> or <code>animation-timeline: view()</code>, you automatically get the same kind of performance benefit that CSS transitions and keyframe animations have long enjoyed. Your scroll-driven animations will stay smooth even when the main thread is busy.</p>
<p>It also includes the following update:</p>
<ul>
<li>Fixed incorrect overlap calculations for transform animations including <code>translate</code>, <code>scale</code>, and <code>rotate</code> properties. (88383253)</li>
</ul>
<h3><a name="positioning"></a>Positioning</h3>
<p>Safari 26.4 includes many refinements for Anchor Positioning. It updates absolutely positioned boxes in scrollable containing blocks to allow alignment overflow in scrollable directions, in accordance with a recent CSS spec change. And it folds several more fixes to positioning:</p>
<ul>
<li>Fixed an infinite style resolution loop when a <code>position-try</code> box was inside a <code>display: none</code> subtree. (161570947)</li>
<li>Fixed <code>position-area</code> normal alignment to align toward the non-auto inset when only one inset is auto, in accordance with recent CSS spec changes. (163317238)</li>
<li>Fixed an issue where fixed-positioned boxes using <code>position-area</code> were incorrectly included in the root scrollable containing block, ensuring they position correctly while still allowing overflow when appropriate. (163955483)</li>
<li>Fixed an issue where <code>padding-inline-end</code> was not included in the scrollable overflow for block containers. (170503510)</li>
<li>Fixed an issue where <code>position-area</code> for elements in scrollable containers only used the initial scrollport bounds instead of the entire scrollable area. (170503694)</li>
<li>Fixed an issue where absolutely-positioned elements inside inline containers did not correctly account for the margin of a preceding block when determining their static position. (170934098)</li>
<li>Fixed incorrect width calculation for <code>positioned</code> elements using <code>box-sizing: border-box</code> with an <code>aspect-ratio</code>, ensuring borders and padding are not double-counted. (121500004)</li>
<li>Fixed <code>getComputedStyle("top")</code> to correctly resolve percentage values for absolutely positioned elements inside inline containers. (161390162)</li>
<li>Fixed an issue where CSS <code>@starting-style</code> entry animations were only applied on the first transition, especially when interacting with anchor positioning or position fallbacks. (163928932)</li>
</ul>
<h3><a name="layout-engine-improvements"></a>Layout Engine Improvements</h3>
<p>For several years, WebKit engineers have been working to rebuild each layout algorithm on a more modern foundation. Rather than waiting until a rewrite is complete before shipping its benefits, we’ve developed a mechanism so the new algorithm handles what it can as early as possible. Each algorithm starts with simpler use cases, then expands coverage over time as it becomes more capable — until it handles every situation.</p>
<p>Inline layout was completed <a href="https://webkit.org/blog/15063/webkit-features-in-safari-17-4/#css">in Safari 17.4</a> two years ago. Now, Safari 26.4 completes blocks-in-inline layout — fixing bugs and improving performance when block-level elements appear inside inline elements. Our work on the new Flexbox algorithm continues as well, covering increasingly complex cases over time.</p>
<p>Work on a new Grid layout engine is also now underway. When you use CSS Grid in a simple fashion, the new implementation in Safari 26.4 may be handling your layout. As the work progresses, support for more complex Grid layouts will follow.</p>
<p>Specific changes in Safari 26.4 include:</p>
<ul>
<li>Fixed incorrect min and max width calculations for block-level boxes inside inline content. (166157696)</li>
<li>Fixed an issue where <code>getClientRects</code> returned an incomplete list of rectangles for inline boxes containing block elements. (167209147)</li>
<li>Fixed baseline alignment for grid items by adding correct first baseline and last baseline row axis handling and properly accounting for baseline offsets. (155967278)</li>
</ul>
<h3><a name="table-layout"></a>Table Layout</h3>
<p>Table layout dates back to the early days of CSS, when the specification left a lot of behavior undefined. Browsers are still working through the consequences.</p>
<ul>
<li>Fixed an issue where <code>max-width</code> was not correctly applied to tables with fixed widths. (96554687)</li>
<li>Fixed table layout so that fixed horizontal margins on <code>&lt;caption&gt;</code> elements now contribute to the table’s minimum preferred logical width, preventing captions from causing narrower than expected tables. (120990942)</li>
<li>Fixed table column width distribution when a <code>colspan</code> spans mixed percentage and auto-width columns to properly respect percentage constraints. (165561401)</li>
<li>Fixed baseline handling for table cells when cell has no inflow children. (160774504)</li>
<li>Fixed <code>element.clientWidth</code> and <code>element.clientHeight</code> to correctly include padding for <code>content-box</code> tables. (165515755)</li>
<li>Fixed table height calculation to correctly account for captions with orthogonal <code>writing-mode</code>. (167220730)</li>
</ul>
<h3><a name="additional-changes-to-css"></a>Additional changes to CSS</h3>
<p>Safari 26.4 removes the deprecated <code>FontFaceSet</code> constructor from the CSS Font Loading API, aligning with a CSSWG resolution that deemed it unnecessary. The constructor was rarely used and its removal shouldn’t affect the web.</p>
<p>And this release includes even more improvements to CSS:</p>
<ul>
<li>Fixed an issue where <code>display: list-item</code> was incorrectly supported on <code>fieldset</code>. (95638460)</li>
<li>Fixed incorrect sizing and fragment URL handling for SVG images used in <code>-webkit-cross-fade()</code>. (106633417)</li>
<li>Fixed <code>text-combine-upright</code> to properly ignore <code>letter-spacing</code> when composing text horizontally, aligning with the CSS Writing Modes specification. (116562622)</li>
<li>Fixed an issue where <code>background-blend-mode</code> was not applied correctly when combined with <code>background-clip: text</code>. (120901898)</li>
<li>Fixed the UA style sheet to use <code>:focus-visible</code> instead of <code>:focus</code> for outline properties. (123155364)</li>
<li>Fixed <code>HighlightRegistry</code> to remove its non-standard <code>constructor</code> and updated tests to use <code>CSS.highlights</code> while ensuring <code>Map.prototype</code> is properly restored after tampering. (125529396)</li>
<li>Fixed handling of <code>@property</code> registration so that the <code>initial-value</code> descriptor can be optional. (131288198)</li>
<li>Fixed scrolling behavior so that <code>scrollRectToVisible()</code> can bring fixed anchor-positioned boxes outside the viewport into view, improving keyboard navigation. (162378346)</li>
<li>Fixed an issue where <code>@font-face</code> and <code>FontFace.family</code> failed when the font family name contained spaces, ensuring the family name is now treated as a plain string instead of being parsed. (162637501)</li>
<li>Fixed incorrect underline positioning for <code>text-decoration</code> when inline box sides are trimmed. (163858721)</li>
<li>Fixed <code>-webkit-line-clamp</code> so that it no longer propagates into <code>inline-block</code> children. (164488778)</li>
<li>Fixed an issue where nested identical CSS <code>filter</code> effects were not rendered. (165163823)</li>
<li>Fixed: Refactored the handling of block-level boxes inside inline boxes. (165523565)</li>
<li>Fixed an issue where <code>text-decoration: underline</code> appeared higher than expected when <code>text-box-trim</code> was applied to the root inline box. (165614136)</li>
<li>Fixed <code>::first-line</code> pseudo-element to always use <code>inline</code> display to match the CSS Display specification. (166068698)</li>
<li>Fixed an issue where <code>shape-outside</code> did not update correctly after web fonts loaded. (166336491)</li>
<li>Fixed incorrect text selection ranges for truncated right-to-left content. (166944754)</li>
<li>Fixed <code>counter-</code> properties serialization order. (167518994) </li>
<li>Fixed <code>outline-width</code> and <code>outline-offset</code> to follow updated computed style resolution rules. (167618367)</li>
<li>Fixed the computed style resolution for <code>border-width</code> properties. (167689519) </li>
<li>Fixed the computed style resolution for the <code>column-rule-width</code> property. (167725940)</li>
<li>Fixed <code>border-width</code>, <code>outline-width</code>, and <code>column-rule-width</code> so they now pixel snap correctly during CSS animations and transitions. (167763497) </li>
<li>Fixed the disclosure triangle in <code>&lt;details&gt;</code> elements to use the larger <code>system-ui</code> font variant, preventing it from rendering as an emoji and ensuring consistent display across writing directions. (168364553)</li>
<li>Fixed CSS rules within <code>@scope</code> not being applied to <code>&lt;input&gt;</code> and <code>&lt;textarea&gt;</code> elements. (169751338)</li>
<li>Fixed an issue where empty CSS rules sharing a selector with non-empty rules could prevent dynamic style updates from applying correctly. (170348749)</li>
<li>Fixed an issue where CSS transitions were incorrectly triggered when <code>border-width</code> computed values did not change, causing unexpected layout shifts. (170657059)</li>
<li>Fixed an issue where multi-column layout rendered columns at incorrect positions for some fonts. (171016194)</li>
</ul>
<h2><a name="webtransport"></a>WebTransport</h2>
<p>Safari 26.4 adds support for <a href="https://www.w3.org/TR/webtransport/">WebTransport</a>, a modern API for low-latency, bidirectional communication between clients and servers.</p>
<p>If you’ve been building real-time applications — like multiplayer games, live collaboration tools, or video conferencing — you’ve likely run into the limitations of existing technologies. WebSockets work well for many use cases, but they’re built on TCP, which means head-of-line blocking can cause delays when packets are lost. HTTP/3 and QUIC solve this problem, but don’t directly offer the same bidirectional streaming capabilities you might need.</p>
<p>WebTransport gives you the best of both worlds. It runs over HTTP/3 and QUIC, providing multiple streams that won’t block each other. You can send data reliably (like WebSockets) or unreliably (when you’d rather drop old data than wait for it), and you can mix both approaches in the same connection. This makes it particularly useful for applications where low latency matters most — think live audio, real-time sensor data, or fast-paced gaming. When the underlying network environment doesn&#8217;t support QUIC, WebTransport can run over HTTP/2 and TCP as a fallback with the same API.</p>
<p>The API is built around streams, similar to the Streams API you might already be using elsewhere. You can open bidirectional streams, send datagrams, and handle backpressure naturally. Here’s a basic example:</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">url</span> <span class="operator">=</span> <span class="char">'https://example.com:443/webtransport'</span>;
<span class="keyword type">const</span> <span class="identifier">transport</span> <span class="operator">=</span> <span class="keyword operator">new</span> <span class="identifier">WebTransport</span>(<span class="identifier">url</span>);

<span class="identifier">await</span> <span class="identifier">transport</span>.<span class="identifier">ready</span>;

<span class="comment">// Send data via a unidirectional stream
</span><span class="keyword type">const</span> <span class="identifier">stream</span> <span class="operator">=</span> <span class="identifier">await</span> <span class="identifier">transport</span>.<span class="identifier">createUnidirectionalStream</span>();
<span class="keyword type">const</span> <span class="identifier">writer</span> <span class="operator">=</span> <span class="identifier">stream</span>.<span class="identifier">getWriter</span>();
<span class="identifier">await</span> <span class="identifier">writer</span>.<span class="identifier">write</span>(<span class="keyword operator">new</span> <span class="identifier">Uint8Array</span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]));
<span class="identifier">await</span> <span class="identifier">writer</span>.<span class="identifier">close</span>();
</code></pre>
<p>WebTransport opens up new possibilities for what you can build on the web, bringing performance characteristics that previously required native applications or complex workarounds.</p>
<p>A related fix also landed:</p>
<ul>
<li>Fixed <code>ReadableStream</code> and <code>WritableStream</code> to correctly pass abort and cancel reasons and improved <code>WebTransport</code> stream handling. (165474756)</li>
</ul>
<p>Also fixed in Networking:</p>
<ul>
<li>Fixed a regression where <code>fetch()</code> would throw a <code>TypeError</code> when using <code>targetAddressSpace: 'loopback'</code> for localhost requests. (166574523)</li>
</ul>
<h2><a name="web-api"></a>Web API</h2>
<h3><a name="keyboard-lock-api"></a>Keyboard Lock API</h3>
<p>Safari 26.4 adds support for the Fullscreen Keyboard Lock API, which allows web applications to capture keyboard input that would normally be handled by the browser.</p>
<p>If you’ve ever built a game, a remote desktop client, or a creative tool, you’ve probably encountered this frustration: certain keyboard shortcuts are off-limits. Press the Escape key and you are thrown out of fullscreen mode. There’s been no way to prevent this — until now.</p>
<p>The Keyboard Lock API lets you request access to specific keys when your application needs it. A game can now use the Escape key for its own menu system. To exit fullscreen mode then the user would need to hold down the escape key for 1.5 seconds. A remote desktop client can pass through all keyboard shortcuts to the remote machine.</p>
<pre><code class="js"><span class="identifier">element</span>.<span class="identifier">requestFullscreen</span>({ <span class="identifier">keyboardLock</span><span class="operator">:</span> <span class="string">"browser"</span> });
</code></pre>
<p>The browser automatically releases the lock when the user leaves fullscreen or switches tabs. And of course, this only works in secure contexts — sites served over HTTPS.</p>
<h3><a name="readablebytestream"></a>ReadableByteStream</h3>
<p>Safari 26.4 adds support for <code>ReadableByteStream</code>, completing the implementation of byte-oriented streams in the Streams API.</p>
<p>Until now, <code>ReadableStream</code> has primarily worked with chunks of any type — objects, strings, or arbitrary data. <code>ReadableByteStream</code> is specifically designed for efficiently handling binary data, like files, network responses, or media streams.</p>
<p>The key advantage is memory efficiency. With byte streams, you can use BYOB (Bring Your Own Buffer) readers, which let you provide your own <code>ArrayBuffer</code> for the stream to fill. This means you can reuse buffers and avoid unnecessary allocations.</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">reader</span> <span class="operator">=</span> <span class="identifier">stream</span>.<span class="identifier">getReader</span>({ <span class="identifier">mode</span><span class="operator">:</span> <span class="char">'byob'</span> });
<span class="keyword type">const</span> <span class="identifier">buffer</span> <span class="operator">=</span> <span class="keyword operator">new</span> <span class="identifier">ArrayBuffer</span>(<span class="number">1024</span>);
<span class="keyword type">const</span> { <span class="identifier">value</span>, <span class="identifier">done</span> } <span class="operator">=</span> <span class="identifier">await</span> <span class="identifier">reader</span>.<span class="identifier">read</span>(<span class="keyword operator">new</span> <span class="identifier">Uint8Array</span>(<span class="identifier">buffer</span>));
</code></pre>
<p>Safari 26.4 also adds support for using byte streams as <code>fetch</code> request and response bodies, and for reading <code>Blob.stream()</code> with a BYOB reader. If you’re working with video, audio, large files, or any scenario where you’re moving significant amounts of binary data around, byte streams give you the tools to do it efficiently.</p>
<p>A related encoding fix also landed:</p>
<ul>
<li>Fixed incorrect handling of invalid UTF-8 sequences in the <code>TextDecoder</code> streaming decoder to properly manage partial sequence buffers. (166583808)</li>
</ul>
<h3><a name="readablestream-async-iteration"></a>ReadableStream Async Iteration</h3>
<p>Safari 26.4 adds support for <code>ReadableStream.getIterator()</code> and the <code>[@@asyncIterator]</code> method, making it much easier to work with streams using modern JavaScript syntax. Previously, reading from a stream required manually calling <code>getReader()</code> and repeatedly calling <code>read()</code> in a loop. Now you can use <code>for await...of</code> to iterate over stream chunks directly:</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">response</span> <span class="operator">=</span> <span class="identifier">await</span> <span class="identifier">fetch</span>(<span class="char">'/data'</span>);
<span class="keyword type">const</span> <span class="identifier">stream</span> <span class="operator">=</span> <span class="identifier">response</span>.<span class="identifier">body</span>;

<span class="keyword control">for</span> <span class="identifier">await</span> (<span class="keyword type">const</span> <span class="identifier">chunk</span> <span class="keyword operator">of</span> <span class="identifier">stream</span>) {
  <span class="comment">// Process each chunk as it arrives
</span>  <span class="identifier">console</span>.<span class="identifier">log</span>(<span class="identifier">chunk</span>);
}
</code></pre>
<p>This is much cleaner than the previous approach and fits naturally with how you’re already using async iteration elsewhere in JavaScript. It’s particularly nice when you’re processing streaming data — like server-sent events, large file uploads, or any scenario where data arrives over time.</p>
<h3><a name="improvements-to-scoped-custom-element-registries"></a>Improvements to Scoped Custom Element Registries</h3>
<p>In September, Safari 26.0 was the first browser to ship support for the standardized version of Scoped Custom Element Registries. Before then, custom elements were always registered globally on a single registry shared across the entire document. This created problems when building component libraries or working with multiple frameworks. If two different parts of an application tried to register the same element name, one would fail.</p>
<p>Scoped registries solve this by letting you create separate registries for different parts of the same document:</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">starRegistry</span> <span class="operator">=</span> <span class="keyword operator">new</span> <span class="identifier">CustomElementRegistry</span>();
<span class="identifier">starRegistry</span>.<span class="identifier">define</span>(<span class="char">'my-button'</span>, <span class="identifier">MyCustomButton</span>);
<span class="identifier">document</span>.<span class="identifier">createElement</span>(<span class="char">'my-button'</span>, { <span class="identifier">customElementRegistry</span><span class="operator">:</span> <span class="identifier">starRegistry</span> });

<span class="keyword type">const</span> <span class="identifier">bananaRegistry</span> <span class="operator">=</span> <span class="keyword operator">new</span> <span class="identifier">CustomElementRegistry</span>();
<span class="identifier">bananaRegistry</span>.<span class="identifier">define</span>(<span class="char">'my-button'</span>, <span class="identifier">MyFancyButton</span>);
<span class="identifier">document</span>.<span class="identifier">createElement</span>(<span class="char">'my-button'</span>, { <span class="identifier">customElementRegistry</span><span class="operator">:</span> <span class="identifier">bananaRegistry</span> });
</code></pre>
<p>Safari 26.4 now extends Scoped Custom Element Registries by:</p>
<ul>
<li>Upgrading elements in <code>CustomElementRegistry.prototype.initialize</code></li>
<li>Supporting the <code>customelementregistry</code> content attribute and handling of <code>nullcustomElementRegistry</code> values in <code>document.createElement</code>, <code>document.createElementNS</code>, and <code>element.attachShadow</code></li>
<li>Fixing <code>shadowrootcustomelementregistry</code> attribute serialization to correctly compare ShadowRoot and document registries. (165476421)</li>
</ul>
<h3><a name="auxiliary-mouse-button-support"></a>Auxiliary Mouse Button Support</h3>
<p>Safari 26.4 adds support for auxiliary mouse button values in <code>MouseEvent.button</code>, so you can now detect additional mouse buttons beyond the standard left, middle, and right clicks. If you’re building applications that take advantage of gaming mice or other input devices with extra buttons, you can now respond to those inputs.</p>
<pre><code class="js"><span class="identifier">element</span>.<span class="identifier">addEventListener</span>(<span class="char">'mousedown'</span>, (<span class="identifier">e</span>) <span class="operator">=</span><span class="operator">&gt;</span> {
  <span class="keyword control">if</span> (<span class="identifier">e</span>.<span class="identifier">button</span> <span class="operator">=</span><span class="operator">=</span><span class="operator">=</span> <span class="number">3</span>) { <span class="comment">/* back button */</span> }
  <span class="keyword control">if</span> (<span class="identifier">e</span>.<span class="identifier">button</span> <span class="operator">=</span><span class="operator">=</span><span class="operator">=</span> <span class="number">4</span>) { <span class="comment">/* forward button */</span> }
});
</code></pre>
<p>The <code>button</code> property will correctly report values for buttons 3, 4, and beyond, matching the behavior in other browsers.</p>
<h3><a name="resource-timing"></a>Resource Timing</h3>
<p>Safari 26.4 adds two new attributes from the Resource Timing Level 3 specification: <code>finalResponseHeadersStart</code> and <code>firstInterimResponseStart</code>. These give you more precise timing measurements for HTTP responses — particularly useful if you’re using 103 Early Hints.</p>
<p><code>firstInterimResponseStart</code> captures when the first interim response (like a 103 Early Hints response) was received, and <code>finalResponseHeadersStart</code> captures when the final response headers arrived. Together they let you measure exactly how much time your 103 Early Hints are saving.</p>
<pre><code class="js"><span class="keyword type">const</span> [<span class="identifier">entry</span>] <span class="operator">=</span> <span class="identifier">performance</span>.<span class="identifier">getEntriesByType</span>(<span class="char">'resource'</span>)
  .<span class="identifier">filter</span>(<span class="identifier">e</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="identifier">e</span>.<span class="identifier">name</span>.<span class="identifier">includes</span>(<span class="char">'example.com'</span>));

<span class="identifier">console</span>.<span class="identifier">log</span>(<span class="identifier">entry</span>.<span class="identifier">firstInterimResponseStart</span>);  <span class="comment">// when 103 arrived
</span><span class="identifier">console</span>.<span class="identifier">log</span>(<span class="identifier">entry</span>.<span class="identifier">finalResponseHeadersStart</span>);  <span class="comment">// when final headers arrived
</span></code></pre>
<p>If you’re not yet using 103 Early Hints, these attributes give you a reason to explore it — you can now actually measure the impact.</p>
<h3><a name="mediadeviceinfo-in-secure-contexts-only"></a>MediaDeviceInfo in Secure Contexts Only</h3>
<p>Safari 26.4 now exposes the <code>MediaDeviceInfo</code> interface only in secure contexts (HTTPS), aligning with the web specification. If you’re working with <code>navigator.mediaDevices.enumerateDevices()</code> to detect cameras and microphones, make sure your site is served over HTTPS.</p>
<p>Along the same lines:</p>
<ul>
<li>Fixed <code>DeviceMotionEvent</code> and <code>DeviceOrientationEvent</code> interfaces so that they only show up in secure contexts just like the corresponding events and made <code>ondevicemotion</code> and <code>ondeviceorientation</code> enumerable, aligning with the specification. (44804273)</li>
</ul>
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<p>Safari 26.4 also includes a number of other Web API fixes:</p>
<ul>
<li>Fixed an issue where <code>IntersectionObserver</code> computed the root rectangle incorrectly when overflow clipping was present. (117143395)</li>
<li>Fixed Trusted Types to correctly send CSP violation reports when a default policy returns an invalid <code>javascript:</code> URL or throws an exception. (160960418)</li>
<li>Fixed <code>Element.requestFullscreen</code> on iOS to correctly reflect hardware keyboard attachment state during fullscreen sessions and exit automatically when the keyboard is detached. (161429040)</li>
<li>Fixed event ordering and committed promise timing for intercepted <code>Navigation API</code> traverse navigations. (161445256)</li>
<li>Fixed the processing order of Trusted Types for DOM attribute setting. (162143148)</li>
<li>Fixed <code>NavigateEvent</code> to correctly fire an <code>AbortSignal</code> when a navigation is aborted. (163957784)</li>
<li>Fixed <code>NavigateEvent.sourceElement</code> to correctly reference elements from different browsing contexts. (163962362)</li>
<li>Fixed the Navigation API to prevent scripts from flooding the system with navigation requests. (164510890)</li>
<li>Fixed an issue where <code>scroll-margin</code> from <code>IntersectionObserver</code> incorrectly applied to scrollers inside cross-origin iframes. (164994009)</li>
<li>Fixed <code>DigitalCredential</code> behavior to make user mediation implicitly required. (165597827)</li>
<li>Fixed an issue where the Big5 <code>TextDecoder</code> failed to recover and emit ASCII characters after encountering an invalid leading byte. (166672674)</li>
<li>Fixed <code>MouseEvent.offsetX</code> and <code>MouseEvent.offsetY</code> so they are now calculated relative to the padding edge of the target element. (168015965)</li>
<li>Fixed an issue where pointer events would fail to dispatch after a parent view&#8217;s custom gesture recognizer blocked <code>touchesEnded:</code> or <code>touchesCancelled:</code>. (169109808)</li>
<li>Fixed an issue where JavaScript-to-native object serialization could fail entirely when any individual key-value pair could not be serialized, causing broken workflows in some apps. (171547386)</li>
</ul>
<h2><a name="javascript"></a>JavaScript</h2>
<p>Safari 26.4 adds support for iterator sequencing. It lets you chain multiple iterators together into a single sequence using <code>Iterator.concat()</code>.</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">odds</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>].<span class="identifier">values</span>();
<span class="keyword type">const</span> <span class="identifier">evens</span> <span class="operator">=</span> [<span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>].<span class="identifier">values</span>();

<span class="keyword control">for</span> (<span class="keyword type">const</span> <span class="identifier">n</span> <span class="keyword operator">of</span> <span class="identifier">Iterator</span>.<span class="identifier">concat</span>(<span class="identifier">odds</span>, <span class="identifier">evens</span>)) {
<span class="identifier">console</span>.<span class="identifier">log</span>(<span class="identifier">n</span>); <span class="comment">// 1, 3, 5, 2, 4, 6
</span>}
</code></pre>
<p>This is a clean alternative to flattening arrays or writing manual chaining logic just to iterate over several collections in sequence.</p>
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<p>Several JavaScript bugs were also fixed:</p>
<ul>
<li>Fixed <code>Date</code> constructor overflow handling so that invalid day values now return <code>NaN</code>. (155776209)</li>
<li>Fixed <code>Intl.DateTimeFormat</code> to throw a <code>RangeError</code> for legacy non-IANA timezones, aligning behavior with TC39 standards. (156857252)</li>
<li>Fixed <code>Intl.Locale.prototype.getWeekInfo()</code> to remove the <code>minimalDays</code> property for compliance with the specification. (165083619)</li>
<li>Fixed <code>Intl.NumberFormat</code> to properly apply <code>minimumFractionDigits</code> and <code>maximumFractionDigits</code> to ensure currency and compact notations behave correctly. (165875014)</li>
<li>Fixed <code>%TypedArray%.prototype.includes</code> to correctly check that the <code>index</code> is less than the array length, aligning its behavior with ECMA-262. (167183441)</li>
<li>Fixed async functions without any <code>await</code> to inline their bodies for performance and corrected async stack traces with a single function entry for exceptions thrown from or through async functions. (167254635)</li>
</ul>
<h2><a name="html"></a>HTML</h2>
<p>Safari 26.4 adds support for using the <code>min()</code>, <code>max()</code>, and <code>clamp()</code> math functions inside the <code>sizes</code> attribute of <code>&lt;img&gt;</code> elements.</p>
<p>The <code>sizes</code> attribute tells the browser how wide an image will be displayed at different viewport sizes, helping it choose the right image from your <code>srcset</code>. Until now, you were limited to media queries and length values. Now you can use CSS math functions for more precise control:</p>
<pre><code class="html"><span class="tag">&lt;<span class="keyword">img</span> 
  <span class="keyword attribute">srcset</span>=<span class="attribute value string">"small.jpg 400w, medium.jpg 800w, large.jpg 1200w"</span>
  <span class="keyword attribute">sizes</span>=<span class="attribute value string">"min(100vw, 1200px)"</span>
  <span class="keyword attribute">src</span>=<span class="attribute value string">"medium.jpg"</span>
  <span class="keyword attribute">alt</span>=<span class="attribute value string">"..."</span>&gt;</span>
</code></pre>
<p>This is particularly useful for responsive images that need to respect both viewport width and maximum content width. You can use <code>clamp()</code> to set minimum, ideal, and maximum sizes:</p>
<pre><code class="html">sizes="clamp(300px, 50vw, 800px)"
</code></pre>
<p>This gives you the same flexible sizing control in <code>sizes</code> that you already have in CSS, making responsive images easier to manage.</p>
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<ul>
<li>Fixed an issue where nested <code>about:blank</code> frames were incorrectly treated as self-referencing, preventing them from loading. (148373033)</li>
<li>Fixed <code>HTMLImageElement.currentSrc</code> to return an empty string for <code>&lt;img src=""&gt;</code> instead of resolving to the document base URL. (167229274)</li>
<li>Fixed image uploading to not transcode images when <code>accept="image/*"</code> is specified. (166124206)</li>
<li>Fixed an issue where input fields did not display user input while typing. (163613957)</li>
<li>Fixed an issue where <code>input[type="search"]</code> fields with <code>appearance: none</code> incorrectly reserved space for the datalist dropdown button. (166754216)</li>
<li>Fixed an incorrect fallback for the menu style for empty lists, improving readability and correctness. (167662316)</li>
</ul>
<h2><a name="svg"></a>SVG</h2>
<p>Safari 26.4 adds support for the <code>lighter</code> operator in <code>SVGFECompositeElement</code>, aligning with the Compositing and Blending specification. This gives you an additional blending mode when compositing SVG filter effects, useful for creating additive lighting and glow effects in your SVG graphics. This example shows it in action. With support, there’s a soft glow around each circle. Without it, the glow is just not there.</p>
<p class="codepen" data-height="365" data-pen-title="Demo of lighter operator in SVGFECompositeElement" data-default-tab="html,result" data-slug-hash="jEMaMLV" data-editable="true" data-user="jensimmons" style="height: 365px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<p>Safari 26.4 also includes a large number of SVG bug fixes:</p>
<ul>
<li>Fixed an issue where <code>stroke-dasharray</code> incorrectly propagated to SVG markers when explicitly marked as &#8216;0&#8217;. (46607685)</li>
<li>Fixed an issue where <code>foreignObject</code> elements in SVG incorrectly allowed margin collapsing. (97208795)</li>
<li>Fixed SVG intrinsic sizing and <code>preferredAspectRatio()</code> to correctly transpose dimensions for vertical writing modes. (103262534)</li>
<li>Fixed animation of the <code>stop-color</code> attribute on <code>&lt;stop&gt;</code> elements. (109823555)</li>
<li>Fixed an issue where dynamically changing <code>marker-start</code>, <code>marker-mid</code>, or <code>marker-end</code> attributes on SVG elements did not trigger re-rendering. (130678384)</li>
<li>Fixed tiling gaps in CSS reference filters using <code>&lt;feDisplacementMap&gt;</code>. (135448018)</li>
<li>Fixed <code>SVGLength</code> parsing to correctly return the initial value when encountering parser errors or invalid values. (136102554)</li>
<li>Fixed an issue where <code>SVGImage</code> did not respect system dark mode changes. (140661763)</li>
<li>Fixed breaking SVG resource referencing when removing a resource which shares its <code>id</code> with other resources. (147015037)</li>
<li>Fixed behavior to avoid incorrect pruning of SVG mask subtrees based on visibility. (157729389)</li>
<li>Fixed an issue where SVG <code>animateTransform</code> animations on hidden elements were triggering full-page rendering updates each frame. (159647563)</li>
<li>Fixed <code>SVGLength.prototype.valueAsString</code> to throw a <code>SyntaxError</code> when assigned an empty string. (165429393)</li>
<li>Fixed <code>SVGLength</code> percentage resolution for elements inside non-instanced <code>&lt;symbol&gt;</code> elements. (165431008)</li>
<li>Fixed an issue where lengths with leading or trailing whitespace failed to be parsed. (165501190)</li>
<li>Fixed an issue where <code>SVGLength.value</code> did not update for font-relative units (e.g., <code>ch</code>, <code>em</code>) after changes to <code>writing-mode</code>. (166190252)</li>
<li>Fixed missing gradient fills when using paint-order <code>stroke fill</code>. (166997630)</li>
<li>Fixed embedded <code>&lt;svg&gt;</code> elements in <code>&lt;img&gt;</code> without an explicit <code>viewBox</code> to synthesize <code>preserveAspectRatio='none'</code> so the SVG stretches to fill the container. (167121931)</li>
<li>Fixed the <code>&lt;stop&gt;</code> element <code>offset</code> attribute in SVG to reject invalid values with trailing characters and correctly fall back to <code>0</code>. (167356988)</li>
<li>Fixed the transform order for <code>clipPath</code> elements so that the bounding box is scaled correctly before applying the local transform. (167417135)</li>
<li>Fixed <code>&lt;clipPath&gt;</code> to clip to its <code>&lt;use&gt;</code> child element based on the visibility of the <code>&lt;use&gt;</code> target element. (167491519)</li>
<li>Fixed incorrect rendering when combining <code>markerUnits=strokeWidth</code> with <code>vector-effect=non-scaling-stroke</code>. (167493417)</li>
<li>Fixed displaying an SVG filter referencing an element with a huge stroke. (167516452)</li>
<li>Fixed hit testing for overlapping <code>&lt;text&gt;</code> and <code>&lt;tspan&gt;</code> elements in SVG. (167691166)</li>
<li>Fixed rendering of dimensionless SVG images. (168176556)</li>
</ul>
<h2><a name="safari-compact-tabs"></a>Safari Compact tabs</h2>
<p>The Compact tabs option on macOS and iPadOS makes a return in Safari 26.4. If you preferred the more space-efficient tab design from earlier versions of Safari, you can now enable it again in Safari settings, under Tabs > Tab layout.</p>
<figure class=""><picture><source srcset="https://webkit.org/wp-content/uploads/safari264-compacttabs-dark.png" type="image/png" media="(prefers-color-scheme: dark)"><img loading="lazy" decoding="async" src="https://webkit.org/wp-content/uploads/safari264-compacttabs-light.png" alt="Safari settings panel, showing where to switch from Separate to Compact tabs." width="1896" height="1154" class="aligncenter size-full wp-image-17883" srcset="https://webkit.org/wp-content/uploads/safari264-compacttabs-light.png 1896w, https://webkit.org/wp-content/uploads/safari264-compacttabs-light-300x183.png 300w, https://webkit.org/wp-content/uploads/safari264-compacttabs-light-1024x623.png 1024w, https://webkit.org/wp-content/uploads/safari264-compacttabs-light-768x467.png 768w, https://webkit.org/wp-content/uploads/safari264-compacttabs-light-1536x935.png 1536w" sizes="auto, (max-width: 1896px) 100vw, 1896px" /></picture></figure>
<h2><a name="web-authentication"></a>Web Authentication</h2>
<p>Safari 26.4 adds two important WebAuthn improvements for advanced authentication scenarios.</p>
<p>The PRF (Pseudo-Random Function) extension enables credential-bound cryptographic secrets during both credential creation and authentication flows with security keys. This maps to the CTAP <code>hmac-secret</code> extension and allows you to derive cryptographic keys from WebAuthn credentials — useful for applications that need to encrypt user data with keys tied to their authentication credentials, such as password managers or encrypted storage systems.</p>
<p>Safari 26.4 also adds support for CTAP PIN/UV Auth Protocol 2, which uses HKDF-SHA-256 for key derivation. This enables proper support for newer FIPS-compliant authenticators, which is important for enterprise and government applications with strict security requirements.</p>
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<ul>
<li>Fixed an issue where the <code>excludeCredentials</code> list was not sent over CTAP when its size was 1. (164546088)</li>
</ul>
<h2><a name="web-inspector"></a>Web Inspector</h2>
<p>In addition to the new Grid Lanes tooling described above, Safari 26.4 includes numerous Web Inspector enhancements to help you debug and build websites more effectively.</p>
<h3><a name="layer-visualization"></a>Layer Visualization</h3>
<p>The Layers tab now shows actual composited layer snapshots instead of outline representations, giving you a more accurate picture of how your page is being rendered and composited.</p>
<figure class=""><picture><source srcset="https://webkit.org/wp-content/uploads/layervis-dark.png" type="image/png" media="(prefers-color-scheme: dark)"><img loading="lazy" decoding="async" src="https://webkit.org/wp-content/uploads/layervis-light.png" alt="The Web Inspector Layers tab, showing a webpage turned in #D space, with the separate layers of the site stacked translucently on top of each other" width="2550" height="1592" class="aligncenter size-full wp-image-17886" srcset="https://webkit.org/wp-content/uploads/layervis-light.png 2550w, https://webkit.org/wp-content/uploads/layervis-light-300x187.png 300w, https://webkit.org/wp-content/uploads/layervis-light-1024x639.png 1024w, https://webkit.org/wp-content/uploads/layervis-light-768x479.png 768w, https://webkit.org/wp-content/uploads/layervis-light-1536x959.png 1536w, https://webkit.org/wp-content/uploads/layervis-light-2048x1279.png 2048w" sizes="auto, (max-width: 2550px) 100vw, 2550px" /></picture></figure>
<h3><a name="developer-experience"></a>Developer Experience</h3>
<p>A new context menu option lets you copy pretty-printed HTML from DOM nodes in the Elements tab — much easier to read than minified markup. In the settings tab, you can now toggle the visibility of User Agent stylesheet rules, reducing clutter when you’re focused on your own styles.</p>
<figure class=""><picture><source srcset="https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-dark-scaled.png" type="image/png" media="(prefers-color-scheme: dark)"><img loading="lazy" decoding="async" src="https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-light-scaled.png" alt="Web Inspector open on a website, with something in the DOM tree selected. The context menu is open, showing options, and Copy HTML (Formatted) is being chosen." width="2560" height="1683" class="aligncenter size-full wp-image-17889" srcset="https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-light-scaled.png 2560w, https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-light-300x197.png 300w, https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-light-1024x673.png 1024w, https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-light-768x505.png 768w, https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-light-1536x1010.png 1536w, https://webkit.org/wp-content/uploads/webinspector-copyformatedHTML-light-2048x1347.png 2048w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></picture></figure>
<p>The Timelines Heap view displays the dominator object when viewing the shortest GC path, making it easier to track down memory leaks. And Web Inspector now fetches CSS property keyword completions based on actual feature support, so auto-complete suggestions reflect what’s actually available.</p>
<h3><a name="worker-debugging"></a>Worker Debugging</h3>
<p>You can now capture <code>console.screenshot</code> images within a Worker, supporting <code>ImageData</code>, <code>ImageBitmap</code>, <code>OffscreenCanvas</code>, and various canvas rendering contexts. Canvas recordings can also be started and stopped from the console within a Worker using <code>console.record()</code> and <code>console.recordEnd()</code>.</p>
<h3><a name="additional-improvements"></a>Additional Improvements</h3>
<p>Auto-completion now includes <code>sideways-lr</code> and <code>sideways-rl</code> values for the <code>writing-mode</code> property, making it easier to work with vertical text layouts.</p>
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<p>Safari 26.4 also includes a number of Web Inspector bug fixes:</p>
<ul>
<li>Fixed incorrect breakpoint and search result positions in the Web Inspector after pretty-printing inline scripts containing multi-line template literals. (29417859)</li>
<li>Fixed the Styles sidebar filter in Web Inspector to be case-insensitive. (36086981)</li>
<li>Fixed an issue where a large number of search results in the Search tab would freeze Web Inspector. (49234522)</li>
<li>Fixed an issue where the Console tab search bar in Web Inspector would disappear when the window was too narrow. (50922509)</li>
<li>Fixed an issue where CSS properties added to new rules were not applied and were marked as invalid. (103548968)</li>
<li>Fixed context menu items to rename <code>Copy HTTP Request</code> and <code>Copy HTTP Response</code> to <code>Copy HTTP Request Headers</code> and <code>Copy HTTP Response Headers</code> for clarity. (117708766)</li>
<li>Fixed incorrect grid track sizing display in the Web Inspector when using CSS custom properties. (141709306)</li>
<li>Fixed an issue in the Console where the count of identical consecutive messages could be wrong. (162612099)</li>
<li>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. (165059693)</li>
<li>Fixed an issue where the Sources navigation sidebar could be empty when reloading the page. (166141968)</li>
<li>Fixed timestamp formatting in the Web Inspector to remove unnecessary trailing <code>.0</code> values for readability. (166500013)</li>
<li>Fixed item order labels in the Web Inspector grid and flex overlays to remove the <code>#</code> symbol, changing from <code>Item #N</code> to <code>Item N</code>. (166767949)</li>
<li>Fixed an issue where the text filter in the Sources tab did not apply to the Local Overrides and Console Snippets sections. (169804196)</li>
<li>Fixed a performance issue in the Web Inspector search panel by limiting initial results to 100 per resource and adding UI controls to load more or all results, reducing unnecessary UI work for large queries. (169804865)</li>
<li>Fixed an issue where the search bar settings icon disappeared when the search field was focused. (169997100)</li>
</ul>
<h2><a name="media-captions"></a>Media Captions</h2>
<p>Safari 26.4 adds improved caption controls on macOS, including a pop-up menu that lets users select and manage caption style profiles and configure subtitle display settings.</p>
<p>These enhancements give users more control over how captions appear — adjusting text size, color, background, and other styling options to match their preferences. If you’re providing video content with captions, users will have a better experience customizing how those captions are displayed.</p>
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<p>Quite a few media bugs were also fixed:</p>
<ul>
<li>Fixed dispatching of enter and exit events on <code>TextTrackCue</code> and <code>VTTCue</code> objects with no associated track, aligning with other browsers. (160195643)</li>
<li>Fixed an issue where changing an <code>HTMLMediaElement</code> volume from <code>0</code> to <code>0</code> did not activate the audio session or update the sleep disabler. (161691743)</li>
<li>Fixed an issue where videos would freeze on the first frame when transitioning from encrypted to clear content by ensuring the decoded buffer maintains at least 100ms of frames even when the next frame is far in the future. (162234566)</li>
<li>Fixed an issue where the mute button disappeared in macOS inline videos with adjustable sizes. (162897286)</li>
<li>Fixed playback of <code>application/ogg</code> blob media. (163119790)</li>
<li>Fixed an issue where Video Viewer UI elements overlapped or exited unexpectedly. (164051864)</li>
<li>Fixed an issue where empty <code>&lt;track&gt;</code> elements prevented media from advancing its readyState and blocked <code>play()</code> calls. (164125914)</li>
<li>Fixed an issue where <code>HTMLMediaElement</code> did not correctly detect new audio or video tracks causing Safari to pause video when leaving a tab. (164514685)</li>
<li>Fixed a crash in <code>AudioData.copyTo()</code> when copying the last channel of 3-channel audio. (164730320)</li>
<li>Fixed an issue where the <code>ended</code> 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. (165430052)</li>
<li>Fixed an issue where caption previews were not shown in the default media controls. (165931046)</li>
<li>Fixed the caption menu&#8217;s <code>On</code> option to correctly enable the highest-scoring text track and mark the appropriate language as checked in the subtitle menu. (166158394)</li>
<li>Fixed <code>parseSequenceHeaderOBU</code> to return an <code>AV1CodecConfigurationRecord</code>, fully decode the Sequence Header OBU, and capture the complete color profile. (166439682)</li>
<li>Fixed an issue where the macOS inline media controls timeline scrubber overlapped the right container buttons. (167634241)</li>
<li>Fixed an issue where <code>WebCodecs VideoDecoder</code> could output H264 frames in the wrong order. (168046597)</li>
<li>Fixed an issue where the mute button and volume slider overlapped in the video player controls when using a right-to-left language. (170174446)</li>
</ul>
<h2><a name="webrtc"></a>WebRTC</h2>
<p>Safari 26.4 adds two significant WebRTC enhancements for audio and networking.</p>
<p>On macOS, <code>getUserMedia</code> now supports capturing audio from multiple microphones simultaneously while intelligently managing echo cancellation. The system dynamically migrates existing audio captures to appropriate processing units, making it easier to build applications like podcasting tools, multi-participant recording, or music collaboration apps that need multiple audio inputs.</p>
<p>On iOS, Safari 26.4 adds network slicing support for WebRTC. Network slicing allows different types of traffic to be prioritized differently on cellular networks, which can improve quality and reliability for real-time communication applications in challenging network conditions.</p>
<h3><a name="resolved-issues"></a>Resolved issues</h3>
<p>Several WebRTC bugs were also fixed:</p>
<ul>
<li>Fixed <code>RTCDataChannelInit</code> to support <code>[EnforceRange]</code> on the <code>maxPacketLifeTime</code> and <code>maxRetransmits</code> fields to align with the WebRTC specification. (133630397)</li>
<li>Fixed an issue on macOS where calling <code>getUserMedia</code> with echo cancellation disabled could unintentionally affect existing audio tracks. (151143554)</li>
<li>Fixed <code>MediaStreamTrackProcessor</code> to respect <code>track.enabled = false</code>. (165199900)</li>
<li>Fixed an issue where <code>RTCDataChannel</code> close events did not fire when <code>RTCPeerConnection</code> was closed. (165617848)</li>
<li>Fixed <code>RTCConfiguration.iceServers</code> to be a non-optional sequence with an empty array as the default, improving spec compliance and ensuring <code>RTCPeerConnection</code> behaves correctly when <code>iceServers</code> is undefined. (167607478)</li>
</ul>
<h2><a name="additional-resolved-issues"></a>Additional resolved issues</h2>
<p>There are even more issues that have been fixed in Safari 26.4.</p>
<h3><a name="accessibility"></a>Accessibility</h3>
<ul>
<li>Fixed an issue where Voice Control commands could cause Safari to hang. (168364189)</li>
<li>Fixed an issue where a button&#8217;s label would not update when a descendant&#8217;s <code>aria-hidden</code> attribute changed. (169012516)</li>
<li>Fixed elements with <code>aria-controls</code> or <code>aria-expanded</code> and the <code>hidden</code> attribute to no longer appear in VoiceOver&#8217;s Form Control menu. (169499630)</li>
<li>Fixed an issue where VoiceOver would announce with extra verbosity when moving onto the first item of a list on the webpage. (169982730)</li>
<li>Fixed an issue where controls with <code>aria-labelledby</code> pointing to visually-hidden elements could not obtain proper bounding box geometry through accessibility APIs. (170639492)</li>
</ul>
<h3><a name="browser"></a>Browser</h3>
<ul>
<li>Fixed Safari gesture support to prevent pages that should not be able to scroll, such as with explicit <code>overflow: hidden</code>, from unexpectedly scrolling. (163660111)</li>
</ul>
<h3><a name="canvas"></a>Canvas</h3>
<ul>
<li>Fixed <code>ImageBitmap</code> created from SVG image sources to correctly honor the <code>flipY</code> orientation. (83959718)</li>
</ul>
<h3><a name="clipboard"></a>Clipboard</h3>
<ul>
<li>Fixed an issue where using the &#8220;Copy Image&#8221; context menu in Safari would also copy the image URL, causing some sites to paste the URL instead of the image. (76598990)</li>
</ul>
<h3><a name="editing"></a>Editing</h3>
<ul>
<li>Fixed incorrect text selection when dragging across pseudo elements. (142905243)</li>
<li>Fixed an issue on iOS 26 where the edit menu would not appear when tapping inside an already-focused text field that had a looping <code>content</code> animation. (164290305)</li>
<li>Fixed an issue where focusing a hidden editable element would incorrectly display the text cursor and selection at full opacity. (165489471)</li>
<li>Fixed a regression where dragging to select text would stop scrolling when the cursor left the window. (169983104)</li>
</ul>
<h3><a name="events"></a>Events</h3>
<ul>
<li>Fixed an issue where <code>mouseleave</code> and <code>mouseout</code> events were not dispatched when a window moved out from under a stationary cursor. (161493924)</li>
</ul>
<h3><a name="privacy"></a>Privacy</h3>
<ul>
<li>Fixed an issue where cross-browser Private Click Measurement recorded attribution entries even when &#8220;Allow privacy-preserving measurement of ad effectiveness&#8221; was disabled. (170669444)</li>
</ul>
<h3><a name="rendering"></a>Rendering</h3>
<ul>
<li>Fixed over-aggressive clipping of child layers in multicolumn layouts to prevent visual overflow issues with <code>position: relative</code> elements and <code>transform:scale()</code> text. (126413036)</li>
<li>Fixed unreadable Scroll-to-Text-Fragment highlights on dark pages. (126539910)</li>
<li>Fixed an issue where auto-positioned absolutely positioned descendants were not always marked for layout when their parent’s border box moved. (131806062)</li>
<li>Fixed an issue where positioned, transformed, or opacity-altered <code>&lt;img&gt;</code> elements with HDR JPEG gainmaps would incorrectly render in SDR. (156858374)</li>
<li>Fixed an issue on iPadOS where closing the sidebar or resizing the window could cause the page to remain zoomed in by recalculating the target scale to automatically match the new minimum scale. (157676989)</li>
<li>Fixed an issue where fixed positioned elements were not rendered correctly in right-to-left pages using the <code>vertical-rl</code> writing mode. (161712734)</li>
<li>Fixed a performance issue in layouts with long <code>pre</code> blocks and <code>word-break: break-all</code> by including whitespace in overflow width calculations. (162695099)</li>
<li>Fixed an issue where overconstrained sticky elements were not properly adjusting their insets when the sticky box rectangle was larger than the viewport. (163654023)</li>
<li>Fixed an issue where applying <code>word-spacing</code> to <code>::first-line</code> could cause other lines to disappear. (163779992)</li>
<li>Fixed inconsistent text layout when using <code>list-style-type</code> by ensuring outside list markers do not affect intrinsic width calculations. (164650313)</li>
<li>Fixed an issue where color fonts could affect the color of other DOM elements. (166631312)</li>
<li>Fixed <code>&lt;col&gt;</code> elements with <code>span &gt; 1</code> not applying their width to all spanned columns during table layout, aligning behavior with other browsers. (167225435)</li>
<li>Fixed table layout <code>min-width</code> distribution for spanning cells with mixed <code>percent</code>, <code>fixed</code>, and <code>auto</code> columns. (167684748)</li>
<li>Fixed: Improved drop-shadow and blur effects rendering performance. (169472992)</li>
</ul>
<h3><a name="spatial-web"></a>Spatial Web</h3>
<ul>
<li>Fixed auto-dimming for playback sessions in visionOS. (163824973)</li>
</ul>
<h3><a name="storage"></a>Storage</h3>
<ul>
<li>Fixed an issue where IndexedDB databases might have mismatched metadata version and database name encoding format. (163219457)</li>
</ul>
<h3><a name="wkwebview"></a>WKWebView</h3>
<ul>
<li>Fixed an issue where <code>WKWebView</code> apps with a toolbar would fail to display a top scroll edge effect when relying on automatic content inset adjustments. (161370795)</li>
</ul>
<h3><a name="web-extensions"></a>Web Extensions</h3>
<ul>
<li>Fixed an issue where <code>window.open()</code> calls from web extensions would incorrectly open &#8220;about:blank&#8221; instead of the intended URL by ensuring each extension URL loads in a fresh tab configuration. (143901129)</li>
</ul>
<h3><a name="webassembly"></a>WebAssembly</h3>
<ul>
<li>Fixed <code>Error.isError(WebAssembly.Exception)</code> to correctly return <code>false</code> based on current WebAssembly spec semantics. (167110254)</li>
</ul>
<h3><a name="webgpu"></a>WebGPU</h3>
<ul>
<li>Fixed incorrect handling of some PNG pixel formats in WebGPU. (158797747)</li>
</ul>
<h2><a name="feedback"></a>Feedback</h2>
<p>We love hearing from you. To share your thoughts, find us online: Jen Simmons on <a href="https://bsky.app/profile/jensimmons.bsky.social">Bluesky</a> / <a href="https://front-end.social/@jensimmons">Mastodon</a>, Saron Yitbarek on <a href="https://bsky.app/profile/saron.bsky.social">BlueSky</a> / <a href="https://front-end.social/@saron">Mastodon</a>, and Jon Davis on <a href="https://bsky.app/profile/jondavis.bsky.social">Bluesky</a> / <a href="https://mastodon.social/@jondavis">Mastodon</a>. You can follow WebKit <a href="https://www.linkedin.com/in/apple-webkit/">on LinkedIn</a>.</p>
<p>If you run into any issues, we welcome your <a href="https://bugs.webkit.org/">bug report</a>. Filing issues really does make a difference.</p>
<p>You can also find this information in the <a href="https://developer.apple.com/documentation/safari-release-notes/">Safari release notes</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Release Notes for Safari Technology Preview 239</title>
		<link>https://webkit.org/blog/17852/release-notes-for-safari-technology-preview-239/</link>
		
		<dc:creator/>
		<pubDate>Thu, 12 Mar 2026 21:21:57 +0000</pubDate>
				<category><![CDATA[Safari Technology Preview]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17852</guid>

					<description><![CDATA[Safari Technology Preview Release 239 is now available for download for macOS Tahoe and macOS Sequoia.]]></description>
										<content:encoded><![CDATA[<p><a href="https://webkit.org/blog/6017/introducing-safari-technology-preview/">Safari Technology Preview</a> Release 239 is now <a href="https://developer.apple.com/safari/resources/">available for download</a> 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.</p>
<p>This release includes WebKit changes between: <a href="https://github.com/WebKit/WebKit/compare/43f381aada9d3b9b13985746b74a0d6a362d3cd2...1c537b0aea640597681150878d85e1bc0bc9ab09">307619@main&#8230;308417@main</a>.</p>
<h3>Accessibility</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where SVG <code>&lt;use&gt;</code> elements referencing <code>&lt;symbol&gt;</code> elements inside an <code>&lt;img&gt;</code> were incorrectly included as unnamed images in VoiceOver&#8217;s Images web rotor. (<a href="https://commits.webkit.org/308126@main">308126@main</a>)  (98999595)</li>
<li>Fixed an issue where VoiceOver was unable to access <code>aria-owned</code> rows and their cells in grids and tables. (<a href="https://commits.webkit.org/308087@main">308087@main</a>)  (168770938)</li>
<li>Fixed an issue where VoiceOver could not find focusable splitter elements when navigating to the next or previous form control. (<a href="https://commits.webkit.org/308089@main">308089@main</a>)  (170187464)</li>
<li>Fixed an issue where controls with <code>aria-labelledby</code> did not use the native label&#8217;s geometry when both the control and its ARIA label had no visible bounding box. (<a href="https://commits.webkit.org/307727@main">307727@main</a>)  (170518900)</li>
</ul>
<h3>CSS</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>:open</code> pseudo-class for <code>&lt;input&gt;</code> elements. (<a href="https://commits.webkit.org/308148@main">308148@main</a>)  (170804152)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where tables with collapsed borders incorrectly calculated the first row width, causing excess border width to spill into the table&#8217;s margin area. (<a href="https://commits.webkit.org/308311@main">308311@main</a>)  (149675907)</li>
<li>Fixed an issue where <code>inset</code> <code>box-shadow</code> was incorrectly positioned on table cells with collapsed borders. (<a href="https://commits.webkit.org/307661@main">307661@main</a>)  (169254286)</li>
<li>Fixed an issue where <code>display: grid</code> subgrids inside <code>grid-lanes</code> containers incorrectly contributed their item intrinsic sizes to the parent&#8217;s track sizing algorithm. (<a href="https://commits.webkit.org/308253@main">308253@main</a>)  (170168798)</li>
<li>Fixed the baseline calculation for <code>inline-block</code> elements so that when <code>overflow</code> is not <code>visible</code>, the baseline is correctly set to the bottom margin edge. (<a href="https://commits.webkit.org/307718@main">307718@main</a>)  (170575015)</li>
<li>Fixed an issue where replaced elements did not correctly apply <code>min-height</code> and <code>min-width</code> constraints in certain configurations. (<a href="https://commits.webkit.org/308212@main">308212@main</a>)  (170765025)</li>
<li>Fixed an issue where children with percentage heights inside absolutely positioned elements using intrinsic height values (<code>fit-content</code>, <code>min-content</code>, <code>max-content</code>) incorrectly resolved against the containing block&#8217;s height instead of being treated as <code>auto</code>. (<a href="https://commits.webkit.org/308226@main">308226@main</a>)  (171179193)</li>
</ul>
<h3>Editing</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>execCommand('FormatBlock')</code> did not preserve inline styles of replaced block elements, causing text formatting to be lost when pasting content. (<a href="https://commits.webkit.org/308365@main">308365@main</a>)  (157657531)</li>
<li>Fixed an issue where <code>text-indent</code> flickered or was ignored on <code>contenteditable</code> elements while typing. (<a href="https://commits.webkit.org/307646@main">307646@main</a>)  (170280101)</li>
</ul>
<h3>Forms</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where a <code>readonly</code> date <code>&lt;input&gt;</code> could still be edited via keyboard using the date picker. (<a href="https://commits.webkit.org/307934@main">307934@main</a>)  (169488939)</li>
</ul>
<h3>MathML</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where dynamic changes to <code>&lt;mo&gt;</code> element attributes did not trigger a relayout. (<a href="https://commits.webkit.org/308014@main">308014@main</a>)  (170907029)</li>
<li>Fixed positioning of the <code>&lt;mprescripts&gt;</code> element within <code>&lt;mmultiscripts&gt;</code> layout. (<a href="https://commits.webkit.org/308013@main">308013@main</a>)  (170909975)</li>
<li>Fixed an issue where the MathML fraction bar was not painted when its thickness was equal to its width. (<a href="https://commits.webkit.org/308025@main">308025@main</a>)  (170934351)</li>
<li>Fixed an issue where <code>&lt;none&gt;</code> and <code>&lt;mprescripts&gt;</code> elements were not laid out as <code>&lt;mrow&gt;</code> elements in MathML. (<a href="https://commits.webkit.org/308050@main">308050@main</a>)  (170940035)</li>
</ul>
<h3>Media</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where the <code>VideoFrame</code> constructor did not handle the video color range correctly for NV12 (I420 BT601) video frames. (<a href="https://commits.webkit.org/307649@main">307649@main</a>)  (170299037)</li>
</ul>
<h3>PDF</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed a regression where form fields in PDF documents were not readable when editing in dark mode. (<a href="https://commits.webkit.org/308330@main">308330@main</a>)  (171198060)</li>
</ul>
<h3>Rendering</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where images were incorrectly stretched in certain page layouts. (<a href="https://commits.webkit.org/307751@main">307751@main</a>)  (170270187)</li>
</ul>
<h3>Scrolling</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where interrupting scroll momentum caused the scrolling container to stop rendering and hit-testing to be misplaced. (<a href="https://commits.webkit.org/308215@main">308215@main</a>)  (116205365)</li>
<li>Fixed an issue where pages could become blank and jump to the top after dynamically loading new content when scroll anchoring was enabled. (<a href="https://commits.webkit.org/308352@main">308352@main</a>)  (170889205)</li>
<li>Fixed an issue where scroll anchoring could cause pages to scroll to negative offsets. (<a href="https://commits.webkit.org/308320@main">308320@main</a>)  (171221075)</li>
</ul>
<h3>Web API</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where the <code>change</code> event was not fired on <code>&lt;input&gt;</code> and <code>&lt;textarea&gt;</code> elements when they lost focus while another application was in the foreground. (<a href="https://commits.webkit.org/308203@main">308203@main</a>)  (98526540)</li>
<li>Fixed an issue where the <code>dragend</code> event had incorrect coordinates when dragging within a nested <code>&lt;iframe&gt;</code>. (<a href="https://commits.webkit.org/308216@main">308216@main</a>)  (170750013)</li>
</ul>
<h3>Web Inspector</h3>
<h4>New Features</h4>
<ul>
<li>Added color contrast information within the Color Picker in Web Inspector. (<a href="https://commits.webkit.org/308318@main">308318@main</a>)  (113887185)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue in the Network panel where the Request / Response menu did not remember the user&#8217;s previously selected value. (<a href="https://commits.webkit.org/308142@main">308142@main</a>)  (108231795)</li>
<li>Fixed an issue in the Elements tab where &#8220;Copy HTML&#8221; only copied HTML for a single node when multiple nodes are selected. (<a href="https://commits.webkit.org/307826@main">307826@main</a>)  (169196441)</li>
</ul>
<h3>WebAssembly</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed WebAssembly streaming compilation APIs to accept the optional <code>compileOptions</code> parameter required to enable JS String builtins. (<a href="https://commits.webkit.org/308419@main">308419@main</a>)  (170989896)</li>
</ul>
<h3>WebRTC</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where <code>RTCPeerConnection.addIceCandidate()</code> did not reject when the connection was already closed. (<a href="https://commits.webkit.org/307702@main">307702@main</a>)  (170470988)</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Release Notes for Safari Technology Preview 238</title>
		<link>https://webkit.org/blog/17848/release-notes-for-safari-technology-preview-238/</link>
		
		<dc:creator/>
		<pubDate>Thu, 26 Feb 2026 22:36:22 +0000</pubDate>
				<category><![CDATA[Safari Technology Preview]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17848</guid>

					<description><![CDATA[Safari Technology Preview Release 238 is now available for download for macOS Tahoe and macOS Sequoia.]]></description>
										<content:encoded><![CDATA[<p><a href="https://webkit.org/blog/6017/introducing-safari-technology-preview/">Safari Technology Preview</a> Release 238 is now <a href="https://developer.apple.com/safari/resources/">available for download</a> 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.</p>
<p>This release includes WebKit changes between: <a href="https://github.com/WebKit/WebKit/compare/a908742cd775de5fa23dbf408618449db7f5fefb...b73f15088293cec470e0c2ceddd58bcd0b8480e5">306596@main&#8230;307618@main</a>.</p>
<h3>Animations</h3>
<h4>New Features</h4>
<ul>
<li>Enabled threaded time-based animation resolution, synchronizing accelerated time-based animations with scroll-driven animations while preserving enhanced performance by running animations off the main thread. This also allows CSS Motion Path animations to be accelerated. (<a href="https://commits.webkit.org/307252@main">307252@main</a>)  (170131323)</li>
</ul>
<h3>CSS</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the CSS <code>:open</code> pseudo-class, which matches form elements and other elements in an open state. (<a href="https://commits.webkit.org/307295@main">307295@main</a>)  (170108337)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed scrollable overflow computation for block containers to account for <code>padding-inline-end</code>, aligning with the CSS Overflow specification. (<a href="https://commits.webkit.org/307212@main">307212@main</a>)  (144312078)</li>
<li>Fixed rendering of linear gradients when all color stops are at the same position. (<a href="https://commits.webkit.org/306823@main">306823@main</a>)  (169063497)</li>
</ul>
<h3>Editing</h3>
<h4>New Features</h4>
<ul>
<li>Added menu items to convert editable text between Simplified and Traditional Chinese characters in the &#8220;Transformations&#8221; submenu. (<a href="https://commits.webkit.org/306761@main">306761@main</a>)  (156354464)</li>
</ul>
<h3>Forms</h3>
<h4>New Features</h4>
<ul>
<li>Enabled the customizable <code>&lt;select&gt;</code> element, allowing custom styling and content in <code>&lt;select&gt;</code> dropdowns using <code>appearance: base-select</code>. (<a href="https://commits.webkit.org/307548@main">307548@main</a>)  (170328089)</li>
</ul>
<h3>Networking</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where Safari&#8217;s address bar could display an internationalized domain name (IDN) homograph as a visually identical legitimate Latin domain, enabling potential phishing attacks. (<a href="https://commits.webkit.org/307005@main">307005@main</a>)  (166796168)</li>
<li>Fixed incorrect URL query percent-encoding when using non-UTF-8 character encodings such as <code>iso-8859-2</code>, <code>windows-1250</code>, and <code>gbk</code>. (<a href="https://commits.webkit.org/306768@main">306768@main</a>)  (169566553)</li>
</ul>
<h3>Rendering</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed a performance issue causing a hang when rendering tables with a large number of <code>rowspan="0"</code> cells. (<a href="https://commits.webkit.org/306891@main">306891@main</a>)  (146056348)</li>
</ul>
<h3>SVG</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed: Updated the default values of <code>fx</code> and <code>fy</code> attributes on <code>SVGRadialGradientElement</code> to <code>50%</code> to align with the SVG2 specification. (<a href="https://commits.webkit.org/306811@main">306811@main</a>)  (169645572)</li>
<li>Fixed <code>SVGAnimatedRect.baseVal</code> to ignore invalid values set on the <code>viewBox</code> attribute, such as negative width or height, aligning with Firefox and Chrome. (<a href="https://commits.webkit.org/307463@main">307463@main</a>)  (170214971)</li>
<li>Fixed SVG length attributes to reset to their default values when removed, rather than retaining previously set values. (<a href="https://commits.webkit.org/307585@main">307585@main</a>)  (170360351)</li>
</ul>
<h3>Scrolling</h3>
<h4>New Features</h4>
<ul>
<li>Enabled scroll anchoring, which prevents visible jumps in scroll position when content is inserted or removed above the viewport. (<a href="https://commits.webkit.org/307475@main">307475@main</a>)  (170279026)</li>
</ul>
<h3>Web API</h3>
<h4>New Features</h4>
<ul>
<li>Added support for <code>ReadableStream.from()</code> to create a <code>ReadableStream</code> from an async iterable or iterable. (<a href="https://commits.webkit.org/306786@main">306786@main</a>)  (169605740)</li>
<li>Added support for transferring <code>ReadableStream</code> objects via <code>postMessage()</code>. (<a href="https://commits.webkit.org/307068@main">307068@main</a>)  (169950592)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where Speculation Rules did not trigger prefetches for anchor elements that were not themselves visible but had visible descendants. (<a href="https://commits.webkit.org/306730@main">306730@main</a>)  (169561588)</li>
<li>Fixed <code>NavigateEvent.canIntercept</code> to correctly return <code>false</code> when navigating to a URL with a different port, aligning with the Navigation API specification. (<a href="https://commits.webkit.org/307316@main">307316@main</a>)  (169845691)</li>
</ul>
<h3>Web Inspector</h3>
<h4>New Features</h4>
<ul>
<li>Improved discoverability of color formats and gamuts in the color picker by adding explicit format and gamut toggle controls. (<a href="https://commits.webkit.org/306691@main">306691@main</a>)  (168216591)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where the text filter in the Sources tab did not apply to Local Overrides and Console Snippets sections. (<a href="https://commits.webkit.org/306647@main">306647@main</a>)  (169443917)</li>
<li>Fixed an issue where tree outlines in Web Inspector would intermittently show blank content while scrolling when a filter was active. (<a href="https://commits.webkit.org/306680@main">306680@main</a>)  (169502061)</li>
<li>Fixed an issue in the Timelines tab where rows containing object previews were sometimes not visible in the heap snapshot data grid. (<a href="https://commits.webkit.org/307358@main">307358@main</a>)  (170164522)</li>
<li>Fixed context menu items in the Elements tab to only display relevant options when multiple DOM nodes are selected. (<a href="https://commits.webkit.org/307485@main">307485@main</a>)  (170307979)</li>
</ul>
<h3>WebAssembly</h3>
<h4>New Features</h4>
<ul>
<li>Added support for JavaScript Promise Integration (JSPI) for WebAssembly, enabling WebAssembly code to suspend and resume execution while waiting for JavaScript promises. (<a href="https://commits.webkit.org/307404@main">307404@main</a>)  (170260385)</li>
</ul>
<h3>WebRTC</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>RTCRtpSynchronizationSource.timestamp</code> to use the correct time base, aligning with the WebRTC specification. (<a href="https://commits.webkit.org/307063@main">307063@main</a>)  (169679084)</li>
<li>Fixed <code>RTCIceCandidate.toJSON()</code> to include the <code>usernameFragment</code> field in the serialized output. (<a href="https://commits.webkit.org/306845@main">306845@main</a>)  (169679947)</li>
<li>Fixed <code>RTCRtpTransceiver.setCodecPreferences()</code> to accept codec entries regardless of the <code>mimeType</code> case, aligning with Firefox and the specification. (<a href="https://commits.webkit.org/307062@main">307062@main</a>)  (169789074)</li>
<li>Fixed <code>RTCRtpSender</code> to allow a <code>maxFramerate</code> encoding parameter value of <code>0</code>, aligning with the specification and other browsers. (<a href="https://commits.webkit.org/307034@main">307034@main</a>)  (169863687)</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Announcing Interop 2026</title>
		<link>https://webkit.org/blog/17818/announcing-interop-2026/</link>
		
		<dc:creator/>
		<pubDate>Thu, 12 Feb 2026 17:00:59 +0000</pubDate>
				<category><![CDATA[News]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17818</guid>

					<description><![CDATA[Exciting news for web developers, designers, and browser enthusiasts alike — Interop 2026 is here, continuing the mission of improving cross-browser interoperability.]]></description>
										<content:encoded><![CDATA[<p>Exciting news for web developers, designers, and browser enthusiasts alike — <a href="https://wpt.fyi/interop-2026">Interop 2026</a> is here, continuing the mission of improving cross-browser interoperability. For the fifth year in a row, we are pleased to collaborate with <a href="https://web.dev/blog/interop-2026">Google</a>, <a href="https://igalia.com/news/interop-2026.html">Igalia</a>, <a href="https://blogs.windows.com/msedgedev/2026/02/12/microsoft-edge-and-interop-2026/">Microsoft</a>, and <a href="https://hacks.mozilla.org/2026/02/launching-interop-2026/">Mozilla</a> to make web technology more consistent and reliable across our browsers.</p>
<h3><a name="introducing-interop-2026"></a>Introducing Interop 2026</h3>
<p>Making your website work in every browser can be a challenge, especially if browser engines have implemented the same web technology in slightly different ways. The Interop Project tackles this challenge by bringing the major browser engines together to improve the same set of features during the same year. Each feature is judged on whether or not it fully aligns with its official web standard — the formal technical specifications that define how each web technology should work. This helps accelerate progress toward a more reliable, consistent platform to build on.</p>
<p>Safari has already implemented many of the features included in Interop 2026. In fact, we were the first browser to ship <code>contrast-color()</code>, Media pseudo-classes, <code>shape()</code>, and Scoped Custom Element Registries. Plus, we have support for Anchor Positioning, Style Queries, Custom Highlights, Scroll Snap, View Transitions and much more. We’re excited that these technologies are being included as focus areas in Interop 2026, ensuring they get implemented across all browsers and any remaining interoperability gaps are closed.</p>
<p>We will also be focused on adding support for the following features: advanced <code>attr()</code>, the <code>getAllRecords()</code> method for IndexedDB, WebTransport, and the JavaScript Promise Integration API for Wasm. Together, these four areas make up 20% of the Interop 2026 score. They are exciting new features that solve real needs.</p>
<h3><a name="focus-areas-for-2026"></a>Focus Areas for 2026</h3>
<p>The Interop Project measures interoperability through Web Platform Tests — automated tests that check whether browsers conform to web standards. Interop 2026 is ambitious, covering twenty focus areas. Fifteen are brand new. And five are carryovers from <a href="https://wpt.fyi/interop-2025">Interop 2025</a>.</p>
<ul class="interop-index">
<li><a href="#anchor-positioning">Anchor Positioning</a></li>
<li><a href="#advanced-attr">Advanced <code>attr()</code></a></li>
<li><a href="#container-style-queries">Container Style Queries</a></li>
<li><a href="#contrast-color"><code>contrast-color()</code></a></li>
<li><a href="#css-zoom">CSS Zoom</a></li>
<li><a href="#custom-highlights">Custom Highlights</a></li>
<li><a href="#dialog-and-popover-additions">Dialog and popover additions</a></li>
<li><a href="#fetch-uploads-and-ranges">Fetch Uploads and Ranges</a></li>
<li><a href="#getallrecords-for-indexeddb"><code>getAllRecords()</code> for IndexedDB</a></li>
<li><a href="#jspi-for-wasm">JSPI for Wasm</a></li>
<li><a href="#media-pseudo-classes">Media pseudo-classes</a></li>
<li><a href="#navigation-api">Navigation API</a></li>
<li><a href="#scoped-custom-element-registries">Scoped Custom Element Registries</a></li>
<li><a href="#scroll-driven-animations">Scroll-driven Animations</a></li>
<li><a href="#scroll-snap">Scroll Snap</a></li>
<li><a href="#shape"><code>shape()</code></a></li>
<li><a href="#view-transitions">View Transitions</a></li>
<li><a href="#web-compat">Web Compat</a></li>
<li><a href="#webrtc">WebRTC</a></li>
<li><a href="#webtransport">WebTransport</a></li>
</ul>
<h2><a name="anchor-positioning"></a>Anchor positioning</h2>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Anchor_positioning">Anchor positioning</a> is a carryover from Interop 2025, where significant progress was made to empower developers to position elements relative to each other. This year’s focus will be on clarifying the spec, resolving test issues, and increasing the reliability of this powerful layout feature.</p>
<h2><a name="advanced-attr"></a>Advanced attr()</h2>
<p>The CSS <a href="https://developer.mozilla.org/docs/Web/CSS/attr"><code>attr()</code></a> function lets you bridge the gap between structural data and visual presentation by pulling values directly from HTML attributes into your CSS, making styles more dynamic and context-aware without the overhead of JavaScript. While <code>attr()</code> has long been supported for the <code>content</code> property, advanced <code>attr()</code> extends it to work across all CSS properties with type conversion — letting you use HTML attribute values as colors, lengths, angles, and other data types. Now that security concerns have been worked through in the specification, browser makers are united in our excitement to ship this long-awaited capability with strong interoperability.</p>
<h2><a name="container-style-queries"></a>Container style queries</h2>
<p>Style queries let you apply styles conditionally, based on the value of a custom property (aka, variable) as defined at a certain container. Similar to how Container size queries let your CSS respond to the size of the container, style queries let it respond to theme values, state flags, and other contextual data.</p>
<pre><code class="css"><span class="keyword">@container</span> <span class="keyword">style</span>(<span class="keyword">--theme</span>: <span class="keyword">dark</span>) {
  .<span class="attribute">card</span> {
    <span class="attribute">background</span>: <span class="string">#1a1a1a</span>;
    <span class="attribute">color</span>: <span class="string">#ffffff</span>;
  }
}
</code></pre>
<p>Style queries started shipping in recent years, including in Safari 18.0. Interop 2026 will help ensure this powerful tool works consistently everywhere.</p>
<h2><a name="contrast-color"></a>contrast-color()</h2>
<p>The <a href="https://developer.mozilla.org/docs/Web/CSS/color_value/contrast-color"><code>contrast-color()</code></a> function in CSS returns a color — either black or white. It puts the burden on the browser to choose whichever has higher contrast with the color specified in the function.</p>
<pre><code class="css"><span class="keyword builtin">.button</span> {
  <span class="attribute">background</span>: <span class="identifier">var</span>(<span class="identifier">--brand-color</span>);
  <span class="attribute">color</span>: <span class="identifier">contrast-color</span>(<span class="identifier">var</span>(<span class="identifier">--brand-color</span>));
}
</code></pre>
<p>By having the browser make the choice, you can architect your design system in a simpler fashion. You don’t need to manually define every color pairing. Safari and Firefox both shipped support in 2025, and now Interop 2026 will ensure this powerful function works consistently across all browsers.</p>
<p>Note, <code>contrast-color()</code> does not magically solve all accessibility concerns. Read about all the details in <a href="https://webkit.org/blog/16929/contrast-color/"><em>How to have the browser pick a contrasting color in CSS</em></a>.</p>
<h2><a name="css-zoom"></a>CSS Zoom</h2>
<p>The <a href="https://developer.mozilla.org/docs/Web/CSS/zoom">CSS <code>zoom</code></a> property scales an element and its contents, affecting layout and making the element take up more (or less) space. Unlike <code>transform: scale()</code>, which is purely visual, <code>zoom</code> changes how the element participates in layout.</p>
<pre><code class="css"><span class="keyword builtin">.card</span> {
  <span class="attribute">zoom</span>: <span class="number">1.5</span>; <span class="comment">/* Element is 150% larger and takes up more space */</span>
}
</code></pre>
<p>While <code>zoom</code> was supported in browsers for years as a non-standard property, it’s been plagued by inconsistencies in edge cases and how it interacts with other layout features. Now that it’s standardized, CSS zoom returns as a focus area in Interop 2026, continuing from 2025.</p>
<h2><a name="custom-highlights"></a>Custom Highlights</h2>
<p>The <a href="https://developer.mozilla.org/docs/Web/API/CSS_Custom_Highlight_API">CSS Custom Highlight API</a> lets you style arbitrary text ranges without adding extra elements to the DOM. Using JavaScript, you create a highlight range, then style it with the pseudo-elements.</p>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/::highlight"><code>::highlight()</code></a> pseudo-element is perfect for highlighting in-page search results, customizing syntax highlighting in code editors, creating an app that allows collaborative editing with user cursors, or any situation where you need to visually mark text without changing the document structure. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/::target-text"><code>::target-text</code></a> pseudo-element styles the text that’s scrolled to when a user taps a <a href="https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Fragment/Text_fragments">link with a text fragment</a>.</p>
<p>With implementations progressing across browsers, Interop 2026 ensures these highlighting capabilities work consistently, giving you reliable tools for text-based interactions.</p>
<h2><a name="dialog-and-popover-additions"></a>Dialog and popover additions</h2>
<p>The <a href="https://developer.mozilla.org/docs/Web/HTML/Element/dialog"><code>&lt;dialog&gt;</code></a> element and <a href="https://developer.mozilla.org/docs/Web/API/Popover_API">popover</a> attribute have transformed how developers build overlays on the web. Dialog was part of Interop 2022 and Popover was in Interop 2024. This year, three recent enhancements to these features make up this focus area for Interop 2026.</p>
<p>The <code>closedby</code> attribute lets you control how users can dismiss dialogs:</p>
<pre><code class="html"><span class="tag">&lt;<span class="keyword">dialog</span> <span class="keyword attribute">closedby</span>=<span class="attribute value string">"any"</span>&gt;</span>
<span class="comment">&lt;!-- Can be closed by clicking outside or pressing Escape --&gt;</span>
<span class="tag">&lt;/<span class="keyword">dialog</span>&gt;</span>
</code></pre>
<p>The <code>popover="hint"</code> attribute creates subordinate popovers that don’t dismiss other auto popovers — perfect for tooltips:</p>
<pre><code class="html"><span class="tag">&lt;<span class="keyword">div</span> <span class="keyword attribute">popover</span>=<span class="attribute value string">"hint"</span> <span class="keyword attribute">id</span>=<span class="attribute value string">"tooltip"</span>&gt;</span>
  This tooltip won’t close the menu!
<span class="tag">&lt;/<span class="keyword">div</span>&gt;</span>
</code></pre>
<p>The <code>:open</code> pseudo-class matches elements with open states, working with <code>&lt;dialog&gt;</code>, <code>&lt;details&gt;</code>, and <code>&lt;select&gt;</code>:</p>
<pre><code class="css"><span class="keyword">dialog</span><span class="preprocessor">:open</span> {
  <span class="attribute">animation</span>: <span class="identifier">slideIn</span> <span class="number">0.3s</span>;
}
</code></pre>
<p>Together, these additions make building accessible, user-friendly UI overlays easier than ever.</p>
<h2><a name="fetch-uploads-and-ranges"></a>Fetch uploads and ranges</h2>
<p>The <a href="https://developer.mozilla.org/docs/Web/API/Fetch_API"><code>fetch()</code></a> method is getting three new powerful capabilities for handling uploads and partial content.</p>
<p>ReadableStream request bodies enable true streaming uploads, letting you upload large files or real-time data without loading everything into memory first:</p>
<pre><code class="js"><span class="identifier">await</span> <span class="identifier">fetch</span>(<span class="char">'/upload'</span>, {
  <span class="identifier">method</span><span class="operator">:</span> <span class="char">'POST'</span>,
  <span class="identifier">body</span><span class="operator">:</span> <span class="identifier">readableStream</span>,
  <span class="identifier">duplex</span><span class="operator">:</span> <span class="char">'half'</span>
});
</code></pre>
<p>Enhanced <a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData">FormData</a> support improves multipart uploads and responses.</p>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Range">Range header</a> support allows partial content requests, essential for video streaming and resumable downloads:</p>
<pre><code class="js"><span class="identifier">fetch</span>(<span class="char">'/video.mp4'</span>, {
  <span class="identifier">headers</span><span class="operator">:</span> { <span class="char">'Range'</span><span class="operator">:</span> <span class="char">'bytes=0-1023'</span> }
});
</code></pre>
<p>These enhancements bring <code>fetch()</code> up to par with more specialized APIs, reducing the need for custom solutions.</p>
<h2><a name="getallrecords-for-indexeddb"></a>getAllRecords() for IndexedDB</h2>
<p><a href="https://developer.mozilla.org/docs/Web/API/IndexedDB_API">IndexedDB</a> is a low-level API that lets you store large amounts of structured data in the browser, including files and blobs. It’s been supported in browsers for <a href="https://caniuse.com/?search=indexdb">many years</a>.</p>
<p>Now, IndexedDB is getting a significant performance boost with the new <a href="https://developer.mozilla.org/docs/Web/API/IDBObjectStore/getAllRecords"><code>getAllRecords()</code></a> methods for <code>IDBObjectStore</code> and <code>IDBIndex</code>. These methods allow you to retrieve records in batches and in reverse order:</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">records</span> <span class="operator">=</span> <span class="identifier">await</span> <span class="identifier">objectStore</span>.<span class="identifier">getAllRecords</span>({
  <span class="identifier">query</span><span class="operator">:</span> <span class="identifier">IDBKeyRange</span>.<span class="identifier">bound</span>(<span class="char">'A'</span>, <span class="char">'M'</span>),
  <span class="identifier">count</span><span class="operator">:</span> <span class="number">100</span>,
  <span class="identifier">direction</span><span class="operator">:</span> <span class="char">'prev'</span>
});
</code></pre>
<p>It’s just this new method that’s being included in Interop 2026. The score only reports the percentage of <code>getAllRecords()</code> tests that are passing  — not all IndexDB tests.</p>
<h2><a name="jspi-for-wasm"></a>JSPI for Wasm</h2>
<p><a href="https://webassembly.org/">WebAssembly</a> has opened the door for running high-performance applications in the browser — games, productivity tools, scientific simulations, and more. But there’s been a fundamental mismatch. Many of these applications were originally written for environments where operations like file I/O or network requests are synchronous (blocking), while the web is fundamentally asynchronous.</p>
<p>The <a href="https://v8.dev/blog/jspi">JavaScript Promise Integration API (JSPI)</a> bridges this gap. It lets WebAssembly code that expects synchronous operations work smoothly with JavaScript’s Promise-based async APIs, without requiring you to rewrite the entire application. This means you can port existing C, C++, or Rust applications to the web more easily, unlocking a wider range of software that can run in the browser.</p>
<p>Interop 2026 will ensure JSPI works consistently across browsers, making WebAssembly a more viable platform for complex applications.</p>
<h2><a name="media-pseudo-classes"></a>Media pseudo-classes</h2>
<p>We’ve proposed media pseudo-classes for inclusion in the Interop Project for many years in a row. We are excited that it’s being included this year!</p>
<p>Seven CSS pseudo-classes let you apply CSS based on the playback state of <code>&lt;audio&gt;</code> and <code>&lt;video&gt;</code> elements:</p>
<ul>
<li><a href="https://developer.mozilla.org/docs/Web/CSS/:playing"><code>:playing</code></a> — media is currently playing</li>
<li><a href="https://developer.mozilla.org/docs/Web/CSS/:paused"><code>:paused</code></a> — media is paused</li>
<li><a href="https://developer.mozilla.org/docs/Web/CSS/:seeking"><code>:seeking</code></a> — user is seeking to a new position</li>
<li><a href="https://developer.mozilla.org/docs/Web/CSS/:buffering"><code>:buffering</code></a> — media is buffering</li>
<li><a href="https://developer.mozilla.org/docs/Web/CSS/:stalled"><code>:stalled</code></a> — playback has stalled</li>
<li><a href="https://developer.mozilla.org/docs/Web/CSS/:muted"><code>:muted</code></a> — audio is muted</li>
<li><a href="https://developer.mozilla.org/docs/Web/CSS/:volume-locked"><code>:volume-locked</code></a> — volume cannot be changed</li>
</ul>
<p>These all shipped in Safari many years ago, but without support in any other browser, most developers don’t use them — or even know they exist. Instead developers need JavaScript to sync UI state with media playback state.</p>
<p>It’s far simpler and more efficient to use media state pseudo-classes in CSS.</p>
<pre><code class="css"><span class="keyword">video</span><span class="preprocessor">:buffering</span>::<span class="keyword">after</span> {
  <span class="attribute">content</span>: <span class="string">"Loading..."</span>;
}
<span class="keyword">audio</span><span class="preprocessor">:muted</span> {
  <span class="attribute">opacity</span>: <span class="number">0.5</span>;
}
</code></pre>
<p>They are especially powerful combined with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:has"><code>:has()</code></a>, since it unlocks the ability to style anything on the page based on playback state, not just elements that are descendants of the media player.</p>
<pre><code class="css"><span class="keyword">article</span><span class="preprocessor">:has</span>(<span class="keyword">video</span><span class="preprocessor">:playing</span>) {
  <span class="attribute">background-color</span>: <span class="identifier">var</span>(<span class="identifier">--backgroundColor</span>); 
  <span class="attribute">color</span>: <span class="identifier">contrast-color</span>(<span class="identifier">var</span>(<span class="identifier">--backgroundColor</span>));
  <span class="attribute">transition</span>: <span class="identifier">background-color</span> <span class="number">0.5s</span> <span class="identifier">ease</span>;
}
</code></pre>
<p>Learn more about the power of <code>:has()</code> in <em><a href="https://webkit.org/blog/13096/css-has-pseudo-class/">Using :has() as a CSS Parent Selector and much more</a></em>.</p>
<h2><a name="navigation-api"></a>Navigation API</h2>
<p>If you’ve built single-page applications, you may have experienced the pain of managing navigation state with <code>history.pushState()</code> and <code>popstate</code> events. <a href="https://developer.mozilla.org/docs/Web/API/Navigation_API">Navigation API</a> gives you a cleaner, more powerful way to intercept and control navigation.</p>
<p>This focus area is a continuation of Interop 2025, where significant progress was made to empower developers to initiate, intercept, and modify browser navigation actions. This year continues work on interoperability, to get the overall score up from the 92.3% test pass result during Interop 2025. Plus, there’s one new feature being added — the <a href="https://developer.mozilla.org/en-US/docs/Web/API/NavigationPrecommitController"><code>precommitHandler</code></a> option. It lets you defer navigation until critical resources are ready, preventing jarring flashes of incomplete content.</p>
<pre><code class="js"><span class="identifier">navigation</span>.<span class="identifier">addEventListener</span>(<span class="char">'navigate'</span>, (<span class="identifier">e</span>) <span class="operator">=</span><span class="operator">&gt;</span> {
  <span class="identifier">e</span>.<span class="identifier">intercept</span>({
    <span class="identifier">async</span> <span class="identifier">precommitHandler</span>() {
      <span class="comment">// Load critical resources before commit
</span>      <span class="identifier">await</span> <span class="identifier">loadCriticalData</span>();
    },
    <span class="identifier">async</span> <span class="identifier">handler</span>() {
      <span class="comment">// Render the new view
</span>      <span class="identifier">renderPage</span>();
    }
  });
});
</code></pre>
<p>Interop 2026 will ensure Navigation API works reliably across browsers, a solid foundation for web applications.</p>
<h2><a name="scoped-custom-element-registries"></a>Scoped custom element registries</h2>
<p>Working with web components, you may have run into a frustrating limitation: the global <code>customElements</code> registry only allows one definition per tag name across your entire application. When two different libraries both define a <code>&lt;my-button&gt;</code> component, they conflict.</p>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry"><code>CustomElementRegistry()</code></a> constructor solves this by letting you create scoped registries. Different parts of your application — or different shadow roots — can have their own definitions for the same tag name.</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">registry</span> <span class="operator">=</span> <span class="keyword operator">new</span> <span class="identifier">CustomElementRegistry</span>();
<span class="identifier">registry</span>.<span class="identifier">define</span>(<span class="char">'my-button'</span>, <span class="identifier">MyButtonV2</span>);
<span class="identifier">shadowRoot</span>.<span class="identifier">registry</span> <span class="operator">=</span> <span class="identifier">registry</span>;
</code></pre>
<p>This is especially valuable for microfrontends, component libraries, and any situation where you’re integrating third-party web components.</p>
<p>Safari 26.0 was the first <a href="https://caniuse.com/wf-scoped-custom-element-registries">browser to ship</a> Scoped custom element registries. Inclusion in Interop 2026 will help ensure this capability works consistently across all browsers.</p>
<h2><a name="scroll-driven-animations"></a>Scroll-driven Animations</h2>
<p><a href="https://developer.mozilla.org/docs/Web/CSS/CSS_scroll-driven_animations">Scroll-driven animations</a> let you more easily create animations that respond to scroll position, now entirely in CSS. As a user scrolls, the animation progresses — no JavaScript needed. You can build scroll-triggered reveals, progress indicators, parallax effects, and interactive storytelling experiences.</p>
<p>Define animations with standard CSS keyframes, then connect them to scroll using <code>animation-timeline</code>:</p>
<pre><code class="css"><span class="keyword builtin">.reveal</span> {
  <span class="attribute">animation</span>: <span class="identifier">fade-in</span> <span class="identifier">linear</span> <span class="identifier">forwards</span>;
  <span class="attribute">animation-timeline</span>: <span class="identifier">view</span>();
  <span class="attribute">animation-range</span>: <span class="identifier">entry</span> <span class="number">0%</span> <span class="identifier">entry</span> <span class="number">100%</span>;
}

<span class="keyword">@keyframes</span> <span class="keyword">fade-in</span> {
  <span class="attribute">from</span> { <span class="attribute">opacity</span>: <span class="number">0</span>; }
  <span class="keyword">to</span> { <span class="attribute">opacity</span>: <span class="number">1</span>; }
}
</code></pre>
<p>Use <code>view()</code> to trigger animations as elements enter and exit the viewport, or <code>scroll()</code> to tie animations to a scrolling container’s position. Learn much more in <a href="https://webkit.org/blog/17101/a-guide-to-scroll-driven-animations-with-just-css/"><em>A guide to Scroll-driven Animations with just CSS</em></a><em>.</em></p>
<p>We shipped support for scroll-driven animations in Safari 26.0. Interop 2026 will help ensure this feature works consistently across all browsers.</p>
<h2><a name="scroll-snap"></a>Scroll Snap</h2>
<p><a href="https://developer.mozilla.org/docs/Web/CSS/CSS_scroll_snap">CSS Scroll Snap</a> controls the panning and scrolling behavior within a scroll container, creating carousel-like experiences:</p>
<pre><code class="css"><span class="keyword builtin">.carousel</span> {
  <span class="attribute">scroll-snap-type</span>: <span class="identifier">x</span> <span class="identifier">mandatory</span>;
  <span class="attribute">overflow-x</span>: <span class="identifier">scroll</span>;
}
<span class="keyword builtin">.carousel</span> &gt; * {
  <span class="attribute">scroll-snap-align</span>: <span class="identifier">center</span>;
}
</code></pre>
<p>Scroll Snap has been <a href="https://caniuse.com/css-snappoints">supported</a> in all modern browsers for many years. But like many of the older CSS specifications, multiple rounds of changes to the specification while early versions were already shipping in browsers created a deep lack of interoperability. With a far more mature web standard, it’s time to circle back and improve interoperability. This is the power of the Interop Project — focusing all the browser teams on a particular feature, and using automated tests to find inconsistencies and disagreements.</p>
<h2><a name="shape"></a>shape()</h2>
<p>For years, when you wanted to create a complex clipping path to use with <code>clip-path</code> or <code>shape-outside</code> you’ve been limited to <code>polygon()</code>, which only supports straight lines, or SVG paths, which aren’t responsive to element size changes.</p>
<p>Now, the <a href="https://developer.mozilla.org/docs/Web/CSS/basic-shape/shape"><code>shape()</code></a> function lets you create complex shapes with path-like commands (<code>move</code>, <code>line</code>, <code>curve</code>). It gives you the best of both worlds — curves like SVG paths, but with percentage-based coordinates that adapt as elements resize.</p>
<pre><code class="css"><span class="keyword builtin">.element</span> {
  <span class="attribute">clip-path</span>: <span class="identifier">shape</span>(
    <span class="identifier">from</span> <span class="number">0%</span> <span class="number">0%</span>,
    <span class="identifier">line</span> <span class="identifier">to</span> <span class="number">100%</span> <span class="number">0%</span>,
    <span class="identifier">line</span> <span class="identifier">to</span> <span class="number">100%</span> <span class="number">100%</span>,
    <span class="identifier">curve</span> <span class="identifier">to</span> <span class="number">0%</span> <span class="number">100%</span> <span class="identifier">via</span> <span class="number">50%</span> <span class="number">150%</span>,
    <span class="identifier">close</span>
  );
}
</code></pre>
<p>We shipped support for the <code>shape()</code> function in Safari 18.4. And we look forward to Interop 2026 improving browser implementations so you can confidently use it to render of complex, responsive curves.</p>
<h2><a name="view-transitions"></a>View transitions</h2>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API">View Transitions</a> was a focus area in Interop 2025, narrowly defined to include <a href="https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API">same-document view transitions</a> and <code>view-transition-class</code>. These features allow for smooth, animated transitions between UI states within a single page, as well as flexible control over styling those transitions.</p>
<p>While Safari finished Interop 2025 with a score of 99.2% for view transitions, the overall interoperability score is at 90.8% — so the group decided to continue the effort, carrying over the tests from 2025.</p>
<p>For Interop 2026, the focus area expands to also include <a href="https://webkit.org/blog/16967/two-lines-of-cross-document-view-transitions-code-you-can-use-on-every-website-today/">cross-document view transitions</a>. This allows you to create smooth, animated transitions in the moments between pages as users navigate your site, rather than an abrupt jump when new page loads. Cross-document view transitions shipped in Safari 18.2. Learn more about it in <a href="https://webkit.org/blog/16967/two-lines-of-cross-document-view-transitions-code-you-can-use-on-every-website-today/"><em>Two lines of Cross-Document View Transitions code you can use on every website today</em></a>.</p>
<h2><a name="web-compat"></a>Web Compat</h2>
<p>Web compatibility refers to whether or not a real world website works correctly in a particular browser. When a site works in one browser, but not another — that’s a “compat” problem. This focus area is made up of a small collection of Web Platform Tests selected because the fact they fail in some browsers causes real websites to not work <em>in other browsers</em> — thus creating problems for both web developers and users.</p>
<p>Each time Web Compat has been a focus area as part of the Interop Project, it’s targeted a different set of compat challenges. This year, Interop 2026’s web compatibility work includes:</p>
<ul>
<li><a href="https://tc39.es/ecma262/#cyclic-module-record">ESM module loading</a>, ensuring cyclic module records and multiple top-level awaits work consistently.</li>
<li><a href="https://html.spec.whatwg.org/#event-loop-processing-model">Timing of scroll events relative to animation events</a>, used to make sure scroll and animation events fire in a predictable, interoperable order.</li>
<li>Support for <a href="https://developer.mozilla.org/docs/Web/CSS/user-select"><code>user-select</code></a>, rather than just <code>-webkit-user-select</code>. It controls whether users can select text. </li>
</ul>
<h2><a name="webrtc"></a>WebRTC</h2>
<p><a href="https://developer.mozilla.org/docs/Web/API/WebRTC_API">WebRTC</a> (Web Real-Time Communication) enables real-time audio, video, and data communication directly between browsers, without requiring plugins or intermediate servers. You can build video conferencing apps, live streaming platforms, peer-to-peer file sharing, and collaborative tools.</p>
<p>Having reached a 91.6% pass rate, WebRTC continues as a focus area in 2026, building on the progress made during Interop 2025. We’re looking forward to fixing the long tail of interop issues of the main spec for WebRTC.</p>
<h2><a name="webtransport"></a>WebTransport</h2>
<p><a href="https://developer.mozilla.org/docs/Web/API/WebTransport_API">WebTransport</a> provides a modern way to transmit data between client and server using the HTTP/3 protocol. It gives you low-latency bidirectional communication with multiple streams over a single connection. You get both unreliable datagram support (like UDP) for speed and reliable stream support (like TCP) for guaranteed delivery.</p>
<pre><code class="js"><span class="keyword type">const</span> <span class="identifier">transport</span> <span class="operator">=</span> <span class="keyword operator">new</span> <span class="identifier">WebTransport</span>(<span class="char">'https://example.com/endpoint'</span>);
<span class="identifier">await</span> <span class="identifier">transport</span>.<span class="identifier">ready</span>;
<span class="keyword type">const</span> <span class="identifier">stream</span> <span class="operator">=</span> <span class="identifier">await</span> <span class="identifier">transport</span>.<span class="identifier">createBidirectionalStream</span>();
<span class="comment">// Stream data efficiently
</span></code></pre>
<p>WebTransport is ideal for gaming, real-time collaboration tools, and applications where you need more control than WebSocket provides but don’t want to manage WebRTC’s complexity. Being part of Interop 2026 ensures WebTransport works consistently across all browsers, making it a reliable choice for real-time data transmission.</p>
<h2><a name="investigation-efforts-a-look-ahead"></a>Investigation Efforts: A Look Ahead</h2>
<p>In addition to the focus areas, the Interop Project includes four investigation areas. These are projects where teams gather to assess the current state of testing infrastructure and sort through issues that are blocking progress.</p>
<h3><a name="accessibility-testing"></a>Accessibility testing</h3>
<p>Continuing from previous years, the Accessibility Testing investigation aims to work towards generating consistent accessibility trees across browsers. This effort will improve the WPT testing infrastructure for accessibility on top of the foundation from Interop 2024. This work ensures that accessibility features are reliable and consistent, helping developers create more inclusive web experiences.</p>
<h3><a name="jpeg-xl"></a>JPEG XL</h3>
<p><a href="https://jpegxl.info/">JPEG XL</a> is a next-generation raster graphics format that supports animation, alpha transparency, and lossy as well as lossless compression. We shipped support for it in Safari 17.0. This investigation will focus on making the feature properly testable by developing comprehensive test suites, opening up the possibility that JPEG XL could be a focus area in the future.</p>
<h3><a name="mobile-testing"></a>Mobile testing</h3>
<p>The Mobile Testing investigation continues work started in 2025. This year, we will focus on improving infrastructure for mobile-specific features like dynamic viewport changes which are crucial for building responsive mobile web experience that billions of users rely on every day.</p>
<h3><a name="webvtt"></a>WebVTT</h3>
<p>Continuing from 2025, the WebVTT investigation addresses a critical challenge facing the web platform. Developers cite WebVTT’s inconsistent behavior across browsers as a major reason for choosing other subtitling and captioning solutions. Our investment in WebVTT last year primarily consisted of validating and fixing the existing test suite, as well as making any necessary spec changes along the way.  We are excited to continue that effort this year to ensure synchronized text tracks and closed captioning work seamlessly across the web.</p>
<h2><a name="a-more-interoperable-web"></a>A more interoperable web</h2>
<p>Interop 2026 brings together twenty focus areas that matter to you as a web developer. Some, like <code>attr()</code> and <code>contrast-color()</code>, give you more flexible ways to architect your CSS. Others, like Scroll-Driven Animations and View Transitions, let you create smoother, more engaging experiences without reaching for JavaScript. Features like WebTransport and the Navigation API give you more powerful tools for building modern web applications.</p>
<p>Just as important are the focus areas working to fix long-standing inconsistencies — ensuring Scroll Snap works reliably, bringing all browsers up to speed on <code>shape()</code>, and solving real-world compatibility problems that have been frustrating developers and breaking sites.</p>
<p>The WebKit team is committed to making these features work consistently across all browsers. Whether you’re building a design system, a single-page application, a video streaming platform, or anything in between, Interop 2026 is working to give you a more reliable foundation to build on.</p>
<p>Here’s to another year of making the web better, together!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Release Notes for Safari Technology Preview 237</title>
		<link>https://webkit.org/blog/17842/release-notes-for-safari-technology-preview-237/</link>
		
		<dc:creator/>
		<pubDate>Thu, 12 Feb 2026 16:59:49 +0000</pubDate>
				<category><![CDATA[Safari Technology Preview]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17842</guid>

					<description><![CDATA[Safari Technology Preview Release 237 is now available for download for macOS Tahoe and macOS Sequoia.]]></description>
										<content:encoded><![CDATA[<p><a href="https://webkit.org/blog/6017/introducing-safari-technology-preview/">Safari Technology Preview</a> Release 237 is now <a href="https://developer.apple.com/safari/resources/">available for download</a> 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.</p>
<p>This release includes WebKit changes between: <a href="https://github.com/WebKit/WebKit/compare/aaeffadb0b6313d7188ebc636446532d1d459c2b...caed0239ff1d606ff67879ac662c1ae83c4aec9a">305774@main&#8230;306595@main</a>.</p>
<h3>Accessibility</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed slot elements referenced by <code>aria-labelledby</code> to correctly use their assigned slotted content for accessible names and ignore hidden slotted nodes. (<a href="https://commits.webkit.org/305882@main">305882@main</a>)  (114500560)</li>
<li>Fixed <code>&lt;meter&gt;</code> element to have consistent labels between <code>aria-label</code> and <code>title</code> attributes. (<a href="https://commits.webkit.org/305883@main">305883@main</a>)  (127460695)</li>
<li>Fixed elements with <code>display: contents</code> and content in a shadow root to have their content properly read when referenced by <code>aria-labelledby</code>. (<a href="https://commits.webkit.org/305918@main">305918@main</a>)  (129361833)</li>
<li>Fixed <code>aria-labelledby</code> to use the checkbox name instead of its value when the checkbox name comes from an associated <code>&lt;label&gt;</code> element. (<a href="https://commits.webkit.org/305894@main">305894@main</a>)  (141564913)</li>
<li>Fixed grid elements with child rows in a shadow root to properly work with VoiceOver. (<a href="https://commits.webkit.org/306159@main">306159@main</a>)  (153134654)</li>
<li>Fixed elements with <code>aria-controls</code> or <code>aria-expanded</code> and the <code>hidden</code> attribute to no longer appear in VoiceOver&#8217;s Form Control menu. (<a href="https://commits.webkit.org/305902@main">305902@main</a>)  (162783041)</li>
<li>Fixed <code>::first-letter</code> text not being exposed in the accessibility tree when no other text accompanies it. (<a href="https://commits.webkit.org/305884@main">305884@main</a>)  (168458291)</li>
</ul>
<h3>CSS</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>:heading</code> pseudo-class selector. (<a href="https://commits.webkit.org/306151@main">306151@main</a>)  (158759228)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed CSS rules within <code>@scope</code> not being applied to <code>&lt;input&gt;</code> and <code>&lt;textarea&gt;</code> elements. (<a href="https://commits.webkit.org/306129@main">306129@main</a>)  (168101378)</li>
<li>Fixed dynamic <code>flow-tolerance</code> changes to trigger relayout for <code>display: grid-lanes</code>. (<a href="https://commits.webkit.org/306093@main">306093@main</a>)  (168711707)</li>
</ul>
<h3>DOM</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>offsetX</code> and <code>offsetY</code> for SVG elements to use the outermost SVG as the base for coordinate calculation. (<a href="https://commits.webkit.org/305993@main">305993@main</a>)  (168548585)</li>
</ul>
<h3>HTML</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>source</code> attribute on <code>ToggleEvent</code> interface. (<a href="https://commits.webkit.org/306152@main">306152@main</a>)  (152580641)</li>
</ul>
<h3>Networking</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>X-Frame-Options</code> to only strip tab or space characters, not vertical tabs. (<a href="https://commits.webkit.org/306279@main">306279@main</a>)  (126915315)</li>
<li>Fixed range request validation to properly handle HTTP 416 (Requested Range Not Satisfiable) responses. (<a href="https://commits.webkit.org/305866@main">305866@main</a>)  (168487440)</li>
</ul>
<h3>Rendering</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed table rendering for rowspanned cells and bottom border color. (<a href="https://commits.webkit.org/306471@main">306471@main</a>)  (94163960)</li>
<li>Fixed <code>&lt;marquee&gt;</code> elements causing incorrect table width calculations. (<a href="https://commits.webkit.org/306059@main">306059@main</a>)  (99826593)</li>
<li>Fixed table layout to properly handle <code>visibility: collapse</code> on columns. (<a href="https://commits.webkit.org/305997@main">305997@main</a>)  (168556786)</li>
<li>Fixed intrinsic sizing for absolutely positioned replaced elements. (<a href="https://commits.webkit.org/306309@main">306309@main</a>)  (168815514)</li>
<li>Fixed percentage padding in table cells to resolve against column widths. (<a href="https://commits.webkit.org/306281@main">306281@main</a>)  (168940907)</li>
<li>Fixed table height distribution to apply to tbody sections instead of only the first section. (<a href="https://commits.webkit.org/306457@main">306457@main</a>)  (169154677)</li>
</ul>
<h3>SVG</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>color-interpolation</code> attribute for SVG gradients. (<a href="https://commits.webkit.org/305921@main">305921@main</a>)  (87294645)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed <code>:visited</code> link color to properly propagate to SVG through <code>currentColor</code>. (<a href="https://commits.webkit.org/306387@main">306387@main</a>)  (98776770)</li>
<li>Fixed removing an item from <code>SVGTransformList</code> to properly allow attribute removal. (<a href="https://commits.webkit.org/306162@main">306162@main</a>)  (117840533)</li>
</ul>
<h3>Web API</h3>
<h4>New Features</h4>
<ul>
<li>Added support for async iteration over <code>ReadableStream</code> objects using <code>for await...of</code> loops. (<a href="https://commits.webkit.org/305808@main">305808@main</a>)  (168049382)</li>
<li>Added support for the Service Worker static routing Resource Timing API. (<a href="https://commits.webkit.org/306006@main">306006@main</a>)  (168499249)</li>
<li>Added <code>srgb-linear</code> and <code>display-p3-linear</code> to <code>PredefinedColorSpace</code>. (<a href="https://commits.webkit.org/306563@main">306563@main</a>)  (169340732)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed Content Security Policy to only recognize ASCII whitespace excluding vertical tabs to align with the specification. (<a href="https://commits.webkit.org/306222@main">306222@main</a>)  (108559413)</li>
<li>Fixed emoji input on Google Docs and similar web applications by supressing keypress events for supplementary characters. (<a href="https://commits.webkit.org/305914@main">305914@main</a>)  (122678873)</li>
<li>Fixed an issue where selecting credentials in the Digital Credentials API sometimes required a second click to trigger verification. (<a href="https://commits.webkit.org/305868@main">305868@main</a>)  (163295172)</li>
<li>Fixed window bar visibility properties (<code>toolbar.visible</code>, <code>statusbar.visible</code>, <code>menubar.visible</code>) to return static values per the HTML specification for privacy and interoperability. (<a href="https://commits.webkit.org/306391@main">306391@main</a>)  (166554327)</li>
<li>Fixed <code>layerX</code> and <code>layerY</code> to return correct values with CSS transforms. (<a href="https://commits.webkit.org/306300@main">306300@main</a>)  (168968832)</li>
</ul>
<h3>Web Authentication</h3>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue in Safari Technology Preview where WebAuthn authentication over NFC failed. (<a href="https://commits.webkit.org/306280@main">306280@main</a>)  (168456474)</li>
</ul>
<h3>Web Extensions</h3>
<h4>New Features</h4>
<ul>
<li>Added support for <code>runtime.getDocumentId()</code> web extension API. (<a href="https://commits.webkit.org/305912@main">305912@main</a>)  (168060269)</li>
</ul>
<h3>Web Inspector</h3>
<h4>New Features</h4>
<ul>
<li>Added support to show each individual request when there are redirects in the Network tab. (<a href="https://commits.webkit.org/306537@main">306537@main</a>)  (152606018)</li>
</ul>
<h4>Resolved Issues</h4>
<ul>
<li>Fixed an issue where a large number of search results in the Search tab would freeze Web Inspector. (<a href="https://commits.webkit.org/306429@main">306429@main</a>)  (49234522)</li>
</ul>
<h3>WebRTC</h3>
<h4>New Features</h4>
<ul>
<li>Added support for the <code>targetLatency</code> attribute in WebRTC. (<a href="https://commits.webkit.org/306062@main">306062@main</a>)  (168225793)</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WebKit features for Safari 26.3</title>
		<link>https://webkit.org/blog/17798/webkit-features-for-safari-26-3/</link>
		
		<dc:creator/>
		<pubDate>Wed, 11 Feb 2026 18:00:49 +0000</pubDate>
				<category><![CDATA[News]]></category>
		<guid isPermaLink="false">https://webkit.org/?p=17798</guid>

					<description><![CDATA[Safari 26.3 is here, with practical improvements for performance and user experience.]]></description>
										<content:encoded><![CDATA[<p>Safari 26.3 is here, with practical improvements for performance and user experience. This release gives you new tools for optimizing how your content is delivered and better control over navigation in single-page applications. We’ve also fixed issues developers have run into with anchor positioning, multi-column layouts, and other features — making them more robust and reliable. Plus, we’ve refined the everyday browsing experience by fixing issues we found while testing real websites.</p>
<h3>Video in visionOS</h3>
<p>Now in Safari 26.3 in visionOS, fullscreen video playback automatically dims the user’s surroundings to help put the focus on content.</p>
<figure><img loading="lazy" decoding="async" src="https://webkit.org/wp-content/uploads/world_around_video_dimmed_Safari263_visionOS.png" alt="A floating rectangular image of a dog running at a dog show, covered by the site &quot;The Ultimate Spectacular&quot;. This rectangle is floating in a world covered by sandy hills, with mountains in the background, and a big cloudy sky above. This is a 3D environment in visionOS. The image is a video that&#039;s full brightness, while the environment around it is not as bright as normal. It&#039;s dimmed." width="1920" height="1080" class="aligncenter size-full wp-image-17799 preserve-color" srcset="https://webkit.org/wp-content/uploads/world_around_video_dimmed_Safari263_visionOS.png 1920w, https://webkit.org/wp-content/uploads/world_around_video_dimmed_Safari263_visionOS-300x169.png 300w, https://webkit.org/wp-content/uploads/world_around_video_dimmed_Safari263_visionOS-1024x576.png 1024w, https://webkit.org/wp-content/uploads/world_around_video_dimmed_Safari263_visionOS-768x432.png 768w, https://webkit.org/wp-content/uploads/world_around_video_dimmed_Safari263_visionOS-1536x864.png 1536w" sizes="auto, (max-width: 1920px) 100vw, 1920px" /><figcaption>Now when a user plays a video in Safari (like <a href="https://www.youtube.com/watch?v=Z6wnDWzhaDA">this trailer</a> on YouTube for <a href="https://tv.apple.com/us/show/top-dogs/umc.cmc.6snqtei46tkkch7odsnoq9nac"><i>Top Dogs</I></a>) and enters fullscreen, the world around the video is dimmed in visionOS 26.3.</figcaption></figure>
<h2>Zstandard</h2>
<p>Safari 26.3 supports Zstandard (Zstd), a compression algorithm you can use to make your website’s files smaller before sending them to browsers. Like gzip and Brotli, it compresses text-based assets — HTML, CSS, JavaScript, JSON, and SVG — so less data travels over the network.</p>
<p>Zstandard decompresses quickly, reducing the workload on users’ devices. It also compresses fast enough to do on-the-fly, whereas Brotli is typically pre-compressed during your build process.</p>
<p>To use it, configure your server to compress responses with Zstandard and send the <code>Content-Encoding: zstd</code> header. Servers will automatically fall back to other compression methods for browsers that don’t have support yet.</p>
<p>Zstandard support is available in Safari 26.3 on iOS 26.3, iPadOS 26.3, visionOS 26.3, and macOS Tahoe 26.3 — and not in Safari 26.3 on earlier versions of macOS. This is because support comes from the system networking stack used by Safari.</p>
<h2>Navigation API</h2>
<p>When building single-page applications with the Navigation API, you might need a reliable way to cancel ongoing work when a navigation gets interrupted. Maybe the user clicked another link before the previous navigation finished, they hit the back button, or your code called <code>navigation.navigate()</code> again. Whatever the reason, you don’t want to keep processing a navigation that&#8217;s no longer relevant.</p>
<p>In Safari 26.3, the Navigation API exposes a <code>AbortSignal</code> on <code>NavigateEvent</code> which triggers when the navigation is aborted, giving you a standard way to clean up and cancel work:</p>
<pre><code class="js"><span class="identifier">navigation</span>.<span class="identifier">addEventListener</span>(<span class="char">'navigate'</span>, (<span class="identifier">event</span>) <span class="operator">=</span><span class="operator">&gt;</span> {
  <span class="identifier">event</span>.<span class="identifier">intercept</span>({
    <span class="identifier">async</span> <span class="identifier">handler</span>() {
      <span class="keyword type">const</span> <span class="identifier">response</span> <span class="operator">=</span> <span class="identifier">await</span> <span class="identifier">fetch</span>(<span class="char">'/api/data'</span>, {
        <span class="identifier">signal</span><span class="operator">:</span> <span class="identifier">event</span>.<span class="identifier">signal</span>  <span class="comment">// Automatically cancels if navigation is aborted
</span>      });

      <span class="keyword type">const</span> <span class="identifier">data</span> <span class="operator">=</span> <span class="identifier">await</span> <span class="identifier">response</span>.<span class="identifier">json</span>();
      <span class="identifier">renderContent</span>(<span class="identifier">data</span>);
    }
  });
});
</code></pre>
<p>If the user navigates away before the fetch completes, the request automatically cancels. You can also listen to the signal’s <code>abort</code> event to clean up other resources like timers or animations.</p>
<p>This gives you fine-grained control over what happens when navigations don’t complete, helping you avoid memory leaks and unnecessary work.</p>
<h2>Bug fixes and more</h2>
<p>Along with the new features, WebKit for Safari 26.3 includes additional improvements to existing features.</p>
<h3>CSS</h3>
<ul>
<li>Fixed a style resolution loop that occurred when a <code>position-try</code> box was inside a <code>display: none</code> ancestor. (163691885)</li>
<li>Fixed an issue where anchor-positioned elements repeatedly transitioning from <code>display: block</code> to <code>display: none</code> cause position jumps during animation. (163862003)</li>
<li>Fixed an issue where <code>fixed</code>-positioned boxes using <code>position-area</code> were incorrectly included in the scrollable containing block calculation. (164017310)</li>
<li>Fixed an issue where <code>text-decoration: underline</code> was rendered too high when <code>text-box-trim</code> was applied to the root inline box. (165945326)</li>
<li>Fixed a multi-column layout issue where the <code>widows</code> and <code>text-indent</code> properties are applied cause an incorrect indent on the portion of the paragraph that flows into the next column. (165945497)</li>
<li>Fixed an issue where CSS cursors like <code>move</code>, <code>all-scroll</code>, <code>ew-resize</code>, and <code>ns-resize</code> did not display correctly. (166731882)</li>
</ul>
<h3>DOM</h3>
<ul>
<li>Fixed incorrect timestamp handling and switched to use the raw touch timestamp. (164262652)</li>
</ul>
<h3>Media</h3>
<ul>
<li>Fixed an issue where the fullscreen button in visionOS inline video controls did not visually indicate interactivity by extending the glow effect to all <code>button.circular</code> elements. (164259201)</li>
<li>Fixed Video Viewer mode for <code>iframe</code> videos on macOS. (164484608)</li>
<li>Fixed an issue where Safari could not play live videos when the <code>sourceBuffer</code> content is removed and re-added causing the seek to not complete. (165628836)</li>
</ul>
<h3>Rendering</h3>
<ul>
<li>Fixed an issue where positioned or transformed <code>&lt;img&gt;</code> elements containing HDR JPEGs with gain maps would incorrectly render as SDR. (163517157)</li>
</ul>
<h3>Safe Browsing</h3>
<ul>
<li>Fixed a bug where if Safe Browsing queried for an entry on the Public Suffix List, and a Safe Browsing vendor responded that the whole effective TLD was unsafe, the whole site would be marked as unsafe. (168155375)</li>
</ul>
<h2>Feedback</h2>
<p>We love hearing from you. To share your thoughts, find us online: Jen Simmons on <a href="https://bsky.app/profile/jensimmons.bsky.social">Bluesky</a> / <a href="https://front-end.social/@jensimmons">Mastodon</a>, Saron Yitbarek on <a href="https://bsky.app/profile/saron.bsky.social">BlueSky</a> / <a href="https://front-end.social/@saron">Mastodon</a>, and Jon Davis on <a href="https://bsky.app/profile/jondavis.bsky.social">Bluesky</a> / <a href="https://mastodon.social/@jondavis">Mastodon</a>. You can follow WebKit <a href="https://www.linkedin.com/in/apple-webkit/">on LinkedIn</a>.</p>
<p>If you run into any issues, we welcome your <a href="https://bugs.webkit.org/">bug report</a>. Filing issues really does make a difference.</p>
<p>You can also find this information in the <a href="https://developer.apple.com/documentation/safari-release-notes/">Safari release notes</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>