Как добавить gradient border для clip path фигуры?

Задача - добавить gradient border для clip path фигуры

Код

.container {
  width: 400px;
  height: 400px;
  background-color: rgba(56, 53, 75, 0.24);
  backdrop-filter: blur(3px);
  border-radius: 0.5rem;
  clip-path: url(#b-clip-path-1);
}
<div class="container">
  <svg width="0" height="0" viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
    <defs>
      <!-- gradient -->
      <linearGradient id="gradient-border" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color="#00f" />
        <stop offset="100%" stop-color="#f00" />
      </linearGradient>

      <!-- clip path -->
      <clipPath id="b-clip-path-1" clipPathUnits="objectBoundingBox">
        <path d="M1,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z" />
      </clipPath>
    </defs>

    <!-- border -->
    <path d="M0,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z" fill="none" stroke="url(#gradient-border)" stroke-width="0.05" />

    <!-- inner path с clip-path -->
    <path d="M0,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z" fill="#f00" clip-path="url(#b-clip-path-1)" />
  </svg>
</div>

Добавил градиент, но он не работает.

Пример, что необходимо получить

Буду рад любой помощи


Ответы (2 шт):

Автор решения: puffleeck

за хромые не ручаюсь, но под FF точно можно немного почитерить с тенями прямо из CSS

.container {
  width: 200px;
  height: 40px;
  background: linear-gradient(45deg, red, gold, lime, cyan, blue, magenta); /*!!!*/
  border-radius: .5rem;
  clip-path: url(#b-clip);
  border: 15px solid magenta;
  box-shadow: inset 0 0 0 35px rgba(0,0,0,.5); /*!!!*/
  padding: 3em;
}

.container:not(:hover) {
  background-clip: text; /*!!!*/
}
<div class="container">
abcdef
</div>

<svg width="0" height="0" viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
  <defs>
    <clipPath id="b-clip" clipPathUnits="objectBoundingBox">
    <path id='myPath' d="M1,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z"/>
    </clipPath>
  </defs>
</svg>

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

если этот чит попробовать "скрестить" с решениями из того конкурса, может что-то интересное да и выйдет, но это не точно.

и да, разумеется есть нюансы. выше описанное хоть и работает с box-shadow но на отрез отказывается хоть как то воспринимать более удобный filter: drop-shadow, потому возлагать сильно больших надежд на скрещивание не стоит.


UPD: можно накинуть сверху блок-рамку вырезанную с помощью mask

body, .y{
  background: linear-gradient(45deg, red, gold, lime, cyan, blue, magenta);
  }
  
  body{
  height: 500vh;
}

.x {
  clip-path: url(#b-clip);
  background: rgba(0, 0, 0, .5);
}

.y {
  mask: url('data:image/svg+xml,<svg viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet"><path d="M1,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z" stroke="black" stroke-width=".05" fill="none"/></svg>') no-repeat;
}

#xyz {
  position: fixed;
  filter: drop-shadow(5px 5px 5px black);
  /* тень только чтоб глаза не вытекли при разглядывании сниппета */
}

.x,
.y {
  position: absolute;
  width: 175px;
  height: 175px;
}
<div id='xyz'>
  <div class="x">
  </div>
  <div class="y">
  </div>
</div>

<svg viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
  <defs>
    <clipPath id="b-clip" clipPathUnits="objectBoundingBox">
    <path d="M1,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z"
    stroke="black"
    stroke-width=".05"
    fill="none"
    comment="атрибуты добавлены для mask(тут только для читабельности)"
    />
    </clipPath>
  </defs>
</svg>

p.s. data-ссылка вынужденная мера, ибо mask в html пространстве с document-fragment работать не умеет.

т.е. вот так: mask: url(#path-id) - на html тегах не сработает


UPD 2: ошибки в исходном варианте

  1. нулевые габариты делают SVG контейнер не отображаемым.

<svg width="0" height="0"

  1. хоть в SVG и нету z-index, но вполне есть DOM иерархия и следующее из неё правило: кто последний тот и сверху.
<path
   d="# эта градиентная рамка первая в документе, а значит именно она будет снизу"
   fill="none"
   stroke="url(#gradient-border)"
   stroke-width="0.05" />
<path
   d="# заливка"
   fill="#f00"
   clip-path="url(#b-clip-path-1)" />

собственно итоговый сниппет с исправлениями

.container {
  width: 400px;
  height: 400px;
  background-color: rgba(56, 53, 75, 0.24);
  backdrop-filter: blur(3px);
  border-radius: 0.5rem;
  clip-path: url(#b-clip-path-1);
}
<div class="container">
<svg viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
  <defs>
    <!-- gradient -->
    <linearGradient id="gradient-border" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" stop-color="#00f" />
      <stop offset="100%" stop-color="#f00" />
    </linearGradient>

    <!-- clip path -->
    <clipPath id="b-clip-path-1" clipPathUnits="objectBoundingBox">
      <path d="M1,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z" />
    </clipPath>
  </defs>

  <!-- inner path с clip-path -->
  <path d="M0,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z"
    fill="#0f0"
    comment="зеленая заливка чтоб не сливалась с рамкой"
    clip-path="url(#b-clip-path-1)" />

  <!-- border -->
  <path d="M0,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z"
    fill="none"
    stroke="url(#gradient-border)"
    stroke-width="0.05" />
</svg>
</div>

→ Ссылка
Автор решения: KREEPAR123

Добавить градиентную рамку к элементу с clip-path — нетривиальная задача, так как clip-path отсекает содержимое, включая границы. Один из рабочих способов — создать псевдоэлемент с большим размером, фоновым градиентом и таким же clip-path. Вот исправленный вариант:

.container-wrapper {
  position: relative;
  display: inline-block;
}

.gradient-border {
  position: absolute;
  top: -5px;
  left: -5px;
  width: calc(100% + 10px);
  height: calc(100% + 10px);
  background: linear-gradient(45deg, #00f, #f00);
  clip-path: url(#b-clip-path-1);
  z-index: -1;
}

.container {
  width: 400px;
  height: 400px;
  background-color: rgba(56, 53, 75, 0.24);
  backdrop-filter: blur(3px);
  border-radius: 0.5rem;
  clip-path: url(#b-clip-path-1);
  position: relative;
  z-index: 1;
}
<div class="container-wrapper">
  <div class="gradient-border"></div>
  <div class="container"></div>

  <svg width="0" height="0" viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg">
            <defs>
              <!-- Градиент -->
              <linearGradient id="gradient-border" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0%" stop-color="#00f" />
                <stop offset="100%" stop-color="#f00" />
              </linearGradient>
        
              <!-- clip-path -->
              <clipPath id="b-clip-path-1" clipPathUnits="objectBoundingBox">
                <path d="M1,0 H0.1 C0.095,0 0.085,0.01 0.085,0.025 V0.57 C0.085,0.59 0.083,0.61 0.078,0.625 L0.015,0.72 C0.007,0.735 0.002,0.755 0.002,0.775 V1 C0.002,1 0.01,1 0.02,1 H1 C1,1 1,1 1,1 V0 C1,0 1,0 1,0Z" />
              </clipPath>
            </defs>
          </svg>
</div>

→ Ссылка