Poll: Detecting external links

Hey there,
for a site I was looking for a way to detect external links (for adding target=_blank, some SVG icon indicating external URLs etc) and came up with this approach:

# Check if URL is external
if (Url::stripPath(Url::to($url)) !== Url::stripPath(site()->url())) {
    # Yep, external
    $target = 'blank';  # or whatever
}

What are your approaches (like, using parse_url() or something)? Did you find this useful? Could my way be improved? (I guess so!)

Cheers
S1SYPHOS

CSS to the rescue for styling / icon…

a:not([href*="//"]) {
    /* CSS for internal links */
}

a[href*="//"] {
    /*CSS for external links */
}

Target blank is a controversial one - if had a choice (sometimes clients ask insist me to do it), I wont add this because it breaks the use of the back button which is bad for accessibility. :man_shrugging:

1 Like

I agree with James on target="_blank", but I‘d detect external links like this:

!Str::startsWith($url, site()->url())
1 Like

In case we have a link like „/some-page“, your approach wouldn’t work. Then again, Kirby doesn’t produce links like that.

I totally forgot about the CSS approach, thanks James!

You can still combine it with the url() helper like so:

!Str::startsWith(url($url), site()->url())

But since I recommend to run all printed URLs through this helper for more consistent URLs, I’d do it beforehand so you don’t need to do it twice.

Thanks!

How could I add the following code to the end of the external link?

    content: url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2211%22%20viewBox%3D%220%200%2010%2011%22%3E%3Cpath%20d%3D%22M4.5%203.5h-4v6h6v-4%22%20fill%3D%22transparent%22%20stroke%3D%22%23ff5b5e%22%2F%3E%3Cpath%20d%3D%22M4.5.5h5v5L9%206%207.5%204.5l-3%203-2-2%203-3L4%201z%22%20fill%3D%22transparent%22%20stroke%3D%22%23ff5b5e%22%20stroke-width%3D%221.001%22%2F%3E%3C%2Fsvg%3E);
    position: relative;
    top: -3px;
    margin: 0 1px 0 3px;

Try right: 100% or use absolute positioning.

It needs to come with :after

::after

But a[href*="//"] doesn’t get activated/selected/used here. Is there a trick?

As Kirby isn’t working with relative links by default I had to come up with a slightly different rule specific to my URL and now it works, thanks a lot!

.text a[href*="peleke"] {
  /* CSS for internal links */
  color: green;
  text-decoration: none;
}
.text a:not([href*="peleke"])::after {
  /*CSS for external links */
  content: url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2211%22%20viewBox%3D%220%200%2010%2011%22%3E%3Cpath%20d%3D%22M4.5%203.5h-4v6h6v-4%22%20fill%3D%22transparent%22%20stroke%3D%22%23ff5b5e%22%2F%3E%3Cpath%20d%3D%22M4.5.5h5v5L9%206%207.5%204.5l-3%203-2-2%203-3L4%201z%22%20fill%3D%22transparent%22%20stroke%3D%22%23ff5b5e%22%20stroke-width%3D%221.001%22%2F%3E%3C%2Fsvg%3E);
  position: relative;
  top: -3px;
  margin: 0 1px 0 3px;
}
2 Likes

The css rule is a wild card partial string match and the // was just a starting point. I just did the relative / so that it wouldnt match the string. You have made it more specific by putting part of you domain name in there.