<body>
  <h1>"Copy bookmark link to clipboard" button</h1>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iure veritatis
    expedita id. Reprehenderit cum in exercitationem tempore, a rem
    praesentium iusto nam ducimus tempora totam minus, fuga, reiciendis
    necessitatibus quisquam!
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <h2>First heading 2</h2>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil fugit,
    distinctio ex incidunt sint sed unde, perferendis, quos modi nulla dolore
    cumque delectus doloremque ab repudiandae earum nemo in adipisci.
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <h3>A heading 3</h3>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates harum
    ipsum, expedita et reprehenderit error asperiores repudiandae aspernatur
    eum optio. Illo unde odit, inventore praesentium et quia voluptatum
    cupiditate similique?
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <h2>Second heading 2</h2>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil fugit,
    distinctio ex incidunt sint sed unde, perferendis, quos modi nulla dolore
    cumque delectus doloremque ab repudiandae earum nemo in adipisci.
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <h3>Heading 3 again</h3>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates harum
    ipsum, expedita et reprehenderit error asperiores repudiandae aspernatur
    eum optio. Illo unde odit, inventore praesentium et quia voluptatum
    cupiditate similique?
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <h4>Heading 4</h4>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates harum
    ipsum, expedita et reprehenderit error asperiores repudiandae aspernatur
    eum optio. Illo unde odit, inventore praesentium et quia voluptatum
    cupiditate similique?
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <h5>Heading 5</h5>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates harum
    ipsum, expedita et reprehenderit error asperiores repudiandae aspernatur
    eum optio. Illo unde odit, inventore praesentium et quia voluptatum
    cupiditate similique?
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <h6>Heading 6</h6>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptates harum
    ipsum, expedita et reprehenderit error asperiores repudiandae aspernatur
    eum optio. Illo unde odit, inventore praesentium et quia voluptatum
    cupiditate similique?
  </p>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium quis,
    alias inventore distinctio laboriosam, quisquam nemo excepturi ipsum
    necessitatibus quia, iusto illum cupiditate eius corporis labore provident
    dignissimos? Iste, dignissimos.
  </p>
  <div id="snackbar">Link copied to clipboard</div>
@import url("https://fonts.googleapis.com/css2?family=Merriweather:wght@700&family=Poppins&display=swap");

body {
  margin: 0 auto;
  max-width: 600px;
  font-family: Poppins, sans-serif;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: Merriweather, serif;
  font-weight: bold;
  display: flex;
  align-items: center;
}

:is(h2, h3, h4, h5, h6) button {
  text-decoration: none;
  color: #767676;
  margin: 0 0.25em;
  padding: 0.1em;
  font: inherit;
  font-size: 0.8em;
  transition: color 0.2s ease-in-out;
}

:is(h2, h3, h4, h5, h6) button:hover {
  color: rgb(27, 27, 252);
}

/* Position it at the top and in the middle of the screen */
#snackbar {
  position: fixed;
  z-index: 1;
  top: 0;
  left: 50%;
  min-width: 250px;
  margin-left: -125px;
  background-color: #333;
  color: #fff;
  text-align: center;
  border-radius: 5px;
  padding: 16px;
  transform: translateY(-10px);
  opacity: 0;
}
let headings = document.querySelectorAll("h2, h3, h4, h5, h6");
let snackbarTimeout;

// we do this to exclude the text fragment
const currentURL = `${window.location.protocol}//${window.location.host}${window.location.pathname}`;

headings.forEach((heading) => {
  let slug = slugify(heading.innerText);
  heading.setAttribute("id", slug);

  const bookmarkBtn = document.createElement("button");
  bookmarkBtn.innerText = "#";
  bookmarkBtn.setAttribute("data-href", `${currentURL}#${slug}`);
  bookmarkBtn.addEventListener("click", copyLink);
  heading.append(bookmarkBtn);
});

/**
 * Produces a slug from the text provided that can be used as an URL fragment. Does it the same as GitHub.
 *
 * @param {string} text - The text to slugify
 * @returns {string} The slug.
 */
function slugify(text) {
  // Anything that is an unwanted punctuation character
  const PUNCTUATION_REGEXP = /[^\p{L}\p{M}\p{N}\p{Pc}\- ]/gu;

  let slug = text.trim().toLowerCase();
  slug = slug.replace(PUNCTUATION_REGEXP, "").replace(/ /g, "-");
  return slug;
}

async function copyLink(event) {
  const button = event.srcElement;
  let text = button.getAttribute("data-href");
  await navigator.clipboard.writeText(text);
  showSnackbar();
}

function showSnackbar() {
  let snackbar = document.getElementById("snackbar");

  let fadeIn = snackbar
    .animate(
      [
        { opacity: 1, offset: 0.1 },
        { opacity: 1, offset: 0.8 },
        { opacity: 0, offset: 1 }
      ],
      {
        duration: 3000
      }
    )
    .play();

  let move = snackbar
    .animate(
      [
        { transform: "translateY(20px)", offset: 0.2 },
        { transform: "translateY(20px)", offset: 0.8 },
        { transform: "translateY(-10px)", offset: 1 }
      ],
      {
        duration: 3000
      }
    )
    .play();
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.