Как добиться адаптивной формы ленты в CSS?

#html #css

Вопрос:

введите описание изображения здесь

Пытаюсь добиться этого с помощью css. Я добился этого, но это ломается, если мой лейбл (КАРЬЕРА) больше по размеру div . Если он длиннее, то содержимое оборачивается, а высота div увеличивается. Но левый разрез ленты не делает этого ответственно. Может ли кто-нибудь предложить лучший подход?

 .custom-tag-container {
  border: 1px solid;
  margin: auto;
  display: flex;
  align-items: stretch;
  border-color: green green green transparent;
  padding: 4px !important;
}

.custom-tag-container>p {
  color: green;
  font-weight: bold;
  flex: 1;
  margin: auto;
}

#triangle-left {
  height: 25px;
  width: 25px;
  background: transparent;
  transform: rotateZ(45deg) translateX(-12.5px) translateY(12.5px);
  border: 1px solid;
  border-color: green green transparent transparent;
} 
 <div class="custom-tag-container">
  <div id="triangle-left" />
  <p>Hello Worldsm</p>
</div> 

JS Скрипка

Комментарии:

1. Ознакомьтесь с этой статьей css-tricks.com/the-shapes-of-css

2. Является ли фон вашей ленты прозрачным или имеет белый фон?

3. @Justinas: В данном случае прозрачный, но в идеале тоже может быть другого цвета.

Ответ №1:

Вот идея, которая основана на асимметричной трансформации, где она будет отзывчивой, и у вас будет прозрачность:

 .box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:0 5px 5px 0;
  position:relative;
  margin:5px;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  left:0;
  height:50%;
  width:3px;
  background:green;
}
.box:before {
  top:0;
  transform:skew(45deg);
  transform-origin:top;
}
.box:after {
  bottom:0;
  transform:skew(-45deg);
  transform-origin:bottom;
} 
 <div class="box"></div>

<div class="box" style="height:80px"></div> 

CSS края ленты

Если вы хотите сохранить одинаковую ширину стрелки, вы можете рассмотреть другую идею с использованием фона:

 .box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:0 5px 5px 0;
  position:relative;
  margin:5px;
  overflow:hidden;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  left:0;
  top:0;
  height:50%;
  width:30px;
  background:
    linear-gradient(to top right,
      transparent calc(50% - 4px),green,transparent 50%) 
      bottom/100% calc(100%   4px);
}
.box:after {
  transform:scaleY(-1);
  transform-origin:bottom;
} 
 <div class="box"></div>

<div class="box" style="height:80px"></div> 

и с SVG тоже

 .box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:0 5px 5px 0;
  position:relative;
  margin:5px;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  left:0;
  top:0;
  height:50%;
  width:30px;
  background:url('data:image/svg xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><line x1="0" y1="-1" x2="15" y2="16" stroke="green"  /></svg>') 0 0/100% 100%;
}
.box:after {
  transform:scaleY(-1);
  transform-origin:bottom;
} 
 <div class="box"></div>

<div class="box" style="height:80px"></div> 

введите описание изображения здесь

Вы также можете оптимизировать код и сделать это без псевдоэлемента:

 .box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:0 5px 5px 0;
  margin:5px;
  background:
   url('data:image/svg xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><line x1="0" y1="-1" x2="15" y2="16" stroke="green"  /></svg>') top left/30px 50%,
   url('data:image/svg xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><line x1="0" y1="16" x2="15" y2="-1" stroke="green"  /></svg>') bottom left/30px 50%;
  background-repeat:no-repeat;
} 
 <div class="box"></div>

<div class="box" style="height:80px"></div> 

Тот же SVG можно использовать для получения первого результата, где ширина стрелки также является динамической. Хитрость заключается в том, чтобы определить только высоту и сохранить соотношение:

 .box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:0 5px 5px 0;
  margin:5px;
  background:
   url('data:image/svg xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15"><line x1="0" y1="-1" x2="15" y2="16" stroke="green"  /></svg>') top left/auto 50%,
   url('data:image/svg xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15"><line x1="0" y1="16" x2="15" y2="-1" stroke="green"  /></svg>') bottom left/auto 50%;
  background-repeat:no-repeat;
} 
 <div class="box"></div>

<div class="box" style="height:80px"></div> 

Вы также можете легко добавить окраску внутри.

С косой трансформацией:

 .box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:0 5px 5px 0;
  position:relative;
  overflow:hidden;
  z-index:0;
  margin:5px;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  z-index:-1;
  left:0;
  right:0;
  height:50%;
  border-left:3px solid green;
  background:yellow;
}
.box:before {
  top:0;
  transform:skew(45deg);
  transform-origin:top;
}
.box:after {
  bottom:0;
  transform:skew(-45deg);
  transform-origin:bottom;
} 
 <div class="box"></div>

<div class="box" style="height:80px"></div> 

С фоном SVG

 .box {
  height: 50px;
  padding-left:30px;
  border: 2px solid green;
  border-left: 0;
  border-radius:0 5px 5px 0;
  margin:5px;
  background:
   url('data:image/svg xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><polygon points="16,17 16,-2 0,-1 " fill="yellow" stroke="green" /></svg>') top left/30px 50%,
   url('data:image/svg xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><polygon points="16,16 16,-2 0,16 " fill="yellow" stroke="green" /></svg>') bottom left/30px 50%,
   yellow content-box;
  background-repeat:no-repeat;
} 
 <div class="box"></div>

<div class="box" style="height:80px"></div> 

Комментарии:

1. большое вам спасибо за помощь. Но я все еще застрял. Здесь вы указываете высоту в стиле. Есть ли способ, которым он автоматически вычисляет размер div и динамически изменяет высоту. Это связано с тем, что у меня нет информации о размере этикетки, которая будет присутствовать. Правка: Исправлено, просто изменил высоту свойства на минимальную высоту. Еще раз большое спасибо!

2. @AbsoluteSith я указываю разные высоты, чтобы выделить отзывчивых. Не нужно добавлять высоту, просто поместите свой контент внутрь, и он автоматически отрегулируется

Ответ №2:

Если у вас белый фон на белом, то вы можете использовать два css-треугольника, которые один закрывает другой и создает кромку для ленты. Если вам нужна некоторая прозрачность, вам следует полагаться clip-path (проверьте, подходит ли поддержка для ваших пользователей) ИЛИ на некоторые элементы SVG.

 * {
  box-sizing: border-box;
}

.ribbon {
  width: 100%;
  height: 100px;
  border: 2px solid blue;
  position: relative;
  padding: 0 120px;
  line-height: 100px;
  text-align: center;
  font-size: 30px;
}
.ribbon:before,
.ribbon:after {
  content: '';
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-left: 100px solid green;
    border-bottom: 50px solid transparent;
    position: absolute;
    top: 0;
    left: 0;
  }
  
  .ribbon:after {
  border-left-color: white;
  left: -3px;
  } 
 <div class="ribbon">CARRIER</div> 

Для менее хакерского подхода используйте простое фоновое изображение.