<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>
body {
  padding: 5px;
}
img-figure {
  display: block;
  max-width: 400px;
  figure {
    margin: 0;
  }
  img {
    max-width: 100%;
  }
  figcaption {
    width: 100%;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
} 
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.innerHTML = this.template({
      src: this.src,
      alt: this.alt,
      caption: this.caption
    });
  }
  
  template(state) { 
    return `
    <figure>
      <img
        src="${state.src}"
        alt="${state.alt || state.caption}">
      <figcaption>${state.caption}</figcaption>
    </figure>
    `;
  }
}

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

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.19/webcomponents-hi-sd-ce.js