<template id="img-figure">
  <figure>
    <img />
    <figcaption></figcaption>
  </figure>
</template>

<img-figure 
  style="max-width: 400px"
  src="//res.cloudinary.com/time2hack/image/upload/ways-to-host-single-page-application-spa-static-site-for-free.png"
  alt="Free Static Hosting"
  caption="Ways to host single page application (SPA) and Static Site for FREE">
</img-figure>
let template = () => `Template tag not supported`;
const t = document.querySelector('#img-figure');
if ('content' in document.createElement('template')) {
  template = (state) => {
    const img = t.content.querySelector('img');
    const caption = t.content.querySelector('figcaption');
    img.setAttribute('src', state.src);
    img.setAttribute('alt', state.alt || state.caption);
    caption.innerHTML = state.caption;
    return document.importNode(t.content, true);
  }
} else {
  template = (state) => { //fallback case
    const d = document.createElement('div');
    d.innerHTML = t.innerHTML;
    const img = d.querySelector('img');
    const caption = d.querySelector('figcaption');
    img.setAttribute('src', state.src);
    img.setAttribute('alt', state.alt || state.caption);
    caption.innerHTML = state.caption;
    return d.firstElementChild;
  }
}

class ImgFigure extends HTMLElement {
  connectedCallback() {
    this.src = this.getAttribute("src") || null;
    this.caption = this.getAttribute("caption") || "";
    this.alt = this.getAttribute("alt") || null;
    this.render();
  }

  render() {
    this.appendChild(template({
      src: this.src,
      alt: this.alt,
      caption: this.caption
    }));
  }
}

customElements.define('img-figure', ImgFigure);

External CSS

  1. https://codepen.io/pankajpatel/pen/XzQLNX.css

External JavaScript

This Pen doesn't use any external JavaScript resources.