WebKit Open Source Web Browser Engine 2026-03-12T21:39:38Z https://webkit.org/feed/atom/ WordPress <![CDATA[Release Notes for Safari Technology Preview 239]]> https://webkit.org/?p=17852 2026-03-12T21:39:38Z 2026-03-12T21:21:57Z Safari Technology Preview Release 239 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 307619@main…308417@main.

Accessibility

Resolved Issues

  • Fixed an issue where SVG <use> elements referencing <symbol> elements inside an <img> were incorrectly included as unnamed images in VoiceOver’s Images web rotor. (308126@main) (98999595)
  • Fixed an issue where VoiceOver was unable to access aria-owned rows and their cells in grids and tables. (308087@main) (168770938)
  • Fixed an issue where VoiceOver could not find focusable splitter elements when navigating to the next or previous form control. (308089@main) (170187464)
  • Fixed an issue where controls with aria-labelledby did not use the native label’s geometry when both the control and its ARIA label had no visible bounding box. (307727@main) (170518900)

CSS

New Features

  • Added support for the :open pseudo-class for <input> elements. (308148@main) (170804152)

Resolved Issues

  • Fixed an issue where tables with collapsed borders incorrectly calculated the first row width, causing excess border width to spill into the table’s margin area. (308311@main) (149675907)
  • Fixed an issue where inset box-shadow was incorrectly positioned on table cells with collapsed borders. (307661@main) (169254286)
  • Fixed an issue where display: grid subgrids inside grid-lanes containers incorrectly contributed their item intrinsic sizes to the parent’s track sizing algorithm. (308253@main) (170168798)
  • Fixed the baseline calculation for inline-block elements so that when overflow is not visible, the baseline is correctly set to the bottom margin edge. (307718@main) (170575015)
  • Fixed an issue where replaced elements did not correctly apply min-height and min-width constraints in certain configurations. (308212@main) (170765025)
  • Fixed an issue where children with percentage heights inside absolutely positioned elements using intrinsic height values (fit-content, min-content, max-content) incorrectly resolved against the containing block’s height instead of being treated as auto. (308226@main) (171179193)

Editing

Resolved Issues

  • Fixed an issue where execCommand('FormatBlock') did not preserve inline styles of replaced block elements, causing text formatting to be lost when pasting content. (308365@main) (157657531)
  • Fixed an issue where text-indent flickered or was ignored on contenteditable elements while typing. (307646@main) (170280101)

Forms

Resolved Issues

  • Fixed an issue where a readonly date <input> could still be edited via keyboard using the date picker. (307934@main) (169488939)

MathML

Resolved Issues

  • Fixed an issue where dynamic changes to <mo> element attributes did not trigger a relayout. (308014@main) (170907029)
  • Fixed positioning of the <mprescripts> element within <mmultiscripts> layout. (308013@main) (170909975)
  • Fixed an issue where the MathML fraction bar was not painted when its thickness was equal to its width. (308025@main) (170934351)
  • Fixed an issue where <none> and <mprescripts> elements were not laid out as <mrow> elements in MathML. (308050@main) (170940035)

Media

Resolved Issues

  • Fixed an issue where the VideoFrame constructor did not handle the video color range correctly for NV12 (I420 BT601) video frames. (307649@main) (170299037)

PDF

Resolved Issues

  • Fixed a regression where form fields in PDF documents were not readable when editing in dark mode. (308330@main) (171198060)

Rendering

Resolved Issues

  • Fixed an issue where images were incorrectly stretched in certain page layouts. (307751@main) (170270187)

Scrolling

Resolved Issues

  • Fixed an issue where interrupting scroll momentum caused the scrolling container to stop rendering and hit-testing to be misplaced. (308215@main) (116205365)
  • Fixed an issue where pages could become blank and jump to the top after dynamically loading new content when scroll anchoring was enabled. (308352@main) (170889205)
  • Fixed an issue where scroll anchoring could cause pages to scroll to negative offsets. (308320@main) (171221075)

Web API

Resolved Issues

  • Fixed an issue where the change event was not fired on <input> and <textarea> elements when they lost focus while another application was in the foreground. (308203@main) (98526540)
  • Fixed an issue where the dragend event had incorrect coordinates when dragging within a nested <iframe>. (308216@main) (170750013)

Web Inspector

New Features

  • Added color contrast information within the Color Picker in Web Inspector. (308318@main) (113887185)

Resolved Issues

  • Fixed an issue in the Network panel where the Request / Response menu did not remember the user’s previously selected value. (308142@main) (108231795)
  • Fixed an issue in the Elements tab where “Copy HTML” only copied HTML for a single node when multiple nodes are selected. (307826@main) (169196441)

WebAssembly

Resolved Issues

  • Fixed WebAssembly streaming compilation APIs to accept the optional compileOptions parameter required to enable JS String builtins. (308419@main) (170989896)

WebRTC

Resolved Issues

  • Fixed an issue where RTCPeerConnection.addIceCandidate() did not reject when the connection was already closed. (307702@main) (170470988)
]]>
<![CDATA[Release Notes for Safari Technology Preview 238]]> https://webkit.org/?p=17848 2026-02-26T22:36:22Z 2026-02-26T22:36:22Z Safari Technology Preview Release 238 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 306596@main…307618@main.

Animations

New Features

  • 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. (307252@main) (170131323)

CSS

New Features

  • Added support for the CSS :open pseudo-class, which matches form elements and other elements in an open state. (307295@main) (170108337)

Resolved Issues

  • Fixed scrollable overflow computation for block containers to account for padding-inline-end, aligning with the CSS Overflow specification. (307212@main) (144312078)
  • Fixed rendering of linear gradients when all color stops are at the same position. (306823@main) (169063497)

Editing

New Features

  • Added menu items to convert editable text between Simplified and Traditional Chinese characters in the “Transformations” submenu. (306761@main) (156354464)

Forms

New Features

  • Enabled the customizable <select> element, allowing custom styling and content in <select> dropdowns using appearance: base-select. (307548@main) (170328089)

Networking

Resolved Issues

  • Fixed an issue where Safari’s address bar could display an internationalized domain name (IDN) homograph as a visually identical legitimate Latin domain, enabling potential phishing attacks. (307005@main) (166796168)
  • Fixed incorrect URL query percent-encoding when using non-UTF-8 character encodings such as iso-8859-2, windows-1250, and gbk. (306768@main) (169566553)

Rendering

Resolved Issues

  • Fixed a performance issue causing a hang when rendering tables with a large number of rowspan="0" cells. (306891@main) (146056348)

SVG

Resolved Issues

  • Fixed: Updated the default values of fx and fy attributes on SVGRadialGradientElement to 50% to align with the SVG2 specification. (306811@main) (169645572)
  • Fixed SVGAnimatedRect.baseVal to ignore invalid values set on the viewBox attribute, such as negative width or height, aligning with Firefox and Chrome. (307463@main) (170214971)
  • Fixed SVG length attributes to reset to their default values when removed, rather than retaining previously set values. (307585@main) (170360351)

Scrolling

New Features

  • Enabled scroll anchoring, which prevents visible jumps in scroll position when content is inserted or removed above the viewport. (307475@main) (170279026)

Web API

New Features

  • Added support for ReadableStream.from() to create a ReadableStream from an async iterable or iterable. (306786@main) (169605740)
  • Added support for transferring ReadableStream objects via postMessage(). (307068@main) (169950592)

Resolved Issues

  • Fixed an issue where Speculation Rules did not trigger prefetches for anchor elements that were not themselves visible but had visible descendants. (306730@main) (169561588)
  • Fixed NavigateEvent.canIntercept to correctly return false when navigating to a URL with a different port, aligning with the Navigation API specification. (307316@main) (169845691)

Web Inspector

New Features

  • Improved discoverability of color formats and gamuts in the color picker by adding explicit format and gamut toggle controls. (306691@main) (168216591)

Resolved Issues

  • Fixed an issue where the text filter in the Sources tab did not apply to Local Overrides and Console Snippets sections. (306647@main) (169443917)
  • Fixed an issue where tree outlines in Web Inspector would intermittently show blank content while scrolling when a filter was active. (306680@main) (169502061)
  • Fixed an issue in the Timelines tab where rows containing object previews were sometimes not visible in the heap snapshot data grid. (307358@main) (170164522)
  • Fixed context menu items in the Elements tab to only display relevant options when multiple DOM nodes are selected. (307485@main) (170307979)

WebAssembly

New Features

  • Added support for JavaScript Promise Integration (JSPI) for WebAssembly, enabling WebAssembly code to suspend and resume execution while waiting for JavaScript promises. (307404@main) (170260385)

WebRTC

Resolved Issues

  • Fixed RTCRtpSynchronizationSource.timestamp to use the correct time base, aligning with the WebRTC specification. (307063@main) (169679084)
  • Fixed RTCIceCandidate.toJSON() to include the usernameFragment field in the serialized output. (306845@main) (169679947)
  • Fixed RTCRtpTransceiver.setCodecPreferences() to accept codec entries regardless of the mimeType case, aligning with Firefox and the specification. (307062@main) (169789074)
  • Fixed RTCRtpSender to allow a maxFramerate encoding parameter value of 0, aligning with the specification and other browsers. (307034@main) (169863687)
]]>
<![CDATA[Announcing Interop 2026]]> https://webkit.org/?p=17818 2026-03-05T00:18:00Z 2026-02-12T17:00:59Z Exciting news for web developers, designers, and browser enthusiasts alike — Interop 2026 is here, continuing the mission of improving cross-browser interoperability. For the fifth year in a row, we are pleased to collaborate with Google, Igalia, Microsoft, and Mozilla to make web technology more consistent and reliable across our browsers.

Introducing Interop 2026

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.

Safari has already implemented many of the features included in Interop 2026. In fact, we were the first browser to ship contrast-color(), Media pseudo-classes, shape(), 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.

We will also be focused on adding support for the following features: advanced attr(), the getAllRecords() 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.

Focus Areas for 2026

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 Interop 2025.

Anchor positioning

Anchor positioning 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.

Advanced attr()

The CSS attr() 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 attr() has long been supported for the content property, advanced attr() 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.

Container style queries

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.

@container style(--theme: dark) {
  .card {
    background: #1a1a1a;
    color: #ffffff;
  }
}

Style queries started shipping in recent years, including in Safari 18.0. Interop 2026 will help ensure this powerful tool works consistently everywhere.

contrast-color()

The contrast-color() 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.

.button {
  background: var(--brand-color);
  color: contrast-color(var(--brand-color));
}

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.

Note, contrast-color() does not magically solve all accessibility concerns. Read about all the details in How to have the browser pick a contrasting color in CSS.

CSS Zoom

The CSS zoom property scales an element and its contents, affecting layout and making the element take up more (or less) space. Unlike transform: scale(), which is purely visual, zoom changes how the element participates in layout.

.card {
  zoom: 1.5; /* Element is 150% larger and takes up more space */
}

While zoom 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.

Custom Highlights

The CSS Custom Highlight API 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.

The ::highlight() 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 ::target-text pseudo-element styles the text that’s scrolled to when a user taps a link with a text fragment.

With implementations progressing across browsers, Interop 2026 ensures these highlighting capabilities work consistently, giving you reliable tools for text-based interactions.

Dialog and popover additions

The <dialog> element and popover 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.

The closedby attribute lets you control how users can dismiss dialogs:

<dialog closedby="any">
<!-- Can be closed by clicking outside or pressing Escape -->
</dialog>

The popover="hint" attribute creates subordinate popovers that don’t dismiss other auto popovers — perfect for tooltips:

<div popover="hint" id="tooltip">
  This tooltip won’t close the menu!
</div>

The :open pseudo-class matches elements with open states, working with <dialog>, <details>, and <select>:

dialog:open {
  animation: slideIn 0.3s;
}

Together, these additions make building accessible, user-friendly UI overlays easier than ever.

Fetch uploads and ranges

The fetch() method is getting three new powerful capabilities for handling uploads and partial content.

ReadableStream request bodies enable true streaming uploads, letting you upload large files or real-time data without loading everything into memory first:

await fetch('/upload', {
  method: 'POST',
  body: readableStream,
  duplex: 'half'
});

Enhanced FormData support improves multipart uploads and responses.

Range header support allows partial content requests, essential for video streaming and resumable downloads:

fetch('/video.mp4', {
  headers: { 'Range': 'bytes=0-1023' }
});

These enhancements bring fetch() up to par with more specialized APIs, reducing the need for custom solutions.

getAllRecords() for IndexedDB

IndexedDB 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 many years.

Now, IndexedDB is getting a significant performance boost with the new getAllRecords() methods for IDBObjectStore and IDBIndex. These methods allow you to retrieve records in batches and in reverse order:

const records = await objectStore.getAllRecords({
  query: IDBKeyRange.bound('A', 'M'),
  count: 100,
  direction: 'prev'
});

It’s just this new method that’s being included in Interop 2026. The score only reports the percentage of getAllRecords() tests that are passing — not all IndexDB tests.

JSPI for Wasm

WebAssembly 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.

The JavaScript Promise Integration API (JSPI) 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.

Interop 2026 will ensure JSPI works consistently across browsers, making WebAssembly a more viable platform for complex applications.

Media pseudo-classes

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!

Seven CSS pseudo-classes let you apply CSS based on the playback state of <audio> and <video> elements:

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.

It’s far simpler and more efficient to use media state pseudo-classes in CSS.

video:buffering::after {
  content: "Loading...";
}
audio:muted {
  opacity: 0.5;
}

They are especially powerful combined with :has(), 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.

article:has(video:playing) {
  background-color: var(--backgroundColor); 
  color: contrast-color(var(--backgroundColor));
  transition: background-color 0.5s ease;
}

Learn more about the power of :has() in Using :has() as a CSS Parent Selector and much more.

Navigation API

If you’ve built single-page applications, you may have experienced the pain of managing navigation state with history.pushState() and popstate events. Navigation API gives you a cleaner, more powerful way to intercept and control navigation.

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 precommitHandler option. It lets you defer navigation until critical resources are ready, preventing jarring flashes of incomplete content.

navigation.addEventListener('navigate', (e) => {
  e.intercept({
    async precommitHandler() {
      // Load critical resources before commit
      await loadCriticalData();
    },
    async handler() {
      // Render the new view
      renderPage();
    }
  });
});

Interop 2026 will ensure Navigation API works reliably across browsers, a solid foundation for web applications.

Scoped custom element registries

Working with web components, you may have run into a frustrating limitation: the global customElements registry only allows one definition per tag name across your entire application. When two different libraries both define a <my-button> component, they conflict.

The CustomElementRegistry() 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.

const registry = new CustomElementRegistry();
registry.define('my-button', MyButtonV2);
shadowRoot.registry = registry;

This is especially valuable for microfrontends, component libraries, and any situation where you’re integrating third-party web components.

Safari 26.0 was the first browser to ship Scoped custom element registries. Inclusion in Interop 2026 will help ensure this capability works consistently across all browsers.

Scroll-driven Animations

Scroll-driven animations 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.

Define animations with standard CSS keyframes, then connect them to scroll using animation-timeline:

.reveal {
  animation: fade-in linear forwards;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

Use view() to trigger animations as elements enter and exit the viewport, or scroll() to tie animations to a scrolling container’s position. Learn much more in A guide to Scroll-driven Animations with just CSS.

We shipped support for scroll-driven animations in Safari 26.0. Interop 2026 will help ensure this feature works consistently across all browsers.

Scroll Snap

CSS Scroll Snap controls the panning and scrolling behavior within a scroll container, creating carousel-like experiences:

.carousel {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
}
.carousel > * {
  scroll-snap-align: center;
}

Scroll Snap has been supported 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.

shape()

For years, when you wanted to create a complex clipping path to use with clip-path or shape-outside you’ve been limited to polygon(), which only supports straight lines, or SVG paths, which aren’t responsive to element size changes.

Now, the shape() function lets you create complex shapes with path-like commands (move, line, curve). It gives you the best of both worlds — curves like SVG paths, but with percentage-based coordinates that adapt as elements resize.

.element {
  clip-path: shape(
    from 0% 0%,
    line to 100% 0%,
    line to 100% 100%,
    curve to 0% 100% via 50% 150%,
    close
  );
}

We shipped support for the shape() 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.

View transitions

View Transitions was a focus area in Interop 2025, narrowly defined to include same-document view transitions and view-transition-class. These features allow for smooth, animated transitions between UI states within a single page, as well as flexible control over styling those transitions.

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.

For Interop 2026, the focus area expands to also include cross-document view transitions. 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 Two lines of Cross-Document View Transitions code you can use on every website today.

Web Compat

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 in other browsers — thus creating problems for both web developers and users.

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:

WebRTC

WebRTC (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.

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.

WebTransport

WebTransport 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.

const transport = new WebTransport('https://example.com/endpoint');
await transport.ready;
const stream = await transport.createBidirectionalStream();
// Stream data efficiently

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.

Investigation Efforts: A Look Ahead

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.

Accessibility testing

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.

JPEG XL

JPEG XL 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.

Mobile testing

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.

WebVTT

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.

A more interoperable web

Interop 2026 brings together twenty focus areas that matter to you as a web developer. Some, like attr() and contrast-color(), 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.

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 shape(), and solving real-world compatibility problems that have been frustrating developers and breaking sites.

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.

Here’s to another year of making the web better, together!

]]>
<![CDATA[Release Notes for Safari Technology Preview 237]]> https://webkit.org/?p=17842 2026-02-12T18:41:31Z 2026-02-12T16:59:49Z Safari Technology Preview Release 237 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 305774@main…306595@main.

Accessibility

Resolved Issues

  • Fixed slot elements referenced by aria-labelledby to correctly use their assigned slotted content for accessible names and ignore hidden slotted nodes. (305882@main) (114500560)
  • Fixed <meter> element to have consistent labels between aria-label and title attributes. (305883@main) (127460695)
  • Fixed elements with display: contents and content in a shadow root to have their content properly read when referenced by aria-labelledby. (305918@main) (129361833)
  • Fixed aria-labelledby to use the checkbox name instead of its value when the checkbox name comes from an associated <label> element. (305894@main) (141564913)
  • Fixed grid elements with child rows in a shadow root to properly work with VoiceOver. (306159@main) (153134654)
  • Fixed elements with aria-controls or aria-expanded and the hidden attribute to no longer appear in VoiceOver’s Form Control menu. (305902@main) (162783041)
  • Fixed ::first-letter text not being exposed in the accessibility tree when no other text accompanies it. (305884@main) (168458291)

CSS

New Features

  • Added support for the :heading pseudo-class selector. (306151@main) (158759228)

Resolved Issues

  • Fixed CSS rules within @scope not being applied to <input> and <textarea> elements. (306129@main) (168101378)
  • Fixed dynamic flow-tolerance changes to trigger relayout for display: grid-lanes. (306093@main) (168711707)

DOM

Resolved Issues

  • Fixed offsetX and offsetY for SVG elements to use the outermost SVG as the base for coordinate calculation. (305993@main) (168548585)

HTML

New Features

  • Added support for the source attribute on ToggleEvent interface. (306152@main) (152580641)

Networking

Resolved Issues

  • Fixed X-Frame-Options to only strip tab or space characters, not vertical tabs. (306279@main) (126915315)
  • Fixed range request validation to properly handle HTTP 416 (Requested Range Not Satisfiable) responses. (305866@main) (168487440)

Rendering

Resolved Issues

  • Fixed table rendering for rowspanned cells and bottom border color. (306471@main) (94163960)
  • Fixed <marquee> elements causing incorrect table width calculations. (306059@main) (99826593)
  • Fixed table layout to properly handle visibility: collapse on columns. (305997@main) (168556786)
  • Fixed intrinsic sizing for absolutely positioned replaced elements. (306309@main) (168815514)
  • Fixed percentage padding in table cells to resolve against column widths. (306281@main) (168940907)
  • Fixed table height distribution to apply to tbody sections instead of only the first section. (306457@main) (169154677)

SVG

New Features

  • Added support for the color-interpolation attribute for SVG gradients. (305921@main) (87294645)

Resolved Issues

  • Fixed :visited link color to properly propagate to SVG through currentColor. (306387@main) (98776770)
  • Fixed removing an item from SVGTransformList to properly allow attribute removal. (306162@main) (117840533)

Web API

New Features

  • Added support for async iteration over ReadableStream objects using for await...of loops. (305808@main) (168049382)
  • Added support for the Service Worker static routing Resource Timing API. (306006@main) (168499249)
  • Added srgb-linear and display-p3-linear to PredefinedColorSpace. (306563@main) (169340732)

Resolved Issues

  • Fixed Content Security Policy to only recognize ASCII whitespace excluding vertical tabs to align with the specification. (306222@main) (108559413)
  • Fixed emoji input on Google Docs and similar web applications by supressing keypress events for supplementary characters. (305914@main) (122678873)
  • Fixed an issue where selecting credentials in the Digital Credentials API sometimes required a second click to trigger verification. (305868@main) (163295172)
  • Fixed window bar visibility properties (toolbar.visible, statusbar.visible, menubar.visible) to return static values per the HTML specification for privacy and interoperability. (306391@main) (166554327)
  • Fixed layerX and layerY to return correct values with CSS transforms. (306300@main) (168968832)

Web Authentication

Resolved Issues

  • Fixed an issue in Safari Technology Preview where WebAuthn authentication over NFC failed. (306280@main) (168456474)

Web Extensions

New Features

  • Added support for runtime.getDocumentId() web extension API. (305912@main) (168060269)

Web Inspector

New Features

  • Added support to show each individual request when there are redirects in the Network tab. (306537@main) (152606018)

Resolved Issues

  • Fixed an issue where a large number of search results in the Search tab would freeze Web Inspector. (306429@main) (49234522)

WebRTC

New Features

  • Added support for the targetLatency attribute in WebRTC. (306062@main) (168225793)
]]>
<![CDATA[WebKit features for Safari 26.3]]> https://webkit.org/?p=17798 2026-02-11T22:25:43Z 2026-02-11T18:00:49Z 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.

Video in visionOS

Now in Safari 26.3 in visionOS, fullscreen video playback automatically dims the user’s surroundings to help put the focus on content.

A floating rectangular image of a dog running at a dog show, covered by the site "The Ultimate Spectacular". 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's full brightness, while the environment around it is not as bright as normal. It's dimmed.
Now when a user plays a video in Safari (like this trailer on YouTube for Top Dogs) and enters fullscreen, the world around the video is dimmed in visionOS 26.3.

Zstandard

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.

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.

To use it, configure your server to compress responses with Zstandard and send the Content-Encoding: zstd header. Servers will automatically fall back to other compression methods for browsers that don’t have support yet.

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.

Navigation API

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 navigation.navigate() again. Whatever the reason, you don’t want to keep processing a navigation that’s no longer relevant.

In Safari 26.3, the Navigation API exposes a AbortSignal on NavigateEvent which triggers when the navigation is aborted, giving you a standard way to clean up and cancel work:

navigation.addEventListener('navigate', (event) => {
  event.intercept({
    async handler() {
      const response = await fetch('/api/data', {
        signal: event.signal  // Automatically cancels if navigation is aborted
      });

      const data = await response.json();
      renderContent(data);
    }
  });
});

If the user navigates away before the fetch completes, the request automatically cancels. You can also listen to the signal’s abort event to clean up other resources like timers or animations.

This gives you fine-grained control over what happens when navigations don’t complete, helping you avoid memory leaks and unnecessary work.

Bug fixes and more

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

CSS

  • Fixed a style resolution loop that occurred when a position-try box was inside a display: none ancestor. (163691885)
  • Fixed an issue where anchor-positioned elements repeatedly transitioning from display: block to display: none cause position jumps during animation. (163862003)
  • Fixed an issue where fixed-positioned boxes using position-area were incorrectly included in the scrollable containing block calculation. (164017310)
  • Fixed an issue where text-decoration: underline was rendered too high when text-box-trim was applied to the root inline box. (165945326)
  • Fixed a multi-column layout issue where the widows and text-indent properties are applied cause an incorrect indent on the portion of the paragraph that flows into the next column. (165945497)
  • Fixed an issue where CSS cursors like move, all-scroll, ew-resize, and ns-resize did not display correctly. (166731882)

DOM

  • Fixed incorrect timestamp handling and switched to use the raw touch timestamp. (164262652)

Media

  • Fixed an issue where the fullscreen button in visionOS inline video controls did not visually indicate interactivity by extending the glow effect to all button.circular elements. (164259201)
  • Fixed Video Viewer mode for iframe videos on macOS. (164484608)
  • Fixed an issue where Safari could not play live videos when the sourceBuffer content is removed and re-added causing the seek to not complete. (165628836)

Rendering

  • Fixed an issue where positioned or transformed <img> elements containing HDR JPEGs with gain maps would incorrectly render as SDR. (163517157)

Safe Browsing

  • 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)

Feedback

We love hearing from you. To share your thoughts, find us online: Jen Simmons on Bluesky / Mastodon, Saron Yitbarek on BlueSky / Mastodon, and Jon Davis on Bluesky / Mastodon. You can follow WebKit on LinkedIn.

If you run into any issues, we welcome your bug report. Filing issues really does make a difference.

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

]]>
<![CDATA[Interop 2025: A year of convergence]]> https://webkit.org/?p=17808 2026-02-09T21:26:06Z 2026-02-06T17:45:28Z Interop 2025 has come to a close, and the results speak for themselves. Now in its fourth year, the Interop project brings together Apple, Bocoup, Google, Igalia, Microsoft, and Mozilla to identify the areas of the web platform where interoperability matters most to you as a web developer — and then do the work to get there. This year was the most ambitious yet: the group selected 19 focus areas and 5 investigation areas spanning CSS, JavaScript, Web APIs, and performance. At the start of 2025, only 29% of the selected tests passed across all browsers. By the end of the year, the Interop score reached a 97% pass rate — and all four experimental browsers (Chrome Canary, Edge Dev, Firefox Nightly, and Safari Technology Preview) reached 99%.

Interop 2025 end of year results. Chrome Canary, Edge Dev, Firefox Nightly, and Safari Technology Preview all have a score of 99%. The overall interop score is 97%.

Each year, the Interop project chooses its focus areas through a collaborative process with proposals, research into what web developers need, and debates about priorities. For Interop 2025, our team advocated for including focus areas that we knew would require significant engineering investment from WebKit — because we knew those areas would make a real difference to you. The results show that commitment paid off. Safari made the largest jump of any browser this year, climbing from 43 to 99.

As always, this year’s focus areas were chosen based on developer feedback, including results from the State of CSS survey, and we’re proud of how much ground we covered. The 19 focus areas touched nearly every corner of the platform. On the CSS and UI side, the project tackled Anchor Positioning, View Transitions, @scope, backdrop-filter, text-decoration, Writing modes, Layout (both Flexbox and Grid, continued from prior years), and the <details> element. For APIs and platform features, we worked on the Navigation API, Storage Access API, URLPattern, Modules, the scrollend event, WebRTC, and WebAssembly. And on the health and compatibility front, there was focused work on Core Web Vitals, Pointer and Mouse events, removing Mutation events, and general web compatibility. Five investigation areas — accessibility testing, Gamepad API testing, mobile testing, privacy testing, and WebVTT — laid groundwork for future Interop cycles.

We want to highlight three focus areas that were especially meaningful this year.

  • Anchor positioning lets you position popovers, tooltips, and menus relative to any element purely in CSS — no JavaScript positioning libraries required. It’s one of the most requested CSS features of the last several years, and it now works interoperably across all browsers.
  • Same-document View Transitions allow smooth, animated transitions between UI states natively in the browser, along with the new view-transition-class CSS property for flexible styling of those transitions. We shipped support in fall 2024, in Safari 18.0 and Safari 18.2. Web developers are excited about View Transitions! This extra attention on interoperability across browsers means it’s ready for you to use.
  • Navigation API — a modern replacement for history.pushState() — gives single-page applications proper navigation handling with interception, traversal, and entries. We shipped support in Safari 26.2, and we’re glad to see it arrive interoperably from the start.
The graphs of scores across the year. A black line shows the overall interoperability rising from around 30% in January to 97% at the end. A blue line representing Safari's progress rises from 43% to be the best score at the top in December, almost at 100%. Orange representing Firefox starts just above Safari, and also follows a similar trajectory across the year. Edge and Chrome have kind of flat progress, starting around 80 and converging with all the other lines at the top at the end.

The graph above tells the story of the year: every browser engine invested heavily, and the lines converge at the top. That convergence is what makes the Interop project so valuable — the shared progress that means you can write code once and trust that it works everywhere.

We want to thank our colleagues across the industry who made this possible. Interoperability is one of the foundational strengths of the web, and we remain committed to this collaboration. You can explore the full results, including scores for each individual focus area, on the Interop 2025 dashboard.

]]>
<![CDATA[Release Notes for Safari Technology Preview 236]]> https://webkit.org/?p=17791 2026-02-03T16:52:01Z 2026-02-03T00:08:11Z Safari Technology Preview Release 236 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 305084@main…305413@main.

CSS

Resolved Issues

  • Fixed handling of padding and margins for flex and grid layouts across all writing modes. (301814@main) (71046552)
  • Fixed text-combine-upright to properly ignore letter-spacing when composing text horizontally, aligning with the CSS Writing Modes specification. (305116@main) (116562622)
  • Fixed an issue where background-blend-mode was not applied correctly when combined with background-clip: text. (305118@main) (120901898)
  • Fixed an issue where CSS @starting-style entry animations were only applied on the first transition, especially when interacting with anchor positioning or position fallbacks. (305371@main) (163928932)
  • Fixed table column width distribution when a colspan spans mixed percentage and auto-width columns to properly respect percentage constraints. (305120@main) (165561401)
  • Fixed an issue where shape-outside did not update correctly after web fonts loaded. (305299@main) (166336491)
  • Fixed table height calculation to correctly account for captions with orthogonal writing-mode. (305110@main) (167220730)
  • Fixed an issue where grid-lanes items incorrectly used a grid area as their containing block in the stacking axis, ensuring proper sizing for cases like fit-content and percentage-based dimensions. (305319@main) (167221488)
  • Fixed counter-* properties serialization order. (305086@main) (167518994)
  • Fixed outline-width and outline-offset to follow updated computed style resolution rules. (305153@main) (167618367)
  • Fixed the computed style resolution for border-*-width properties. (305212@main) (167689519)
  • Fixed the computed style resolution for the column-rule-width property. (305240@main) (167725940)
  • Fixed border-*-width, outline-width, and column-rule-width so they now pixel snap correctly during CSS animations and transitions. (305272@main) (167763497)

Forms

Resolved Issues

  • Fixed an issue where input[type="search"] fields with appearance: none incorrectly reserved space for the datalist dropdown button. (305314@main) (166754216)
  • Fixed an incorrect fallback for the menu style for empty lists, improving readability and correctness. (305228@main) (167662316)

HTML

New Features

  • Added support for using the min(), max(), and clamp() math functions in the sizes attribute of <img> elements. (305226@main) (167526292)

Resolved Issues

  • Fixed an issue where nested about:blank frames were incorrectly treated as self-referencing, preventing them from loading. (305404@main) (148373033)

Images

Resolved Issues

  • Fixed image uploading to not transcode images when accept="image/*" is specified. (305283@main) (166124206)

Media

Resolved Issues

  • Fixed an issue where <video> poster images were incorrectly double-scaled when zoom was applied by using the cached intrinsic poster size without reapplying zoom. (305347@main) (150976146)
  • Fixed an issue where the macOS inline media controls timeline scrubber overlapped the right container buttons. (305177@main) (167634241)

Rendering

Resolved Issues

  • Fixed an issue where auto-positioned absolutely positioned descendants were not always marked for layout when their parent’s border box moved. (305229@main) (131806062)
  • Fixed an issue where color fonts could affect the color of other DOM elements. (305254@main) (166631312)
  • Fixed an issue by disabling CoreGraphics blur and drop-shadow filters due to system framework bugs and reverting the previous workaround. (305216@main) (166631624)
  • Fixed <col> elements with span > 1 not applying their width to all spanned columns during table layout, aligning behavior with other browsers. (305113@main) (167225435)
  • Fixed table layout min-width distribution for spanning cells with mixed percent, fixed, and auto columns. (305215@main) (167684748)

SVG

Resolved Issues

  • Fixed breaking SVG resource referencing when removing a resource which shares its id with other resources. (305197@main) (147015037)
  • Fixed <clipPath> to clip to its <use> child element based on the visibility of the <use> target element. (305374@main) (167491519)
  • Fixed displaying an SVG filter referencing an element with a huge stroke. (305136@main) (167516452)
  • Fixed hit testing for overlapping <text> and <tspan> elements in SVG. (305221@main) (167691166)

Web API

Resolved Issues

  • Fixed DeviceMotionEvent and DeviceOrientationEvent interfaces so that they only show up in secure contexts just like the corresponding events and made ondevicemotion and ondeviceorientation enumerable, aligning with the specification. (305266@main) (44804273)
  • Fixed handling of unknown DigitalCredential protocols by gracefully filtering them out and showing a console warning instead of throwing an error. (305257@main) (166673454)

WebRTC

Resolved Issues

  • Fixed RTCConfiguration.iceServers to be a non-optional sequence with an empty array as the default, improving spec compliance and ensuring RTCPeerConnection behaves correctly when iceServers is undefined. (305152@main) (167607478)
]]>
<![CDATA[When will CSS Grid Lanes arrive? How long until we can use it?]]> https://webkit.org/?p=17758 2026-01-30T00:37:53Z 2026-01-22T10:00:30Z Anytime an exciting new web technology starts to land in browsers, developers want to know “when in the world am I going to be able to use this?”

Currently, the finalized syntax for Grid Lanes is available in Safari Technology Preview. Edge, Chrome and Firefox have all made significant progress on their implementations, so it’s going to arrive sooner than you think.

Plus, you can start using it as soon as you want with progressive enhancement. This article will show you how.

Web page of content items — each item is a group with an image, headline and text inside a card with rounded corners. The page is in a browser window on the left, with a layout created with Grid Lanes. The items have different aspect ratios, and nestle together into columns, where all of the content for each item can be seen. On the right, is another browser window with the same content — this time laid out in columns again, but also rows. In order for the items to fit into the rows, the photos have all been cropped into squares, the headlines are truncated to fit onto one line, and the teaser descriptions are all chopped to only be three paragraphs long. All the rest of the content is simply missing, not shown in order to force each item to be the same shape and size as the others. And fit on the grid.
Deliver the layout on the left using Grid Lanes to browsers with support, while providing a fallback for other browsers.

(If you haven’t heard of Grid Lanes yet, it’s a new tool for layout that makes it easy to create masonry-style layouts in CSS alone. Read Introducing CSS Grid Lanes to learn all about it. And read New Safari developer tools provide insight into CSS Grid Lanes to learn about our new developer tooling that makes using Grid Lanes it even easier.)

Current status of implementations

Where are browsers in the process of getting ready to ship support for Grid Lanes? Let’s look at the progress that’s been made over the last seven years.

Firefox was first

It’s the team that was at Mozilla in 2019-2020 who wrote the original CSS Working Group Editor’s Draft for Grid level 3, proposing concrete ideas for how masonry-style layouts would work in CSS. The feature shipped in Firefox Nightly in very early 2020. Some of the syntax has since changed, but under the hood, the way this new layout feature relies on and expands CSS Grid is basically the same, which means much of the heavy lifting for implementing it in the Gecko layout engine is underway.

Firefox does need to update their implementation (including updating to the new syntax and adding the new flow-tolerance property, among other things) but if you want to try it out in Firefox today, you can enter about:config in the URL bar, search for “masonry” and set the flag to true — or use Firefox Nightly where it’s already on by default. (At the moment, remember to use the original grid-template-*: masonry syntax to trigger this layout, instead of display: grid-lanes.)

Safari picked up the pace

In 2022, Safari’s WebKit team picked up where Mozilla left off in 2020, and started implementing the same original proposal for CSS Grid Layout Level 3. We also restarted the discussion inside the CSS Working Group, hoping to advance the original Editor’s Draft to a point where it was mature enough that browsers could feel confident shipping.

The WebKit implementation was enabled on-by-default in Safari Technology Preview 163 in February 2023. It’s been updated continuously as the CSS specification has changed.

You can use Safari Technology Preview today to try out the official web standard, make demos using display: grid-lanes, and learn how it works. Keep an eye on the Safari Release notes to see when it ships in Safari beta.

Screenshot of webpage for CSS Grid Layout Module level 3 specification.
Grid Lanes is defined in CSS Grid Layout Module Level 3.

Chrome & Edge are on board, too

A variation for how masonry layouts could work in CSS landed in Chrome and Edge 140 behind a flag in July 2025. Rather than implementing the same syntax as Safari and Firefox, Chromium experimented with an alternative proposal. This drove debates in the CSSWG about how exactly this feature should work and what its syntax should be. With key syntax decisions now finalized, Chromium engineers at Edge are updating their implementation. Keep an eye on the Chrome Status issue for the latest news.

Bottom line — all the major browser engines are making progress. Now is a great time to learn how Grid Lanes works. And consider if, when and how you could start using it.

Yes, you can start using it kinda soon-ish

Great developers are always mindful of users whose browsers don’t have support. Not only does it take time for all browsers to ship new features, it takes time for all users to update. But this does not mean you have to wait multiple years before using new technologies. It just means you just have to be savvy.

You can progressively enhance your code to create masonry-style layouts, and support older browsers, both at the same time. How? As always, there are multiple options. Which choice is best for you depends on your use case, your team, and your code base. Let’s go through three different approaches you could use:

Option 1: Polyfill — use a JavaScript library as a backup for Grid Lanes

One common trick for using a new CSS feature when it’s still not available in all browsers is to use a polyfill — i.e.: use JavaScript to fill in the missing functionality.

Lucky for you, there are already tried and true JS libraries out in the world for creating masonry layouts. Masonry.js is a popular one. Perhaps you are using it now. You can keep using it by itself, and ignore Grid Lanes. Or you can switch to using the JS library as a polyfill.

The approach here is to go ahead and use CSS Grid Lanes to handle the layout in CSS alone — in browsers with support for Grid Lanes, even if that’s still only preview browsers. At the same time, architect your code to also work with a JavaScript library. Test in a browser without support for Grid Lanes to make sure the JS layout works.

The key is to structure your code with conditionals, so browsers with Grid Lanes support use CSS, while those without use JS. In your CSS, use Feature Queries to ensure the right CSS is used under the right conditions. In JavaScript, use if statements.

For example, you can structure your CSS like this:

/* Native Grid Lanes for supporting browsers */
@supports (display: grid-lanes) {
  .grid {
    display: grid-lanes;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1lh;
  }
}

/* Additional CSS needed only for browsers without Grid Lanes */
@supports not (display: grid-lanes) {
  .grid-item {
    margin: 1lh;
  }
  /* Perhaps also include a fallback layout in case JS doesn't run */
}

Then in JavaScript, you can check to see whether or not Grid Lanes is supported. If not, load the file. And then start using Masonry JS (or another library), according to its documentation.

// Check if CSS Grid Lanes is NOT supported
if (!CSS.supports('display', 'grid-lanes')) {

    // Dynamically load masonry.js
    const script = document.createElement('script');
    script.src = 'https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js';
    script.onload = function() {

    // Use Masonry.js after the script loads
    new Masonry('.grid', {
        itemSelector: '.grid-item',
        columnWidth: 200,
    });
    };
    document.head.appendChild(script);
}

It’s important to conditionally load the JS library only if the browser doesn’t support Grid Lanes. There’s no reason to have all users download and run the JS file when some percent don’t need it. That percentage might be small today (even zero), but over time it will grow to 100%.

Save future you the task of having to change your code later. Structure it today so in a future when all users have Grid Lanes, no one has to do anything. Users get the best experience, even if no one on your team ever cleans out the old code.

With this technique, browsers with Grid Lanes support use pure CSS, while older browsers load and use JavaScript. By switching to using the JavaScript library a polyfill, not as the primary layout mechanism, increasing numbers of users will get the benefit of a faster and more robust layout sooner.

Of course, maybe this won’t work for your project. Maybe it’s too complicated to architect your HTML and surrounding layout to work for both Grid Lanes and a masonry library at the same time. So what are the other options?

Option 2: Don’t use Grid Lanes — use another layout in CSS instead

Of course, you might be screaming “it’s too early to use Grid Lanes!” There is always the option of simply waiting to use a new technology. Perhaps another layout mode in CSS like Grid level 1, Flexbox or Multicolumn are good enough for your needs. And you can hold off using any tool for accomplishing a masonry-style layout until you feel more confident about Grid Lanes.

CSS Multicolumn is an interesting option that you might not be familiar with. It shipped in browsers decades ago (before Can I Use kept track). With origins that date back to the 1990s, Multicolumn suffered from the fate of most early CSS — the specification was not detailed enough, and that resulted in a lot of differences between browser implementations. This frustrated developers, resulting in Multicolumn falling out of favor.

In more recent years, Multicolumn level 1 has gotten a lot of love, and the specification now contains far more detail. This has helped browsers squash interop bugs. There’s even a Multicolumn level 2 specification bringing new features in the future. There’s still more work to do to create true interoperability, but it’s worth reconsidering Multicolumn to see if can solve your use case today.

Multicolumn and Grid Lanes can result in very similar-looking layouts. They are fundamentally different, however, in the way content flows. These differences impact the order of what comes into focus when tabbing through content, readability / scanability, and user experience. So consider carefully.

graphic comparing Grid Lanes layout vs Multicolumn. Two browser windows side by side. The layouts are basically the same visually, but Grid Lanes flows the content across the page, keeping 20 items above the bottom edge of the viewport. Multicolumn pours the items 1 to 5 down the first column, then starts the next column with the 16th item, showing 16-19... etc. Where is item 6-15? Not on screen.

Try out the demos we created to compare how Multicolumn and Grid Lanes work. Select different layouts from the dropdown menus, and turn on item numbers to emphasize the difference.

Option 3: Use Grid Lanes — along with a fallback layout in CSS

While “don’t use Grid Lanes” is always an option, perhaps the best approach is to write your code so that Grid Lanes is used when supported, and another layout mode in CSS is used as the fallback. This avoids using JavaScript for layout, while still delivering the newer layout to the users who do have support.

For example, let’s imagine we want to use Grid Lanes, and leverage CSS Grid (level 1) when Grid Lanes isn’t supported. To make the original Grid layout work, can use CSS to force all the items be the same aspect ratio by cropping images and truncating text.

To do this, we can apply layout to the container using the display property — twice. First we’ll declare display: grid, then we’ll immediately declare display: grid-lanes.

.grid-container {
  display: grid;
  display: grid-lanes; /* will override grid in browsers that support */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1lh;
}

In browsers that support Grid Lanes, the second declaration will override the first. The display: grid rule will be ignored. And the layout will use Grid Lanes, resulting in a layout that packs content of different aspect ratios into a set of columns.

In browsers that do not support Grid Lanes, the browser will ignore the second declaration. It sees display: grid-lanes and goes “what? That’s not a thing. You must have misspelled something. Ignore!” This leaves grid as the layout that’s applied. The content will be laid out into clear rows as well as columns.

This is a tried and true technique that’s been used by developers for over two decades — relying on the fact that CSS just ignores anything it doesn’t understand. It does not throw an error message. It does not stop parsing. It just ignores that line of code and moves along.

We can also use a Feature Query to write code that only gets applied in browsers without support for Grid Lanes. Let’s use the aspect-ratio property to force all images into the same aspect ratio. And use object-fit: cover to crop those images to fit in the box, instead of letting them be squished.

/* Additional CSS for browsers without Grid Lanes support */
@supports not (display: grid-lanes) {
  .grid-item {
    img {
      aspect-ratio: 1; /* resize every image into a square */
      object-fit: cover; /* crop, don't squish the image */
    }
    h3 {
      white-space: nowrap; /* don't wrap the headline */
      overflow: hidden; /* crop the extra */
      text-overflow: ellipsis; /* add an ellipsis if it overflows */
    }
    p {
      display: -webkit-box; /* current practice in all browsers */
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 3; /* clamps to this many lines of text */
      overflow: hidden;
    }
  }
}

We can force our headline to not wrap with white-space: nowrap. Once the headline is on one line, we can hide whatever doesn’t fit with overflow: hidden. Then, text-overflow: ellipsis adds “…” to the end of what’s visible.

When we want to truncate multi-line text to a specific number of lines, we can use the -webkit-line-clamp technique. While originally invented by the WebKit team long ago when prefixes were the best practice for browsers rolling out new ideas, today -webkit-box, -webkit-box-orient and -webkit-line-clamp are supported by all browsers. (No browser has shipped a replacement yet because a complete web standard for defining such a tool is still under debate.)

This is the exact same image from the opening of the article. Web page of content items — each item is a group with an image, headline and text inside a card with rounded corners. The page is in a browser window on the left, with a layout created with Grid Lanes. The items have different aspect ratios, and nestle together into columns, where all of the content for each item can be seen. On the right, is another browser window with the same content — this time laid out in columns again, but also rows. In order for the items to fit into the rows, the photos have all been cropped into squares, the headlines are truncated to fit onto one line, and the teaser descriptions are all chopped to only be three paragraphs long. All the rest of the content is simply missing, not shown in order to force each item to be the same shape and size as the others. And fit on the grid.

This approach results in a masonry-style waterfall layout being delivered to the browsers that support Grid Lanes, while a more traditional layout of equal-sized boxes are delivered using CSS Grid level 1 to browsers that don’t yet support Grid Lanes.

It’s up to you

It’s totally up to you how you want to handle the fallback for a lack of support for Grid Lanes, but you definitely have options. This is one of the benefits of writing CSS, and not just using a 3rd-party utility framework that abstracts all the flexibility away. Progressive enhancement techniques bring the future into the present, and let you start using Grid Lanes far sooner!

Learn more about Grid Lanes

This is our third article in a series about Grid Lanes. The first introduces CSS Grid Lanes, explaining what it is and how to use it (and yes, it can be used “in the other direction”). The second article shows off our new developer tools and explains why they are particularly helpful for setting flow tolerance. Also, check out our demos in Safari Technology Preview. And be sure to come back to webkit.org soon for more articles about Grid Lanes.

  1. Introducing CSS Grid Lanes
  2. New Safari developer tools provide insight into CSS Grid Lanes
  3. Demos of Grid Lanes
]]>
<![CDATA[New Safari developer tools provide insight into CSS Grid Lanes]]> https://webkit.org/?p=17746 2026-01-23T00:22:24Z 2026-01-14T22:45:00Z You might have heard recently that Safari Technology Preview 234 landed the final plan for supporting masonry-style layouts in CSS. It’s called Grid Lanes.

web browser showing a 6-column layout of photos of various aspect ratios, packed vertically
Try out all our demos of CSS Grid Lanes today in Safari Technology Preview.

CSS Grid Lanes adds a whole new capability to CSS Grid. It lets you line up content in either columns or rows — and not both.

This layout pattern allows content of various aspect ratios to pack together. No longer do you need to truncate content artificially to make it fit. Plus, the content that’s earlier in the HTML gets grouped together towards the start of the container. If new items get lazy loaded, they appear at the end without reshuffling what’s already on screen.

It can be tricky to understand the content flow pattern as you are learning Grid Lanes. The content is not flowing down the first column to the very bottom of the container, and then back up to the top of the second column. (If you want that pattern, use CSS Multicolumn or Flexbox.)

With Grid Lanes, the content flows perpendicular to the layout shape you created. When you define columns, the content flows back and forth across those columns, just like to how it would if rows existed. If you define rows, the content will flow up and down through the rows — in the column direction, as if columns were there.

diagram showing how for waterfall layout there are columns, while content flows side to side. And for brick, the content is laid out in rows, while it the order flows up and down.

Having a way to see the order of items can make it easier to understand this content flow. Introducing the CSS Grid Lanes Inspector in Safari. It’s just the regular Grid Inspector, now with more features.

Grid Lanes photo demo in Safari, with Web Inspector open to the Layout panel, and all the tools for the Grid Inspector turned on. Grid lines are marked with dotted lines. Columns are labeled with numbers and sizes. And each photo is marked with a label like Item 1 — which makes it clear the order of content in the layout.

Safari’s Grid Inspector already reveals the grid lines for Grid Lanes, and labels track sizes, line numbers, line names, and area names. Now it has a new feature — “Order Numbers”.

By turning on the order numbers in the example above, we can clearly see how Item 1, 2, 3, and 4 flow across the columns, as if there were a row. Then Item 5 is in the middle right, followed by Item 6 on the far right, and so on.

You might be tempted to believe the content order doesn’t matter. With pages like this photo gallery — most users will have no idea how the photos are ordered in the HTML. But for many users, the content order has a big impact on their experience. You should always consider what it’s like to tab through content — watching one item after another sequentially come into focus. Consider what it’s like to listen to the site through a screenreader while navigating by touch or keyboard. With Grid Lanes, you can adjust flow-tolerance to reduce the jumping around and put items where people expect.

To know which value for flow tolerance to choose, it really helps to quickly see the order of items. That makes it immediately clear how your CSS impacts the result.

Order Numbers in the Grid Inspector is an extension of a feature Safari’s Flexbox Inspector has had since Safari 16.0 — marking the order of Flex items. Seeing content order is also helpful when using the order property in Flexbox.

Web browser showing photo layout — this time a Flexbox layout. The Web Inspector is open to the Layout tab, and the Flexbox Inspector is enabled. The lines of the layout are marked with dotted lines... and each item is labeled with its order.

Order Numbers in Safari’s Grid Inspector works for CSS Grid and Subgrid, as well as Grid Lanes.

Try out Safari’s layout tooling

The Grid and Flexbox layout inspectors might seem similar across browsers, but the team behind Safari’s Web Inspector has taken the time to finely polish the details. In both the Grid and Flexbox Inspectors, you can simultaneously activate as many overlays as you want. No limits. And no janky scrolling due to performance struggles.

Safari’s Flexbox Inspector visually distinguishes between excess free space and Flex gaps, since knowing which is which can solve confusion. It shows the boundaries of items, revealing how they are distributed both on the main axis and the cross axis of Flexbox containers. And it lists all the Flexbox containers, making it easier to understand what’s happening overall.

Our Grid Inspector has a simple and clear interface, making it easy to understand the options. It lists all of the Grid containers — and you can show the overlay for every single one at the same time. The overlays don’t disappear when you scroll. And of course, you can change the default colors of the overlays, to best contrast with your site content.

And Safari’s Grid and Flexbox Inspectors are the only browser devtools that label content order. We hope seeing the order of content in Grid Lanes helps you understand it more thoroughly and enjoy using this powerful new layout mechanism.

Try out Order Numbers

Order Numbers in Safari’s Grid Inspector shipped today in Safari Technology Preview 235. Let us know what you think. There’s still time to polish the details to make the most helpful tool possible. You can ping Jen Simmons on Bluesky or Mastodon with links, comments and ideas.

For more

Note: Learn more about Web Inspector from the Web Inspector Reference documentation.
]]>
<![CDATA[Release Notes for Safari Technology Preview 235]]> https://webkit.org/?p=17739 2026-01-14T22:28:19Z 2026-01-14T22:28:19Z Safari Technology Preview Release 235 is now available for download for macOS Tahoe and macOS Sequoia. If you already have Safari Technology Preview installed, you can update it in System Settings under General → Software Update.

This release includes WebKit changes between: 304072@main…305083@main.

CSS

New Features

  • Added support for parsing and evaluating name-only @container queries that have no conditions, allowing named containers to match without explicit constraints. (304388@main) (164648718)
  • Added support for math-depth. (305010@main) (167332590)

Resolved Issues

  • Fixed an issue where display: list-item was incorrectly supported on fieldset. (304102@main) (95638460)
  • Fixed baseline handling for table cells when cell has no inflow children. (304477@main) (160774504)
  • Fixed -webkit-line-clamp so that it no longer propagates into inline-block children. (304956@main) (164488778)
  • Fixed an issue where nested identical CSS filter effects were not rendered. (304143@main) (165163823)
  • Fixed ::first-line pseudo-element to always use inline display to match the CSS Display specification. (304096@main) (166068698)
  • Fixed incorrect text selection ranges for truncated right-to-left content. (304821@main) (166944754)

Deprecations

  • Removed the FontFaceSet constructor from the CSS Font Loading API as it was deemed unnecessary, aligning with the CSSWG resolution. (304912@main) (132031306)

Canvas

Resolved Issues

  • Fixed ImageBitmap created from SVG image sources to correctly honor the flipY orientation. (304137@main) (83959718)

Clipboard

Resolved Issues

  • Fixed an issue where using the “Copy Image” context menu in Safari would also copy the image URL, causing some sites to paste the URL instead of the image. (304166@main) (76598990)

Editing

Resolved Issues

  • Fixed incorrect text selection when dragging across pseudo elements. (304719@main) (142905243)
  • Fixed an issue where focusing a hidden editable element would incorrectly display the text cursor and selection at full opacity. (304160@main) (165489471)

Encoding

Resolved Issues

  • Fixed incorrect handling of invalid UTF-8 sequences in the TextDecoder streaming decoder to properly manage partial sequence buffers. (304496@main) (166583808)

Forms

Resolved Issues

  • Fixed an issue where input fields did not display user input while typing . (304311@main) (163613957)

HTML

Resolved Issues

  • Fixed HTMLImageElement.currentSrc to return an empty string for <img src="proxy.php?url="> instead of resolving to the document base URL. (304982@main) (167229274)

JavaScript

Resolved Issues

  • Fixed %TypedArray%.prototype.includes to correctly check that the index is less than the array length, aligning its behavior with ECMA-262 (304485@main). (166578170)
  • Fixed %TypedArray%.prototype.includes to correctly check that the index is less than the array length, aligning its behavior with ECMA-262. (304940@main) (167183441)

MathML

New Features

  • Added support for CSS size containment in MathML elements using contain-intrinsic-inline-size and contain-intrinsic-block-size. (304458@main) (166323213)
  • Added support for math-style and math-shift to animate as discrete values. (305017@main) (167369164)

Resolved Issues

  • Fixed incorrect positioning of mpadded content in right-to-left mode. (304087@main) (166045517)
  • Fixed an issue where RenderMathMLRoot did not reset its radical operator when msqrt or mroot children were dynamically added or removed.(304822@main) (166556627)
  • Fixed <mpadded> so that percentage values for width, height, and depth attributes are treated as absent and use content dimensions as defaults, matching the MathML Core specification. (305027@main) (167350169)

Media

Resolved Issues

  • Fixed an issue where changing an HTMLMediaElement volume from 0 to 0 did not activate the audio session or update the sleep disabler. (304297@main) (161691743)
  • Fixed playback of application/ogg blob media. (304530@main) (163119790)
  • Fixed an issue where HTMLMediaElement did not correctly detect new audio or video tracks causing Safari to pause video when leaving a tab. (304336@main) (164514685)
  • Fixed a crash in AudioData.copyTo() when copying the last channel of 3-channel audio. (304728@main) (164730320)
  • Fixed the caption menu’s On option to correctly enable the highest-scoring text track and mark the appropriate language as checked in the subtitle menu. (304462@main) (166158394)
  • Fixed parseSequenceHeaderOBU to return an AV1CodecConfigurationRecord, fully decode the Sequence Header OBU, and capture the complete color profile. (304474@main) (166439682)

Networking

Resolved Issues

  • Fixed a regression where fetch() would throw a TypeError when using targetAddressSpace: 'loopback' for localhost requests. (304577@main) (166574523)

Rendering

Resolved Issues

  • Fixed an issue where overconstrained sticky elements were not properly adjusting their insets when the sticky box rectangle was larger than the viewport. (304335@main) (163654023)
  • Fixed inconsistent text layout when using list-style-type by ensuring outside list markers do not affect intrinsic width calculations. (304947@main) (164650313)
  • Fixed incorrect min and max width calculations for block-level boxes inside inline content. (304170@main) (166157696)
  • Fixed an issue where getClientRects returned an incomplete list of rectangles for inline boxes containing block elements. (304949@main) (167209147)

SVG

New Features

  • Added support for the lighter operator in SVGFECompositeElement IDL to align with the Compositing and Blending specification. (304941@main) (166704079)

Resolved Issues

  • Fixed an issue where stroke-dasharray incorrectly propagated to SVG markers when explicitly marked as ‘0’. (305042@main) (46607685)
  • Fixed an issue where foreignObject elements in SVG incorrectly allowed margin collapsing. (304916@main) (97208795)
  • Fixed an issue where dynamically changing marker-start, marker-mid, or marker-end attributes on SVG elements did not trigger re-rendering. (304880@main) (130678384)
  • Fixed tiling gaps in CSS reference filters using <feDisplacementMap>. (304830@main) (135448018)
  • Fixed behavior to avoid incorrect pruning of SVG mask subtrees based on visibility. (305047@main) (157729389)
  • Fixed an issue where SVG animateTransform animations on hidden elements were triggering full-page rendering updates each frame. (304744@main) (159647563)
  • Fixed SVGLength percentage resolution for elements inside non-instanced <symbol> elements. (304197@main) (165431008)
  • Fixed an issue where SVGLength.value did not update for font-relative units (e.g., ch, em) after changes to writing-mode. (304657@main) (166190252)
  • Fixed missing gradient fills when using paint-order stroke fill. (288788@main) (166997630)
  • Fixed embedded <svg> elements in <img> without an explicit viewBox to synthesize preserveAspectRatio='none' so the SVG stretches to fill the container. (305043@main) (167121931)
  • Fixed the <stop> element offset attribute in SVG to reject invalid values with trailing characters and correctly fall back to 0. (305036@main) (167356988)
  • Fixed the transform order for clipPath elements so that the bounding box is scaled correctly before applying the local transform. (305078@main) (167417135)
  • Fixed incorrect rendering when combining markerUnits=strokeWidth with vector-effect=non-scaling-stroke. (305077@main) (167493417)

Web API

New Features

  • Added support for pointer event and mouse event button support for the back and forward mouse buttons when they are available. (304761@main) (137592588)

Resolved Issues

  • Fixed an issue where IntersectionObserver computed the root rectangle incorrectly when overflow clipping was present. (304296@main) (117143395)
  • Fixed DigitalCredential behavior to make user mediation implicitly required. (304676@main) (165597827)
  • Fixed an issue where the Big5 TextDecoder failed to recover and emit ASCII characters after encountering an invalid leading byte. (304591@main) (166672674)

Web Inspector

New Features

  • Added a context menu option to DOM nodes in the Elements Tab to copy pretty-printed HTML. (304698@main) (102125455)
  • Added support for toggling the visibility of User Agent stylesheet rules in the Elements tab, including hiding related “go-to” arrows in the Computed panel when the setting is disabled. (304627@main) (164265183)
  • Added support for showing actual composited layer snapshots in the 3D Layers view. (304758@main) (164977594)
  • Added support for Web Inspector to fetch CSS property keyword completions based on feature support. (304195@main) (165914089)
  • Added support for displaying Order Numbers in CSS Grid and CSS Grid Lanes overlays in Web Inspector, including new UI settings for toggling order number visibility. (304645@main) (166648769)
  • Added support for visualizing gaps between items in the masonry axis of grid-lanes layouts within the Web Inspector grid overlay. (304861@main) (166984079)

Resolved Issues

  • Fixed the Styles sidebar filter in Web Inspector to be case-insensitive. (304153@main) (36086981)
  • Fixed context menu items to rename Copy HTTP Request and Copy HTTP Response to Copy HTTP Request Headers and Copy HTTP Response Headers for clarity. (304768@main) (117708766)
  • Fixed an issue where the Sources navigation sidebar could be empty when reloading the page. (304221@main) (166141968)
  • Fixed timestamp formatting in the Web Inspector to remove unnecessary trailing .0 values for readability. (304851@main) (166500013)
  • Fixed item order labels in the Web Inspector grid and flex overlays to remove the # symbol, changing from Item #N to Item N. (304771@main) (166767949)

WebAssembly

Resolved Issues

  • Fixed Error.isError(WebAssembly.Exception) to correctly return false based on current WebAssembly spec semantics. (304917@main) (167110254)

WebRTC

Resolved Issues

  • Fixed RTCDataChannelInit to support [EnforceRange] on the maxPacketLifeTime and maxRetransmits fields to align with the WebRTC specification. (304499@main) (133630397)
  • Fixed an issue where RTCDataChannel close events did not fire when RTCPeerConnection was closed. (304859@main) (165617848)
]]>