# Animations & Interactions

## Animations & Interactions

**Files:** `src/config/config.toml`, section content files · **Skill level:** Beginner

Homio's motion is calm on purpose: content fades in with a small rise, once, as it scrolls into view. There is no blur, tilt, or floating, and hover effects change colour or underline only. Every animation respects the visitor's **reduce motion** setting.

### Fade-In On Scroll
```toml
[settings.animation]
  enable               = true
  respectReducedMotion = true
  easing               = "cubic-bezier(0.215, 0.61, 0.355, 1)" # standard ease-out; avoid springy curves
  duration             = "600ms"   # reveal and intro duration
  distance             = "0.75rem" # how far content rises while fading in
  rootMargin           = "0px 0px -8% 0px"
  threshold            = 0.14      # how much of an element is visible before it starts
```

- `enable = false` shows everything at once, with no fade.
- Keep `respectReducedMotion = true`: some visitors get dizzy from motion.
- Keep `distance` small for a calm feel.

Content already in view when the page loads fades in right away, without waiting for a scroll. Without JavaScript, everything shows with no fade.

Developers can add the effect to any element with the `data-scroll-reveal` attribute (most theme sections use `data-scroll-reveal="fade-up"`). `data-scroll-reveal-delay` and `data-scroll-reveal-duration` set the timing of one element, in milliseconds. The script is in `src/layouts/components/widgets/GlobalScripts.astro`, and the styles in `src/styles/animation.css`.

### Count-Up Numbers
Numbers count up from zero when they scroll into view: the numbers section (`metrics-section.md`), the figures in the about hero, the why-us `story` block, the trust strip rating, the reviews counter and rating summary, and the booking `card`.

```yaml
# src/content/sections/english/metrics-section.md
list:
  - value: 12 # sample
    appendValue: "k+"
    label: "Homes cleaned"
  - value: 4.9 # sample; keep it equal to the rating in trust-strip.md
    label: "Average rating"
```

- Write `value` as a plain number, and put text before or after it in `prependValue` or `appendValue`.
- The number follows the page language: `4.9` in English shows as `4,9` in French.
- The page's HTML always holds the final value, so search engines, screen readers, and visitors without JavaScript see the real number.
- With reduced motion, or `[settings.animation] enable = false`, the final value shows at once.
- In the about hero, `count: false` on a figure keeps it still (the founding year `2014` doesn't count up).

### Instant Estimate Total
The estimator's total counts between the old and new price when the visitor changes the job:

```toml
[settings.estimator]
  animateTotal = true # count between totals; always off with reduced motion
```

The new total is also announced once to screen readers.

### Accordions And Disclosures
FAQ questions slide open and closed. Other disclosures (such as "Show all rooms", the list of all areas, the hours table, and the footer columns on phones) slide too, in browsers that can animate to an automatic height; in others they open at once. With reduced motion, they all open without animation. The styles are in `src/styles/animation.css`.

### The Header Menu
On large screens, the header menus share one dropdown panel. When a menu opens, the panel tilts into place while it fades in, and its rows and columns rise one after another. Moving between menus, the panel resizes and glides to the new item while the content slides across. With reduced motion, the panel only fades. There is no setting for it; the styles are in `src/styles/navigation.css`. See [Header & Mobile Bar](/homio/customization/header/).

### Moving Reviews (Marquee)
The reviews `marquee` layout shows rows of short reviews moving slowly in opposite directions. A row pauses on hover and keyboard focus. Its speed is in `reviews-section.md`:

```yaml
marquee:
  duration: "90s" # one full loop; slower is calmer
  rows: 2         # 1 | 2 (phones always show one row)
  reverse: ""     # "reverse" flips both rows
```

With reduced motion, or `[settings.animation] enable = false`, the reviews show as a still row you can scroll.

### Smooth Scrolling (Off By Default)
Homio uses the browser's normal scrolling. You can turn on smooth scrolling (powered by Lenis):

```toml
[settings.smoothScroll]
  enable               = false  # true turns on Lenis smooth scrolling
  respectReducedMotion = true
  duration             = 1.1    # higher feels slower and smoother
  easing               = "expo" # expo | linear | easeOutQuad | easeOutCubic
  smoothWheel          = true
  syncTouch            = false
  anchors              = true
```

Native scrolling is the safer choice for most visitors, especially on phones and with keyboard or assistive navigation. If you turn it on, keep `respectReducedMotion = true`.

### Other Interactions
These are not animations to configure, but they move:

| Where | What it does |
| --- | --- |
| Before/after (`before-after-section.md`) | Drag the line, or use the arrow keys, Page Up/Down, Home, and End, to compare the photos |
| Reviews `carousel`, `single`, `spotlight`, `band` | Arrows and dots step through the reviews |
| Why us `collage` | A circle of words rotates slowly between the photos (stops with reduced motion) |
| Plans | The visit-frequency toggle swaps every price, with no JavaScript |
| Buttons | `hoverEffect: "text-flip"` flips the label on hover (see [Common Changes](/homio/customization/common-changes/#button-options)) |
| Light/dark switch | The sun and moon icon rotates; colours change at once, with no fade |

<Aside type="note">
  With reduced motion on, content appears without fading, numbers show their
  final value, accordions open at once, the header panel only fades, the review
  marquee stands still, and the why-us circle stops.
</Aside>

### Do It With AI
```text
Make the animations on my Homio site [calmer | off]: in [settings.animation] of
src/config/config.toml, [set enable = false | set duration to "400ms" and distance to "0.5rem"].
Keep respectReducedMotion = true and leave [settings.smoothScroll] off. Then tell me which pages to
check.
```