DEV Community

Cover image for Fancy favicon external link component in Vue
Alvaro Saburido
Alvaro Saburido

Posted on

Fancy favicon external link component in Vue

Have you notice that several apps such as Confluence automatically add a pretty little favicon just left to the link whenever you paste one?

Screenshot 2021-06-01 at 10.07.11

Sometimes the subtle things are the most enjoyable, specially when talking about UX.

In this tutorial I will show you how to create a link component that automatically grabs the favicon of the link.

I'm gonna asume you have the basics of Vue + Composition API before continuing.

 Create a link component

Le's start by creating a component wrapper for the link, we will call it our FaviconFancyLink.vue

<template>
  <a :href="href" class="fancy-link"><slot /></a>
</template>
<script>

const props = {
  href: {
    type: String
  },
};

export default {
  name: 'FaviconFancyLink',
  props,
}
</script>

<style scoped>
.fancy-link {
  border: 1px solid #ababab;
  border-radius: 3px;
  padding: 0.1rem 6px 0.1rem 24px;
  text-decoration: none;
  background: gray;
}
</style>
Enter fullscreen mode Exit fullscreen mode

The component as now is pretty simple, you pass href as a prop and you pass it down to the <a> tag.

We could even improve this by using v-bind="$attrs" instead of props so we get all the other attributes for links but for now, let's keep it simple.

Getting the favicon

This is where the magic happens, you can easily get the favicon using Google's Favicon Service

https://www.google.com/s2/favicons?domain=dev.to
Enter fullscreen mode Exit fullscreen mode

The trick is to get the hostname from the href prop and add add the image with the favicon api dynamically.

Best way to get the hostname is by using a regex like this:

function getDomain(url) {
  return url.match(/:\/\/(.[^/]+)/)[1];
}
Enter fullscreen mode Exit fullscreen mode

Next step will be to add the favicon image to the link. Easiest way is to use a computed property to add styles with the icon as a background-image

<script>
import { computed } from 'vue';

const props = {
  href: {
    type: String
  },
};

export default {
  name: 'FaviconFancyLink',
  props,
  setup(props) {
      const styles = computed(() => ({
      background: `url(http://www.google.com/s2/favicons?domain=${getDomain(
        props.href
      )}) 4px center no-repeat`,
    }));

    return {
      styles
    };
  }
</script>
Enter fullscreen mode Exit fullscreen mode

Now, let's bind styles into the <a /> element

<template>
  <a :href="href" class="fancy-link" :style="styles"><slot /></a>
</template>
Enter fullscreen mode Exit fullscreen mode

Add it to your app

fancy

Now let's add our fancy link component and see the magic

  <div class="links">
    <FaviconFancyLink href="https://dev.to">Dev.to</FaviconFancyLink>

    <FaviconFancyLink href="https://twitter.com/">Twitter</FaviconFancyLink>

    <FaviconFancyLink href="https://alvarosaburido.dev/"
      >AS - Portfolio</FaviconFancyLink
    >
  </div>
Enter fullscreen mode Exit fullscreen mode

After styling it you will get something like this

And that's pretty much it, easy right? If you enjoy this short tutorial make sure to comment and give some love.

Top comments (1)

Collapse
 
kapcash profile image
Florent Catiau-Tristant

To parse the url, you can also use the URL constructor:

new URL(props.href).host
Enter fullscreen mode Exit fullscreen mode

Nice post anyway! I didn't know that api to get the favicon :)