Medium-like social sharing in Vue

Medium-like social sharing in Vue

In this tutorial, we cover how to use the share-this package (itself inspired by Medium) in Vue for your readers to highlight and share your content. This Medium-like social sharing package is lightweight and extensible with some unique and impressive features.

Before going any further, the implementation for this is using the Creating a blog with NuxtJS and Netlify CMS series template, so check that out for some context if you need it.

Getting started

First of all, install the share-this package with:

yarn add share-this or npm i share-this

Using either of these commands installs the package and adds the dependency to your package.json file.

Next, you need to add this to the page template you want readers to be able to highlight:

// pages/blog/_slug.vue
import shareThis from 'share-this'
import * as twitterSharer from 'share-this/dist/sharers/twitter'
import * as facebookSharer from 'share-this/dist/sharers/facebook'
import * as redditSharer from 'share-this/dist/sharers/reddit'

You'll notice we're importing the Twitter, Facebook and Reddit sharing options for this tutorial. For the full list and how to add custom sharers, consult the docs.

From here, it's easy to enable this for a section on your page:

export default {
  mounted() {
    const selectionShare = shareThis({
      selector: '#shareable',
      sharers: [twitterSharer, facebookSharer, redditSharer]
    })

    selectionShare.init()
  }
}

For this example, all you need is an HTML element with the id of shareable for this to work:

<article id="shareable" class="post-content" v-html="html"></article>

Implementing styles

By default, the package contains some basic styles that are useable from the share-this/dist/share-this.css location. If you're happy with the default styling, then go for it! However, in our case, we'll customise it.

Another fantastic aspect of this package is the simple markup, which makes it easy for us to add our styles. For this tutorial, we'll implement the styles made for this blog:

.share-this-popover {
  animation: share-this 360ms forwards linear;

  &::before {
    border-color: #252525 transparent;
    border-style: solid;
    border-width: 0.4em 0.4em 0;
    bottom: 100%;
    content: '';
    height: 0;
    left: 50%;
    transform: translateX(-50%);
    margin: 0;
    position: absolute;
    width: 0;
  }

  ul {
    background-color: #252525;
    border-radius: 0.5rem;
    transform: translate(-50%, -110%);
    background: linear-gradient(to bottom, rgba(49, 49, 47, 0.99), #252525);
    padding: 0;
    margin: 0;
    display: inline-block;
    color: #fff;
    left: 50%;
    display: flex;
    list-style: none;
    position: absolute;
    white-space: nowrap;
    padding: 0.5rem 0.7rem;

    li {
      display: inline-block;
      height: 1.2rem;
      line-height: 1.2rem;
      text-align: center;
      margin: 0;
      padding: 0 0.4rem;
      width: 2rem;

      &:first-child {
        padding-left: 0;
        width: 1.6rem;
      }
      &:last-child {
        padding-right: 0;
        width: 1.6rem;
      }

      a {
        color: #fff;
        box-shadow: none;
        display: block;
      }
    }
  }
}

@keyframes share-this {
  0% {
    opacity: 0;
    -webkit-transform: matrix(0.97, 0, 0, 1, 0, 12);
    transform: matrix(0.97, 0, 0, 1, 0, 12);
  }
  20% {
    opacity: 0.7;
    -webkit-transform: matrix(0.99, 0, 0, 1, 0, 2);
    transform: matrix(0.99, 0, 0, 1, 0, 2);
  }
  40% {
    opacity: 1;
    -webkit-transform: matrix(1, 0, 0, 1, 0, -1);
    transform: matrix(1, 0, 0, 1, 0, -1);
  }
  70% {
    opacity: 1;
    -webkit-transform: matrix(1, 0, 0, 1, 0, 0);
    transform: matrix(1, 0, 0, 1, 0, 0);
  }
  100% {
    opacity: 1;
    -webkit-transform: matrix(1, 0, 0, 1, 0, 0);
    transform: matrix(1, 0, 0, 1, 0, 0);
  }
}

Most of these styles were inspired by Rich Tabor, so many thanks to him for such an elegant implementation. However, there are a few optimisations here (such as padding, widths and the arrow location code has been improved)!

Wrapping Up

As you can see, this package is effortless to set up and integrate into your current Vue / Nuxt website. It offers some excellent features, and the package author has created a couple of superb custom "sharers" to take notes and read the text with the speech synthesis API.

Of course, feel free to change the styles to suit your blog styling and colour scheme. For any questions or suggestions, contact me on Twitter or check out the nuxt-netlify-cms-starter project on Github.