Fancy favicon external link component in Vue
Tags: vue, favicon, tutorial
Published: 2021-06-01 10:50:38

Have you notice that several apps such as [Confluence](https://www.atlassian.com/software/confluence?&aceid=&adposition=&adgroup=98645588106&campaign=9616887043&creative=425944361986&device=c&keyword=confluence&matchtype=e&network=g&placement=&ds_kids=p52353093997&ds_e=GOOGLE&ds_eid=700000001542923&ds_e1=GOOGLE&gclid=CjwKCAjwtdeFBhBAEiwAKOIy5xMNtQrwM4lqBEjEowMUbbqGFdnnJYoNwHAZeA5wo6nKb1rw4MU74BoCkboQAvD_BwE&gclsrc=aw.ds) automatically add a pretty little favicon just left to the link whenever you paste one?

![Screenshot 2021-06-01 at 10.07.11](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9otg6697tgjfpekbj9s.png)

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`

```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>
```

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](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attributes) 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
```

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:

```javascript
function getDomain(url) {
  return url.match(/:\/\/(.[^/]+)/)[1];
}
```

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`

```vue
<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>
```

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

```html
<template>
  <a :href="href" class="fancy-link" :style="styles"><slot /></a>
</template>
```


# Add it to your app

![fancy](https://media.giphy.com/media/HDNcjt5ELkJSE/giphy.gif)

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

```vue
  <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>
```

After styling it you will get something like this

{% codesandbox 8cswb %}


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