artCode

CSS 2025: le 7 funzionalità native che eliminano JavaScript

Scopri le 7 funzionalità di CSS 2025 (Container Queries, Anchor Positioning, light-dark()) che eliminano JavaScript e migliorano performance. Con esempi pratici e browser support.

Tags

  • CSS
  • Javascript

Published

Reading Time

10 min
CSS 2025: le 7 funzionalità native che eliminano JavaScript - Container Queries, Nesting, Anchor Positioning

Il CSS moderno ha compiuto passi da gigante negli ultimi anni, introducendo funzionalità che fino a poco tempo fa richiedevano necessariamente JavaScript. Nel 2025, abbiamo a disposizione 7 potenti funzionalità native che permettono di eliminare dipendenze JavaScript, ridurre il bundle size e migliorare significativamente le performance delle nostre applicazioni web.

1. Container Queries: responsività component-based

Le container queries rappresentano una rivoluzione nel design responsive. A differenza delle media queries che si basano sulla viewport, le container queries permettono di stilizzare elementi in base al loro contenitore, non alla finestra del browser.

Questo approccio consente di creare componenti veramente riutilizzabili che si adattano al loro contesto. Dal 2024 il supporto è universale: Chrome 107+, Firefox 110+, Safari 16.5+.

Il vantaggio principale? Nessuna libreria JavaScript necessaria: i calcoli sono gestiti nativamente dal browser, eliminando -8 KB di dipendenze e mantenendo tutta la logica di layout nel CSS.

CSS
.card-container { container-type: inline-size; container-name: card; } .card { display: grid; grid-template-columns: 1fr; gap: 1rem; } /* Quando il container supera 500px */ @container card (min-width: 500px) { .card { grid-template-columns: 200px 1fr; } .card__image { aspect-ratio: 1; } } /* Quando il container supera 700px */ @container card (min-width: 700px) { .card { grid-template-columns: 300px 1fr; gap: 2rem; } }

Container query units sono altrettanto potenti:

  • cqw: 1% della larghezza del container
  • cqh: 1% dell'altezza del container
  • cqi: 1% della dimensione inline
  • cqb: 1% della dimensione block
  • cqmin, cqmax: il più piccolo/grande tra cqi e cqb
CSS
.card__title { /* Font size si adatta alla larghezza del container */ font-size: clamp(1.2rem, 4cqw, 2.5rem); margin-bottom: 2cqh; } .card__description { font-size: calc(1rem + 0.5cqw); line-height: 1.6; }

2. CSS Nesting: addio ai preprocessor

Dal dicembre 2023, il CSS nesting nativo è supportato universalmente (Chrome 113+, Firefox 117+, Safari 16.6+). Questa funzionalità elimina la necessità di preprocessor per la maggior parte dei casi d'uso, azzerando i tempi di build e riducendo il bundle di 12 KB.

La sintassi è simile a Sass ma con alcune differenze importanti: il CSS nativo viene parsato dal browser, non pre-compilato, quindi il codice che vedi nel browser è identico a quello che scrivi.

CSS
/* Sass/SCSS tradizionale */ .card { padding: 1rem; background: white; .card__title { font-size: 1.5rem; color: #333; } .card__content { margin-top: 1rem; } &:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.1); } }
CSS
/* CSS nativo con nesting */ .card { padding: 1rem; background: white; /* Nesting diretto (funziona senza &) */ .card__title { font-size: 1.5rem; color: #333; } .card__content { margin-top: 1rem; } /* & necessario per pseudo-classi e compound selectors */ &:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.1); } /* Nesting di media queries */ @media (width >= 768px) { padding: 2rem; .card__title { font-size: 2rem; } } }

Differenze chiave da Sass

  • Non puoi concatenare stringhe come in Sass (&__element non funziona in CSS nativo)
  • La specificità è calcolata come :is(), non come selettori normali
  • I type selector devono venire per primi nei compound selector

Se utilizzi Tailwind CSS in React, puoi comunque sfruttare il nesting nativo per customizzazioni avanzate nei file CSS.

3. light-dark(): gestione tema nativo

La funzione light-dark() è disponibile universalmente da maggio 2024 (Chrome 123+, Safari 17.5+, Firefox) e semplifica drasticamente la gestione dei temi.

Fino ad ora, implementare un theme switcher richiedeva JavaScript per manipolare classi o attributi data, più complesse media queries prefers-color-scheme. Con light-dark(), tutto si riduce a poche righe di CSS.

JavaScript
/* Approccio tradizionale con JavaScript + CSS */ /* CSS */ :root { --bg-color: #ffffff; --text-color: #1a1a1a; } [data-theme="dark"] { --bg-color: #1a1a1a; --text-color: #ffffff; } body { background: var(--bg-color); color: var(--text-color); } /* JavaScript necessario */ const toggle = document.querySelector('.theme-toggle'); toggle.addEventListener('click', () => { const currentTheme = document.documentElement.getAttribute('data-theme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-theme', newTheme); localStorage.setItem('theme', newTheme); });
CSS
/* Approccio moderno con light-dark() */ :root { color-scheme: light dark; } body { background: light-dark(#ffffff, #1a1a1a); color: light-dark(#1a1a1a, #ffffff); } .card { background: light-dark(#f5f5f5, #2a2a2a); border: 1px solid light-dark(#e0e0e0, #404040); box-shadow: 0 2px 8px light-dark( rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.3) ); } .button--primary { background: light-dark(#0066cc, #4d9fff); color: light-dark(#ffffff, #000000); }

Come funziona

  1. Imposti color-scheme: light dark (solitamente su :root)
  2. Il browser rileva automaticamente la preferenza utente da prefers-color-scheme
  3. La funzione light-dark(light-value, dark-value) ritorna il primo valore in modalità chiara, il secondo in modalità scura

Controllo manuale tramite CSS

CSS
/* Toggle manuale senza JavaScript */ :root { color-scheme: light dark; } /* Override: forza modalità chiara */ :root[data-theme="light"] { color-scheme: light; } /* Override: forza modalità scura */ :root[data-theme="dark"] { color-scheme: dark; }

Vantaggi

  • Nessun JavaScript necessario: rispetta automaticamente prefers-color-scheme del sistema
  • Bundle size: -3 KB eliminando tutta la logica di theme management

4. Relative Color Syntax: manipolazione colori dinamica

La relative color syntax ha raggiunto supporto completo nel 2024 (Chrome 121+, Safari 16.6+, Firefox 128+) e permette di creare variazioni di colori dinamicamente nel CSS. Puoi modificare luminosità, saturazione e tonalità senza alcuna dipendenza JavaScript, usando spazi colore moderni come OKLCH per risultati percettivamente uniformi.

La sintassi usa la keyword from per riferirsi a un colore base e manipolarne i canali.

CSS
:root { --brand-color: #0066cc; } /* Schiarire un colore del 25% */ .button--light { background: oklch(from var(--brand-color) calc(l * 1.25) c h); } /* Scurire un colore del 20% */ .button--dark { background: oklch(from var(--brand-color) calc(l * 0.8) c h); } /* Creare versione semi-trasparente */ .overlay { background: rgb(from var(--brand-color) r g b / 0.5); } /* Rotare la tonalità di 30 gradi */ .accent { color: oklch(from var(--brand-color) l c calc(h + 30)); } /* Invertire la luminosità mantenendo hue */ .inverted { background: oklch(from var(--brand-color) calc(100% - l) c h); }

Spazi colore supportati

  • rgb() / rgba(): tradizionale, compatibilità massima
  • hsl() / hsla(): intuitivo per modifiche hue/saturazione
  • oklch(): raccomandato per modifiche percettivamente uniformi
  • lab(), lch(), oklab(): avanzati per precisione scientifica

5. Scroll-driven Animations: animazioni native on scroll

Le scroll-driven animations sono disponibili in Chrome 115+ e Safari 26 beta, con polyfill per Firefox. Questa feature elimina librerie JavaScript per animazioni on scroll, gestendo tutto nativamente nel browser con performance ottimali.

Ci sono due tipi di timeline:

  • Scroll timeline: animazione basata sulla posizione di scroll del container
  • View timeline: animazione basata su quando l'elemento entra/esce dalla viewport
CSS
/* Progress bar che si riempie durante lo scroll della pagina */ .progress-bar { position: fixed; top: 0; left: 0; height: 4px; background: linear-gradient(to right, #3b82f6, #8b5cf6); transform-origin: 0 50%; animation: scroll-progress linear; animation-timeline: scroll(root); } @keyframes scroll-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } } /* Fade in quando l'elemento entra in viewport */ .fade-in-on-scroll { opacity: 0; transform: translateY(30px); animation: fade-in linear forwards; animation-timeline: view(); animation-range: entry 0% entry 100%; } @keyframes fade-in { to { opacity: 1; transform: translateY(0); } }

Accessibilità:

È fondamentale rispettare la preferenza prefers-reduced-motion per utenti sensibili al movimento.

CSS
@media (prefers-reduced-motion: reduce) { .fade-in-on-scroll, .parallax-bg, .section__image { animation: none; opacity: 1; transform: none; } }

Vantaggi

  • Performance: 60fps nativi con animazioni su compositor thread, nessun JavaScript loop sul main thread
  • Bundle size: -30 KB eliminando GSAP ScrollTrigger con migliore battery life su mobile

6. Anchor Positioning: posizionamento relazionale nativo

CSS Anchor Positioning è disponibile in Chrome 125+, Edge 125+ e Safari 26 beta. Questa feature permette di posizionare tooltip e popover senza JavaScript, con calcoli nativi e responsive automatici.

Nota: Pur essendo estremamente potente, questa feature non è ancora Baseline (supporto limitato). Usala con progressive enhancement o fallback.

CSS
/* Definire un anchor element */ .trigger-button { anchor-name: --tooltip-anchor; } /* Posizionare il tooltip relativamente all'anchor */ .tooltip { position: absolute; position-anchor: --tooltip-anchor; /* Posiziona il tooltip sotto il bottone */ top: anchor(bottom); /* Centra orizzontalmente */ left: anchor(center); transform: translateX(-50%); /* Styling */ background: #1a1a1a; color: white; padding: 0.5rem 1rem; border-radius: 0.375rem; white-space: nowrap; z-index: 10; } /* Freccia del tooltip */ .tooltip::before { content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); border: 6px solid transparent; border-bottom-color: #1a1a1a; }

Casi d'uso ideali:

  • Tooltip e popover
  • Menu dropdown
  • Context menu
  • Date picker
  • Autocomplete suggestions
  • Annotation markers

Vantaggi (quando supportato):

  • Zero JavaScript: nessuna libreria tipo Popper.js o Floating UI, calcoli nativi e responsive automatici
  • Bundle size: -15 KB con gestione focus automatica per accessibilità top-layer

La View Transitions API è supportata in Chrome 111+, Edge 111+ e parzialmente in Safari 18+ (solo SPA). Questa API permette di creare transizioni fluide tra stati del DOM con supporto nativo del browser, riducendo drasticamente la necessità di librerie di animazione come Framer Motion o React Spring.

La View Transitions API è supportata in Chrome 111+, Safari 18.4 e Firefox 144 (ottobre 2025). Questa feature è parte di Interop 2025 e permette di creare transizioni fluide con supporto nativo del browser.

Supporta sia same-document transitions (SPA) che cross-document transitions (MPA, Chrome 126+).

JavaScript
// JavaScript per attivare la transizione function updateView() { // Verifica supporto if (!document.startViewTransition) { // Fallback: aggiorna direttamente updateDOM(); return; } // Avvia transizione document.startViewTransition(() => { updateDOM(); }); } // Funzione che modifica il DOM function updateDOM() { document.querySelector('.content').innerHTML = newContent; }

Customizzazione CSS:

La vera potenza sta nel controllo CSS delle transizioni tramite pseudo-elementi.

CSS
/* Transizione di default */ ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.3s; } /* Slide in/out personalizzato */ ::view-transition-old(root) { animation: slide-out 0.3s ease-out; } ::view-transition-new(root) { animation: slide-in 0.3s ease-out; } @keyframes slide-out { to { transform: translateX(-100%); } } @keyframes slide-in { from { transform: translateX(100%); } } /* Transizioni specifiche per elementi */ .card { view-transition-name: card-detail; } ::view-transition-old(card-detail), ::view-transition-new(card-detail) { height: 100%; overflow: clip; } ::view-transition-old(card-detail) { animation: scale-down 0.4s ease; } ::view-transition-new(card-detail) { animation: scale-up 0.4s ease; } @keyframes scale-down { to { transform: scale(0.8); opacity: 0; } } @keyframes scale-up { from { transform: scale(0.8); opacity: 0; } }

Cross-document transitions (MPA):

Per siti multi-page, puoi abilitare transizioni automatiche tra pagine diverse.

CSS
/* Abilita transizioni cross-document */ @view-transition { navigation: auto; } /* Transizione fade per navigazione */ ::view-transition-old(root) { animation: fade-out 0.2s ease-out; } ::view-transition-new(root) { animation: fade-in 0.2s ease-in; } @keyframes fade-out { to { opacity: 0; } } @keyframes fade-in { from { opacity: 0; } }

Vantaggi

  • UX superiore: transizioni hardware-accelerated che riducono cognitive load con fallback automatico
  • Bundle size: -25 KB eliminando Framer Motion o React Spring per la maggior parte dei casi d'uso

Confronto performance: CSS vs JavaScript

Ecco una tabella comparativa basata su benchmark reali (metodologia: Chrome DevTools Performance panel, media di 10 run su MacBook Pro M1, throttling CPU 4x).

Confronto performance e bundle size: approcci JavaScript vs CSS nativi
FeatureApproccio JSBundle SizeFPS medioApproccio CSSBundle SizeFPS medioRisparmio
Responsive layoutreact-responsive+8 KB58 fpsContainer Queries0 KB60 fps-8 KB
Nestingnode-sass+12 KBN/ACSS Nesting0 KBN/A-12 KB
Theme switchCustom hook + state+3 KB57 fpslight-dark()0 KB60 fps-3 KB
Color variationscolor-mix utils+2 KBN/ARelative colors0 KBN/A-2 KB
Scroll animationsGSAP ScrollTrigger+30 KB52 fpsScroll-driven0 KB60 fps-30 KB
TooltipsPopper.js+15 KB55 fpsAnchor Positioning0 KB60 fps-15 KB
Page transitionsFramer Motion+25 KB54 fpsView Transitions0 KB60 fps-25 KB
TOTALE-+95 KB54 fps-0 KB60 fps-95 KB

Conclusione

Il CSS del 2025 ha raggiunto un livello di maturità che permette di eliminare gran parte delle dipendenze JavaScript tradizionalmente necessarie per layout complessi, temi, animazioni e posizionamento.

Recap delle 7 funzionalità:

  1. Container Queries: layout responsive basato su container, non viewport
  2. CSS Nesting: organizzazione codice senza preprocessor
  3. light-dark(): gestione temi nativa e automatica
  4. Relative Color Syntax: manipolazione colori dinamica
  5. Scroll-driven Animations: animazioni on scroll performanti
  6. Anchor Positioning: tooltip e popover senza JavaScript (sperimentale)
  7. View Transitions API: transizioni fluide tra stati

Quando adottarle

  • Container Queries, Nesting, light-dark(), Relative colors: ora (supporto universale)
  • Scroll-driven animations: ora con fallback (polyfill per Firefox)
  • Anchor Positioning: progressive enhancement (supporto limitato)
  • View Transitions: SPA ora, MPA in valutazione (supporto in crescita)

Impatto reale

  • -95 KB di JavaScript nel bundle (media)
  • +11% performance (da 54 a 60 fps)
  • Meno dipendenze da mantenere e aggiornare
  • Better DX: logica di presentazione nel CSS, non sparsa tra JS e CSS

Se vuoi approfondire altre proprietà CSS utili, leggi anche il nostro articolo su attr(), una funzione CSS poco conosciuta ma estremamente versatile.

Inizierai ad adottare queste feature nei tuoi progetti? Condividi la tua esperienza nei commenti!

CSS 2025: 7 Funzionalità Native che Sostituiscono JavaScript | artCode