4

Есть картинка карточки с градиентом и обрезанным уголком, полученным с помощью clip-path:

.card {
  width: 200px;
  height: 200px;
  background: linear-gradient(to bottom, blue, green);
  clip-path: polygon(20px 0, 100% 0, 100% 100%, 0 100%, 0 20px);
}
<div class="card"></div>

Обрезанный угол должен иметь фиксированный размер вне зависимости от размера карточки, поэтому я использую фиксированные размеры (в пискелях) для обрезания угла.

Но clip-path имеет не самую лучшую поддержку браузеров, поэтому я попытался превратить этот HTML/CSS в SVG.

.container {
  width: 200px;
  height: 200px;
}
<div class="container">
  <svg viewBox="0 0 100 100" clip-path="url(#myClip)">
    <defs>
      <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
        <stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
      </linearGradient>
    </defs>
&lt;polygon points="20,0 100,0 100,100 0,100 0,20" fill="url(#grad1)" /&gt;

</svg> </div>

Но проблема в том, что я не могу сделать так, чтобы обрезанный угол иметь фиксированный размер, независящий от размера всей картинки.

  • ассоциация: https://stackoverflow.com/q/53742988/1548895 – Vadim Ovchinnikov Dec 12 '18 at 12:38
  • А если к примеру карточка будет меньше а угол должен остаться таким же ? – Резидент Казахстана Dec 12 '18 at 12:42
  • @UbuntuUser Ну это вряд ли, что картинка будет меньше, чем 20x20, поэтому данный случай можете не учитывать. – Vadim Ovchinnikov Dec 12 '18 at 12:43
  • А svg mask не подходит ? – Резидент Казахстана Dec 12 '18 at 12:44
  • @UbuntuUser Да всё подходит, что будет работать во всех браузерах, даже не SVG. Напишите решение, которое работает, я сразу дам обратную связь. – Vadim Ovchinnikov Dec 12 '18 at 12:45
  • Супруга за моим компом а с планшета не научился ещё я такое делать и кстати clip path css работает на планшете – Резидент Казахстана Dec 12 '18 at 12:46
  • @UbuntuUser Да, но есть мои "любимые" IE и MS Edge (которые может скоро и добавят, но этого пока не случилось), которые пока это не поддерживают:) – Vadim Ovchinnikov Dec 12 '18 at 12:48
  • Я тоже люблю осла и сафари ....вампиры они – Резидент Казахстана Dec 12 '18 at 12:49
  • @Vadim Ovchinnikov обещал тебе ответить на этот вопрос, но не успел. И здесь @Геннадий Журов нашёл отличное решение и на Enso хорошо ответили Мне кажется, если поставлена ассоциация с Enso надо и здесь разместить перевод их ответа. Хочешь переведу или сам? – Alexandr_TT Dec 14 '18 at 07:33
  • @Alexandr_TT А зачем переводить их ответ, если у нас он реально лучше? Один с CSS, но довольно громоздкий, другой на SVG, но с хаком. Но в любом случае, дело твоё, я как минимум не против. – Vadim Ovchinnikov Dec 14 '18 at 11:39
  • @VadimOvchinnikov ну обычно в комплексе ассоциацию делают: перевод вопроса и ответа Там на Enso вам отвечал **Paul LeBeau** По моему один из лучших спецов по svg на Enso. На мой взгляд, хорошо бы отметить его ответ галочкой – Alexandr_TT Dec 14 '18 at 11:46
  • @Alexandr_TT Я голосую не за спецов, а за ответы, его ответ не лучший, как мне видится. Также ассоциация не отображается в обратную сторону (с ruSO на enSO), поэтому она мне кажется ещё более уместной, когда у нас ответ лучше. – Vadim Ovchinnikov Dec 14 '18 at 11:49

3 Answers3

3

Этот вариант уже озвучивал в комментариях @UbuntuUser , но прошли почти сутки поэтому:

var widthInput = document.querySelector('[name=width]'),
    image = document.querySelector('image');

widthInput.addEventListener('input', function() { image.width.baseVal.value = this.value; });

body {
  background-color: #ddd;
}

svg {
  width: 470px;
  height: 300px;
  outline: 1px solid;
}
input{
  vertical-align:top;
}
<svg>
  <defs>
    <mask id="triangle-clip">
      <rect x="0" y="0" width="100%" height="100%" fill="#fff" />
      <path d="M0,20 v-20 h20 z" fill="#000" />
    </mask>
  </defs>  
  <image xlink:href="https://cs4.pikabu.ru/post_img/big/2016/06/25/5/1466835263296535231.jpg" x="0" y="0" width="300" mask="url(#triangle-clip)" />
</svg>
<input type="number" name="width" min="40" max="470" placeholder="ширина картинки" />
zhurof
  • 10,427
2

Для моего случая озвученного в вопросе решение будет таким

.container {
  width: 200px;
  height: 200px;
}

svg { width: 100%; height: 100%; }

<div class="container">
  <svg>
    <defs>
      <mask id="triangle-clip">
        <rect x="0" y="0" width="100%" height="100%" fill="#fff" />
        <path d="M0,20 v-20 h20 z" fill="#000" />
      </mask>

    <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
          <stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
        </linearGradient>
    </defs>
    <rect width="100%" height="100%" fill="url(#grad1)" mask="url(#triangle-clip)" />
  </svg>
</div>
2

Для сохранения фиксированного размера уголка, вы не можете использовать viewBox SVG

Просто обрежьте угол, который вам нужен, и сделайте так, чтобы другие углы были вытянуты так, чтобы clippath покрывал любой размер, который вам может понадобиться. В приведенном ниже примере я увеличил значение Clippath до (10000,10000).

Здесь мы применяем градиент к 100% x 100% <rect>. Это нужно, чтобы градиент всегда масштабировался по размеру экрана. Затем мы применяем clippath к прямоугольнику, чтобы получить вырез.

html, body {
  height: 100%;
}

.container { width: 50%; height: 50%; }

<div class="container">
  <svg width="100%" height="100%">
    <defs>
      <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
        <stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
      </linearGradient>
      <clipPath id="clip1">
        <polygon points="20,0 10000,0 10000,10000 0,10000 0,20"/>
      </clipPath>
    </defs>

    <rect width="100%" height="100%" fill="url(#grad1)" clip-path="url(#clip1)"/>
 </svg>
</div>

Источник ответа: @Paul LeBeau

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384