Dà profondità alle superfici e trasforma la barra in vetro
Fondo pagina, carte e `secondary` stavano dentro tre punti di luminosità:
carta e fondo avevano un rapporto di contrasto di 1.04, cioè erano lo stesso
bianco. Le carte non si leggevano come carte, e l'unica cosa che le staccava
era `shadow-card` — 6% di nero, che su un telefono al sole non esiste. Da qui
l'impressione che fondo, barra ed elementi fossero «tre bianchi».
La rampa dei neutri è ridistanziata: fondo 0.93, carta 1.0, `secondary` 0.90.
Carta e fondo passano a 1.23, un elemento dentro una carta sta a 1.35 dalla
carta ed è più scuro di essa, come nelle liste raggruppate di iOS. 0.93 è il
fondo più scuro possibile senza toccare altro: il limite lo impone
`text-accent` appoggiato sul fondo, che a 0.92 scenderebbe sotto 4.5.
Due colori vanno corretti di conseguenza, altrimenti la modifica peggiora la
leggibilità: l'accento scende a 0.54 (a 0.58 come testo faceva 4.07 sul nuovo
fondo; ora fa 4.62, e migliora anche il bianco che ci sta sopra, da 4.65 a
5.51) e `muted-foreground` a 0.48. Verificati convertendo le oklch in sRGB e
calcolando i rapporti, non a occhio.
`--destructive` e `--ring` erano *lo stesso identico colore* dell'accento:
«elimina», «selezionato» e «ho il focus qui» davano il medesimo segnale. Il
distruttivo resta rosso ma più scuro e cupo, il focus viene dal neutro.
Le ombre passano da una a tre quote: `shadow-card` per il contenuto,
`shadow-chrome` per barra, drawer e toast (più profonda, più il filo chiaro sul
bordo alto), `shadow-alza` neutra per l'hover — `premi` metteva un alone rosso
sotto ogni riga di classifica.
La barra ora usa `vetro`: fondo al 62% invece dell'85%, così ci si vede
attraverso, più tre ombre interne che sono il bordo illuminato. L'85% di
`materiale` esiste per tenere allineati WebKit e Blink (608f2ed) su una fascia
larga quanto lo schermo; su una pillola di 60 px lo scarto non si legge.
Dietro `@supports`, un `feDisplacementMap` distorce davvero il fondale: solo
Blink accetta un filtro SVG in `backdrop-filter`, e WebKit ignorando l'url
scarterebbe anche il blur. Miglioria progressiva, non l'effetto principale.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,8 +5,8 @@
|
|||||||
"lang": "it",
|
"lang": "it",
|
||||||
"start_url": "/",
|
"start_url": "/",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"background_color": "#fafafb",
|
"background_color": "#e4e8ed",
|
||||||
"theme_color": "#fafafb",
|
"theme_color": "#e4e8ed",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
import { CalendarDays, Home, Trophy, Users } from "lucide-react";
|
import { CalendarDays, Home, Trophy, Users } from "lucide-react";
|
||||||
|
import { motion, useReducedMotion } from "motion/react";
|
||||||
|
import { molla } from "@/lib/molla";
|
||||||
|
|
||||||
// Quattro voci e non cinque: il profilo sta in alto a destra
|
// Quattro voci e non cinque: il profilo sta in alto a destra
|
||||||
// nell'intestazione di ogni pagina, dove lo cerca chi arriva da iOS.
|
// nell'intestazione di ogni pagina, dove lo cerca chi arriva da iOS.
|
||||||
@@ -11,6 +13,8 @@ const items = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export function BottomNav() {
|
export function BottomNav() {
|
||||||
|
const ridotto = useReducedMotion();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
aria-label="Navigazione principale"
|
aria-label="Navigazione principale"
|
||||||
@@ -20,31 +24,75 @@ export function BottomNav() {
|
|||||||
// arrivare al contenuto sotto.
|
// arrivare al contenuto sotto.
|
||||||
className="pad-sicura-fondo pointer-events-none fixed inset-x-0 bottom-0 z-40 px-3"
|
className="pad-sicura-fondo pointer-events-none fixed inset-x-0 bottom-0 z-40 px-3"
|
||||||
>
|
>
|
||||||
|
{/*
|
||||||
|
La mappa di spostamento del vetro. `feTurbulence` a bassa frequenza dà
|
||||||
|
una deformazione lenta e irregolare — la stessa cosa che fa un vetro non
|
||||||
|
perfettamente piano — e la sfocatura che segue toglie il granuloso del
|
||||||
|
rumore, altrimenti il fondale si sgranerebbe invece di piegarsi.
|
||||||
|
|
||||||
|
Nessuna dimensione e nessun colore: è solo la definizione del filtro che
|
||||||
|
il CSS richiama per id. La usa solo Blink (vedi `@supports` in
|
||||||
|
styles.css); su WebKit questo SVG resta lì senza fare niente.
|
||||||
|
*/}
|
||||||
|
<svg aria-hidden="true" className="absolute h-0 w-0" focusable="false">
|
||||||
|
<filter id="vetro-rifrazione" colorInterpolationFilters="sRGB">
|
||||||
|
<feTurbulence
|
||||||
|
type="fractalNoise"
|
||||||
|
baseFrequency="0.008 0.016"
|
||||||
|
numOctaves={2}
|
||||||
|
seed={7}
|
||||||
|
result="rumore"
|
||||||
|
/>
|
||||||
|
<feGaussianBlur in="rumore" stdDeviation={3} result="mappa" />
|
||||||
|
<feDisplacementMap
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="mappa"
|
||||||
|
scale={16}
|
||||||
|
xChannelSelector="R"
|
||||||
|
yChannelSelector="G"
|
||||||
|
/>
|
||||||
|
</filter>
|
||||||
|
</svg>
|
||||||
|
|
||||||
{/*
|
{/*
|
||||||
Altezza fissa dal token, non dedotta dal contenuto: la striscia
|
Altezza fissa dal token, non dedotta dal contenuto: la striscia
|
||||||
toccabile misura uguale su iOS e Android, e sotto varia solo l'inset
|
toccabile misura uguale su iOS e Android, e sotto varia solo l'inset
|
||||||
di sistema. Prima l'altezza dipendeva dai padding delle voci e nessuno
|
di sistema. Prima l'altezza dipendeva dai padding delle voci e nessuno
|
||||||
poteva saperla da fuori.
|
poteva saperla da fuori.
|
||||||
*/}
|
*/}
|
||||||
<div className="materiale pointer-events-auto mx-auto grid h-[var(--altezza-nav)] max-w-md grid-cols-4 overflow-hidden rounded-full border border-border/60 px-1 shadow-lg">
|
{/* `vetro` porta con sé le proprie ombre, quindi niente `shadow-chrome`:
|
||||||
|
sarebbero due `box-shadow` sullo stesso elemento e una vincerebbe. */}
|
||||||
|
<div className="vetro pointer-events-auto mx-auto grid h-[var(--altezza-nav)] max-w-md grid-cols-4 rounded-full border border-white/40 p-1.5">
|
||||||
{items.map(({ to, label, icon: Icon }) => (
|
{items.map(({ to, label, icon: Icon }) => (
|
||||||
<Link
|
<Link
|
||||||
key={to}
|
key={to}
|
||||||
to={to}
|
to={to}
|
||||||
activeOptions={{ exact: to === "/" }}
|
activeOptions={{ exact: to === "/" }}
|
||||||
activeProps={{ "aria-current": "page" }}
|
activeProps={{ "aria-current": "page" }}
|
||||||
// Lo stato attivo non è solo colore: cambia anche il peso del
|
// Lo stato attivo non è solo colore: è la capsula piena sotto la
|
||||||
// testo e compare la barretta sopra l'icona.
|
// voce, più il peso del testo. Chi non distingue i colori vede
|
||||||
className="group relative flex h-full flex-col items-center justify-center gap-1 text-xs font-semibold text-muted-foreground transition-colors data-[status=active]:font-extrabold data-[status=active]:text-accent"
|
// comunque quale voce è quella corrente.
|
||||||
|
className="group relative flex h-full flex-col items-center justify-center gap-0.5 rounded-full text-xs font-semibold text-muted-foreground transition-colors data-[status=active]:font-extrabold data-[status=active]:text-accent-foreground"
|
||||||
>
|
>
|
||||||
{({ isActive }) => (
|
{({ isActive }) => (
|
||||||
<>
|
<>
|
||||||
<span
|
{isActive ? (
|
||||||
|
<motion.span
|
||||||
|
// `layoutId`: la capsula è un solo elemento che scivola da
|
||||||
|
// una voce all'altra invece di sparire e ricomparire. La
|
||||||
|
// molla è interrompibile, quindi due tocchi rapidi non
|
||||||
|
// fanno saltare la posizione.
|
||||||
|
layoutId="capsula-nav"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="absolute inset-x-4 top-0 h-0.5 rounded-full bg-accent opacity-0 transition-opacity group-data-[status=active]:opacity-100"
|
className="bg-accent-grad absolute inset-0 rounded-full shadow-pop"
|
||||||
|
transition={ridotto ? { duration: 0 } : molla.ui}
|
||||||
/>
|
/>
|
||||||
|
) : null}
|
||||||
|
{/* Sopra la capsula, che è in flusso normale sotto di loro. */}
|
||||||
|
<span className="relative flex flex-col items-center gap-0.5">
|
||||||
<Icon className="h-5 w-5" strokeWidth={isActive ? 2.6 : 2.2} />
|
<Icon className="h-5 w-5" strokeWidth={isActive ? 2.6 : 2.2} />
|
||||||
{label}
|
{label}
|
||||||
|
</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const DrawerContent = React.forwardRef<
|
|||||||
<DrawerPrimitive.Content
|
<DrawerPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
|
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background shadow-chrome",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
|||||||
toastOptions={{
|
toastOptions={{
|
||||||
classNames: {
|
classNames: {
|
||||||
toast:
|
toast:
|
||||||
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
|
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-chrome",
|
||||||
description: "group-[.toast]:text-muted-foreground",
|
description: "group-[.toast]:text-muted-foreground",
|
||||||
actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
||||||
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()(
|
|||||||
{ name: "author", content: "CRAP Volley" },
|
{ name: "author", content: "CRAP Volley" },
|
||||||
// Deve combaciare con --background, altrimenti la barra di stato resta
|
// Deve combaciare con --background, altrimenti la barra di stato resta
|
||||||
// nera sopra un'interfaccia chiara.
|
// nera sopra un'interfaccia chiara.
|
||||||
{ name: "theme-color", content: "#fafafb" },
|
{ name: "theme-color", content: "#e4e8ed" },
|
||||||
{ property: "og:title", content: "CrAPP — L'app del CRAP Volley" },
|
{ property: "og:title", content: "CrAPP — L'app del CRAP Volley" },
|
||||||
{
|
{
|
||||||
property: "og:description",
|
property: "og:description",
|
||||||
|
|||||||
+122
-12
@@ -75,7 +75,25 @@
|
|||||||
*/
|
*/
|
||||||
--altezza-nav: 3.75rem;
|
--altezza-nav: 3.75rem;
|
||||||
--pad-sicura-fondo: max(env(safe-area-inset-bottom), 0.5rem);
|
--pad-sicura-fondo: max(env(safe-area-inset-bottom), 0.5rem);
|
||||||
--background: oklch(0.985 0.002 240);
|
/*
|
||||||
|
* Rampa dei neutri, distanziata per essere vista.
|
||||||
|
*
|
||||||
|
* Prima fondo (0.985), carta (1.0) e `secondary` (0.955) stavano dentro tre
|
||||||
|
* punti di luminosità: carta e fondo avevano un rapporto di contrasto di
|
||||||
|
* 1.04, cioè erano lo stesso bianco. Le carte non si leggevano come carte e
|
||||||
|
* l'unica cosa che le staccava era `shadow-card`, che su un telefono al sole
|
||||||
|
* sparisce.
|
||||||
|
*
|
||||||
|
* Ora fondo 0.93 e carta 1.0 stanno a 1.23, e `secondary` (0.90) sta a 1.35
|
||||||
|
* dalla carta: un elemento dentro una carta è più scuro della carta, come
|
||||||
|
* nelle liste raggruppate di iOS.
|
||||||
|
*
|
||||||
|
* 0.93 è il fondo più scuro possibile senza toccare altro: il limite lo
|
||||||
|
* impone `text-accent` appoggiato sul fondo, che qui vale 4.62 e a 0.92
|
||||||
|
* scenderebbe a 4.48, sotto AA. Per andare più giù va scurito anche
|
||||||
|
* l'accento.
|
||||||
|
*/
|
||||||
|
--background: oklch(0.93 0.008 255);
|
||||||
--foreground: oklch(0.16 0.01 260);
|
--foreground: oklch(0.16 0.01 260);
|
||||||
--card: oklch(1 0 0);
|
--card: oklch(1 0 0);
|
||||||
--card-foreground: oklch(0.16 0.01 260);
|
--card-foreground: oklch(0.16 0.01 260);
|
||||||
@@ -83,17 +101,29 @@
|
|||||||
--popover-foreground: oklch(0.16 0.01 260);
|
--popover-foreground: oklch(0.16 0.01 260);
|
||||||
--primary: oklch(0.16 0.012 265);
|
--primary: oklch(0.16 0.012 265);
|
||||||
--primary-foreground: oklch(0.99 0 0);
|
--primary-foreground: oklch(0.99 0 0);
|
||||||
--secondary: oklch(0.955 0.004 250);
|
--secondary: oklch(0.9 0.01 255);
|
||||||
--secondary-foreground: oklch(0.2 0.012 265);
|
--secondary-foreground: oklch(0.2 0.012 265);
|
||||||
--muted: oklch(0.955 0.004 250);
|
--muted: oklch(0.925 0.008 255);
|
||||||
--muted-foreground: oklch(0.52 0.015 260);
|
/* 0.48 e non 0.52: sul nuovo `secondary` il vecchio valore scendeva a 4.2. */
|
||||||
--accent: oklch(0.58 0.22 27);
|
--muted-foreground: oklch(0.48 0.015 260);
|
||||||
|
/*
|
||||||
|
* Accento più scuro (era 0.58): su un fondo più scuro il rosso di prima
|
||||||
|
* scendeva a 4.07 come testo. A 0.54 migliora in tutte e tre le direzioni —
|
||||||
|
* 4.62 sul fondo, 5.67 sulla carta, 5.51 per il bianco che ci sta sopra.
|
||||||
|
*/
|
||||||
|
--accent: oklch(0.54 0.22 27);
|
||||||
--accent-foreground: oklch(0.99 0 0);
|
--accent-foreground: oklch(0.99 0 0);
|
||||||
--destructive: oklch(0.58 0.22 27);
|
/*
|
||||||
|
* Distruttivo e accento erano lo stesso identico colore: «elimina» e
|
||||||
|
* «selezionato» davano lo stesso segnale. Resta rosso — è la convenzione —
|
||||||
|
* ma più scuro e più cupo dell'accento del brand.
|
||||||
|
*/
|
||||||
|
--destructive: oklch(0.47 0.19 18);
|
||||||
--destructive-foreground: oklch(0.99 0 0);
|
--destructive-foreground: oklch(0.99 0 0);
|
||||||
--border: oklch(0.915 0.006 255);
|
--border: oklch(0.875 0.01 255);
|
||||||
--input: oklch(0.915 0.006 255);
|
--input: oklch(0.875 0.01 255);
|
||||||
--ring: oklch(0.58 0.22 27);
|
/* Il focus non è una selezione: viene dal neutro, non dall'accento. */
|
||||||
|
--ring: oklch(0.35 0.03 265);
|
||||||
/* Luminosità scelte perché il testo bianco sopra superi 4.5:1 (WCAG AA). */
|
/* Luminosità scelte perché il testo bianco sopra superi 4.5:1 (WCAG AA). */
|
||||||
--success: oklch(0.53 0.16 152);
|
--success: oklch(0.53 0.16 152);
|
||||||
--success-foreground: oklch(0.99 0 0);
|
--success-foreground: oklch(0.99 0 0);
|
||||||
@@ -117,9 +147,26 @@
|
|||||||
oklch(0.24 0.03 20) 55%,
|
oklch(0.24 0.03 20) 55%,
|
||||||
oklch(0.45 0.19 27)
|
oklch(0.45 0.19 27)
|
||||||
);
|
);
|
||||||
--gradient-accent: linear-gradient(120deg, oklch(0.58 0.22 27), oklch(0.68 0.19 40));
|
/* Parte dall'accento nuovo: era rimasto sul vecchio 0.58 e il gradiente
|
||||||
|
risultava più chiaro del colore pieno che gli sta accanto. */
|
||||||
|
--gradient-accent: linear-gradient(120deg, oklch(0.54 0.22 27), oklch(0.64 0.19 40));
|
||||||
|
/*
|
||||||
|
* Tre quote, non una. Prima `shadow-card` valeva sia per una tessera 3x3 sia
|
||||||
|
* per la barra di navigazione: superfici grandi e piccole sullo stesso piano.
|
||||||
|
* Una superficie più grande deve leggersi più spessa.
|
||||||
|
*/
|
||||||
--shadow-card: 0 1px 2px oklch(0.16 0.01 260 / 6%), 0 12px 28px -18px oklch(0.16 0.01 260 / 35%);
|
--shadow-card: 0 1px 2px oklch(0.16 0.01 260 / 6%), 0 12px 28px -18px oklch(0.16 0.01 260 / 35%);
|
||||||
--shadow-pop: 0 18px 40px -20px oklch(0.58 0.22 27 / 55%);
|
/*
|
||||||
|
* Chrome flottante: barra, drawer. Ombra più profonda e più diffusa, più il
|
||||||
|
* filo chiaro sul bordo alto — la luce che prende il materiale, ed è quello
|
||||||
|
* che lo fa leggere come un oggetto sopra il contenuto invece che un buco.
|
||||||
|
*/
|
||||||
|
--shadow-chrome:
|
||||||
|
inset 0 1px 0 oklch(1 0 0 / 60%), 0 1px 3px oklch(0.16 0.01 260 / 10%),
|
||||||
|
0 24px 48px -24px oklch(0.16 0.01 260 / 45%);
|
||||||
|
/* Sollevamento al passaggio del mouse: neutro, non tinto di accento. */
|
||||||
|
--shadow-alza: 0 12px 28px -14px oklch(0.16 0.01 260 / 40%);
|
||||||
|
--shadow-pop: 0 18px 40px -20px oklch(0.54 0.22 27 / 55%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
@@ -158,6 +205,10 @@
|
|||||||
box-shadow: var(--shadow-pop);
|
box-shadow: var(--shadow-pop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@utility shadow-chrome {
|
||||||
|
box-shadow: var(--shadow-chrome);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Il tracking del display è specifico per taglia: Bebas Neue a corpo grande
|
* Il tracking del display è specifico per taglia: Bebas Neue a corpo grande
|
||||||
* legge troppo spaziato (serve tracking negativo), a corpo piccolo troppo
|
* legge troppo spaziato (serve tracking negativo), a corpo piccolo troppo
|
||||||
@@ -290,7 +341,9 @@
|
|||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: var(--shadow-pop);
|
/* Neutra: `shadow-pop` è un alone di accento, e sotto una riga di
|
||||||
|
classifica era colore senza significato. */
|
||||||
|
box-shadow: var(--shadow-alza);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -378,6 +431,63 @@
|
|||||||
-webkit-backdrop-filter: blur(20px) saturate(150%);
|
-webkit-backdrop-filter: blur(20px) saturate(150%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Vetro della barra flottante. È `materiale` spinto: si vede attraverso.
|
||||||
|
*
|
||||||
|
* `materiale` sta all'85% di card perché è una superficie larga quanto lo
|
||||||
|
* schermo, dove il divario di blur fra WebKit e Blink si nota (608f2ed). Qui
|
||||||
|
* la superficie è una pillola piccola: si può scendere al 62% e lasciare che
|
||||||
|
* sia il blur a fare il lavoro, che è la condizione perché si legga come vetro
|
||||||
|
* invece che come plastica bianca.
|
||||||
|
*
|
||||||
|
* Le tre ombre interne sono la luce sul bordo, non decorazione: filo chiaro in
|
||||||
|
* alto (la luce che entra), filo scuro in basso (lo spessore del vetro), alone
|
||||||
|
* chiaro diffuso appena dentro il bordo (il riflesso sulla curva). Senza queste
|
||||||
|
* un rettangolo sfocato resta un rettangolo sfocato.
|
||||||
|
*/
|
||||||
|
@utility vetro {
|
||||||
|
background-color: color-mix(in srgb, var(--color-card) 62%, transparent);
|
||||||
|
backdrop-filter: blur(18px) saturate(180%) brightness(1.04);
|
||||||
|
-webkit-backdrop-filter: blur(18px) saturate(180%) brightness(1.04);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 oklch(1 0 0 / 85%),
|
||||||
|
inset 0 -1px 0 oklch(0.16 0.01 260 / 8%),
|
||||||
|
inset 0 0 12px oklch(1 0 0 / 35%),
|
||||||
|
0 1px 3px oklch(0.16 0.01 260 / 10%),
|
||||||
|
0 24px 48px -24px oklch(0.16 0.01 260 / 45%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* La distorsione vera: `feDisplacementMap` sposta i pixel del fondale, quindi
|
||||||
|
* quello che sta sotto si deforma davvero invece di sfocarsi soltanto.
|
||||||
|
*
|
||||||
|
* Sta dietro `@supports` perché solo Blink accetta un filtro SVG dentro
|
||||||
|
* `backdrop-filter`: WebKit lo ignora — e ignorandolo scarterebbe tutta la
|
||||||
|
* dichiarazione, blur compreso — quindi su iPhone resta la regola sopra. È una
|
||||||
|
* miglioria progressiva, non l'effetto principale: se sparisse domani la barra
|
||||||
|
* resterebbe quella giusta.
|
||||||
|
*/
|
||||||
|
@supports (backdrop-filter: url("#vetro-rifrazione")) {
|
||||||
|
.vetro {
|
||||||
|
backdrop-filter: url("#vetro-rifrazione") blur(18px) saturate(180%) brightness(1.04);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Il vetro traslucido è un vezzo: se l'utente chiede meno trasparenza sparisce. */
|
||||||
|
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
|
||||||
|
.vetro {
|
||||||
|
background-color: var(--color-card);
|
||||||
|
backdrop-filter: none;
|
||||||
|
-webkit-backdrop-filter: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
|
||||||
|
.vetro {
|
||||||
|
background-color: var(--color-card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Chrome su Android disattiva `backdrop-filter` quando l'accelerazione
|
* Chrome su Android disattiva `backdrop-filter` quando l'accelerazione
|
||||||
* hardware non è disponibile: senza questo, su quei device la barra resta
|
* hardware non è disponibile: senza questo, su quei device la barra resta
|
||||||
|
|||||||
Reference in New Issue
Block a user