Opens in a new tab

Pagina de carte — sapte miscari mici pe o pagina de produs

Demo propriu, nu portare. Inspirat de paginile de rezumat de carte de pe deepstash.com (octombrie 2026): am luat miscarile, nu designul, nu textele si nu brandul. Pagina live: /pagina-de-carte/. Textul e scris aici; cartea, Meditatiile lui Marcus Aurelius, e domeniu public. Nicio imagine — coperta e desenata in CSS.

Ce face — sapte miscari

  1. Antetul (o pastila alba, fixata sus) iese in sus cand derulezi in jos si revine la orice urcare. In primii 120px ramane mereu vizibil.
  2. La incarcare, coperta cade usor rotita si se aseaza, apoi eticheta, titlul, autorul si cele doua cifre urca pe rand. La hover, coperta se indreapta (de la -3 grade la 0) si o dunga de lumina trece peste ea — asta e CSS, nu GSAP.
  3. Nuanta paginii trece din galben-pal in alb cand incepe lista de idei, si inapoi la urcare.
  4. Ideile urca pe rand din transparent (20px), in loturi, pe masura ce intra in ecran. Apoi se deschid singure, una dupa alta, cand ajung la 66% din inaltimea ecranului, si raman deschise — ca in original. Prima e deschisa de la inceput. Un click pe titlu inchide sau redeschide doar ideea aceea; sageata se roteste, inaltimea se animeaza pana la auto.
  5. Bara de citire urca din josul ecranului cat timp esti in lista de idei si arata ideea din dreptul mijlocului ecranului („#3 — Pregateste-te dimineata…”), cu buton si iconita audio. Iese cand treci de lista.
  6. Cardurile de abonament se suprapun. Fiecare se lipeste sus (position: sticky), cu 28px mai jos decat cel dinainte, iar cel care vine peste el il micsoreaza putin (0,95, apoi 0,90). La final ramane un teanc in care se vad marginile celor de dedesubt.
  7. Bufnita din footer (copie dupa /bufnita/, aceeasi desenare SVG cu clasele redenumite bk-ow-*) sta in spatele cardului negru al footer-ului si urca peste marginea lui pe masura ce derulezi spre final (scrub). Odata iesita, se uita dupa mouse: pupilele cel mai mult, fata aluneca peste craniu (capul se intoarce in ax), corpul se apleaca abia simtit; clipeste din cand in cand si, fara mouse, se uita singura in jur. Inspirat de mascota din footer-ul paginii originale.

Ce cere site-ul

  • GSAP 3.13.0 + ScrollTrigger — deja globale. Nimic altceva: fara Lenis, fara plugin-uri.
  • Fonturi: Bricolage Grotesque (titluri) si Inter (text).
  • Culorile sunt cele patru ale site-ului (#111, #fff, #fff318, #FECB00), ca la Bufnita. Nuantele deschise sunt aceleasi culori cu transparenta.
  • Totul in px (tema are baza rem de 10px).

Cum e construit in Bricks

O sectiune, doua elemente Code: demo-ul si lista de animatii. Markup 8,5 KB, CSS 11,6 KB, JS 7,5 KB. 17 ScrollTrigger-e: unul pentru antet, unul pentru nuanta, sase pentru aparitia ideilor, unul pentru bara, sase pentru „ideea curenta” si doua pentru teanc.

  • Radacina: sectiunea .bk, _padding 0, _width: 100%. Element Code cu noRoot, executeCode, language: html, signature => wp_hash($code).
  • Page settings: bodyClasses: bk, headerDisabled, footerDisabled, disableLazyLoad. Pagina are antetul ei.
  • Pozitia de sus a fiecarui card de abonament vine din style="--i:0|1|2" in markup: top: calc(110px + var(--i) * 28px) (90px + 20px pe telefon). Al patrulea card primeste --i:3.
  • Constantele de reglaj sunt sus in JS: HEADER_SHOW_ABOVE, TINT, IDEA_RISE, OPEN_DURATION, STACK_SCALE_STEP.
  • Fara JavaScript pagina se citeste normal: prima idee e deschisa din CSS, bara de citire ramane ascunsa, cardurile tot se suprapun (sticky e CSS), doar fara micsorare.
  • Lista de animatii. Al doilea element Code al paginii, „Lista de animatii (se sterge la clonare)”, pune pe marginea dreapta o eticheta neagra Animatii. La click deschide lista numerotata a miscarilor de pe pagina; un click pe un rand duce pagina la animatia respectiva si o incadreaza cateva secunde. Randurile sunt scrise in markup (data-target = selectorul elementului care se misca); scriptul nu stie nimic despre pagina. La clonare se sterge tot elementul — nu atinge demo-ul.

Capcane

  • document.querySelector('.bk') intoarce <body>. Clasa din bodyClasses sta si pe body, iar body vine primul in document. Pe celelalte pagini nu s-a vazut, pentru ca toate cautarile pornesc de la radacina si body le contine pe toate. Aici s-a vazut: nuanta paginii se anima pe body, nu pe sectiune, si nu se schimba nimic. Radacina e .bk:not(body). Merita verificat pe orice pagina care animeaza chiar radacina.
  • Sticky nu suporta overflow: hidden pe niciun parinte. Radacina foloseste overflow-x: clip, care taie la fel, dar nu creeaza un container de derulare.
  • Antetul si bara erau centrate cu translate: -50%. GSAP citeste proprietatea translate si o muta in propriul transform — a mers, dar e fragil. Acum sunt centrate cu left: 0; right: 0; margin: auto, iar transformul e doar al lui GSAP.
  • Coperta are tranzitie CSS pe transform (pentru hover). Intrarea de la incarcare e pusa pe parintele .bk-book, nu pe coperta, altfel tranzitia CSS ar fi netezit fiecare cadru GSAP si intrarea ar fi intarziat.
  • Deschiderea automata merge una cate una, nu cu cate un ScrollTrigger pe idee. Prima varianta avea cate un trigger once pe fiecare idee. Ideile inchise stau aproape una de alta, asa ca la o singura rotita doua-trei treceau linia odata si se deschideau toate deodata. Acum un singur trigger pe sectiune masoara, la fiecare scroll, doar urmatoarea idee din coada, si o deschide abia dupa ce s-a terminat de deschis cea dinainte (care a impins-o in jos).
  • Dupa ce o idee se deschide sau se inchide, totul de dedesubt se muta, deci ScrollTrigger.refresh() la sfarsitul animatiei. La fel dupa document.fonts.ready.

Pasi de reproducere

  1. Copiaza markup-ul, CSS-ul si JS-ul in trei campuri ale unui element Code; pune clasa bk pe sectiune si pe body.
  2. Schimba textul (titlu, idei, abonamente). Numarul de idei si de carduri nu e scris nicaieri in JS — se numara singure.
  3. Verifica: 17 ScrollTrigger-e (sau cate rezulta din numarul de idei), nuanta trece in alb la lista, bara apare in lista si arata ideea corecta, cardurile ajung la scalare 0,90 / 0,95 / 1, zero overflow orizontal la latime mare si la 390px.