Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 83 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ just a few small guidelines you need to follow.
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
part of the project. Head over to [Google Open Source CLA](https://cla.developers.google.com/)
to see your current agreements on file or to sign a new one.

You generally only need to submit a CLA once, so if you've already submitted one
You generally only need to submit a CLA once. So if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.

Expand All @@ -26,3 +26,83 @@ information on using pull requests.

This project follows [Google's Open Source Community
Guidelines](https://opensource.google.com/conduct/).

## Developing & testing your changes

### 1. Polyfill development environment

Run a development environment:

```shell script
npm i
npm run dev
```

Then open `http://localhost:3000` and choose one of the demos (test) to see how your changes apply.

### 2. Configuring & running tests

Test configurations are available in `test/tests.config.json` which include:

- `polyfillFiles`: an array of our JS shim / polyfill files, those will be injected in WPT tests files.
- `harnessTests`: an array of WPT harness tests we want to test the polyfill against.
- `browsers.local`: Browser our local selenium-webdriver will test against locally.
- `browsers.sauce`: Browser our local selenium-webdriver will test against in Saucelabs / CI environment.

#### Run the tests locally

Simple test will serve the WPT tests folder and intercepts requests. If the request path matches a harness test we are interested in polyfilling, it will inject the polyfill.

_Required environment variables:_

```dotenv
WPT_DIR=test/wpt #defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
```

_Command_

```shell script
npm run test:simple
```

Go to `localhost:8081/scroll-animations/current-time-nan.html` as an example.

#### Run the tests via Web Driver

##### Local web driver

_Required environment variables:_

```dotenv
WPT_DIR=test/wpt # defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
LOCAL_BROWSER=chrome # choose one of 'chrome', 'edge', 'firefox', 'safari'
LOCAL_WEBDRIVER_BIN=? #/path/to/webdriver-binaries
```

_Command_

```shell script
npm run test:wpt
```

##### SauceLabs / CI

_Required environment variables:_

```dotenv
TEST_ENV=sauce
WPT_DIR=test/wpt # defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
SC_TUNNEL_ID=sc-wpt-tunnel # please specify 'sc-wpt-tunnel' as a SauceConnect Proxy Tunnel ID

SAUCE_NAME=<secret> # Your saucelabs account username
SAUCE_KEY=<secret> # Your API key
```

_Command_

```shell script
TEST_ENV=sauce npm run test:wpt
```
202 changes: 129 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,126 +1,182 @@
# Scroll-timeline Polyfill
# Scroll-timeline Polyfill for Scroll-driven Animations

A polyfill of ScrollTimeline and ViewTimeline as defined by the [spec](https://drafts.csswg.org/scroll-animations-1/).
A polyfill of ScrollTimeline and ViewTimeline as defined by [the CSS WG spec](https://drafts.csswg.org/scroll-animations-1/).

View a [cool demo showing its usage](https://flackr.github.io/scroll-timeline/demo/parallax/)!
- [View a cool demo showing its usage.](https://flackr.github.io/scroll-timeline/demo/parallax/)
- [Track the browser support for native Scroll-driven Animations.](https://caniuse.com/?search=animation-timeline)

# Usage
> [!TIP]
> When the scroll-driven animations feature is widely available as a native feature, this polyfill may not be necessary except to support older versions of browsers.

To use this polyfill, import the module into your site and you can start creating animations that use a `ScrollTimeline` or `ViewTimeline`.
## Installation

Use one of these methods to add the polyfill and it should begin working immediately. If it's not working, see the [_Known Limitations_](#known-limitations) section.

### [NPM package](https://www.npmjs.com/package/scroll-timeline-polyfill)

```sh
npm install scroll-timeline-polyfill
```

You may also use `pnpm` or `yarn`. Once installed, import it:

```js
import 'https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js';

document.getElementById('parallax').animate(
{ transform: ['translateY(0)', 'translateY(100px)']},
{ fill: 'both',
timeline: new ScrollTimeline({
source: document.documentElement,
}),
rangeStart: new CSSUnitValue(0, 'px'),
rangeEnd: new CSSUnitValue(200, 'px'),
});
import "scroll-timeline-polyfill/dist/scroll-timeline.js";
```

Also works with CSS Animations that use a `view-timeline` or `scroll-timeline`
### JavaScript import (CDN)

```js
import "https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js";
```

### HTML script tag (CDN)

```html
<script src="https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js"></script>
```

## Usage

To use this polyfill, start creating animations using CSS or JavaScript.

### JavaScript usage

Use a `ScrollTimeline` or `ViewTimeline` instance to define animations.

```js
document.getElementById("parallax").animate(
{ transform: ["translateY(0)", "translateY(100px)"] },
{
fill: "both",
timeline: new ScrollTimeline({
source: document.documentElement,
}),
rangeStart: new CSSUnitValue(0, "px"),
rangeEnd: new CSSUnitValue(200, "px"),
}
);
```

### CSS usage

Use `animation-timeline` property with `scroll` or `view` to define animations:

```css
@keyframes parallax-effect {
to { transform: translateY(100px) }
to {
transform: translateY(100px);
}
}
#parallax {
.parallax {
animation: parallax-effect linear both;
animation-timeline: scroll(block root);
animation-range: 0px 200px;
}
```

Please ensure your CSS is hosted on the same domain as your website or included directly on the page within a <style> tag.
> [!CAUTION]
> Please ensure your CSS is hosted on the same domain as your website or included directly on the page within a `<style>` tag.
>
> If you are loading stylesheets from other origins, the polyfill might not be able to fetch and apply them correctly, due to browser security restrictions.

If you are loading stylesheets from other origins, the polyfill might not be able to fetch and apply them correctly, due to browser security restrictions.
### More details and Use Cases

For more details on and use-cases of scroll-driven animations, please refer to [https://developer.chrome.com/articles/scroll-driven-animations/](https://developer.chrome.com/articles/scroll-driven-animations/) and [https://scroll-driven-animations.style/](https://scroll-driven-animations.style/)
- [Animate elements on scroll with Scroll-driven animations](https://developer.chrome.com/articles/scroll-driven-animations/)
- [Scroll-driven Animations - Demos and Tools](https://scroll-driven-animations.style/)

# Contributing

### 1. Polyfill dev
## Known Limitations

Running a dev environment
### Loading Demos or Running Locally

```shell script
npm i
npm run dev
```
Ensure that the demo project or your project is built and/or served using an HTTP server. For example, you may need to execute `npm run build` and then `npm run dev`. You may also use other methods like a Python3 HTTP server, WAMP server, Nginx or `npx http-server`.

Then open the browser `http://localhost:3000`, choose one of the demos (test) to see how your changes.
> [!NOTE]
> You won't be able to use the polyfill if you open the `.html` file directly in a file browser. This is because the polyfill needs to be able to fetch the CSS files in order to read them. The browser doesn't allow this from `file:///` origins as that would allow reading other files from your system.

### 2. Configure & Run Tests
### Safari Feature Flag

Test configurations are available in: `test/tests.config.json` that file includes:
In Safari (macOS), a developer feature flag called "Scroll-driven Animations" can be enabled in the Feature Flags panel. (This panel is shown if "Show features for web developers" advanced option is checked.)

1. polyfillFiles: an array of our JS shim / polyfill files, those will be injected in WPT tests files.
2. harnessTests: an array of WPT harness tests we want to test the polyfill against.
3. browsers.local: Browser our local selenium-webdriver will test against
4. browsers.sauce: Browser our local selenium-webdriver will test against in Saucelabs / CI environment.
This feature flag reports to feature detection that the scroll-driven animations feature is natively available in the browser, effectively disabling the polyfill. However, the developer preview version of the feature doesn't work correctly, causing broken animations.

#### Run the tests locally
> [!IMPORTANT]
> If this is your case, disable the feature flag and reload your web page. The polyfill will apply the animations.

Simple test will serve the WPT tests folder and intercepts requests, if the request path matches a harness test we are interested in polyfilling, it will inject the polyfill.
### Media Query for Reduced Motion

*Required environment variables:*
If you wrap the CSS in a media query block to apply it only when reduced motion is not preferred, the polyfill will not be able to process it:

```dotenv
WPT_DIR=test/wpt #defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
```css
/* ❌ Don't do this */
@media (prefers-reduced-motion: no-preference) {
.parallax {
animation: parallax-effect linear both;
animation-timeline: scroll(block root);
}
}
```

*Command*
Instead, override the `animation` property when reduced motion is preferred:

```shell script
npm run test:simple
```
```css
.parallax {
animation: parallax-effect linear both;
animation-timeline: scroll(block root);

Go to `localhost:8081/scroll-animations/current-time-nan.html` as an example.
@media (prefers-reduced-motion: reduce) {
animation: none;
}
}
```

#### Run the tests via Web Driver
### Dynamic CSS classes

##### Local web driver
Using Javascript to dynamically apply CSS classes in order to apply a scroll-driven anmiation will not work with the polyfill. This is because the polyfill needs to read the static classes and the CSS to track the DOM elements that should have the animations.

*Required environment variables:*
Instead, dynamically attach overriding classes to disable the statically applied animation:

```dotenv
WPT_DIR=test/wpt #defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
LOCAL_BROWSER=chrome # choose one of 'chrome', 'edge', 'firefox', 'safari'
LOCAL_WEBDRIVER_BIN=? #/path/to/webdriver-binaries
```css
.no-parallax {
animation: none !important;
}
```

*Command*
#### Tailwind utility classes

```shell script
npm run test:wpt
```
Tailwind v4 brings the power of [utility classes](https://tailwindcss.com/docs/styling-with-utility-classes). However, the polyfill may not work with them since they are a form of dynamic classes.

Instead, use regular CSS classes. You can use CSS features like variables to apply dynamic configurations to the same animation.

##### SauceLabs / CI
```css
@keyframes parallax-effect {
to {
transform: translateY(calc(var(--parallax-multiplier, 1) * 100px));
}
}

*Required environment variables:*
.parallax-2 {
--parallax-multiplier: 2;
}

```dotenv
TEST_ENV=sauce
WPT_DIR=test/wpt #defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
SC_TUNNEL_ID=sc-wpt-tunnel # please specify 'sc-wpt-tunnel' as a SauceConnect Proxy Tunnel ID
.parallax-3 {
--parallax-multiplier: 3;
}

SAUCE_NAME=<secret> # Your saucelabs account username
SAUCE_KEY=<secret> # Your API key
.parallax,
.parallax-2,
.parallax-3 {
animation: parallax-effect linear both;
animation-timeline: scroll(block root);
}
```

*Command*
## Contributing

```shell script
TEST_ENV=sauce npm run test:wpt
```
Thank you for choosing to contribute fixes and improvements to our project.

Please see our [contribution guidelines](/CONTRIBUTING.md) page to:
- Sign the Contributor License Agreement.
- Understand the code review process.
- Read the open source community guidelines.
- Learn how to develop and test your changes.