移动端卡片边框怎么做高级?我用 CSS 实现了设计师的刁钻要求

张开发
2026/4/8 0:09:17 15 分钟阅读

分享文章

移动端卡片边框怎么做高级?我用 CSS 实现了设计师的刁钻要求
一个让产品经理和设计师都满意的卡片边框方案 前言上周设计突然甩过来一张图问我能不能不切图做出这种效果我蒙了一下第一反应感觉可以无非就是常规的伪类渐变。但尝试了一下发现两个致命问题1、border-image支持渐变但不支持每条边自定义设置82、使用伪类可以解决线的问题但是不能解决圆角问题忙乎半天又问了问ai感觉还是实现起来不容易但随后产品过来又是那老一套。拿着别人家的产品看人家这个如何好看如何优雅巴拉巴拉。大有一种别人能做你做不了。这是不能接受的于是又潜心研究了下有了最后的效果。 需求拆解先梳理一下具体需求需求描述位置卡片左下角 L 形左边 底边渐变左下角颜色最深向两端渐淡粗细视觉上 1px长度左边和底边长度大致相等圆角适配卡片 20px 圆角性能纯 CSS无图片无 SVG看起来简单做起来全是坑。 方案探索方案一两个伪元素分别画线最直观的想法用::before画底部线::after画左边线。scss.card { ::before { // 底部线 background: linear-gradient(90deg, gold, transparent); } ::after { // 左边线 background: linear-gradient(0deg, gold, transparent); } }问题两条线在圆角处有接缝怎么都对不齐。调整了半天还是能看到明显的拼接痕迹。结论放弃圆角处无法完美衔接。方案二SVG 路径描边SVG 可以精确控制路径和圆角效果确实完美。问题需要额外 HTML 结构移动端多一个网络请求或内联代码响应式适配需要额外处理结论能用但不够优雅性能也不够极致。方案三border-image 渐变scssborder-image: radial-gradient(circle at bottom left, gold, transparent) 1;问题border-image会覆盖四边无法只控制左下角。结论放弃。方案四radial-gradient mask最终方案经过多次尝试我发现径向渐变的圆心在左下角时渐变会自然地向左和向上扩散形成完美的 L 形。配合mask组合可以精确控制只显示边框区域而不是整个渐变圆。完美解决所有问题 最终代码以下是基于vue2的一个组件CornerGradientCard开箱即用。但注意基于他的点击事件要使用click.native!!!template div :classgradient-wrapper ${type} :stylewrapperStyle div classgradient-wrapper__content :style{ borderRadius: radiusRem } slot/slot /div /div /template script /** 与 postcss.config.js 中非 vant 资源的 rootValue(75) 一致设计稿 px → rem */ const POSTCSS_ROOT_VALUE 75 function pxToRem(px) { const n Number(px) if (Number.isNaN(n)) return 0rem return ${parseFloat((n / POSTCSS_ROOT_VALUE).toFixed(10))}rem } export default { props: { type: { default: , type: String }, radius: { default: 12, type: Number }, marginBottom: { default: 14, type: Number } }, computed: { radiusRem() { return pxToRem(this.radius) }, wrapperStyle() { const r this.radiusRem return { borderRadius: r, marginBottom: pxToRem(this.marginBottom), --corner-radius: r } } } } /script style langscss scoped $gradient-first-percent: 4%; // 第一个实色节点百分比 $gradient-second-percent: 10%; // 第二个半透明节点百分比 $gradient-transparent-percent: 30%; // 透明节点百分比 .gradient-wrapper { width: 100%; position: relative; padding: 0 0 1px 1px; box-sizing: border-box; background-color: #fff; overflow: hidden; -webkit-backface-visibility: hidden; backface-visibility: hidden; __content { width: 100%; position: relative; z-index: 3; margin: 0 0 1px 1px; box-sizing: border-box; overflow: hidden; background-color: transparent; } // 渐变边框线核心 ::after { content: ; position: absolute; z-index: 2; bottom: 0; left: 0; width: 100%; height: 100%; border-radius: var(--corner-radius); pointer-events: none; mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude; -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; padding: 1px; } // 渐变底色光晕效果 ::before { content: ; position: absolute; z-index: 1; bottom: 1px; left: 1px; width: 143px; height: 73px; border-radius: var(--corner-radius); filter: blur(10px); pointer-events: none; } .WX { ::after { background: radial-gradient( circle at bottom left, #B6E2C8 $gradient-first-percent, #DFF7EA $gradient-second-percent, transparent $gradient-transparent-percent ); } ::before { background: radial-gradient( 83% 83% at 31% 52%, #F0FBF5 0%, rgba(239,255,246,0) 100%); } } } /styleCornerGradientCard v-for(item, index) in infoData :keyitem.id :iditem.id :typeitem.type click.nativeclickItem(item) !-- 卡片内容 -- /CornerGradientCard 参数调节指南参数位置作用移动端建议padding: 1px.wrapper边框粗细保持 1px4% / 10% / 30%径向渐变边框长度根据卡片大小调整blur(10px)光晕柔和度移动端 8-12px 较佳border-radius全局圆角与设计稿保持一致当然基于此样式还可以可发出各种变种例如将渐变等放到常规的右上角替代常规的卡片标签展示样式。

更多文章