margin-top:-20px;代替元素position:relative,top:-20且不占用文档流

渐变边框实现:
background-clip
核心原理:图层叠加法
我们要实现的效果其实是三层信息的叠加:
- 最底层:深色的、明显的边框渐变色(铺满整个
border-box)。 - 中间层:半透明的、淡淡的内部背景色(铺在
padding-box,也就是边框以内)。 - 最顶层:文字和标签。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18.gradient-border-card {
margin: 30rpx;
border-radius: 40rpx;
position: relative;
/* 【关键点】 */
/* 1. 设置透明边框,预留出 4rpx 的宽度 */
border: 4rpx solid transparent;
/* 2. 背景绘制两个层级:
第一个背景是纯白色,裁切到 padding-box(不包含边框区);
第二个背景是渐变色,裁切到 border-box(包含边框区)。
*/
background-image: linear-gradient(#fff, #fff),
linear-gradient(to right, #F8D7E8, #E2D9F3);
background-origin: border-box;
background-clip: padding-box, border-box;
}- 最底层:深色的、明显的边框渐变色(铺满整个
“遮罩反选法” (Mask Composite)
1. 铺满背景
首先,你在伪元素
::before上设置了一个完整的渐变背景。如果不做任何处理,它就是一个实心的、带渐变的圆角矩形,会把卡片内部的文字全部遮住。2. 画两个“遮罩面积”
关键在于这一行:
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);这里其实画了两层遮罩(虽然颜色是白色,但遮罩只看透明度):
- **第一层 (content-box)**:只覆盖内容区域(不含边框)。
- **第二层 (默认 border-box)**:覆盖整个卡片(含边框)。
3. “减法”运算(最核心的一步)
代码里最神奇的是这行:
-webkit-mask-composite: destination-out;(或者标准写法mask-composite: exclude;)它的逻辑是:“用第二层减去第一层”。
- 想象你有一张完整的大饼(第二层:整个卡片)。
- 你拿一个模具从中间压下去,把中间的部分扣掉(第一层:内容区)。
- 剩下的,就只有那一圈 4rpx 宽的边缘了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59<style lang="scss" scoped>.gradient-border-card {
position: relative;
margin: 30rpx;
border-radius: 40rpx; // 卡片的圆角
background: #ffffff; // 卡片内部的背景色
overflow: hidden;
/* 使用伪元素 ::before 来制作渐变边框 */
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 4rpx; // 【这个值就是边框的粗细吖!】
border-radius: 40rpx; // 必须和父级的圆角一致
/* 1. 设置渐变背景色 */
background: linear-gradient(to right, #F8D7E8, #E2D9F3);
/* 2. 使用 mask (遮罩) 核心技术 */
/* 我们画两个纯色遮罩,一个覆盖内容区(content-box),一个覆盖整个边框区(border-box) */
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
/* 3. 关键点:把两个遮罩重叠的部分“减去” */
/* 这样就只剩下 border 那个圈圈显示渐变色了! */
-webkit-mask-composite: destination-out;
mask-composite: exclude;
pointer-events: none; // 确保伪元素不会阻碍卡片内部的点击事件
}
}/* 内部装饰样式 */.content {
padding: 40rpx 30rpx;
.title {
font-size: 32rpx;
font-weight: bold;
color: #4A4A8A; // 这里的颜色可以根据图片微调
}
}.tags {
display: flex;
margin-top: 30rpx;
gap: 20rpx;
.tag-item {
padding: 10rpx 30rpx;
border-radius: 40rpx;
font-size: 26rpx;
border: 1px solid #E2D9F3;
color: #666;
&.active {
background: #E2D9F3;
color: #4A4A8A;
border: none;
}
}
}
</style>外面套一层盒子,背景为渐变吖吖
发就开了;的
渐变可以多层叠加,是顶层到底层,第一层有透明度就会显示第二层,第二层有透明度就会显示第三层吖吖。
在 CSS 布局中,**gap** 是一个非常实用的属性,它专门用来设置子元素之间的间距。
你可以把它想象成元素之间的“防火隔离带”,它只存在于元素与元素之间,而不会在容器的边缘(四周)产生多余的空格。
1. 它解决了什么痛点?
在没有 gap 之前,我们如果想让一排按钮之间有 20px 的间距,通常得这么写:
- 给每个按钮加
margin-right: 20px;。 - 然后还得用
:last-child把最后一个按钮的margin-right删掉,否则最后一项会把整个容器撑大,导致不对称。
有了 gap 之后: 你只需要在父容器上写一行 gap: 20px;,剩下的浏览器全帮你算好了。
2. gap 的构成
gap 实际上是两个属性的简写:
- **
row-gap**:行与行之间的间距。 - **
column-gap**:列与列之间的间距。
语法示例:
gap: 20px;—— 水平和垂直间距都是 20px。gap: 10px 30px;—— 行间距 10px,列间距 30px。
3. 它在哪里可以用?
gap 最初只能在 Grid(网格) 布局里用,但现在它在 Flex(弹性) 布局里也得到了完美支持(这也是目前最常用的场景)。
在 Flex 里的用法:
CSS
1 | .tags { |
4. 为什么大家现在都爱用 gap?
- 干净:不会在容器的最左边或最右边多出空位。
- 省事:不需要用
:first-child或:last-child去修补 margin。 - 直观:在父元素上统一管理间距,不用去每个子元素里找 margin 设置。
5. 小提醒
虽然现在 gap 在微信小程序和现代浏览器中支持得非常好,但如果你需要兼容非常老旧的安卓手机系统(比如 2020 年以前的),Flex 里的 gap 可能会失效。不过在目前绝大多数开发场景下,它已经是“标配”了。
你之前代码里的那一段:
CSS
1 | .tags { |
它的作用就是让“饭搭子”、“运动搭子”这些标签之间保持 20rpx 的距离。
简单来说:**margin: 0 auto 是“自动推开”,而 translateX 是“手动位移”。**
1. 什么时候用 margin: 0 auto;?
适用场景: 固定宽度的块级元素(如 div)。
- 条件: 1. 必须有明确的宽度(比如
width: 300px或width: 50%)。 2. 元素必须是块级(display: block)。 - 原理: 浏览器会自动计算左右剩余的空间,并将它们平分给左右外边距。
- 优点: 性能最好,代码最简洁。
- 注意: 它不需要配合
transform!
2. 什么时候用 transform: translateX(-50%);?
适用场景: 绝对定位(position: absolute)的元素。 这种情况就是你记忆中出现“50%偏移”的地方。
原理拆解:
left: 50%;:这会把元素的左边缘推到父容器的正中间。此时元素整体偏右了。transform: translateX(-50%);:这会让元素向左移动它自身宽度的一半。
为什么不直接用 margin? 因为绝对定位的元素脱离了文档流,margin: auto 拿不到剩余空间,失效了。