title: CSS ribbons that resizes accordingly to viewport
body: <p>For some time already I've been using <a href="http://www.cssportal.com/css-ribbon-generator/" rel="nofollow noreferrer">this</a> to create corner ribbons and so far it always worked fine:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-css lang-css prettyprint-override"><code>body {
    margin: 10%
  }
  
  img {
    border-radius: 0.5vw;
  }
  
  .picture {
    position: relative;
  }
  
  .ribbon {
    position: absolute;
    left: -5px; top: -5px;
    z-index: 1;
    overflow: hidden;
    width: 75px; height: 75px;
    text-align: right;
  }
  .ribbon span {
    font-size: 10px;
    font-weight: bold;
    color: #FFF;
    text-transform: uppercase;
    text-align: center;
    line-height: 20px;
    transform: rotate(-45deg);
    -webkit-transform: rotate(-45deg);
    width: 100px;
    display: block;
    background: #79A70A;
    background: linear-gradient(#9BC90D 0%, #79A70A 100%);
    box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
    position: absolute;
    top: 19px; left: -21px;
  }
  .ribbon span::before {
    content: "";
    position: absolute; left: 0px; top: 100%;
    z-index: -1;
    border-left: 3px solid #79A70A;
    border-right: 3px solid transparent;
    border-bottom: 3px solid transparent;
    border-top: 3px solid #79A70A;
  }
  .ribbon span::after {
    content: "";
    position: absolute; right: 0px; top: 100%;
    z-index: -1;
    border-left: 3px solid transparent;
    border-right: 3px solid #79A70A;
    border-bottom: 3px solid transparent;
    border-top: 3px solid #79A70A;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div class="picture"&gt;
  
      &lt;div class="ribbon ribbon-top-left"&gt;
        &lt;span&gt;TEXT&lt;/span&gt;
      &lt;/div&gt;
  
      &lt;img src="http://i.imgur.com/5lWqOGT.png" /&gt;
      
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>This always worked because the image below the ribbon markup always had fixed dimensions, so when the image is resized the ribbon is resized together and both get smaller (or bigger) equally.</p>
  
  <p>However, I'm now redesigning a UI in which I don't want things to shrink or grow without much control, so I'm using Bootsrap for the Grid and <code>vh</code> / <code>vw</code> units for some other properties like <code>width</code>, <code>height</code>, <code>border</code>...</p>
  
  <p>And this is the problem with this ribbon code. In this new approach, when resizing the viewport, the image (for this example) hardly changes its dimensions, but the ribbon, because was created in pixels, gets too small (or too big).</p>
  
  <p>Here, let's take the same code above, but now let's add a <code>height: 60vh</code> to the <code>img</code>:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-css lang-css prettyprint-override"><code>body {
    margin: 10%
  }
  
  img {
    border-radius: 0.5vw;
    height: 60vh;
  }
  
  .picture {
    position: relative;
  }
  
  .ribbon {
    position: absolute;
    left: -5px; top: -5px;
    z-index: 1;
    overflow: hidden;
    width: 75px; height: 75px;
    text-align: right;
  }
  .ribbon span {
    font-size: 10px;
    font-weight: bold;
    color: #FFF;
    text-transform: uppercase;
    text-align: center;
    line-height: 20px;
    transform: rotate(-45deg);
    -webkit-transform: rotate(-45deg);
    width: 100px;
    display: block;
    background: #79A70A;
    background: linear-gradient(#9BC90D 0%, #79A70A 100%);
    box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
    position: absolute;
    top: 19px; left: -21px;
  }
  .ribbon span::before {
    content: "";
    position: absolute; left: 0px; top: 100%;
    z-index: -1;
    border-left: 3px solid #79A70A;
    border-right: 3px solid transparent;
    border-bottom: 3px solid transparent;
    border-top: 3px solid #79A70A;
  }
  .ribbon span::after {
    content: "";
    position: absolute; right: 0px; top: 100%;
    z-index: -1;
    border-left: 3px solid transparent;
    border-right: 3px solid #79A70A;
    border-bottom: 3px solid transparent;
    border-top: 3px solid #79A70A;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div class="picture"&gt;
  
      &lt;div class="ribbon ribbon-top-left"&gt;
        &lt;span&gt;TEXT&lt;/span&gt;
      &lt;/div&gt;
  
      &lt;img src="http://i.imgur.com/5lWqOGT.png" /&gt;
      
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Now resize the viewport and you'll see.</p>
  
  <p>I tried to replace all units used in the original code with <code>vw</code> / <code>vh</code> but, apparently, this is not enough - or I'm doing something wrong >.&lt;</p>
  
  <p>So, is it possible to create these ribbons and make them fluid, responsive, fixed... (I'm not sure the right term here, sorry) and make them proportional to the viewport when resizing like the image?</p>
  
  <p>I've tested several other codes but in summary all of them have a box with fixed dimensions for the ribbon to work, just like this one. The closest I've found was <a href="https://codepen.io/nxworld/pen/oLdoWb" rel="nofollow noreferrer">this pen</a> in which I was able to remove its box dimensions but when adding the image with the <code>vh</code> unit, the same thing happened.</p>