HTML code in GitHub’s README.md file

When creating README.md file for your GitHub’s repository you can of course use Markdown with all it’s nifty styling. This includes as set of HTML tags that you can embed into any Markdown document.

GitHub extends this set with some extra tags, because it uses GitHub Flavored Markdown Spec, not the core Markdown implementation (a bit limited). But, it also limits it quite a lot, for security reasons.

One of the most missing feature is an ability to use in-line styling. So far, I thought that using CSS styles is simply impossible (or to be precise: you can use them, but GitHub quite aggressively strips them off when rendering Markdown content).

However, it turns out that with using a really sneaky approach, you can embed into your README.md file in your GitHub repo not only a full set of CSS styles, but also iframes, scripts and a whole lot of magic! :)

Since you can insert any image into README.md file (or any other Markdown document), you can also point <img> tag to a .svg “image”. “Image” (in quotation marks), because it is actually an SVG document which — thanks to foreignObject SVG element — can include nearly everything.

Forbidden (by GitHub) HTML tags, all the CSS styling, CSS animations or transformations, iframes, Javascript… and everything else that you can think of!

The idea was crafted by Nikola Đuza as a part of his Pragmatic Pineapple blog. In his article he has covered actually everything, so there is no point in copy-pasting this content, except for a really quicky summary (in case blog would ever become not accessible).

BTW: Visit Nikola’s profile at GitHub and hover mouse pointer over his name to see what kind of “magic” we are talking here! :) Truly, the sky is the limit when to comes into what you can achieve with <img> tag plus .svg “image” and embedding them into any GitHub’s Markdown document or content.

Some magic in SVG images

A piece of text horizontally and vertically centered

Here we go:

<svg fill="none" viewBox="0 0 600 300" width="600" height="300" xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="100%" height="100%">
    <div xmlns="http://www.w3.org/1999/xhtml">
      <style>
        @keyframes hi  {
            0% { transform: rotate( 0.0deg) }
           10% { transform: rotate(14.0deg) }
           20% { transform: rotate(-8.0deg) }
           30% { transform: rotate(14.0deg) }
           40% { transform: rotate(-4.0deg) }
           50% { transform: rotate(10.0deg) }
           60% { transform: rotate( 0.0deg) }
          100% { transform: rotate( 0.0deg) }
        }

        .container {
          background-color: black;

          width: 100%;
          height: 300px;

          display: flex;
          justify-content: center;
          align-items: center;
          color: white;

          font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
        }

        .hi {
          animation: hi 1.5s linear -0.5s infinite;
          display: inline-block;
          transform-origin: 70% 70%;
        }

        @media (prefers-reduced-motion) {
          .hi {
            animation: none;
          }
        }
      </style>

      <div class="container">
        <h1>Hi there, my name is Nikola <div class="hi">👋</div></h1>
      </div>
    </div>
  </foreignObject>
</svg>

Keyframes-based CSS animation and background transformation

Another one, even more nifty:

<svg fill="none" viewBox="0 0 600 300" width="600" height="300" xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="100%" height="100%">
    <div xmlns="http://www.w3.org/1999/xhtml">
      <style>
        @keyframes hi  {
            0% { transform: rotate( 0.0deg) }
           10% { transform: rotate(14.0deg) }
           20% { transform: rotate(-8.0deg) }
           30% { transform: rotate(14.0deg) }
           40% { transform: rotate(-4.0deg) }
           50% { transform: rotate(10.0deg) }
           60% { transform: rotate( 0.0deg) }
          100% { transform: rotate( 0.0deg) }
        }

        @keyframes gradient {
          0% {
            background-position: 0% 50%;
          }
          50% {
            background-position: 100% 50%;
          }
          100% {
            background-position: 0% 50%;
          }
        }

        .container {
          background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
          background-size: 400% 400%;
          animation: gradient 15s ease infinite;

          width: 100%;
          height: 300px;

          display: flex;
          justify-content: center;
          align-items: center;
          color: white;

          font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
        }

        .hi {
          animation: hi 1.5s linear -0.5s infinite;
          display: inline-block;
          transform-origin: 70% 70%;
        }

        @media (prefers-reduced-motion) {
          .container {
            animation: none;
          }

          .hi {
            animation: none;
          }
        }
      </style>

      <div class="container">
        <h1>Hi there, my name is Nikola <div class="hi">👋</div></h1>
      </div>
    </div>
  </foreignObject>
</svg>

Color schemes

Want something even more cool? Since GitHub can display its content in both light and dark theme, you can style your SVG “image”, using the prefers-color-scheme CSS rule, to make sure that it will visually adapt to the scheme (dark or white) that user has set for GitHub.

<svg fill="none" viewBox="0 0 600 300" width="600" height="300" xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="100%" height="100%">
    <div xmlns="http://www.w3.org/1999/xhtml">
      <style>
        @keyframes hi  {
            0% { transform: rotate( 0.0deg) }
           10% { transform: rotate(14.0deg) }
           20% { transform: rotate(-8.0deg) }
           30% { transform: rotate(14.0deg) }
           40% { transform: rotate(-4.0deg) }
           50% { transform: rotate(10.0deg) }
           60% { transform: rotate( 0.0deg) }
          100% { transform: rotate( 0.0deg) }
        }

        @keyframes gradient {
          0% {
            background-position: 0% 50%;
          }
          50% {
            background-position: 100% 50%;
          }
          100% {
            background-position: 0% 50%;
          }
        }

        .container {
          --color-main: #5452ee;
          --color-primary: #e73c7e;
          --color-secondary: #23a6d5;
          --color-tertiary: #ffff;

          background: linear-gradient(-45deg, var(--color-main), var(--color-primary), var(--color-secondary), var(--color-tertiary));
          background-size: 400% 400%;
          animation: gradient 15s ease infinite;

          width: 100%;
          height: 300px;

          display: flex;
          justify-content: center;
          align-items: center;
          color: white;

          font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
        }

        .hi {
          animation: hi 1.5s linear -0.5s infinite;
          display: inline-block;
          transform-origin: 70% 70%;
        }

        @media (prefers-color-scheme: light) {
          .container {
            --color-main: #F15BB5;
            --color-primary: #24b0ef;
            --color-secondary: #4526f6;
            --color-tertiary: #f6f645;
          }
        }

        @media (prefers-reduced-motion) {
          .container {
            animation: none;
          }

          .hi {
            animation: none;
          }
        }
      </style>

      <div class="container">
        <h1>Hi there, my name is Nikola <div class="hi">👋</div></h1>
      </div>
    </div>
  </foreignObject>
</svg>

Rendering SVG in GitHub’s README.md document

To show an SVG image in full width of a README on GitHub, you can render it like so:

<div style="width: 100%;">
  <img src="animated.svg" style="width: 100%;" alt="Click to see the source">
</div>

This makes sure that the width of an SVG is 100% of the width of the Markdown file so it shows up nicely.

That would be all, folks!

Again, all the glory and approbation and all the copyrights goes to Nikola for his great article about this “hidden GitHub feature”. Visit this text, if you want to read about even more cool things that I haven’t copy-pasted to this article.

Leave a Reply