diff --git a/dist/dsap.es.js b/dist/dsap.es.js index c08d9fc..a2cec58 100644 --- a/dist/dsap.es.js +++ b/dist/dsap.es.js @@ -1,7 +1,7 @@ var m = Object.defineProperty; var p = (a, t, e) => t in a ? m(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e; var r = (a, t, e) => (p(a, typeof t != "symbol" ? t + "" : t, e), e); -class S { +class g { constructor() { r(this, "elems"); r(this, "maxScrollDelta", 1e3); @@ -15,10 +15,10 @@ class S { doScroll() { const t = window.scrollY, e = t + window.innerHeight; let i = [`:root{--dsap-max-scroll-delta: ${this.maxScrollDelta}}`]; - this.elems.forEach((l) => { - const o = l.getBoundingClientRect().top + t, h = o + l.getBoundingClientRect().height, c = !!l.dataset.dsapScroll; - let s = !1, n = !1, d = 0; - e < o ? n = !1 : t > h ? n = !0 : s = !0, c && (s ? d = ((e - o) / (l.getBoundingClientRect().height + window.innerHeight) * this.maxScrollDelta).toFixed(0) : n && (d = this.maxScrollDelta)), l.dataset.dsapIs = s ? "in" : n ? "above" : "below", s && (l.dataset.dsapSeen = !0), c && i.push(`[data-dsap="${l.dataset.dsap}"]{--dsap-scroll-delta: ${d}}`); + this.elems.forEach((s) => { + const o = s.getBoundingClientRect().top + t, h = o + s.getBoundingClientRect().height, c = s.hasAttribute("data-dsap-scroll"); + let l = !1, n = !1, d = 0; + e < o ? n = !1 : t > h ? n = !0 : l = !0, c && (l ? d = ((e - o) / (s.getBoundingClientRect().height + window.innerHeight) * this.maxScrollDelta).toFixed(0) : n && (d = this.maxScrollDelta)), s.dataset.dsapIs = l ? "in" : n ? "above" : "below", l && (s.dataset.dsapSeen = !0), c && i.push(`[data-dsap="${s.dataset.dsap}"]{--dsap-scroll-delta: ${d}}`); }), this.style.innerHTML !== i.join("") && (this.style.innerHTML = i.join("")); } debounce(t) { @@ -31,5 +31,5 @@ class S { } } export { - S as DSAP + g as DSAP }; diff --git a/docs/docs.css b/docs/docs.css index 4dc6534..aacb7bf 100644 --- a/docs/docs.css +++ b/docs/docs.css @@ -2,14 +2,18 @@ body, html { margin: 0; padding: 0; + line-height: 1.5; +} + +p,li{ } :root { - --white: #ffffff; + --: #ffffff; --black: #000000; - --primary: #1c1c27; + --primary: #f9f9f9; --theme: var(--primary); @@ -25,7 +29,7 @@ html { --darker: color-mix(in srgb, #000000 10%, var(--primary)); --darkest: color-mix(in srgb, #000000 20%, var(--primary)); - --shadow: 0 2rem 2rem rgba(0, 0, 0, .15); + --shadow: 0 2px 4px rgba(0, 0, 0, .15); } [data-dsap] { @@ -35,7 +39,7 @@ html { body { background-color: var(--background); - color: var(--text-color); + color: var(--black); font-family: 'Inter', sans-serif; font-optical-sizing: auto; font-weight: 400; @@ -48,58 +52,27 @@ h3, h4, h5, h6 { - color: var(--heading-text); + color: var(--black); font-family: "Roboto Serif", serif; font-weight: 500; transition: font-weight .2s ease-out; } code { - background-color: var(--darkest); + background-color: #3b3b3b; border: 1px solid var(--overlay-border); - border-radius: 8px; - box-shadow: var(--shadow); + border-radius: 4px; + color: #ffffff; display: inline-block; - padding: .25rem .5rem; -} - - -ul li a { - text-decoration: none; - color: var(--text-color); - padding: .75rem 1rem; - border-radius: 8px; - display: block; - transition: background-color .2s ease-out, color .2s ease-out, box-shadow .2s ease-out; - background-color: var(--primary); - box-shadow: 0 0px 0 var(--darkest); -} - -ul li a:hover { - background-color: var(--light-1); - color: var(--whiter); + padding: .125rem .5rem; } -ul li a.active { - --background: var(--light-1); - background-color: var(--background); - box-shadow: 0 5px 0 var(--darkest); - color: var(--white); -} - -ul li a:hover, -ul li a.active {} - .container { max-width: 1200px; width: 100%; margin: 0 auto; } -.muted { - color: var(--muted); -} - .docs { display: flex; gap: 24px; @@ -121,7 +94,7 @@ ul li a.active {} .intro h1 { display: flex; position: relative; - transition: font-weight .2s ease-out, opacity .2s ease-out, gap .2s ease-out, font-size .2s ease-out; + transition: font-weight .2s ease-out, opacity .2s ease-out, gap .2s ease-out, font-size .2s ease-out, scale .2s ease-out; --font-weight-from: 100; --font-weight-to: 700; @@ -137,8 +110,8 @@ ul li a.active {} --font-size-from: 0.75; --font-size-to: 1; - --font-size-start: .3; - --font-size-stop: .8; + --font-size-start: .25; + --font-size-stop: 1; font-size: 96px; --opacity-from: 1; @@ -154,6 +127,7 @@ ul li a.active {} .intro[data-dsap]:not([data-dsap=""]) h1 { scale: clamp(var(--font-size-from), calc(var(--font-size-from) + (var(--font-size-to) - var(--font-size-from)) * ((var(--percentage) - var(--font-size-start)) / (var(--font-size-stop) - var(--font-size-start)))), var(--font-size-to)); + //font-weight: clamp(var(--font-weight-from), calc(var(--font-weight-from) + (var(--font-weight-to) - var(--font-weight-from)) * ((var(--percentage) - var(--font-weight-start)) / (var(--font-weight-stop) - var(--font-weight-start)))), var(--font-weight-to)); //gap: clamp(var(--gap-from), calc(var(--gap-from) + (var(--gap-to) - var(--gap-from)) * ((var(--percentage) - var(--gap-start)) / (var(--gap-stop) - var(--gap-start)))), var(--gap-to)); // opacity: clamp(var(--opacity-to), calc(var(--opacity-from) + (var(--opacity-to) - var(--opacity-from)) * ((var(--percentage) - var(--opacity-start)) / (var(--opacity-stop) - var(--opacity-start)))), var(--opacity-from)); diff --git a/docs/index.html b/docs/index.html index 6783db3..3b1df55 100644 --- a/docs/index.html +++ b/docs/index.html @@ -24,7 +24,7 @@
-
+

DSAP

@@ -38,30 +38,76 @@

DSAP

Overview

-

DSAP is a small library that provides you with the tools to create powerful CSS-based animations

-

Usage

-

Add data-dsap to elements you want to track in the viewport. DSAP will then calculate - the position of the element in the viewport and keep track of it during scroll.

-

The following CSS variables are exposed to each instance of a DSAP element:

+

DSAP is a streamlined library that equips you with a suite of functionalities for crafting compelling + CSS-based + animations.

+

What DSAP is not

+

+ DSAP is a specialized utility designed to enhance CSS animations with scroll and visibility + tracking, complementing + rather than replacing robust animation libraries like GSAP. It's optimized for performance, yet + developers need to + integrate it thoughtfully, ensuring it contributes to improved website performance metrics such + as LCP and CLS, + thereby facilitating smooth and captivating user interactions.

+

How to Implement DSAP

    -
  • --dsap-scroll-delta - This indicates how much of the element has been scrolled within the - viewport. This value ranges from 0 to --dsap-max-scroll-delta (see below). This is not a percentage +
  • + Visibility Tracking: +

    Tag HTML elements with the data-dsap attribute to monitor their presence + within the viewport. +

  • +
  • + Scroll Position Monitoring: +

    Apply the data-dsap-scroll attribute to track an element's location in the + viewport as it + scrolls. This capability is essential for executing scroll-driven animations.

    +
  • +
+

CSS Variables for DSAP Elements

+

DSAP imparts each element with specific CSS variables:

+
    +
  • --dsap-scroll-delta: Reflects the vertical scroll progress of an element within + the viewport, + spanning from 0 to --dsap-max-scroll-delta. This measurement is not a + percentage.
  • +
  • --dsap-max-scroll-delta: Defines the scale for scroll delta interpolation, with + a default setting + of 1000. This variable is crucial for formulating scroll-related animations.
-

The following global CSS variables are available globally to assist with calculations:

+

Data Attributes for DSAP Elements

+

DSAP enhances elements with a set of data attributes for detailed animation control:

    -
  • --dsap-max-scroll-delta - Used as the value a scroll delta should interpolate - between. By default, this is 1000.
  • +
  • data-dsap: This attribute prompts DSAP to monitor the element. Upon initialisation, it will be assigned an + identifier for CSS targeting.
  • +
  • data-dsap-scroll: Use this to opt-in to scroll position tracking
  • +
  • data-dsap-is: Offers a simple descriptor of the element's vertical + position—whether it is "above", + "in", or "below" the viewport.
  • +
  • data-dsap-seen: A boolean flag that determines if the element has ever been + visible in the + viewport.
-

The following data attributes are present on all DSAP elements:

+

Performance Considerations

+

DSAP has been fine-tuned for performance with the following methodologies:

    -
  • data-dsap - As well as using this attrivute to tell DSAP to track this element
  • -
  • data-dsap-is - A simple value to determine if the element is "above", "in" or - "below" the viewport. Useful for creating directional transitions. For example, Creating a fade - in effect when the element enters the viewport from the bottom
  • -
  • data-dsap-seen - A true/false value indicating whether the element has ever entered - the viewport. Useful for making one-time animations that don't trigger every time the element - comes into the viewport
  • +
  • + Efficient Variable Updates: Instead of inline style adjustments for each + element, DSAP modifies + a single style element on scroll, enhancing efficiency. This approach relies on unique + identifiers for DSAP + elements, allowing precise targeting via the head style. +
  • +
  • + Optimized Scroll Event Handling: Scroll-related computations are delegated + to + requestAnimationFrame(), minimizing impact on the main thread and preventing performance + bottlenecks. This + function aligns with the user's display refresh rate, typically at 60Hz, to limit excessive + processing and + seamlessly adapts to higher refresh-rate screens, ensuring fluid animation transitions. +

Get started

diff --git a/lib/dsap.js b/lib/dsap.js index dd37082..49fdb1d 100644 --- a/lib/dsap.js +++ b/lib/dsap.js @@ -51,7 +51,7 @@ class DSAP { // Get the element's top and bottom position const elementTop = elem.getBoundingClientRect().top + scrollY; const elementBottom = elementTop + elem.getBoundingClientRect().height; - const trackScroll = !!elem.dataset.dsapScroll; + const trackScroll = elem.hasAttribute('data-dsap-scroll'); // Setup some variables to track the element's position relative to the viewport let inViewport = false;