Upgrade to Pro — share decks privately, control downloads, hide ads and more …

State of CSS 2025

State of CSS 2025

The web platform has evolved rapidly in recent years, with browser vendors modernizing CSS and introducing long-overdue features to enhance web development and interoperability. Thanks to evergreen browsers, we can adopt these new features today.

In this session, we'll explore the latest CSS capabilities and their practical applications. You'll learn how to utilize these new features through practical examples.

Avatar for Benjamin Kott

Benjamin Kott

August 07, 2025
Tweet

More Decks by Benjamin Kott

Other Decks in Programming

Transcript

  1. Disclaimer: The information provided is subject to change and is

    intended to summarize current available information as of the presentation date. Please verify all details independently and conduct your own research. The views expressed are my own.
  2. Keeping up with new features in web standards and making

    it work across browsers is still a challenge.
  3. Interop 2025 Anchor positioning backdrop-filter Core Web Vitals <details> element

    Layout Modules Navigation API Pointer and mouse events Remove mutation events @scope scrollend event Storage Access API text-decoration URLPattern View Transition API WebAssembly Web compat WebRTC Writing modes https://web.dev/blog/interop-2025 https://wpt.fyi/interop-2025
  4. Baseline Web Platform Baseline tries to bring clarity to information

    about browser support for web platform features. https://web.dev/baseline
  5. Newly available Limited availability Widely available The feature becomes supported

    by all of the core browsers. 30 months have passed since the newly interoperable date. The feature has just become available in some core browsers.
  6. 2022 CSS-Variables Prefers Color Scheme CSS Cascade Layers Containment Grid

    Layout Accent Color Has 2024 Color Light-Dark Relative Color Popover API Starting Style Transition Behavior Scroll Driven Animations 2023 Focus Visible Focus Within Custom Properties Text-Wrap Color Spaces Color Mix Nesting
  7. Baseline since Developer Days 2024 (August) Page setup ruby-align ruby-position

    scrollbar-gutter scrollbar-width ::target-text Garbage collection (Wasm) Tail call optimization (Wasm) Fetch priority requestVideoFrameCallback() Color management for WebGL Color management for WebGL2 text-wrap-mode text-wrap: stable Scroll to text fragment backdrop-filter willReadFrequently cookieEnabled getHTML() HTTP/3 Relative colors Typed function references (Wasm) Mutually exclusive <details> elements @starting-style transition-behavior dialog.requestClose() print-color-adjust RegExp.escape() JSON import attributes Float16Array Single color stop gradients Atomics.pause() ClipboardItem.supports() Iterator methods Screen wake lock contenteditable="plaintext-only" Intl.DurationFormat Popover Promise.try()
  8. Relevant Baseline since Developer Days 2024 (August) Page setup scrollbar-gutter

    scrollbar-width ::target-text text-wrap-mode text-wrap: stable Scroll to text fragment Relative color Mutually exclusive <details> elements print-color-adjust Single color stop gradients contenteditable="plaintext-only" Popover @starting-style transition-behavior
  9. Agenda Developer Days 2025 Mutually exclusive <details> elements @starting-style transition-behavior

    Popover Anchor positioning … Page setup scrollbar-gutter scrollbar-width ::target-text text-wrap Relative color Scroll to text fragment print-color-adjust Single color stop gradients contenteditable="plaintext-only"
  10. :( Your PC hit a little snag and needs to

    restart. We’re grabbing some info behind the scenes and will have things spinning again in no time! 120% complete Check out the thrilling details at: http://windows.com/stopcode If you're calling tech, just drop this bombshell: Stop code: IDWCM (It died. We cried. Moving on.)
  11. The @starting-style CSS at-rule is used to define starting values

    for properties set on an element that you want to transition from when the element receives its first style update, i.e. when an element is first displayed on a previously loaded page. https://developer.mozilla.org/en-US/docs/Web/CSS/@starting-style
  12. @starting-style .modal { /* ... */ display: none; top: 50%;

    opacity: 1; scale: 1; @starting-style { top: 100%; opacity: 0; scale: 0.25; } &.show { display: block; } }
  13. Animation type: Discrete The property's values are not additive, and

    interpolation swaps from the start value to the end value at 50%. Specifically, denoting by the progress value: If progress < 0.5, then value_result = value_start. If progress ≥ 0.5, then value_result = value_end. Examples for discrete properties: display and content-visibility
  14. transition-behavior allow-discrete Allows to swap the values of discrete properties

    during the keyframe animation instead of swapping them at 50%. When not set to a key-frame the property will swap at 0 or 100% of the animation progress. normal Discrete properties will swap at 50% of the animation progress.
  15. transition-behavior .modal { display: none; transition-property: opacity, display; transition-duration: 0.5s;

    transition-behavior: allow-discrete; opacity: 0; /* ... */ &.show { display: block; opacity: 1; @starting-style { opacity: 0; } } }
  16. Anchor Positioning: Overview Enables positioning of elements relative to any

    other element (not just ancestors) Useful for UI elements like tooltips, dropdowns, badges, and popovers Avoids layout shifts by not affecting document flow Supports fallback strategies when preferred anchors aren't available Allows precise control over alignment areas and edge preferences Designed to work with future HTML and JavaScript integrations
  17. Anchor Positioning: Properties anchor-name: Registers an element as a layout

    anchor. position-anchor: Specifies which anchor to use for positioning. position-area Defines the area (e.g. normal, inset) used for anchoring. position-try-fallbacks Lists fallback anchors if the main one fails. position-try-order Controls the order in which fallbacks are tried. position-visibility Determines when the element is visible based on positioning success.
  18. Anchor Positioning API: Demo <div id="anchor" class="anchor"> </div> <div id="tooltip"

    class="tooltip">…</div> .anchor { anchor-name: --anchor-element; } .tooltip { position: absolute; position-anchor: --anchor-element; position-area: block-start; }
  19. Anchor Positioning: Functions anchor() Gets the position of an anchor.

    anchor-size() Retrieves the width/height of an anchor top: anchor(bottom); top: anchor(--myAnchor bottom); top: anchor(--myAnchor bottom, 50%); width: anchor-size(width); width: anchor-size(--myAnchor width); width: anchor-size(--myAnchor width, 50%);
  20. <div class="anchor" id="example-anchor"> </div> <div class="infobox" anchor="example-anchor"> <p>This is an

    information box.</p> </div> const posElem = document.querySelector(".infobox"); console.log(`The anchor elements id is ${posElem.anchorElement.id}.`); // output: example-anchor
  21. Anchor Positioning: Summary Still under development CSS-only for now (no

    full HTML integration yet) Supported in: Chrome, Edge, Opera Safari: Partial support (Preview only) Firefox: No implementation yet HTML anchor attribute: Experimental JS anchorElement property: Experimental
  22. Popover API: Demo <button type="button" popovertarget="mypopover"> Open </button> <div id="mypopover"

    popover> <button type="button" popovertarget="mypopover" popovertargetaction="hide"> Close </button> <p>...</p> </div>
  23. Popover API: Attributes popover="<auto|manual>" Add the popover attribute to the

    element that could contain your popover content. Optionally, you can set the value to auto or manual. The auto options equals a „light dismiss“, the popup will be closed as soon as you click outside the popover. With manual you need to control the state yourself. popovertarget="mypopover" Add the popovertarget attribute with the matching id to your popover element to a button and you can toggle the popover. popovertargetaction="<hide|show|toggle>" The popovertargetaction can be used to control the action the button should trigger.
  24. Popover API Declarative API Automatic top layer promotion Does not

    set the page to inert like <dialog> Should be used for menus, notifications, content pickers … Default closed popover is set to display: none Default opened popover is set to display: block Animations through @starting-style and transition-behavior Positioning will be handled in the future through anchor() Only one popover can be shown at a time This rule can be avoided by nested popovers and manual popovers.
  25. Open UI is a W3C Community Group working to make

    native web UI components like <select> and checkboxes fully styleable and extensible. By standardizing their structure, behavior, and accessibility, and providing test suites and polyfills, the group aims to reduce the need for custom implementations while supporting design systems that still choose to build their own. Long term, it seeks to establish a standard process for adding robust UI controls to the web platform. https://open-ui.org
  26. <select id="select-modern" name="select-modern" class="select-modern"> <button class="select-modern-button"> <selectedcontent></selectedcontent> <svg class="select-modern-button-chevron" role="img"

    aria-hidden="true"> <use href="/assets/actions.svg#actions-chevron-expand" /> </svg> </button> <div role="group"> <label>Page</label> <option value="1"> <svg class="select-modern-option-icon" role="img" aria-hidden="true"> <use href="/assets/apps.svg#apps-pagetree-page-default" /> </svg> <span class="select-modern-option-label">Standard</span> </option> <option value="6">...</option> </div> <div role="group">...</div> <div role="group">...</div> </select>
  27. <select id="select-modern" name="select-modern" class="select-modern"> <button class="select-modern-button"> <selectedcontent></selectedcontent> <svg class="select-modern-button-chevron" role="img"

    aria-hidden="true"> <use href="/assets/actions.svg#actions-chevron-expand" /> </svg> </button> <div role="group"> <label>Page</label> <option value="1"> <svg class="select-modern-option-icon" role="img" aria-hidden="true"> <use href="/assets/apps.svg#apps-pagetree-page-default" /> </svg> <span class="select-modern-option-label">Standard</span> </option> <option value="6">...</option> </div> <div role="group">...</div> <div role="group">...</div> </select>
  28. /* Starting Style Animation */ .select-modern { &::picker(select) { opacity:

    0; transition: opacity .35s allow-discrete; } &::picker(select):popover-open { opacity: 1; } } @starting-style { .select-modern::picker(select):popover-open { opacity: 0; } }
  29. /* Transition when option is selected */ .select-modern selectedcontent >

    * { transition: transform .7s var(--select-animation), display .7s allow-discrete, opacity .7s; opacity: 1; @starting-style { opacity: 0; transform: translateY(1rem); } }
  30. Driven by Google and part of Interop 2025 Implemented as

    a Web Component Built on top of the Popover API Built on top of the Anchor Positioning API Highlighted in MDN’s Learning Area <select multiple> Not yet supported Not yet supported in Firefox; Safari support in Preview only <select multiple>
  31. If the Anchor Positioning API lands successfully as part of

    Interop 2025, Customizable Selects could reach Baseline status by early 2026.
  32. Resources Request for developer feedback: customizable select https://developer.chrome.com/blog/rfc-customizable-select The <select>

    element can now be customized with CSS https://developer.chrome.com/blog/a-customizable-select Open UI Proposal https://open-ui.org/components/customizableselect Customizable select elements https://developer.mozilla.org/en- US/docs/Learn_web_development/Extensions/Forms/Customizable_select
  33. Scroll-driven animations Animations without JavaScript based on progression of a

    scroll-based timeline Unsupported Browsers will get the default experience, capable browsers get enhanced animations. Can be combined with prefers-reduced-motion media queries
  34. Scroll-driven animations: Reading animation @keyframes readinganimation { from { width:

    0; } to { width: 100%; } } .reading-indicator-progress { animation: readinganimation linear; animation-timeline: scroll(); }
  35. Scroll-driven animations: Appearing cards @keyframes appear { from { scale:

    .85; opacity: 0; } to { scale: 1; opacity: 1; } } .vcard { animation: appear linear; animation-timeline: view(); animation-range: entry contain 25%; }
  36. Scroll-driven animations: animation-timeline animation-timeline: <none|auto|scroll()|view()> scroll() An anonymous scroll progress

    timeline is provided by some ancestor scroller of the current element. The function parameters allow you to select the scroller, and the scrolling axis the timeline will be measured along. view() An anonymous view progress timeline is provided by the subject that animation-timeline: view(); is set on. The function parameters allow you to select the scrollbar axis along which timeline progress will be tracked and an inset that adjusts the position of the box in which the subject is deemed to be visible.
  37. Scroll-driven animations: animation-range animation-range: normal 25%; animation-range: 25% normal; animation-range:

    25% 50%; animation-range: entry exit; animation-range: cover cover 200px; animation-range: entry 10% exit; animation-range: 10% exit 90%; animation-range: entry 10% 90%;
  38. Scroll-driven animations: Link Collection Unleash the power of Scroll-Driven Animations

    https://youtu.be/5noL_qFobm0?list=PLNYkxOF6rcICM3ttukz9x5LCNOHfWBVnn Scroll-driven Animations Demos https://scroll-driven-animations.style/ MDN Documentation https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll-driven_animations
  39. Keeping up with new features in web standards and making

    it work across browsers is still a challenge.