stinger-soft/jquery-scrollto-bundle
A Symfony bundle that packages the jQuery ScrollTo plugin, providing smooth animated scrolling to page elements and anchors through Twig templates and the asset pipeline, with configurable duration, easing, and offsets for building fluid in-page navigation.
Read this first: this is a Symfony bundle, not a Laravel package. It ships jquery.scrollTo (Flesler's plugin) as a Symfony asset and nothing else — no service provider, no facade, no config, no Blade directives. For a Laravel codebase the only part you can actually use is the vendored JS file inside Resources/public/js/.
Where to look in the repo, in order:
composer.json — confirms symfony/framework-bundle (and probably Assetic) as the real dependency; note the 2016 constraint ranges.Resources/public/js/ — the actual payload (jquery.scrollTo.min.js, ~2–10 KB).DependencyInjection/ + JQueryScrollToBundle.php — almost certainly an empty extension class. If there's no Configuration.php, there is nothing to configure.Resources/views/ — if empty, there is no Twig helper either; you include the asset by hand.If you genuinely have a Symfony app (the intended path):
composer require stinger-soft/jquery-scrollto-bundle
# bundles.php (Symfony 4+) or AppKernel::registerBundles()
# new StingerSoft\JQueryScrollToBundle\JQueryScrollToBundle(),
bin/console assets:install --symlink public
Then, after jQuery:
<script src="{{ asset('bundles/jqueryscrollto/js/jquery.scrollTo.min.js') }}"></script>
If you're in Laravel (the realistic path): skip Composer entirely. Either npm i jquery.scrollto, or copy the minified file out of vendor/stinger-soft/jquery-scrollto-bundle/Resources/public/js/ into resources/js/vendor/ and import it in resources/js/app.js after jQuery.
First use case: a "back to top" button and smooth anchor navigation on a long marketing page. That's 95% of what this library is ever used for.
Pattern 1 — Back-to-top control (the canonical use).
document.querySelector('[data-scroll-top]')?.addEventListener('click', () => {
$.scrollTo(0, 400);
});
Pattern 2 — Anchor nav with a fixed header offset. This is where the plugin still beats naive scrollIntoView on old browsers:
$('a[href^="#"]').on('click', function (e) {
const target = $(this.hash);
if (!target.length) return;
e.preventDefault();
$.scrollTo(target, { duration: 600, offset: -($('header').outerHeight() || 0) });
});
Pattern 3 — Post-validation scroll in a Blade form. After a 422 redirect, scroll to the first invalid field:
@if ($errors->any())
<script>
document.addEventListener('DOMContentLoaded', () => {
const first = document.querySelector('.is-invalid');
if (first && window.jQuery && jQuery.scrollTo) {
jQuery.scrollTo(first, { duration: 400, offset: -120 });
}
});
</script>
@endif
Pattern 4 — Restore scroll position after a Livewire/Inertia navigation or after expanding an accordion, using $.scrollTo($('#section-' + id), 300).
Pattern 5 — Symfony/Assetic (legacy) integration, if you inherited a 2.x/3.x app:
{% javascripts
'bundles/jqueryscrollto/js/jquery.scrollTo.min.js'
output='js/scroll.js' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
Integration tips
$.fn and $.scrollTo. Ordering bugs here surface as $.scrollTo is not a function.vendor/ aren't transformed — either npm i jquery.scrollto or add the file to resources/js/vendor/ and import it.$.scrollTo.defaults.duration = 500; $.scrollTo.defaults.axis = 'y';.jquery.scrollTo is archived/unmaintained. No CVE feed, no compatibility guarantees with jQuery 4 or modern Symfony. Audit it before adding it to anything client-facing.Resources/public after assets:install. The URL is bundles/<lowercased-bundle-name-without-Bundle>/js/... — verify with the network tab rather than guessing casing.config/bundles.php by hand, and there's no config/packages/*.yaml to tune.offset sign confusion. offset: -80 moves the final scroll position up by 80px — that's what you want under a sticky header. Positive values push past the element. Test with a real fixed header, not a mock.$(window) vs $('html, body'). The plugin normalizes this, but any hand-rolled fallback you write beside it will behave differently in older Safari/Chrome. Don't mix the two in one codebase.typeof $.scrollTo in the console → confirm the script tag actually loaded → confirm jQuery loaded once (double-loading breaks the plugin's internal state and produces jitter) → confirm the target selector exists at click time (SPA re-renders are a common cause of silent no-ops).html { scroll-behavior: smooth; }
section[id] { scroll-margin-top: 96px; } /* replaces the offset option */
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
Keep the plugin only if you need per-call easing/duration/onAfter callbacks or must support very old browsers. Also move focus to the scroll destination for keyboard and screen-reader users — the plugin scrolls pixels but never touches focus, so a plain anchor click will strand assistive tech.resources/js (dropping the bundle wrapper entirely) is legally fine and is the sanest exit path if you inherit a dependency on it.How can I help you explore Laravel packages today?