Scroll suave en enlaces ancla y activado de enlaces correspondientes

abril 30, 2025 10:09 pm Publicado por

¿Tienes un sitio web con secciones en la misma página y un menú con enlaces tipo #ancla? Entonces este truco te va a encantar. Vamos a ver cómo hacer scroll animado al pulsar un enlace y cómo detectar qué sección está en pantalla para resaltar el enlace correspondiente del menú con la clase active.

🧩 1. Scroll suave al hacer clic en enlaces ancla

El siguiente fragmento de código hace que, al pulsar un enlace ancla (como #servicios, #contacto, etc.), la página se desplace suavemente hasta esa sección. Añade este código JavaScript a tu tema (por ejemplo en un archivo custom.js o en el personalizador):

$(document).on("click", 'a[href^="#"]', function (event) {
  event.preventDefault();

  $("html, body").animate(
    {
      scrollTop: $($.attr(this, "href")).offset().top - 50,
    },
    500
  );
});

💡 Consejo: El número 50 se puede ajustar para compensar la altura del menú fijo si usas uno.

👁️ 2. Detectar qué sección es visible y activar su enlace en el menú

Este segundo script es aún más interesante. Usando IntersectionObserver, detectamos cuál de las secciones (.vc_row, en este ejemplo) es la más visible en el viewport y activamos su enlace correspondiente del menú de navegación (.nav a):

jQuery(document).ready(function($) {

  const navLinks = $('.nav a');
  const sections = $('.vc_row');

  const visibleSections = {};

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        visibleSections[entry.target.id] = entry.intersectionRatio;
      } else {
        delete visibleSections[entry.target.id];
      }
    });

    let maxRatio = 0;
    let sectionMasVisible = null;

    for (const [sectionId, ratio] of Object.entries(visibleSections)) {
      if (ratio > maxRatio) {
        maxRatio = ratio;
        sectionMasVisible = sectionId;
      }
    }

    if (sectionMasVisible) {
      navLinks.removeClass('active');
      navLinks.filter(`[href="#${sectionMasVisible}"]`).addClass('active');
    }

  }, {
    threshold: construirListaThresholds()
  });

  sections.each((i, sec) => observer.observe(sec));

  function construirListaThresholds() {
    let thresholds = [];
    for (let i = 0; i <= 1; i += 0.01) {
      thresholds.push(i);
    }
    return thresholds;
  }

});

💡 Detalles a tener en cuenta

  • Cada sección debe tener un id único: id="servicios", id="contacto", etc.
  • El selector .vc_row se usa en temas con WPBakery. Puedes cambiarlo por .elementor-section, .seccion, .bloque según tu constructor.
  • El selector .nav a debe apuntar al menú que contiene los enlaces ancla.

🧪 Bonus: cómo probarlo

Puedes copiar este código en un archivo .js dentro de tu tema hijo y cargarlo en functions.php así:

function cargar_scripts_scroll_menu() {
    wp_enqueue_script('scroll-menu', get_stylesheet_directory_uri() . '/js/scroll-menu.js', array('jquery'), null, true);
}
add_action('wp_enqueue_scripts', 'cargar_scripts_scroll_menu');

📥 ¿Te gustaría tenerlo como plugin?

Estamos valorando publicar este código como un plugin gratuito para facilitar su uso sin tocar código. Si te interesa, escríbenos desde el formulario de contacto y le daremos prioridad.

Los comentarios están cerrados.