skip to Main Content

I would like to reduce the width of the ribbon so it fits without changing the position of the ribbon.

Can someone guide me as to where I’m going wrong?

.ribbon-content {
  position: relative;
}

.ribbon-content>[class*=ribbon] {
  position: absolute;
  z-index: 2000;
  line-height: 2em;
  display: block;
  width: 10em;
  height: 2.5em;
  text-align: center;
  text-decoration: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.ribbon-content>[class*=ribbon]::before,
.ribbon-content>[class*=ribbon]::after {
  content: '';
  position: absolute;
  inset: 0;
  -webkit-clip-path: polygon(2em 0, 8em 0, 10em 2em, 10em 2.5em, 9.5em 2em, 0.5em 2em, 0 2.5em, 0 2em);
  clip-path: polygon(2em 0, 8em 0, 10em 2em, 10em 2.5em, 9.5em 2em, 0.5em 2em, 0 2.5em, 0 2em);
}

.ribbon-content>[class*=ribbon]::before {
  top: 0.1em;
  height: 1.8em;
  border: 1px dotted rgba(0, 0, 0, 0.3);
  border-left: none;
  border-right: none;
}

.ribbon-content>[class*=ribbon]::after {
  z-index: -1;
  background-color: #ff6347;
  border-bottom: 0.5em solid #505050;
  transition: background-color 0.2s ease-in-out;
}

.ribbon-content>.ribbon-top-left {
  top: 0;
  left: 0;
  transform: translate(-3.85em, 1.4em) rotate(-45deg);
  color: #fff;
  font-size: 0.65rem;
}

.box {
  width: 100%;
  max-width: 20em;
  min-height: 10em;
  margin: 2em;
  background-color: #333;
}
<div class="box ribbon-content"><span class="ribbon-top-left" href="#">NEW</span></div>

2

Answers


  1. The width, the tramsform property and the parameter for clip-path are all related to the width so I’d use CSS custom properties and calc to ensure they scale.

    I’ve done the clip-path for you but you’ll have to sort out the translate yourself. You might need to do a bit of geometry to figure this out. Code below:

    .ribbon-content {
      position: relative;
      --width: 5em;
    }
    
    .ribbon-content>[class*=ribbon] {
      position: absolute;
      z-index: 2000;
      line-height: 2em;
      display: block;
      width: var(--width);
      height: 2.5em;
      text-align: center;
      text-decoration: none;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }
    
    .ribbon-content>[class*=ribbon]::before,
    .ribbon-content>[class*=ribbon]::after {
      content: '';
      position: absolute;
      inset: 0;
      -webkit-clip-path: polygon(
        calc(var(--width) * 0.2) 0,
        calc(var(--width) * 0.8) 0,
        calc(var(--width)) 2em, 
        calc(var(--width)) 2.5em, 
        calc(var(--width) * 0.95) 2em, 
        calc(var(--width) * 0.05) 2em, 
        0 2.5em, 
        0 2em);
      clip-path: polygon(
        calc(var(--width) * 0.2) 0, 
        calc(var(--width) * 0.8) 0, 
        calc(var(--width)) 2em, 
        calc(var(--width)) 2.5em, 
        calc(var(--width) * 0.95) 2em, 
        calc(var(--width) * 0.05) 2em, 
        0 2.5em, 
        0 2em);
    }
    
    .ribbon-content>[class*=ribbon]::before {
      top: 0.1em;
      height: 1.8em;
      border: 1px dotted rgba(0, 0, 0, 0.3);
      border-left: none;
      border-right: none;
    }
    
    .ribbon-content>[class*=ribbon]::after {
      z-index: -1;
      background-color: #ff6347;
      border-bottom: 0.5em solid #505050;
    }
    
    .ribbon-content>.ribbon-top-left {
      top: 0;
      left: 0;
      /* you'd need to do a bit of geometry to make this work consistently */
      transform: translate(calc(var(--width) * -0.3), 0) rotate(-45deg);
      color: #fff;
      font-size: 0.65rem;
    }
    
    .box {
      width: 100%;
      max-width: 20em;
      min-height: 10em;
      margin: 2em;
      background-color: #333;
    }
    <div class="box ribbon-content"><span class="ribbon-top-left" href="#">NEW</span></div>
    Login or Signup to reply.
  2. This is kind of a two part answer. The second builds on the first.

    You want a block to change span to div and remove the display:block since that is the difference there.

    Move the ribbon to "wrap around" better
    top: 0.75em; left: 0.5em;

    Remove the box position: relative; and the ribbon position: absolute; as not needed.

    Then, set up the box as a border box with no margin or padding:

          margin: 0;
          padding: 0;
          box-sizing: border-box;
          font-size: 16px;
        }
    

    Font size not strictly needed here but since all modern browsers default to that but this makes it specific.

    Set the margin on the ribbon margin-left: 1.5em; so it moves to "wrap" the box visually.

    Remove the /* top: 0.1em; height: 1.8em;*/ as not needed.

    .ribbon-content {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-size: 16px;
    }
    
    .ribbon-content>[class*=ribbon] {
      margin-left: 1.5em;
      z-index: 2000;
      line-height: 2em;
      width: 10em;
      height: 2.5em;
      text-align: center;
      text-decoration: none;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }
    
    .ribbon-content>[class*=ribbon]::before,
    .ribbon-content>[class*=ribbon]::after {
      content: '';
      position: absolute;
      inset: 0;
      -webkit-clip-path: polygon(2em 0, 8em 0, 10em 2em, 10em 2.5em, 9.5em 2em, 0.5em 2em, 0 2.5em, 0 2em);
      clip-path: polygon(2em 0, 8em 0, 10em 2em, 10em 2.5em, 9.5em 2em, 0.5em 2em, 0 2.5em, 0 2em);
    }
    
    .ribbon-content>[class*=ribbon]::before {
      /*  top: 0.1em;
      height: 1.8em;*/
      border: 1px dotted rgba(0, 0, 0, 0.3);
      border-left: none;
      border-right: none;
    }
    
    .ribbon-content>[class*=ribbon]::after {
      z-index: -1;
      background-color: #ff6347;
      border-bottom: 0.5em solid #505050;
      transition: background-color 0.2s ease-in-out;
    }
    
    .ribbon-content>.ribbon-top-left {
      top: 0.75em;
      left: 0.5em;
      transform: translate(-3.85em, 1.4em) rotate(-45deg);
      color: #fff;
      font-size: 0.65rem;
    }
    
    .box {
      width: 100%;
      max-width: 20em;
      min-height: 10em;
      /* margin: 2em; can be anything since this is BOTH elements contained */
      background-color: #333;
    }
    <div class="box ribbon-content">
      <div class="ribbon-top-left" href="#">NEW</div>
    </div>

    Now with all the above just adjust the ribbon font size as needed perhaps:

    .ribbon-content>.ribbon-top-left {
      font-size: 0.5rem;
      top: 0.75em;
      left: 0.5em;
      transform: translate(-3.85em, 1.4em) rotate(-45deg);
      color: #fff;
    }
    
    .ribbon-content {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-size: 16px;
    }
    
    .ribbon-content>[class*=ribbon] {
      margin-left: 1.5em;
      z-index: 2000;
      line-height: 2em;
      width: 10em;
      height: 2.5em;
      text-align: center;
      text-decoration: none;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }
    
    .ribbon-content>[class*=ribbon]::before,
    .ribbon-content>[class*=ribbon]::after {
      content: '';
      position: absolute;
    
      inset: 0;
      -webkit-clip-path: polygon(2em 0, 8em 0, 10em 2em, 10em 2em, 9.5em 2em, 0.5em 2em, 0 2.5em, 0 2em);
      clip-path: polygon(2em 0, 8em 0, 10em 2em, 10em 2.5em, 9.5em 2em, 0.5em 2em, 0 2.5em, 0 2em);
    }
    
    .ribbon-content>[class*=ribbon]::before {
      border: 1px dotted rgba(0, 0, 0, 0.3);
      border-left: none;
      border-right: none;
    }
    
    .ribbon-content>[class*=ribbon]::after {
      z-index: -1;
      background-color: #ff6347;
      border-bottom: 0.5em solid #505050;
      transition: background-color 0.2s ease-in-out;
    }
    
    .ribbon-content>.ribbon-top-left {
      font-size: 0.5rem;
      top: 0.75em;
      left: 0.5em;
      transform: translate(-3.85em, 1.4em) rotate(-45deg);
      color: #fff;
    }
    
    .box {
      width: 100%;
      max-width: 20em;
      min-height: 10em;
      /* margin: 2em; can be anything since this is BOTH elements contained */
      background-color: #333;
    }
    <div class="box ribbon-content">
      <div class="ribbon-top-left" href="#">NEW</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search