Как добавить 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 шт):
за хромые не ручаюсь, но под 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: ошибки в исходном варианте
- нулевые габариты делают
SVGконтейнер не отображаемым.
<svg width="0" height="0"
- хоть в
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>
Добавить градиентную рамку к элементу с 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>
