I tried to implement the button and the link with polygon border based on the Houdini API. Sadly I found out that when I add "href" attribute to tag, it no longer works. Do you have any ideas how to fix this or is this browser bug?
Here is the demo (but it does not work outside of Codepen):
registerPaint('polygon-border', class {
static get inputProperties() {
return [
'--path',
'--border',
'--dash'
]
}
paint(ctx, size, properties) {
const points = properties.get('--path').toString().split(',');
const b = parseFloat(properties.get('--border').value);
const d = properties.get('--dash').toString().split(',');
const w = size.width;
const h = size.height;
const cc = function(x,y) {
var fx=0,fy=0;
if (x.indexOf('calc') > -1) {
var tmp = x.replace('calc(','').replace(')','');
if (tmp.indexOf('+') > -1) {
tmp = tmp.split('+');
fx = (parseFloat(tmp[0])/100)*w + parseFloat(tmp[1]);
} else {
tmp = tmp.split('-');
fx = (parseFloat(tmp[0])/100)*w - parseFloat(tmp[1]);
}
} else if (x.indexOf('%') > -1) {
fx = (parseFloat(x)/100)*w;
} else if(x.indexOf('px') > -1) {
fx = parseFloat(x);
}
if (y.indexOf('calc') > -1) {
var tmp = y.replace('calc(','').replace(')','');
if (tmp.indexOf('+') > -1) {
tmp = tmp.split('+');
fy = (parseFloat(tmp[0])/100)*h + parseFloat(tmp[1]);
} else {
tmp = tmp.split('-');
fy = (parseFloat(tmp[0])/100)*h - parseFloat(tmp[1]);
}
} else if (y.indexOf('%') > -1) {
fy = (parseFloat(y)/100)*h;
} else if(y.indexOf('px') > -1) {
fy = parseFloat(y);
}
return [fx,fy];
}
var p = points[0].trim().split(/(?!\(.*)\s(?![^(]*?\))/g);
p = cc(p[0],p[1]);
ctx.beginPath();
ctx.setLineDash(d);
ctx.moveTo(p[0],p[1]);
for (var i = 1; i < points.length; i++) {
p = points[i].trim().split(/(?!\(.*)\s(?![^(]*?\))/g);
p = cc(p[0],p[1]);
ctx.lineTo(p[0],p[1]);
}
ctx.closePath();
ctx.lineWidth = 2*b;
ctx.strokeStyle = '#000';
ctx.stroke();
}
})
@property --border{
syntax: '<length>';
inherits: true;
initial-value: 0;
}
@property --s{
syntax: '<number>';
inherits: true;
initial-value: 0;
}
button, a {
--border:4px;
display: inline-block;
text-decoration: none;
padding:10px 30px;
margin:5px 10px;
font-size:25px;
font-weight:bold;
text-transform:uppercase;
color:#00aaff;
border:none;
background:none;
cursor:pointer;
position:relative;
transition:.5s;
clip-path:polygon(var(--path));
}
button:before, a:before {
content:"";
position:absolute;
z-index:-1;
inset:0;
-webkit-mask:paint(polygon-border);
background:currentColor;
}
button:hover, a:hover {
color:#ff00aa;
}
.f {
background:linear-gradient(#00aaff 0 0) bottom/100% 0% no-repeat;
transiton:.5s;
}
.f:before {
background:#00aaff;
}
.f:hover {
color:#fff;
background-size:100% 100%;
}
.d {
--dash:11,5;
}
.h {
--s:5;
--dash:11,var(--s);
transition:--s .7s;
}
.h:hover {
--s:0;
}
.b1 { --path:10% 0,100% 0,90% 100%,0 100%}
.b2 { --path:10% 0,90% 0,100% 50%,90% 100%,10% 100%,0 50%}
.b3 { --path:10% 0,100% 0,100% 50%,90% 100%,0 100%,0 50%}
.b4 { --path:0 0,100% 0,90% 50%,100% 100%,0 100%,10% 50%}
.b5 { --path:5px 0,calc(100% - 5px) 0,calc(100% - 10px) 10px,100% 5px,100% calc(100% - 5px),calc(100% - 10px) calc(100% - 10px),calc(100% - 5px) 100%,5px 100%,10px calc(100% - 10px),0 calc(100% - 5px),0 5px,10px 10px}
body {
background:#f3f3f3;
}
<button class="b3 f">button</button>
<br>
<a class="b3 f">without href</a>
<br>
<a href="/does-href-break-border" class="b3 f">with href</a>
<script>
if (CSS.paintWorklet) {
CSS.paintWorklet.addModule('/t_afif/pen/abwBPPz.js');
} else {
alert("Your browser cannot run this demo. Consider Chrome or Edge instead")
}
</script>