28256 sujets

CSS et mise en forme, CSS3

Modérateur
Salut tout le monde,

J'ai fait quelques tests avec l'API des View Transitions sur un projet « bac à sable » Flask.

Je sais que le support des navigateurs est encore partiel , mais je me suis dit que ce n'était pas un problème : au pire, on est pile dans le concept d'amélioration progressive.

Le problème, c'est que de mon côté, le rendu n'est pas du tout convaincant.

Alors qu'en local sur des fichiers HTML plats (ou via un bête python -m http.server), le pré-rendu et les transitions sont d'une fluidité absolue (façon SPA), dès que ça tourne derrière Flask ou autres, le comportement devient super instable : j'ai des micros-saccades, des silent discards (le navigateur qui jette la page pré-rendue au dernier moment) ou des transitions qui sautent au clic.

J'ai essayé de creuser (middlewares asynchrones avec gevent / Gunicorn, nettoyage des en-têtes HTTP comme Vary, forçage du cache), mais le navigateur semble hyper capricieux dès qu'il communique avec un serveur dynamique plutôt qu'avec du statique pur.

Du coup, je serais curieux d'avoir vos retours : avez-vous expérimenté le sujet en dehors de fichiers HTML plats ? Vous avez réussi à avoir un truc stable et fluide sur un environnement de dev dynamique ?

Merci d'avance pour vos lumières !

ps : En attendant, j'utilise d'autres solutions. Mais j'aimerais passer en natif
Modifié par Niuxe (26 May 2026 - 23:50)
Bonjour Niuxe,

Je viens de faire un test pour voir (car je ne m'y étais encore jamais collé), sur un site statique seulement, des Github Pages), j'ai fais ceci :
/* 1. Activation du moteur de transition inter-documents */
@view-transition {
  navigation: auto;
}

/* 2. Mapping des discriminants sur les invariants de la structure HTML */
.nav {
  view-transition-name: layout-nav;
}

#main {
  view-transition-name: layout-main;
}

.footer {
  view-transition-name: layout-footer;
}

.alert {
  view-transition-name: layout-alert;
}


Le résultat : scriptura.github.io

Donc pas d'injection JS, pour l'instant c'est c'est très généraliste et dédié au Multi-Page.

Et toi Niuxe, qu'as-tu tenté comme essai pour l'instant (édit : sur Flask) ? Tu peux nous montrer ?
Modifié par Olivier C (28 May 2026 - 14:44)
Avant de tester moi aussi les pages dynamiques je me suis un peu penché sur ton problème :

Pour un Cross-Document View Transition le navigateur déclenche un timeout, si la valeur définie par le navigateur est dépassée (sans doute en millisecondes, mais combien ? ***) le contrat avec l'API est rompu et l'API n'est plus applicable.

Situation aggravante : si Flask envoie le HTML par fragments et que ceux-ci sont mal orchestrés, là encore Cross-Document View Transition échouera.

Ton problème Niuxe : tu as cherché à optimiser la concurrence et le cache, mais le problème vient de la latence. Ici le cache n'est d'aucun secours si ta page est entièrement dynamique, en effet, dans ce cas là le navigateur est obligé de contourner le cache ou d'émettre une requête de revalidation, ce qui ne supprime pas la latence.

Une ressource utile : CSS Tricks : Cross-Document View Transitions: The Gotchas Nobody Mentions, Your Transition Will Randomly Die, and Here’s Why

---
*** édit : l'article de css-tricks le précise : un délai d'expiration silencieux de 4 secondes qui annule la transition si la page met trop de temps à charger.
Modifié par Olivier C (28 May 2026 - 17:25)
Modérateur
Bonsoir Olivier,

Merci beaucoup pour ton retour et pour tes tests ! Ton exemple sur GitHub Pages montre bien que sur du statique pur, l'API fait des miracles sans une seule ligne de JS.

Voici la base CSS que j'utilise pour mes tests :

/* Animations Layer */
@layer animations {
    /* View Transitions */
    @view-transition {
        navigation: auto;
    }

    ::view-transition-group(nav-shadow) {
        animation-duration: .5s;
        animation-timing-function: linear(
        0, 0.14 4%, 0.94 17%, 1.15 24% 30%, 1.02 43%, 0.98 51%, 1
        );
        animation-fill-mode: both;
    }

    ::view-transition-old(nav-shadow),
    ::view-transition-new(nav-shadow) {
        height: 100%;
    }

    ::view-transition-group(navigation) {
        z-index: 1;
    }

    ::view-transition-old(main) {
        animation:
        .2s cubic-bezier(0.4, 0, 1, 1) both fade-out,
        .5s cubic-bezier(0.4, 0, 0.2, 1) both slide-out;
    }

    ::view-transition-new(main) {
        animation:
        .3s cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
        .5s cubic-bezier(0.4, 0, 0.2, 1) both slide-in;
    }

    /* Keyframe Animations */
    @keyframes fade-in {
        from { opacity: 0; }
    }

    @keyframes fade-out {
        to { opacity: 0; }
    }

    @keyframes slide-in {
        from { transform: translateY(-2rem); }
    }

    @keyframes slide-out {
        to { transform: translateY(5rem); }
    }
}



Et côté HTML, j'ai écrit ces Speculation Rules pour essayer de forcer le pré-rendu en tâche de fond

        <script type="speculationrules">
        {
            "prerender": [
                {
                    "where": {
                        "href_matches": "/*"
                    },
                    "eagerness": "moderate"
                }
            ]
        }
        </script>


Le serveur de dev de Flask n'est pas réputé pour sa rapidité fulgurante, c'est un fait (c'est normal, en fait). Pour en avoir le cœur net, j'ai migré mes tests sur un environnement PHP local basique. Résultat : j'obtiens quasiment le même comportement instable.

Un serveur de fichiers plats (comme GitHub Pages ou Nginx configuré pour du statique) renvoie le code instantanément sans se poser de questions.

Dès que l'on passe sur du dynamique (Flask, PHP, Django...), le cycle de vie est totalement différent :

1. Analyse de la requête.
2. Connexion et requêtes vers la base de données.
3. Compilation et injection des données dans le moteur de template (Jinja2, Twig, etc.).

Même sur un projet léger, on se prend facilement une latence de 100ms à 300ms (parfois un peu plus en dev). Et c'est là que le bât blesse : bien que le timeout « officiel » de l'API soit de 4 secondes pour charger la page complète, le moteur graphique de Chromium, lui, semble faire des silent discards (il jette le snapshot de transition à la poubelle) bien avant si les premiers octets (TTFB) mettent plus de quelques dizaines de millisecondes à arriver.

Le navigateur repasse alors instantanément en navigation classique, ce qui provoque ces micro-saccades ou ces transitions qui sautent de manière aléatoire.

C'est dommage, car l'approche « zéro JS » est intéressante sur le papier, mais pour l'instant, l'API native semble trop rigide pour encaisser proprement la latence naturelle des architectures serveurs classiques en cours de développement.