Next Link and Mailto in Safari

Using the Next.js Link component for mailto email links works fine everywhere except for Safari on macOS, which throws the following JavaScript alert upon tap:

A browser alert on Safari saying 'This website has been blocked from automatically composing an email.'
“This website has been blocked from automatically composing an email.”

It’s probably caused by the Link component doing some fancy intercepting, which looks suspect to the browser. You can fix this by just using a regular <a> tag instead.

In other words, take this problematic starting point:

import Link from "next/link";

<Link href="mailto:you@example.com">Email me</Link>;

And just swap out the <Link> with a regular HTML <a> tag:

<a href="mailto:you@example.com">Email me</a>

The same problem and solution applies to tel and sms links, too.

Better

I personally roll-up my own Hyperlink component with an as prop. It renders either a Link component or <a> tag depending on what I pass through as a value to an as prop. Here’s what it looks like in practice:

<Hyperlink as="anchor" href="mailto:you@example.com">
  Email me
</Hyperlink>

This setup lets me define styles in one component and just occasionally override the element type for email links via that as prop, like so:

import Link from "next/link";
import { styled } from "@pigment-css/react";

// Define styles
const getSharedStyles = ({ theme }) => ({
  color: theme.colors.text.primary,
  fontWeight: "500",
  textDecoration: "underline",
  transition: "opacity 150ms ease-in-out",
  "&:hover": {
    opacity: 0.65,
  },
});

// Share the same styles across whatever element is rendered
const StyledLink = styled(Link)(getSharedStyles);
const StyledAnchor = styled("a")(getSharedStyles);

// Export the component
export default function Hyperlink({ as = Link, children, href, ...props }) {
  if (as === "anchor") {
    return (
      <StyledAnchor href={href} {...props}>
        {children}
      </StyledAnchor>
    );
  }

  return (
    <StyledLink href={href} {...props}>
      {children}
    </StyledLink>
  );
}

There’s probably a way to do that automatically by reading the href contents but that’s a little too fancy for my liking. I prefer to be explicit about what’s being rendered, when.

Best

You should also encode your email address so it doesn’t end up forever receiving spam.