css 下边框-现代CSS高级方法,不规则边界解决方案

在本文中,我们将尝试使用 CSS 绘画 API 来实现过去在 CSS 中特别无法实现的一点,即如何勾勒不规则图形的边框。

CSS 绘画接口

快速轻松地了解 CSS Painting API 是什么。CSS

Painting API 是 CSS Houdini 的一部分。Houdini是一组低级API,它们公开了CSS引擎的各个部分,允许开发人员通过合并浏览器渲染引擎的样式和布局过程来增强CSS。Houdini是一组API,允许开发人员直接访问CSS对象模型[1](CSSOM),允许开发人员编写浏览器可以解析为CSS的代码,创建新的CSS功能,而无需等待它们在浏览器中本地实现。CSS

Paint API 的当前版本是 CSS Painting API Level 1 [2]。它也被称为CSS Custom Paint或Houdini's Paint Worklet。

我们可以理解为 JS 中的 CSS,利用 JavaScript Canvas 的强大功能来实现过去 CSS 无法实现的功能。

过去,CSS实现了不规则图形的边框形式

CSS

实现不规则的图形边框,一直是CSS的难点之一。过去,尽管我们有很多形式来破解不规则的图形边框。

让我们看一下这张图:

使用 CSS 实现这样的图形相对简单css 下边框,可以借助背景中的蒙版或渐变来实现,如下所示:

<div class="arrow-button"></div>

.arrow-button {
    position: relative;
    width180px;
    height64px;
    background#f49714;

    &::after {
        content"";
        position: absolute;
        width32px;
        height64px;
        top0;
        right: -32px;
        background
            linear-gradient(-45deg, transparent 0, transparent 22px, #f49714 22px, #f49714 100%),
            linear-gradient(-135deg, transparent 0, transparent 22px, #f49714 22px, #f49714 100%);
        background-size32px 32px;
        background-repeat: no-repeat;
        background-position0 bottom, 0 top;
    }
}

但是,如果要实现这个图形,但只有一层边框,那么用CSS实现就不那么容易了,就像这样:

过去,有两种相对不错的方法可以实现这种不规则的图形边框:

使用过滤器,利用多个投影()。

这是通过 SVG 过滤器实现的

让我们快速回顾一下这两个技巧。

使用

过滤器,使用多个drop-shadow()来实现不规则边框

或者里面的图形css 下边框,我们可以借助多个 drop-shadow() 大致获得它的边框效果。代码如下:

div {
    position: relative;
    width180px;
    height64px;
    background#fff;

    &::after {
        content"";
        position: absolute;
        width32px;
        height64px;
        top0;
        right: -32px;
        background
            linear-gradient(-45deg, transparent 0, transparent 22px, #fff 22px, #fff 100%),
            linear-gradient(-135deg, transparent 0, transparent 22px, #fff 22px, #fff 100%);
        background-size32px 32px;
        background-repeat: no-repeat;
        background-position0 bottom, 0 top;
    }
}
div {
    filter
        drop-shadow(0px 0px .5px #000)
        drop-shadow(0px 0px .5px #000)
        drop-shadow(0px 0px .5px #000);
}

可以看出,这里我们叠加 3 层 drop-shadow() 来实现不规则图形的边框,虽然使用 drop-shadow() 来生成阴影,但是叠加具有小多层值的阴影具有类似于边框的效果:

使用 SVG 滤镜实现不规则边框

另一种形式需要对 SVG 过滤器有更深入的了解。通过实现一个特殊的SVG过滤器,然后通过CSS过滤器引入它,实现了不规则的边界。

看看代码:

<div></div>

<svg width="0" height="0">
    <filter id="outline">
        <feMorphology in="SourceAlpha" result="DILATED" operator="dilate" radius="1"></feMorphology>
        <feMerge>
            <feMergeNode in="DILATED" />
            <feMergeNode in="SourceGraphic" />
        </feMerge>
    </filter>
</svg>

div {
    position: relative;
    width180px;
    height64px;
    background#fff;

    &::after {
        content"";
        position: absolute;
        width32px;
        height64px;
        top0;
        right: -32px;
        background
            linear-gradient(-45deg, transparent 0, transparent 22px, #fff 22px, #fff 100%),
            linear-gradient(-135deg, transparent 0, transparent 22px, #fff 22px, #fff 100%);
        background-size32px 32px;
        background-repeat: no-repeat;
        background-position0 bottom, 0 top;
    }
}
div {
    filterurl(#outline);
}

让我们简要看一下这个 SVG 过滤器代码:使用原始图像

的不透明部分作为输入,将扩张模式使用到半径=“1”的范围,并生成比原始图像大1px的白色瓷砖

使用 feMerge 将红色磁贴叠加在原始图像的顶部

您可以通过控制过滤器中的radius=“1”来控制边框的大小

这样,还可以实现不规则图形的边框效果:

CodePen Demo -- 实现不规则边框的 3 种方法[3]

使用 CSS 绘画 API 实现不规则边框

好吧,明天,有了 CSS 绘画 API,我们有一个更直接的方法来解决这个问题。

或者里面的图形,让我们使用剪辑路径来实现它。

<div></div>

div {
    position: relative;
    width200px;
    height64px;
    background#f49714;
    clip-pathpolygon(85% 0%100% 50%85% 100%0% 100%0% 0%;); 
}

我们可以得到这样的图形:

当然,本文的主角是 CSS 绘画 API,由于我们有剪辑路径参数,我们实际上可以使用 CSS 绘画 API 的 borderDraw 来绘制这个图。

让我们尝试一下,修改我们的代码:

<div></div>
<script>
if (CSS.paintWorklet) {              
   CSS.paintWorklet.addModule('/CSSHoudini.js');
}
</script>

div {
    position: relative;
    width200px;
    height64px;
    backgroundpaint(borderDraw);
    --clipPath85% 0%100% 50%85% 100%0% 100%0% 0%;); 
}

在这里,我们

将原始 clip-path 的特定 path 参数定义为 CSS 变量 --clipPath,并将其传递给我们要实现的 borderDraw 方法。整个图形效果是在背景的帮助下绘制它:paint(borderDraw)。

接下来,让我们看看我们需要实现 borderDraw。核心点是我们取 --clipPath 参数,解析它,然后借助画布通过循环函数勾勒出图形。

// CSSHoudini.js 文件
registerPaint(
    "borderDraw",
    class {
        static get inputProperties() {
            return ["--clipPath"];
        }

        paint(ctx, size, properties) {
            const { width, height } = size;
            const clipPath = properties.get("--clipPath");
            const paths = clipPath.toString().split(",");
            const parseClipPath = function (obj{
                const x = obj[0];
                const y = obj[1];
                let fx = 0,
                    fy = 0;
                if (x.indexOf("%") > -1) {
                    fx = (parseFloat(x) / 100) * width;
                } else if (x.indexOf("px") > -1) {
                    fx = parseFloat(x);
                }
                if (y.indexOf("%") > -1) {
                    fy = (parseFloat(y) / 100) * height;
                } else if (y.indexOf("px") > -1) {
                    fy = parseFloat(y);
                }
                return [fx, fy];
            };

            var p = parseClipPath(paths[0].trim().split(" "));
            ctx.beginPath();
            ctx.moveTo(p[0], p[1]);
            for (var i = 1; i < paths.length; i++) {
                p = parseClipPath(paths[i].trim().split(" "));
                ctx.lineTo(p[0], p[1]);
            }
            ctx.closePath();            
            ctx.fill();
        }
    }
);

简单解释上面的代码,注意 parseClipPath() 方法的解释,这是最难理解的。

首先,我们可以通过properties.get(“--clipPath”)获取--clipPath参数。

通过 spilt() 方法,将 --clipPath 划分为多个段,这是我们图的实际草图绘制步骤。

需要注意的是 parseClipPath() 方法,因为我们 -clipPath 的每一段都可能是 100% 50% 构造的,但在实际的绘制过程中,我们需要实际坐标的绝对值,例如在 100 x 100 的画布上,我们需要将 50% 50% 的比例坐标转换为实际绝对值 50 50

在理解了parseClipPath()之后,剩下的就很容易理解了,我们用ctx.beginPath()、ctx.move、ctx.lineTo和ctx.closePath()勾勒出整个--clipPath图。

最后,使用 ctx.fill() 勾选图形

这样,我们得到了这样的图表:

已收到完整的图形,

所以我们只勾勒出这个图形的边框,没有勾线,难道我们没有得到它的边框效果吗?

对一些 JavaScript 代码的最后一部分进行简单的重塑:

// CSSHoudini.js 文件
registerPaint(
    "borderDraw",
    class {
        static get inputProperties() {
            return ["--clipPath"];
        }
        paint(ctx, size, properties) {
            // ...
            ctx.closePath();            
            // ctx.fill();
            ctx.lineWidth = 1;
            ctx.strokeStyle = "#000";
            ctx.stroke();
        }
    }
);

通过这种方式,我们得到了图形的边框效果:

仅凭背景概述的缺陷

但是,仅使用[bacg](背景:paint(borderDraw “bacg”))来勾勒边框的效果存在一些问题。

在上图中,我们只分配了 1px 的边框,如果我们将边框更改为 5px 怎么办?看看会发生什么?

// CSSHoudini.js 文件
registerPaint(
    "borderDraw",
    class {
        static get inputProperties() {
            return ["--clipPath"];
        }
        paint(ctx, size, properties) {
            // ...
            ctx.lineWidth = 5;
            ctx.strokeStyle = "#000";
            ctx.stroke();
        }
    }
);

此时,整个图表将用于:

如你所见,没有显示完整的 5px 边框,因为整个画布只是元素的高度和宽度,而在上面的代码中,元素边框的一部分轮廓在画布之外,所以整个图形并不是我们预期的效果。

因此,我们需要用不同的方式解决这个问题,并继续修改我们的代码,只是 CSS 代码:

div {
    position: relative;
    width200px;
    height64px;
    margin: auto;
    clip-pathpolygon(var(--clipPath)); 
    --clipPath85% 0%100% 50%85% 100%0% 100%0% 0%;
    
    &::before {
      content:"";
      position:absolute;
      inset0;
      maskpaint(borderDraw);
      background#000;
    }
}

在这里,我们的元素本身在clip-path:polygon(var(--clipPath))的帮助下自我切割,同时,我们使用伪元素来实现特定的边框效果。

虽然这里用一种内外切割思维来达到边界疗效:

使用父元素的clip-path: polygon(var(--clipPath))剪切外围图形

使用掩码到

伪元素作为实际的绘画(borderDraw)方法,图形的内部被挖空,只留下边框部分

设置 ctx.lineWidth = 5,看看会发生什么:

看起来不错,但实际上,虽然边框长度设置为5px,

但实际上上图中的边框长度只有2.5px,因为另一半边框实际上被切断了。

因此,如果我们需要达到 5px 的功效,我们实际上需要 ctx.lineWidth =10。

当然,我们可以通过 CSS 变量来控制边框的大小:

div {
    position: relative;
    width200px;
    height64px;
    margin: auto;
    clip-pathpolygon(var(--clipPath)); 
    --clipPath85% 0%100% 50%85% 100%0% 100%0% 0%;
    --borderWidth5;
    
    &::before {
      content:"";
      position:absolute;
      inset0;
      maskpaint(borderDraw);
      background#000;
    }
}

在实际的 borderDraw 函数中,我们将 --borderWidth 参数乘以 2:


registerPaint(
    "borderDraw",
    class {
        static get inputProperties() {
            return ["--clipPath""--borderWidth"];
        }
        paint(ctx, size, properties) {
            const borderWidth = properties.get("--borderWidth");
            // ...
            ctx.lineWidth = borderWidth * 2;
            ctx.strokeStyle = "#000";
            ctx.stroke();
        }
    }
);

通过这种方式,我们每次都能得到我们想要的边框宽度:

CodePen Demo -- CSS Hudini & UnregularCustom Border[4]

至此,整个实现就完成了,虽然整个过程有很多非常关键的点,但会有一点点的不理解,你可能需要实际调试自己才能找到实现的原理。

特定应用

掌握了上面的方法后,我们就可以用这种方法来实现各种不规则形状的边框效果,我们只需要传入 clip-path 参数和我们想要的边框宽度即可。

那么,通过这种方式,我们可以实现具有各种不同不规则形状的边框的效果。

喜欢这个:

div {
    position: relative;
    width200px;
    height200px;
    clip-pathpolygon(var(--clipPath)); 
    --clipPath0% 15%15% 15%15% 0%85% 0%85% 15%100% 15%100% 85%85% 85%85% 100%15% 100%15% 85%0% 85%;
    --borderWidrh1;
    --color#000;
    
    &::before {
      content:"";
      position:absolute;
      inset0;
      maskpaint(borderDraw);
      backgroundvar(--color);
    }
}

div:nth-child(2) {
    --clipPath50% 0%61% 35%98% 35%68% 57%79% 91%50% 70%21% 91%32% 57%2% 35%39% 35%;
    --borderWidrh2;
    --color#ffcc00;
}
div:nth-child(3) {
    --clipPath90% 58%90% 58%69% 51%69% 51%50% 21%50% 21%39% 39%39% 39%15% 26%15% 26%15% 55%15% 55%31% 87%31% 87%14% 84%14% 84%44% 96%44% 96%59% 96%59% 96%75% 90%75% 90%71% 83%71% 83%69% 73%69% 73%88% 73%88% 73%89% 87%89% 87%94% 73%94% 73%;
    --borderWidrh1;
    --color: deeppink;
}
div:nth-child(4) {
    --clipPath0% 0%100% 0%100% 75%75% 75%75% 100%50% 75%0% 75%;
    --borderWidrh1;
    --color: yellowgreen;
}
div:nth-child(5) {
    --clipPath20% 0%0% 20%30% 50%0% 80%20% 100%50% 70%80% 100%100% 80%70% 50%100% 20%80% 0%50% 30%;
    --borderWidrh3;
    --color#c7b311;
}

获得不同图形的边框效果:

CodePen Demo -- CSS Hudini & UnregularCustom Border[5]

或者基于它们,实现各种关键效果,这在前几年用CSS特别难以实现:

它们的核心原理是一样的,就连悬停效果都特别轻松:

完整的代码,你可以在这里戳:

代码笔演示 -[6]

到目前为止,我们再次使用 CSS 绘画 API 实现了过去使用 CSS 无法实现的完全无法实现的效果。这就是 CSS Houdini 的魅力,JS In CSS 的魅力。

兼容性

CSS Painting API 的兼容性到底是什么?

1. 动漫 CSS 边框

当我们想让我们的项目更加可见时,我们该怎么办?

让我们动漫吧!

我们可以为我们的边界设置动画,即使不改变元素的大小,这非常简单。

为此,我们只需要为动漫创建一个自定义关键帧,并在元素的 CSS 代码的动画参数中使用它。

我们来看一个反例,HTML 如下

<div id="box">
编程适合那些有不同想法的人... <br/>
对于那些想要创造大事物并愿意改变世界的人们。
</div>

编译CSS和动漫

@keyframes animated-border {
0% {
box-shadow: 0000rgba(255,255,255,0.4);
}
100% {
box-shadow: 00020pxrgba(255,255,255,0);
}
}
#box {
animation: animated-border 1.5s infinite;
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
border: 2px solid;
border-radius: 10px;
padding: 15px;
}

功效如下

2.CSS图像边框

你有没有想过在你的元素周围有冰淇淋?

如今,您可以通过纯CSS添加它们,而无需太多编码。

因此,您需要在元素的 CSS 代码中使用边框图像属性。

让我们看一个反例,再次是前面的HTML

<div id="box">
编程适合那些有不同想法的人... <br/>
对于那些想要创造大事物并愿意改变世界的人们。
</div>

编译云服务器

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
border: 40px solid transparent;
border-image: url(https://image.flaticon.com/icons/svg/648/648787.svg);
border-image-slice: 100%;
border-image-width: 60px;
padding: 15px;
}

功效如下

3.蛇CSS边框

如果我们需要双色超声波边框怎么办?

我们可以穿上蛇的衣服,随心所欲地给它上色。

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
padding: 15px;
border: 10px dashed #FF5722;
background:
linear-gradient(to top, green, 10px, transparent 10px),
linear-gradient(to right, green, 10px, transparent 10px),
linear-gradient(to bottom, green, 10px, transparent 10px),
linear-gradient(to left, green, 10px, transparent 10px);
background-origin: border-box;
}

功效如下

4. 阶梯式 CSS 边框

您是否尝试在 div 周围添加 3D 样式边框?

为我们的元素添加一些多色深度非常容易,我们只需要在 CSS 中添加一些小的方形阴影。

让我们测试一下我们的反例!

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
padding: 40px;
box-shadow:
inset #0096880005px,
inset #059c8e0001px,
inset #0cab9c00010px,
inset #1fbdae00011px,
inset #8ce9ff00016px,
inset #48e4d600017px,
inset #e5f9f700021px,
inset #bfecf700022px
}

疗效

5. 只有阴影 CSS 边框

有时我们必须为现有设计添加边框,但添加更多像素可能会有问题,它会改变元素的位置。

现在我们可以将围绕元素的框阴影用作边框,请看一下代码。

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
padding: 40px;
border-radius: 10px;
box-shadow: 00010px white;
}

疗效

6.CSS 带有阴影和轮廓的边框

有几种方法可以实现与蛇姿势类似的效果。其中之一是在元素 CSS 中混合框阴影和出站属性。

我看看。

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
padding: 40px;
box-shadow: 00010px white;
outline: dashed 10px#009688;
}

疗效

7.少量的阴影和轮廓

我们甚至可以在边框中创建一些颜色和元素。

因此,我们需要混合阴影和轮廓,如下例所示。

让我们试试吧。

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
padding: 40px;
box-shadow:
0001px#009688,
0005px#F44336,
0009px#673AB7,
00010px#009688;
outline: dashed 10px#009688;
}

疗效

8.带阴影的双CSS边框

我们还可以混合一些框阴影和轮廓边框。

这将用刺创造一个漂亮的腰围效果,如下例所示。

让我们测试代码!

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
padding: 40px;
box-shadow: 00010px#009688;
border: 10px solid #009688;
outline: dashed 10px white;
}

疗效

9. 多色CSS边框

如果我们想为边框添加比上面示例更多的颜色怎么办?

我们甚至可以将元素的每一面设置为不同的颜色。

因此,我们将需要一些带有渐变的自定义背景。

看看下面的反例。

#box {
font-family: Arial;
font-size: 18px;
line-height: 30px;
font-weight: bold;
color: white;
padding: 40px;
background:
linear-gradient(to top, #4caf50, #4caf50 10px, transparent 10px),
linear-gradient(to right, #c1ef8c, #c1ef8c 10px, transparent 10px),
linear-gradient(to bottom, #8bc34a, #8bc34a 10px, transparent 10px),
linear-gradient(to left, #009688, #00968810px, transparent 10px);
background-origin: border-box;
}

疗效

结束

好的css 下边框,这是最后一个想法css 下边框,所以让我们暂时离开它。

我希望你

喜欢它,我希望这些观点对您有用。

随意测试它,尝试它,并在评论中显示您发现的边框与众不同的内容。

最近

看一看 ❤️