Skip to content

Add Share buttons to your Blog

One feature that is currently missing from the Material for MkDocs Blog plugin1 are share buttons that would allow your readers to share your blog post on Social media platforms.
This guide will show you how you can implement this yourself!

Prerequisites

This Guide requires you to have knowledge in extending the Material for MkDocs theme as it requires changes to some of its pages.
Should you not have experience in theme extending can you read about it here.

1. Setting the button data

This setup will use values you set within your mkdocs.yml file, namely inside the extra option. In our case would we have the following values:

mkdocs.yml
extra:
  # Other values
  share:
    - link: 'https://example.com?text={title}&url={url}'
      icon: 'material/share'
      title: 'Share this Post!'
      class: 'md-button__social--example'

We would iterate through the list of entries in share and use the values accordingly.

link would be the URL of the social media site where you want to share your post. {title} and {url} would be replaced with specific values.
icon would be an SVG icon offered by Material for MkDocs. Basically any icon that can be found in .icons/ would be usable, meaning you could also use your own if you set some.
title would be the text used for the title attribute of the Link Element.
class would be classes that get added alongside md-button and md-button__social (More on that later).

You can of course choose a different aproach of providing values, or even hard-code them into the template itself. I chose this aproach as it is a simple way of adding or removing share button when needed.

2. Creating share.html

The first thing you should do is create a new template file.
I call mine share.html and put it in <custom_dir>/partials/ (<custom_dir> being the theme -> custom_dir folder you've set in your mkdocs.yml file). You could also edit the blog-post.html file directly, but a separate file can make it easier for you to edit and maintain, which is why I chose this aproach.

Once you've created the file, would you add the following content to it:

share.html
{% if config.extra and config.extra.share %}
  Share this Post:<br>
  {% for entry in config.extra.share %}
    {% set page_title = page.title | urlencode %}
    {% set url = share.link | replace("{url}", page.canonical_url) | replace("{title}", page_title) %}
    {% set icon = share.icon | d("material/share") %}
    <a href="{{ url }}" class="md-button md-button__social {{ share.class | d('md-button--primary') }}" title="{{ share.title | d('Share this Post!') }}" target="_blank" rel="noopener">
      {% include ".icons/" ~ icon ~ ".svg" %}
    </a>
  {% endfor %}
{% endif %}

Here is how it works: The template first checks if the extra config option exists and if it contains share. Should this be the case will it go through each entry of the share option.
For each option would it do the following:

  • Get the page Title and URL Encode it to use later in the final href value.
  • Get the share.link value defined and replace {url} with the canonical page URL and {title} with the previously retrieved page title.
  • Get the share.icon to use, defaulting to material/share () if none is found.
  • Create a a HTML element containing the following:
    • href being set to the previously created url object.
    • class being set to md-button md-button__social and either the value provided through share.class or md-button--primary if not set.
    • title being set to the value of share.title, defaulting to Share this Post! if none is found.
    • target="_blank" and rel="noopener" to open the links in new tabs.

This would now create buttons one can click to open a Link to share your blog post. However, the template file isn't used yet and also doesn't look that appealing, which we will work on in the next sections.

3. Use the share.html template

Making a dedicated share.html now gives us the freedom of choosing where the buttons should actually be displayed.
In this example will I add an additional section to the left sidebar of blog-post.html, right under the Metadata section, to display the buttons. This requires me to copy the content of blog-post.html2 to extend and customize it.
The result of implementing the template would look something similar to this:

blog-post.html
<!--                                                       -->
<!-- Parts of this file have been omitted for readibility. -->
<!-- Please check the original file for all the content.   -->
<!--                                                       -->
{% extends "main.html" %}
{% import "partials/nav-item.html" as item with context %}
{% block container %}
  <div class="md-content md-content--post" data-md-component="content">
    <div class="md-sidebar md-sidebar--post" data-md-component="sidebar" data-md-type="navigation">
      <div class="md-sidebar__scrollwrap">
        <div class="md-sidebar__inner md-post">
          <nav class="md-nav md-nav--primary">
            <!-- Omitted -->
            <ul class="md-post__meta md-nav__list">
              <!-- Omitted -->
              <li>
                <div class="md-post__title">
                  <span class="md-ellipsis">
                    Share
                  </span>
                </div>
                <nav class="md-nav">
                  <ul class="md-nav__list">
                    <li class="md-nav__item">
                      <div class="md-nav__link">
                        {% include "partials/share.html" %}
                      </div>
                    </li>
                  </ul>
                </nav>
              </li>
            </ul>
            <!-- Omitted -->
          </nav>
          {% if "toc.integrate" in features %}
            {% include "partials/toc.html" %}
          {% endif %}
        </div>
      </div>
    </div>
    <article class="md-content__inner md-typeset">
      {% block content %}
        {% include "partials/content.html" %}
      {% endblock %}
    </article>
  </div>
{% endblock %}

This would add a section labeled Share right after the Metadata section, adding our Share template via {% include ... %} function of Jinja2.
You would now see the buttons, but their general style may look off. This can be fixed by making some extra CSS now.

4. Adding CSS

Our setup uses some unique classes: md-button__social and additional classes you would add via the share.class option. In our example are we using md-button__social--<platform> as class names for this option.

The md-button__social class is used to adjust certain attributes of the default md-button class which is used too. Some of these values include changing the line-height to 0 to have an equal padding around the icon itself, which we also set to .625em.
I suggest to use simple/... SVG icons, as they are all a consistent 24x24 pixels, allowing the bottom to have an equal height and width.

Here is an example CSS setup that contains common collors used for common social media platforms:

share.css
:root {
  --md-button__mastodon: #6364FF;
  --md-button__bluesky: #0886FE;
  --md-button__twitter: #1DA1F2; /* (1) */
  --md-button__facebook: #0866FF;

  /* (2) */
  --md-button__mastodon--lighter: #8283FF;
  --md-button__bluesky--lighter: #399EFE;
  --md-button__twitter--lighter: #4AB4F5; /* (3) */
  --md-button__facebook--lighter: #3985FF;
}

.md-post .md-button.md-button__social {
  line-height: 0;
  padding: .625em;
  color: white;
  border-radius: .1rem; /* (4) */
}

.md-post .md-button.md-button_social:hover {
  color: white; /* (5) */
}

.md-button.md-button__social--mastodon {
  background-color: var(--md-button__mastodon);
  border-color: var(--md-button__mastodon);
}

.md-button.md-button__social--bluesky {
  background-color: var(--md-button__bluesky);
  border-color: var(--md-button__bluesky);
}

.md-button.md-button__social--twitter {
  background-color: var(--md-button__twitter);
  border-color: var(--md-button__twitter);
}

.md-button.md-button__social--facebook {
  background-color: var(--md-button__facebook);
  border-color: var(--md-button__facebook);
}

.md-button.md-button__social--mastodon:hover {
  background-color: var(--md-button__mastodon--lighter);
  border-color: var(--md-button__mastodon--lighter);
}

.md-button.md-button__social--bluesky:hover {
  background-color: var(--md-button__bluesky--lighter);
  border-color: var(--md-button__bluesky--lighter);
}

.md-button.md-button__social--twitter:hover {
  background-color: var(--md-button__twitter--lighter);
  border-color: var(--md-button__twitter--lighter);
}

.md-button.md-button__social--facebook:hover {
  background-color: var(--md-button__facebook--lighter);
  border-color: var(--md-button__facebook--lighter);
}
  1. If you want to use X branding colors, change this to #000.
  2. These colors are used when hovering over the buttons to "highlight" them.
  3. If you want to use X branding colors, change this to #333.
  4. The border radius isn't applied within md-post so we have to re-apply it here.
  5. The color for hovering is being changed in md-post so we have to force it back to white here.

Note

Don't forget to add this File as extra_css to your mkdocs.yml file!

You can now use f.e. md-button__social--mastodon to have the button use the Mastodon brand color as its background.

You're done

That should be it!

If you followed this tutorial should you have the following:

  • A share.html file located at <custom_dir>/partials/
  • A blog-post.html file located at <custom_dir>/ including the share.html template via {% include "partials/share.html" %}
  • A share.css file located in the assets folder of your docs_dir and added to your mkdocs.yml as extra_css
  • A share option inside extra of your mkdocs.yml file containing entries for individual sites.

As an example are here the share values used for this blog:

mkdocs.yml
extra:
  share:
    - link: 'https://mastodonshare.com/?url={url}&text={title}'
      icon: 'simple/mastodon'
      title: 'Toot Post on Mastodon!'
      class: 'md-button__social--mastodon'
    - link: 'https://bsky.app/intent/compose?text={title}%0A{url}'
      icon: 'simple/bluesky'
      title: 'Share Post on Bluesky!'
      class: 'md-button__social--bluesky'

For a working example can you look at the sidebar of this post which should display the above links as buttons.

Here is a quick collection of common social media platforms and the recommended links to use.

Mastodon

Recommended Link: https://mastodonshare.com/?url={url}&text={title}

Mastodon offers a share option in the form of <instance_domain>/share?text=<text>.
However, due to its decentralized nature could the user sharing your post not use the same instance as you. Thankfully, the community created a solution in the form of mastodonshare.com which provides a main URL for sharing posts. The downside is, that the user has to first provide the instance Domain to be forwarded to its share link. This, however, is only a one-time thing as the site remembers the instance provided and redirects the user on their next visit.

Bluesky

Recommended Link: https://bsky.app/intent/compose?text={title}%0A{url}

Bluesky only provides a text query parameter, requiring us to use URL encoded values in the final URL if we want to include both {title} and {url}.
We use %0A which is a URL-encoded newline and is treated as a space character by Bluesky. You may also use %20 for an actual Space character. Keep in mind that adding multiple of %0A won't add multiple newlines as Bluesky will strip them from the Compose UI.

Twitter

Recommended Link: https://twitter.com/intent/tweet?url={url}&text={title}

I personally recommend to not support Twitter anymore by adding a Share button to it. But if you want, then the above URL would be the one you should use.


Footnotes

Comments

Comment system powered by Mastodon.
Leave a comment using Mastodon or another Fediverse-compatible account.


Last update: 19. February 2025 ()