# Reveal on scroll

> A section that fades in and slides up gently as it enters the screen.

- Category: [Text & scroll](https://library.aimran.es/components/text-scroll)
- Built with: React + Motion
- Live editor: https://library.aimran.es/blocks/scroll-section-reveal
- Library: AIMRAN Library (https://library.aimran.es), free, no sign-up, by Aimran Oukham

## Where to use it

A soft reveal on scroll gives long pages a sense of rhythm, as if each part arrives when you reach it. It suits the steps of a “How it works” section, the testimonials of a coaching site or a long sales page. Done this subtly, a fade in on scroll animation supports the reading instead of interrupting it.

Keep the distance small, 20 to 30 pixels; bigger jumps feel like the page is loading late. Do not apply it to every paragraph. Reveal whole sections, and leave the first screen static so nothing is hidden when the page opens.

## Code

### React (Motion)

```tsx
import { motion } from "framer-motion";

const spring = { type: "spring" as const, stiffness: 300, damping: 30 };

interface ScrollRevealProps {
  distance?: number;
  /** true: caja de demo con scroll propio. false: solo la sección, que aparece con el scroll de la página. */
  contained?: boolean;
}

export default function ScrollReveal({
  distance = 28,
  contained = true,
}: ScrollRevealProps) {
  // whileInView observa el viewport y tiene en cuenta el recorte del contenedor, así sirve en ambos modos.
  const section = (
    <motion.div
      initial={{ opacity: 0, y: distance }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: false, amount: 0.6 }}
      transition={spring}
      className="rounded-[22px] bg-white dark:bg-[#1c1c1e] p-6 text-[#1d1d1f] dark:text-[#f5f5f7] shadow-[0_1px_2px_rgba(0,0,0,0.03),0_8px_28px_rgba(0,0,0,0.05)]"
    >
      <h3 className="text-lg font-semibold sm:text-xl">A pause, right here.</h3>
      <p className="mt-2 text-sm text-[#86868b]">This content appears as it scrolls into view.</p>
    </motion.div>
  );

  if (!contained) return section;

  return (
    <div className="h-60 w-full overflow-y-auto rounded-2xl bg-black/5 p-5 dark:bg-white/10">
      <div className="h-24" />
      {section}
      <div className="h-32" />
    </div>
  );
}
```

## Prompt for AI assistants

Paste this into ChatGPT, Claude, Cursor, v0 or Lovable to adapt the block to your stack (Tailwind, Vue, Svelte…):

````text
I want to add the “Reveal on scroll” block (Text & scroll) from AIMRAN Library to my project.

## What it is
A section that fades in and slides up gently as it enters the screen.

## Chosen settings
- Distance: 28px (from 10 to 60px)

## What I need
1. Add it to my project with the same look and animation as the reference code: same sizes, colours, radii, shadows, timings and easing.
2. It is built with React + TypeScript, with framer-motion for the animation and lucide-react for the icons. If my project uses something else (Vue, Svelte, Astro, plain HTML…), translate it without losing any behaviour. If I use Tailwind, turn the styles into classes; if not, keep the CSS in its own file.
3. Expose the settings above as props (or CSS variables) with those values as defaults.
4. Make it work well on phones: nothing that depends only on hover, touch targets of at least 44 px and no overflow on 320 px screens.
5. Make it look right in light and dark mode.
6. Keep it accessible: semantic HTML, roles and aria-* where needed, visible focus and keyboard support.
7. Respect prefers-reduced-motion: with reduced motion, no big animations but the same end result.

## Reference code
```tsx
import { motion } from "framer-motion";

const spring = { type: "spring" as const, stiffness: 300, damping: 30 };

interface ScrollRevealProps {
  distance?: number;
  /** true: caja de demo con scroll propio. false: solo la sección, que aparece con el scroll de la página. */
  contained?: boolean;
}

export default function ScrollReveal({
  distance = 28,
  contained = true,
}: ScrollRevealProps) {
  // whileInView observa el viewport y tiene en cuenta el recorte del contenedor, así sirve en ambos modos.
  const section = (
    <motion.div
      initial={{ opacity: 0, y: distance }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: false, amount: 0.6 }}
      transition={spring}
      className="rounded-[22px] bg-white dark:bg-[#1c1c1e] p-6 text-[#1d1d1f] dark:text-[#f5f5f7] shadow-[0_1px_2px_rgba(0,0,0,0.03),0_8px_28px_rgba(0,0,0,0.05)]"
    >
      <h3 className="text-lg font-semibold sm:text-xl">A pause, right here.</h3>
      <p className="mt-2 text-sm text-[#86868b]">This content appears as it scrolls into view.</p>
    </motion.div>
  );

  if (!contained) return section;

  return (
    <div className="h-60 w-full overflow-y-auto rounded-2xl bg-black/5 p-5 dark:bg-white/10">
      <div className="h-24" />
      {section}
      <div className="h-32" />
    </div>
  );
}
```

Give me the complete final code, ready to paste, and tell me in one line where to put it in my project.
````
