Menu Scroll Correction Script

Menu Scroll Correction Script

Menu Scroll Correction Script

1. Calculate Header Dimensions

When you click a link that points to a specific section (e.g., #contacts), the browser usually brings that section to the very top of the page. If you have a fixed menu at the top, it will cover the first few pixels of the section (often the title).

  • What the script does: It calculates the height of your header (#hdr) and subtracts that measurement from the final scroll position. This way, the section stops exactly below the menu.

2. Smooth Scrolling

Instead of an immediate, abrupt “jump” to the desired section, the script forces the browser to glide smoothly downward, improving the user experience.

3. Dynamic Link Management

It uses “event delegation” (document.addEventListener('click', ...)). This means the script also works on buttons or links loaded at a later time (e.g., via AJAX or dynamic widgets) without needing to reload the script.

4. Resolves Elementor Loading Issues

Page builders like Elementor sometimes take a fraction of a second to calculate the correct page heights.

  • The solution in the code: The script includes “delays” (60ms, 350ms, and 500ms). If a user arrives at the site via a direct link to a section (e.g., yoursite.com/#services), the script waits for the page to be ready before scrolling, preventing the position from being incorrect.

5. Updates the URL Without Reloading

It uses history.pushState. When you click a link, the address in the browser bar updates (adding #section) without causing the flickering or jumping typical of standard browser behavior.


In summary, you need this if:

  1. You have a fixed header that covers section titles when you click on them.
  2. You want the scrolling to be smooth and elegant.
  3. You want links to work properly even when a user arrives at the page from an external link pointing to a specific anchor.

Technical note: If you change your header’s ID on the site, remember to modify this line in the code: const HDR_SELECTOR = '#hdr'; (replace #hdr with your header’s correct ID).

				
					
(function(){
  'use strict';

  // --- CONFIG ---
  // Se il tuo header ha un altro ID/class modifica qui:
  const HDR_SELECTOR = '#hdr';

  // Delay usato per garantire che Elementor abbia renderizzato i widget (ms)
  const ONLOAD_DELAY = 60;

  // --- UTILS ---
  function getHeaderHeight(){
    const hdr = document.querySelector(HDR_SELECTOR);
    return hdr ? Math.ceil(hdr.getBoundingClientRect().height) : 0;
  }

  function scrollToElement(el, smooth = true){
    if(!el) return;
    const hdrH = getHeaderHeight();
    const top = el.getBoundingClientRect().top + window.pageYOffset - hdrH;
    window.scrollTo({
      top: Math.max(0, Math.round(top)),
      behavior: smooth ? 'smooth' : 'auto'
    });
  }

  function isSamePageAnchor(href){
    // true se href è solo "#something" oppure "#"
    return href && href.startsWith('#') && (location.pathname === location.pathname);
  }

  // --- HANDLERS ---
  // Delegazione click su document per intercettare link anchor (anche aggiunti dinamicamente)
  document.addEventListener('click', function(e){
    const a = e.target.closest && e.target.closest('a[href]');
    if(!a) return;

    const href = a.getAttribute('href').trim();

    // Ignota: solo anchor semplici (es. "#section") sulla stessa pagina
    if(!href || !href.startsWith('#')) return;

    // Ignora link vuoti
    if(href === '#') return;

    const target = document.querySelector(href);
    if(!target) return; // niente da fare se target non esiste sulla pagina

    // Previeni comportamento default e scrolla con offset
    e.preventDefault();

    // Aggiorna l'URL senza ricaricare la pagina
    try { history.pushState(null, '', href); } catch (err) { location.hash = href; }

    scrollToElement(target, true);
  }, {passive: false});

  // Quando cambia l'hash direttamente (es. back/forward) -> scroll immediato (no smooth per compatibilità)
  window.addEventListener('hashchange', function(){
    const h = location.hash;
    if(!h) return;
    const target = document.querySelector(h);
    if(target) scrollToElement(target, false);
  });

  // All load: se c'è un hash iniziale scrollalo dopo un piccolo delay (per Elementor rendering)
  function initialHashScroll(){
    if(location.hash){
      const target = document.querySelector(location.hash);
      if(target){
        // primo tentativo senza smooth per evitare jump visibili, ma con delay per render
        setTimeout(function(){ scrollToElement(target, false); }, ONLOAD_DELAY);
      } else {
        // se non trovato subito, riproviamo una volta dopo un po' (utile con caricamenti dinamici)
        setTimeout(function(){
          const t = document.querySelector(location.hash);
          if(t) scrollToElement(t, false);
        }, 350);
      }
    }
  }

  // ricalcola se il header cambia dimensione: se l'header è dinamico potresti voler ri-applicare scroll
  // (qui teniamo una soluzione leggera: ri-scroll se la finestra viene ridimensionata e c'è hash)
  let resizeTimer = null;
  window.addEventListener('resize', function(){
    if(!location.hash) return;
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(function(){
      const t = document.querySelector(location.hash);
      if(t) scrollToElement(t, false);
    }, 150);
  });

  // assicurati di eseguire su DOMContentLoaded e anche su window.load
  document.addEventListener('DOMContentLoaded', initialHashScroll);
  window.addEventListener('load', initialHashScroll);

  // Piccola compatibilità: alcuni widget Elementor possono essere renderizzati dopo il caricamento.
  // Questo tenta di eseguire ancora una volta qualche centinaio di ms dopo load.
  setTimeout(initialHashScroll, 500);

})();

				
			

Privacy Policy

Informativa sul trattamento dei dati personali ai sensi dell’Art. 13 del Regolamento (UE) 2016/679 (GDPR)

Data Ultimo Aggiornamento: 06/11/25


1. Identità e dati di contatto del Titolare del Trattamento

Titolare del trattamento dei dati personali è:

Angelo Marra
Indirizzo: Via Marcantonio Franceschini 10, 40128 Bologna (BO)
Partita IVA: IT04068171208
Codice Fiscale: MRRNGL80B13A509N
Email: angelo@marrisonlab.com
PEC: angelomarra80@pec.it


2. Dati trattati, Finalità e Base Giuridica

2.1. Dati Raccolti e Finalità (Modulo Contatti)

Dati Raccolti: Nome, Cognome, Indirizzo email, Messaggio e qualsiasi altro dato spontaneamente inserito dall’utente nel modulo.

Finalità: I Suoi Dati Personali sono trattati esclusivamente per rispondere alle Sue richieste di informazione, contatto, preventivo e/o per adempiere a misure precontrattuali adottate su Sua richiesta.

Base Giuridica: La base giuridica del trattamento è l’esecuzione di misure precontrattuali adottate su richiesta dello stesso (Art. 6.1, lett. b, GDPR).

2.2. Dati di Navigazione (Esplicativo)

I sistemi informatici acquisiscono dati (es. indirizzi IP) la cui trasmissione è implicita nell’uso dei protocolli di Internet. Tali dati sono utilizzati al solo fine di ricavare informazioni statistiche anonime e controllarne il corretto funzionamento. Si rimanda alla Cookie Policy per i dettagli sull’uso dei cookie.


3. Periodo di Conservazione dei Dati e Destinatari

Modalità del Trattamento: Il trattamento dei dati avviene mediante strumenti manuali, informatici e telematici.

Conservazione: I dati raccolti tramite il modulo di contatto sono conservati per il tempo strettamente necessario a evadere la Sua richiesta, salvo diversi obblighi di legge.

Destinatari: I Suoi dati non saranno diffusi. Potranno essere trattati da soggetti autorizzati (collaboratori) e da soggetti esterni (es. fornitori di servizi hosting) che agiscono come Responsabili del Trattamento, opportunamente nominati.


4. I Suoi Diritti (Art. 15-22 GDPR)

In qualità di Interessato, Lei ha il diritto di esercitare i seguenti diritti in qualsiasi momento:

  • Diritto di accesso (Art. 15)
  • Diritto di rettifica (Art. 16)
  • Diritto alla cancellazione (Diritto all’Oblio, Art. 17)
  • Diritto di limitazione di trattamento (Art. 18)
  • Diritto di opposizione al trattamento (Art. 21)
  • Diritto alla portabilità dei dati (Art. 20)

Per esercitare tali diritti, La preghiamo di contattare il Titolare all’indirizzo email angelo@marrisonlab.com o PEC angelomarra80@pec.it.

Inoltre, Lei ha il diritto di proporre reclamo all’Autorità di Controllo competente (Garante per la Protezione dei Dati Personali – www.garanteprivacy.it).

1
Asistente IA
Online · Guest
Hi! I'm Marrison Assistant, your virtual assistant. How can I help you?
Now
By writing in this chat you accept our privacy policy.
Powered By Marrisonlab