Frontend Shorts: How to create link content previewer with React, Vue, and Vanilla JavaScript
Tags: javascript, react, vue, webdev
Published: 2020-04-16 08:48:22

---
title: Frontend Shorts: How to create link content previewer with React, Vue, and Vanilla JavaScript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/yzfom0qy9747q4cvj213.jpg
published: true
description: In this post, I will show you how you can quickly develop a link content previewer feature for your blog with React, Vue, and Vanilla JavaScript.
tags: javascript, react, vue, webdev
---

I love not only blogging but read blogs too! Traditionally, when bloggers state some scientific-based facts or refer to other posts, they have to add a link to sources.

**The question for readers is, whether it would be worth to stop reading the post and switch to reading a source now?**

Because along with the post, we might have up to 10 links to different sources. Which can we skip then?

That's why nowadays, the link content previewer is a must-have feature for blogs and even chats. You have seen them already in many different forms on Facebook, LinkedIn, Twitter, WhatsApp, etc.

The main benefit of the link content previewer is that readers can have some expectations of what they are going to read later before they follow the link.

Usually, a link content previewer contains the domain name (URL), the title, text, and an image. You can also create it with more information by providing more data to its content. 

In this post, I will show you **how you can quickly develop a link content previewer feature for your blog with React, Vue, and Vanilla JavaScript**.

![Link Content Previewer](https://dev-to-uploads.s3.amazonaws.com/i/aukl8h6ktfl78xgehkt1.gif)

From simple to more complicated concepts, let's start with Vanilla JavaScript implementation:

## Part I: Link content previewer with VanillaJS

The first step is to add straightforward text content to the `index.html`:

```html
<!--index.html-->

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Link Content Previewer</title>
</head>
<body>

<div class="wrapper">
    <p>Hi there! 👋</p>
    <p>I would like to share some frontend tips and tricks that
        I have already applied to some of my projects.</p>
    <p>Happily coming back with <br/> my
        <a href="https://dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og"
    	     class="link-with-preview"
        >
            frontend shorts
        </a>
        series on
        <a href="https://dev.to"
	     class="link-with-preview"
        >
            dev.to.
        </a>
        Let me show you how...
    </p>
</div>

</body>
</html>
```

Next, it's necessary to have a `card` element that will include and preview the information from the referred source:

```html
<!--index.html-->
...
<div class="card">
    <img src="" class="card-img-top">
    <div class="card-body">
        <h5 class="card-title"></h5>
        <p class="card-text"></p>
    </div>
</div>
```
So far, you see, that I use`Bootstrap 4` and custom CSS-classes for card styling. They should be imported to the `<head />` too:

```html
<!--index.html-->
...
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="index.css">
...
```
Thanks to `Boostrap 4` functionality, element positioning, and some basic styles are applied automatically from the library. So, the `index.css` file is not large, so below you find all needed styles for a link content previewer feature:

```css
/*index.css*/

body {
    font-size: 24px;
}

.wrapper {
    width: 500px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    position: absolute;
}

.card {
    width: 150px;
    display: none;
    font-size: 10px;
    color: black;

    position: absolute;
    z-index: 100;

    bottom: 30px;
    left: 50%;
    transform: translateX(-50%);
}

.link-with-preview {
    position: relative;
}

.card img {
    width: 150px;
}

.card-title {
    font-size: 14px;
}
```
To make a link content previewer work, we have to write JavaScript. I hope you haven't forgotten to add the script to the end of the `body` in `index.html`:

```html
<!--index.html-->
...
<script src="index.js"></script>
```
And ready to start coding in JavaScript:

```javascript
const card = document.querySelector(".card");

const hideLinkPreview = () => {
    return card.style.display = 'none';
};

const showLinkPreview = event => {
    const image = event.currentTarget.getAttribute("data-image");
    card.querySelector('img').setAttribute("src", image);

    const title = event.currentTarget.getAttribute("data-title");
    card.querySelector('h5').textContent = title;

    const text = event.currentTarget.getAttribute("data-text");
    card.querySelector('p').textContent = text;

    event.currentTarget.appendChild(card);

    return card.style.display = 'inline-block';
};

document.querySelectorAll(".link-with-preview").forEach(el => {
    el.addEventListener("mouseover", showLinkPreview);
    el.addEventListener("mouseleave", hideLinkPreview)
});
```
1. Declare the`card` and implement two functions `hideLinkPreview(event)` and `showLinkPreview(event)` with the `event` parameter. In our case, it's `onmouseover` and `onmouse leave` events for the `<a />` link.

2. `hideLinkPreview(event)` works easy. It just hides the content preview (a card) on a mouse leave event.

3. For `showLinkPreview(event)`, it's important to get attributes like `data-image`, `data-title` and `data-text` from the `<a />` link, set them with to the `card` instance to show and preview the content of the referred resource on mouseover event.

4. `event.currentTarget.appendChild(card);` helps us to append the `card` inside the link content previewer and position/center the card properly above the link.

5. Pass all the needed data to `index.html` to preview not-empty `card` in your browser on hover:

```html
<!--index.html-->

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Link Content Previewer</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="index.css">
</head>
<body>
<div class="wrapper">
    <p>Hi there! 👋</p>
    <p>I would like to share some frontend tips and tricks that
        I have already applied to some of my projects.</p>
    <p>Happily coming back with <br/> my
        <a href="https://dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og"
           onmouseover="showLinkPreview()"
           onmouseleave="hideLinkPreview()"
           class="link-with-preview"
           data-image="https://dev-to-uploads.s3.amazonaws.com/i/3zp478dfafzy1mgfaevn.jpg"
           data-title="Frontend Shorts: Vue.js + Vanilla.js — Digital Dices"
           data-text="Let me show you how you can implement a dice-rolling simulator in less than 30 minutes of your time on the front-end."
        >frontend shorts</a>
        series on
        <a href="https://dev.to"
           onmouseover="showLinkPreview()"
           onmouseleave="hideLinkPreview()"
           class="link-with-preview"
           data-image="https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png"
           data-title="DEV Community 👩‍💻👨‍💻"
           data-text="Where programmers share ideas and help each other grow—A constructive and inclusive social network."
        >
            dev.to.
        </a>
        Let me show you how...
    </p>
</div>

<div class="card">
    <img src="" class="card-img-top">
    <div class="card-body">
        <h5 class="card-title"></h5>
        <p class="card-text"></p>
    </div>
</div>

<script src="index.js"></script>
</body>
</html>
```

**The full source code of the VanillaJS implementation** you can find:

[VanillaJS — index.html](https://gist.github.com/ilonacodes/178291a653cfe5b679e7c7e396350190)

[VanillaJS — index.css](https://gist.github.com/ilonacodes/82215b8c73c54a7c2e17535f9c4dd2d3)

[VanillaJS — index.js](https://gist.github.com/ilonacodes/7c3e8c6c537ac76026c2cff922dafd4d)

## Part II: Link content previewer with Vue.js

As you guess so far, `index.html` and `index.css` will look similar to the `index.html` and `index.css` from the VanillaJS implementation too:

```html
<div id="app">
    <div class="wrapper">
        <p>Hi there! 👋</p>
        <p>I would like to share some frontend tips and tricks that
            I have already applied to some of my projects.</p>
        <p>Happily coming back with <br/> my
            <link-previewer
                    href="https://dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og"
                    text="frontend shorts"
                    preview-img="https://dev-to-uploads.s3.amazonaws.com/i/3zp478dfafzy1mgfaevn.jpg"
                    preview-title="Frontend Shorts: Vue.js + Vanilla.js — Digital Dices"
                    preview-text="Let me show you how you can implement a dice-rolling simulator in less than 30 minutes of your time on the front-end."
            ></link-previewer>
            series on
            <link-previewer
                    href="https://dev.to"
                    text="dev.to."
                    preview-img="https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png"
                    preview-title="DEV Community 👩‍💻👨‍💻"
                    preview-text="Where programmers share ideas and help each other grow—A constructive and inclusive social network."
            ></link-previewer>
            Let me show you how...
        </p>
    </div>

</div>
```

To use Vue.js framework, you need to add Vue.js script for that:

```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
```

According to the `index.html`, we are still missing `link-previewer` component with the corresponding props: `href`, `text`, `previewTitle`, `previewImg` and`previewText`. Let's create the `link-previewer` component with Vue.js in `index.html` below:

```html
...
<script>
    Vue.component('link-previewer', {
        props: ['href', 'text', 'previewTitle', 'previewImg', 'previewText'],

        data() {
            return {
                shown: false
            };
        },

        methods: {
            show() {
                this.shown = true;
            },

            hide() {
                this.shown = false;
            }
        },

        // this enables proper syntax highlighting and auto-completion in the IDE for the HTML code snippet below:
        //language=HTML
        template: `
            <a v-bind:href="href"
               v-on:mouseover="show"
               v-on:mouseleave="hide"
               class="link-with-preview"
            >
                {{ text }}
                <div class="card"
                     v-bind:class="{'card-show': shown}">
                    <img v-bind:src="previewImg" alt=""
                         class="card-img-top">
                    <div class="card-body">
                        <h5 class="card-title">{{ previewTitle }}</h5>
                        <div class="card-text">
                            {{ previewText }}
                        </div>
                    </div>
                </div>
            </a>
        `
    });

    const app = new Vue({
        el: '#app'
    });
</script>
```

- The only data that changes the state of the 'link-previewer' component is  `shown: false` in `data()`

- That depends on call of ` show()` and `hide()` methods

- In the case of Vue.js implementation, the `card` component with its referred props will be built as a `template`.

- The data is passing from the `link-previewer` to the `card` with the help of the `v-bind` shorthand, and the events via `v-on`.

**The full solution with Vue.js**, you can see here: [Vue.js — index.html](https://gist.github.com/ilonacodes/57255a75a174aafcea0fe40ee0d00647).


## Part III: Link content previewer with React.js

The HTML-structure of the `App.js` component is almost the same as `index.html` for the VanillaJS implementation:

```javascript
// App.js

import React from "react";
import "./styles.css";
import { LinkPreviewer } from "./LinkPreviewer";

export default function App() {
  return (
    <div className="App">
      <div>
        <p>Hi there! 👋</p>
        <p>
          I would like to share some frontend tips and tricks that I have
          already applied to some of my projects.
        </p>
        <p>
          Happily coming back with <br /> my
          <LinkPreviewer
            href="https://dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og"
            image="https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png"
            title="Frontend Shorts: Vue.js + Vanilla.js — Digital Dices"
            text="Let me show you how you can implement a dice-rolling simulator in less than 30 minutes of your time on the front-end."
          >
            frontend shorts
          </LinkPreviewer>
          series on
          <LinkPreviewer
            href="https://dev.to"
            image="https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png"
            title="DEV Community"
            text="Where programmers share ideas and help each other grow—A constructive and inclusive social network."
          >
            dev.to
          </LinkPreviewer>
        </p>
      </div>
    </div>
  );
}
```
The difference is only that we need to create `LinkPreviewer` component and use it to render the right data for link content previewing:

```javascript
// LinkPreviewer

import React, { useState } from "react";
import "./styles.css";

export const LinkPreviewer = props => {
  const [isShown, setIsShown] = useState(false);

  return (
    <a
      href={props.href}
      className="link-with-preview"
      onMouseEnter={() => setIsShown(true)}
      onMouseLeave={() => setIsShown(false)}
    >
      <span> {props.children} </span>
      {isShown && (
        <Card image={props.image} title={props.title} text={props.text} />
      )}
    </a>
  );
};

const Card = props => {
  return (
    <div className="card">
      <img src={props.image} className="card-img-top" alt="" />
      <div className="card-body">
        <h5 className="card-title">{props.title}</h5>
        <p className="card-text">{props.text}</p>
      </div>
    </div>
  );
};
```
- The `LinkPreviewer` will return `<a/>` with the needed properties, events and styling class to render the content previewing feature  properly in the browser.

- The `Card` component renders content like image, title, and text of the referred source in preview when `isShown` is true.

- Thanks to React hook `const [isShown, setIsShown] = useState(false);` it's easy to handle two events `onMouseEnter` and `onMouseLeave` of `LinkPreviewer`on hover to hide and show the link content previewer.`

**The CSS-classes are identical to the `index.css` of the VanillaJS approach.**

The code snippets with the **React implementation** are [here](https://codesandbox.io/s/dreamy-wu-0j7f0).


## 💬 Conclusion

As you can see, creating a link content previewer feature is easy, not depending on which JavaScript framework or library you are going to use for it. Because any implementation will not be that much different from another. The approach stays the same.

If you are a developer or a tech-savvy person who has their own blog, then you will not need to rely on a third-party library to have this kind of functionality. You can develop it on your own.

**Thank you for reading!**

I hope you found this frontend short useful and practical and would help me to spread it on the Internet, for example, via Twitter.

Code your best,
Ilona Codes.

___

_Photo by Matteo Catanese on Unsplash_