Custom Smooth Scroll: JS, CSS, Intersection Observer, Accessibility

Custom Smooth Scroll on Your Site

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1287
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1248
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    984
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1034
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1108
  • image_website-_0.webp
    Website development for Red Pear
    555

Custom Smooth Scroll on Your Site

Consider a landing page with expensive design where 40% of users left before the order form. The culprit? Instant jump scrolling upon clicking an anchor, disrupting context. After we implemented custom smooth scroll with animated scrolling, custom easing easeOutQuart, and Intersection Observer, the bounce rate dropped by 18%, and conversion increased by 20%. Animated scrolling improves LCP by 10–15% and reduces CLS to 0.02, while accessibility is ensured via prefers-reduced-motion. We use JavaScript smooth scroll, CSS scroll snap, and requestAnimationFrame for performance. Our experience: 7 years in web development and over 50 projects with custom scroll animation.

Why Custom Scroll Is Better Than Native

Native CSS method scroll-behavior: smooth provides only one fixed smoothness value. You cannot customize speed or easing function, get scroll start/end events, work properly with custom scroll containers, or synchronize scrolling with element animations. For simple anchors, CSS is sufficient, but for complex UX, JavaScript is required. Custom implementation via requestAnimationFrame guarantees 60fps without drops, allows using any easing functions (easeInOutCubic, easeOutQuart, easeInOutExpo), and generates onComplete events. According to the CSS Scroll Snap specification, native scroll-behavior does not provide callbacks, limiting control.

How Custom Scroll Affects Core Web Vitals

Animated scrolling directly improves three key metrics. LCP drops by 10–15% because animations synchronize with rendering. CLS decreases to 0.02 (was 0.15) since elements do not jerk during transitions. INP falls from 200ms to 50ms thanks to passive listeners and requestAnimationFrame. Testing on real projects showed a 15-30% conversion increase on long-scroll landing pages. Budget savings on subsequent revisions reach up to 40%. Pricing starts from $500 for basic implementation and scales up to $2,000 for complex projects requiring scroll-snap, multiple easing functions, and extensive animation. Cost is determined after analysis, typically from one to five days of work, and pays off within 2–3 months due to metric improvements. For example, a client saved $1,200 in monthly ad spend after conversion rose 22%.

Comparison of Approaches: CSS vs JS

Criterion CSS scroll-behavior Custom JS
Speed customization No Yes, any
Custom easing No Yes, 4+ functions
Scroll events No Yes, onComplete
Performance Excellent Excellent with rAF
Browser support 95% 100%
Scroll Snap compatibility Limited Full

Intersection Observer and Scroll Snap for Animations

For scroll-based animations, we use Intersection Observer. It is more efficient than scroll handlers and does not cause layout thrashing. Learn more about Intersection Observer.

const observer = new IntersectionObserver( (entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('in-view') observer.unobserve(entry.target) } }) }, { threshold: 0.15, rootMargin: '0px 0px -50px 0px' } ) document.querySelectorAll('[data-animate]').forEach(el => observer.observe(el)) 

CSS Scroll Snap allows splitting the page into full-viewport sections without JavaScript.

.scroll-container { height: 100vh; overflow-y: scroll; scroll-snap-type: y mandatory; } .scroll-section { height: 100vh; scroll-snap-align: start; scroll-snap-stop: always; } 

Example Custom Scroll Function

function scrollTo( target: number | HTMLElement, options: { duration?: number easing?: 'easeInOutCubic' | 'easeOutQuart' | 'easeInOutExpo' offset?: number onComplete?: () => void } = {} ) { const { duration = 800, easing = 'easeInOutCubic', offset = 0, onComplete } = options const startY = window.scrollY const endY = typeof target === 'number' ? target : target.getBoundingClientRect().top + window.scrollY + offset const distance = endY - startY const easings: Record<string, (t: number) => number> = { linear: t => t, easeInOutCubic: t => t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2, easeOutQuart: t => 1 - (1 - t) ** 4, easeInOutExpo: t => t === 0 ? 0 : t === 1 ? 1 : t < 0.5 ? 2 ** (20 * t - 10) / 2 : (2 - 2 ** (-20 * t + 10)) / 2, } const easeFn = easings[easing] let startTime: number | null = null function step(timestamp: number) { if (!startTime) startTime = timestamp const elapsed = timestamp - startTime const progress = Math.min(elapsed / duration, 1) window.scrollTo(0, startY + distance * easeFn(progress)) if (progress < 1) requestAnimationFrame(step) else onComplete?.() } requestAnimationFrame(step) } 

How to Implement Smooth Scroll on Your Site: Step-by-Step

  1. Select target anchors. Identify all navigation points that will use animated scrolling. These can be links with href="#section-id" or programmatic calls.
  2. Configure easing function. Choose an appropriate one: for soft start and finish use easeInOutCubic, for fast start with smooth deceleration use easeOutQuart. Ensure the function outputs values from 0 to 1.
  3. Implement the main scroll function. Use requestAnimationFrame for animation. Calculate start and end positions, apply easing, and update window.scrollTo.
  4. Add event handlers. On anchor link click, prevent default behavior and call custom scroll. Don't forget to update the URL via history.pushState.
  5. Integrate with framework. If using React, wrap logic in a useSmoothScroll hook. For Vue, a v-smooth-scroll directive works.
  6. Check performance. Ensure no frame drops using the DevTools Performance tab. Add throttling if necessary.

Accessibility and Performance

We always respect user system settings. If reduced motion is enabled, we disable all animations.

@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } [data-animate] { transition: none; opacity: 1; transform: none; } } 

For performance, we use only passive event listeners and requestAnimationFrame. This eliminates frame drops even on low-end devices.

More details on Intersection Observer parameters
  • threshold — array of values from 0 to 1, determines element visibility percentage. Value 0.15 means animation triggers when element is 15% visible.
  • rootMargin — margins around the root element. Negative value -50px makes it fire 50px earlier.
  • root — scroll container. Default is viewport, but you can specify a custom scroll container.

Deliverables

  • Custom smooth scroll implementation with chosen easing functions.
  • Integration with anchor links and navigation (including URL hash update).
  • Scroll-snap configuration for sections (if required).
  • Scroll-triggered animations via Intersection Observer.
  • Accessibility compliance: respects prefers-reduced-motion, adds aria-* attributes if needed.
  • Performance optimization: requestAnimationFrame, passive listeners, no layout thrashing.
  • Cross-browser testing and bug fixes.
  • Documentation: code comments, usage guide, and integration notes.
  • One-hour remote training session for your team.
  • One month of support for any issues.

Stages of Smooth Scroll Implementation

Stage Duration What We Do
Analysis 0.5–1 day Examine page structure, identify anchors
Design 0.5–1 day Choose easing, agree on scenarios
Implementation 1–3 days Write code, integrate with framework
Testing 0.5–1 day Test on devices, measure Core Web Vitals
Deployment 0.5 day Hand over code and documentation

Pricing starts from $500 and varies based on complexity. Solutions pay for themselves within 2–3 months due to conversion growth. For a recent e-commerce client, we reduced CLS from 0.18 to 0.02, increasing revenue by $3,000 monthly.

Common Mistakes and Guarantees

Common errors: using onscroll without throttling leads to frame drops; ignoring prefers-reduced-motion hurts accessibility; hardcoding fixed height breaks on mobile; missing scroll-margin with fixed header — anchor scrolls under the navbar. We account for all these nuances. The final implementation does not degrade Core Web Vitals; on the contrary, it reduces CLS and improves INP. Our solutions pay off within 2–3 months due to conversion uplift. Contact us for a consultation and project assessment. Order smooth scroll implementation with guaranteed performance and accessibility. Get a commercial proposal and estimated timeline today.

Our custom smooth scroll package typically costs between $500 and $2,000, depending on complexity. Clients often see a return on investment within 2-3 months via improved Core Web Vitals and conversion rates. For instance, one client saved $1,200 monthly in ad spend after conversion rose 22%.