Agregue enlaces de anclaje profundo a su blog usando JavaScript

Los enlaces de anclaje profundo, también conocidos como enlaces de salto, son útiles para permitir a los usuarios compartir enlaces directos a partes específicas del artículo. No solo crean una mejor experiencia de usuario, sino que también son buenos para compartir en las redes sociales y vincular directamente a diferentes secciones del documento.

En este artículo, aprenderemos cómo convertir los encabezados de las publicaciones de blog en enlaces de anclaje profundo utilizando JavaScript estándar. No utilizaremos ningún complemento de terceros para este fin.

Para este propósito, no necesita agregar ID a los encabezados ni preocuparse por las URL. De hecho, usaremos el texto del encabezado para generar una identificación y un enlace de anclaje al lado del texto del encabezado. ¿Ya tienes las identificaciones? Sin preocupaciones. No los cambiaremos.

Marcado HTML

Aquí hay un ejemplo de marcado HTML al que queremos agregar enlaces de anclaje profundo.

<!DOCTYPE html>
<html lang="en">
<body>

<h1>15 ways food processors are completely overrated</h1>
<time>24 March, 2019</time>

<div class="post-content">
    <h2>Introduction</h2>
    <p>...</p>

    <h2>A Brief History</h2>
    <p>...</p>

    <h3>Fast Food</h3>
    <p>...</p>

    <h3>Home Made Food</h3>
    <p>...</p>

    <h2>Conclusion</h2>
    <p>...</p>
</div>
</body>
</html>

Como puede ver arriba, tenemos múltiples h2 y h3 encabezados sin ID. Nuestro objetivo es convertir estos encabezados en enlaces ancla profundos.

Generación de enlaces de anclaje

Comencemos a escribir JavaScript para lograr nuestro objetivo de generación de enlaces. El primer paso es generar ID y enlaces basados ​​en textos de encabezado. El siguiente fragmento de código JavaScript hace este trabajo:

document.querySelectorAll('.post-content h1, .post-content h2, .post-content h3, .post-content h4').forEach($heading => {

    //create id from heading text
  var id = $heading.getAttribute("id") || $heading.innerText.toLowerCase().replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').replace(/ +/g, '-');

  //add id to heading
  $heading.setAttribute('id', id);

  //append parent class to heading
  $heading.classList.add('anchor-heading');

  //create anchor
  $anchor = document.createElement('a');
  $anchor.className = 'anchor-link';
  $anchor.href = '#' + id;
  $anchor.innerText = '#';

  //append anchor after heading text
  $heading.appendChild($anchor);
});

El código JavaScript anterior selecciona todos los h1 , h2 , h3 y h4 dentro del .post-content selector. ¿Por qué este selector de clase? Porque queremos agregar enlaces ancla a los encabezados solo dentro del contenido del artículo y no en toda la página.

forEach() es un método de elemento de JavaScript que llama a la función proporcionada una vez para cada encabezado. Dentro de la función provista, en primer lugar, creamos una ID basada en el valor de ID existente o el texto del encabezado. El ID generado luego se agrega al encabezado usando el setAttribute() método.

Al final, creamos un nuevo elemento ancla, establecemos su URL y mostramos el texto (# ) antes de agregarlo junto al texto del encabezado. En resumen, si tenemos el encabezado como este <h2>Introduction</h2> , se convertirá en lo siguiente:

<h2 id="introduction" class="anchor-heading">Introduction<a class="anchor-link" href="#introduction">#</a></h2>

También es posible que desee agregar un desplazamiento suave a los enlaces de anclaje recién generados. De forma predeterminada, si hace clic en cualquiera de estos enlaces, saltará repentinamente a la parte superior. Puede cambiar este comportamiento con el siguiente código para que sea una transición de desplazamiento suave.

document.querySelectorAll('a.anchor-link').forEach($anchor => {
    $anchor.addEventListener('click', function (e) {
        e.preventDefault();
        document.querySelector(this.getAttribute('href')).scrollIntoView({
            behavior: 'smooth',
            block: 'start' //scroll to top of the target element
        });
    });
});

En este punto, hemos terminado con la generación de enlaces y su suave desplazamiento hacia la parte superior. Pero solo funciona después de que la página está completamente cargada. Si desea saltar directamente a una determinada sección del artículo ingresando un enlace ancla en la ventana del navegador, debemos trabajar un poco más:

if (window.location.hash.length > 0) {
    setTimeout(function () {
        document.querySelector('a[href="' + window.location.hash + '"]').click();
    }, 150);
}

Observe el setTimeout() función. Estamos usando esto para retrasar nuestra navegación manual para 150ms para que los enlaces de anclaje profundo se generen y agreguen a DOM.

Finalmente, agreguemos algunos estilos CSS para mostrar enlaces de anclaje profundos solo cuando el usuario pasa el mouse sobre los encabezados. Esto es exactamente lo que estoy haciendo en mi blog. Si pasa el cursor sobre cualquier título, verá un enlace ancla.

.anchor-heading .anchor-link {
    display: inline-block;
    padding-left: .25rem;
    text-decoration: none;
    opacity: 0;
    transition: opacity ease-in-out .25s;
}

.anchor-heading .anchor-link:hover {
    opacity: 1 !important;
}

.anchor-heading:hover .anchor-link {
    opacity: .5;
}

De forma predeterminada, los enlaces de anclaje son invisibles (la opacidad es 0 ). Cuando pasas el cursor sobre el encabezado, la opacidad del enlace ancla aumenta a .5 o 50% . La opacidad se incrementa a 100% cuando se desplaza directamente sobre el enlace.

Bonificación:Solución jQuery

Si ya está utilizando jQuery en su sitio web, agregar enlaces de anclaje profundos es aún más fácil. Reemplace el código JavaScript Vanilla anterior con el siguiente código equivalente de jQuery:

$(document).ready(function () {
    $('.post-content h1, .post-content h2, .post-content h3, .post-content h4').each(function () {

        //create id from heading text
        var id = $(this).attr('id') || $(this).text().toLowerCase().replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '').replace(/ +/g, '-');

        //add id to heading
        $(this).attr('id', id);

        //append parent class to heading
        $(this).addClass('anchor-heading');

        //create anchor
        var anchor = $('<a class="anchor-link" href="#' + id + '">#</a>');

        //append anchor link after heading text
        $(this).append(anchor);
    });

    //add smooth scroll for anchor links
    $(document).on('click', 'a.anchor-link', function (e) {
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: $($(this).attr('href')).offset().top - 50
        }, 1000, 'linear');
    });

    //navigate to anchor if available
    if (window.location.hash.length > 0) {
        $('a[href="' + window.location.hash + '"]').trigger('click');
    }
});

Conclusión

Eso es todo para convertir encabezados en una publicación de blog o cualquier otro documento HTML en enlaces de anclaje profundo. Discutimos las soluciones basadas en JavaScript y jQuery. No es la única forma de agregar enlaces de anclaje profundo. Existen muchas otras formas creativas de agregar dichos enlaces.

Si necesita una solución más avanzada (más opciones para mostrar/ocultar íconos, ubicación de enlaces, etc.), le recomiendo Anchor.js. Es un archivo JavaScript minimizado de ~6 KB que le permite agregar enlaces de anclaje profundos sobre la marcha. Pero si le preocupa el rendimiento del sitio web, simplemente agregue las pocas líneas de código anteriores y estará listo.

Si tiene alguna pregunta o sugerencia, no dude en enviarme un tweet en cualquier momento.