Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS ribbons that resizes accordingly to viewport

Tags:

html

css

For some time already I've been using this to create corner ribbons and so far it always worked fine:

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;
}
<div class="picture">

    <div class="ribbon ribbon-top-left">
      <span>TEXT</span>
    </div>

    <img src="http://i.imgur.com/5lWqOGT.png" />
    
</div>

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.

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 vh / vw units for some other properties like width, height, border...

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).

Here, let's take the same code above, but now let's add a height: 60vh to the img:

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;
}
<div class="picture">

    <div class="ribbon ribbon-top-left">
      <span>TEXT</span>
    </div>

    <img src="http://i.imgur.com/5lWqOGT.png" />
    
</div>

Now resize the viewport and you'll see.

I tried to replace all units used in the original code with vw / vh but, apparently, this is not enough - or I'm doing something wrong >.<

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?

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 this pen in which I was able to remove its box dimensions but when adding the image with the vh unit, the same thing happened.

like image 881
Bruno Augusto Avatar asked Jul 18 '17 15:07

Bruno Augusto


2 Answers

If you scale the width and the position with CSS vh (since you're already scaling your image height with vh), you can adjust it responsively:

width: 40vh;
top: 9.3vh;
left: -7.7vh;

You could do same with the font-size and line-height. See the Fiddle below.

Demo: JSFiddle

like image 93
trevorp Avatar answered Nov 20 '22 11:11

trevorp


This is as close as I could get. I used the CSS calc() function to multiply vh to get fractions. It looks okay at least in Safari.

body {
  margin: 10%
}

img {
  border-radius: 0.5vw;
  height: 60vh;
}

.picture {
  position: relative;
}

.ribbon {
  position: absolute;
  left: calc(100vh * -0.01);
  top: calc(100vh * -0.01);
  z-index: 1;
  width: calc(100vh * 0.15); 
  height: calc(100vh * 0.15);
  overflow: hidden;
}
.ribbon span {
  font-size: calc(100vh * 0.025);
  font-weight: bold;
  color: #FFF;
  text-transform: uppercase;
  text-align: center;
  line-height: calc(100vh * 0.05);
  transform: rotate(-45deg) translate(-25%, -30%);
  -webkit-transform: rotate(-45deg) translate(-25%, -30%);
  width: calc(100vh * 0.15);
  display: block;
  background: #79A70A;
  background: linear-gradient(#9BC90D 0%, #79A70A 100%);
  box-shadow: 0 calc(100vh * 0.0075) calc(100vh * 0.0125) 0 rgba(0,0,0,0.4);
  position: absolute;
}

.ribbon span::before {
  content: "";
  position: absolute; left: 0px; top: 100%;
  z-index: -1;
  border-left: calc(100vh * 0.01) solid #79A70A;
  border-right: calc(100vh * 0.01) solid transparent;
  border-bottom: calc(100vh * 0.01) solid transparent;
  border-top: calc(100vh * 0.01) solid #79A70A;
}
.ribbon span::after {
  content: "";
  position: absolute; right: 0px; top: 100%;
  z-index: -1;
  border-left: calc(100vh * 0.01) solid transparent;
  border-right: calc(100vh * 0.01) solid #79A70A;
  border-bottom: calc(100vh * 0.01) solid transparent;
  border-top: calc(100vh * 0.01) solid #79A70A;
}
<div class="picture">

    <div class="ribbon ribbon-top-left">
      <span>TEXT</span>
    </div>

    <img src="http://i.imgur.com/5lWqOGT.png">
    
</div>
like image 37
Nicholas Avatar answered Nov 20 '22 12:11

Nicholas