直接写一个带圆角的棋盘格背景,还能在格子交叉点上加星星装饰?这事儿真能成

3,106字
13–20 分钟
in

想在网页背景里搞出棋盘格图案不难,可一旦想要把那些小方块的棱角磨圆润,再在每个格子交点上塞一颗小星星,常规的CSS写法就有点不够用了。翻来翻去试了好多法子,最后发现一个有点野的路子——用重复渐变画出网格骨架,再借一个编码过的SVG把星星图案精准贴在每个交叉点上。整个过程不需要折腾canvas,也不用堆一堆div,纯粹靠background属性叠罗汉就能搞定。

目录

啥是重复线性渐变

repeating-linear-gradient 这个CSS函数能生成一张重复平铺的渐变图。跟普通的线性渐变不一样,它不会只画一次就结束,而是把定义好的颜色段当模板,像铺瓷砖一样在整个背景区域里无限复制。比如写 repeating-linear-gradient(to right, red 0px, red 10px, blue 10px, blue 20px),浏览器就会生成红蓝交替的竖条纹,每条宽10像素,从左到右一直铺满。

搭骨架

先搞出一个基础的棋盘格网格。用两层 repeating-linear-gradient 叠起来,一层画水平方向的白色线框,一层画垂直方向的白色线框。两层一交叉,自然就切出了一个个独立的小方块。

.box {
  background: 
    repeating-linear-gradient(
      to right, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    repeating-linear-gradient(
      to bottom, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    linear-gradient(45deg, #f8a5c2, #6c5ce7);
}

这段代码里,第一个渐变生成竖向的白色条纹:从透明开始,保持50像素透明,然后突然变成白色,白色只占5像素宽,接着又变回透明。第二个渐变完全一样,只是方向改成 to bottom,生成横向的白色条纹。两层叠在一起,透明区域就露出了底层的粉色到蓝色渐变,而白色条纹相交的地方恰好围出一个个50×50像素的透明方块。底层那个45度线性渐变是整块背景的底色,被白色网格切割后,每个格子里的颜色其实还是连续的渐变过渡。

写代码的时候注意,白色条纹的宽度(5像素)决定了格子之间的缝隙粗细。如果希望格子之间挨得更紧,就把 55px 改成接近 50px 的值,比如 51px;想要宽边框,就加大差值。另外,透明区域的尺寸 50px 直接决定了每个方格的边长,这个数字后面还要跟星星图案的位置对齐,改的时候要前后一致。

贴星星

现在每个格子交叉点上还是空的。目标是在每条白色横线和白色竖线的交叉中心,也就是每个格子左上角那个点,放一颗小星星。这需要在 background 属性里再加一层图像,而且这层图像必须是重复平铺的,平铺的间距恰好等于格子宽度(55像素),同时偏移量要让星星正好落在交叉点上。

.box {
  background: 
    repeat left -17px top -22px / 55px 55px
    url("data:image/svg+xml,
      <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 35px 35px'>
        <foreignObject width='35px' height='35px'>
          <div xmlns='http://www.w3.org/1999/xhtml' style='color:white; font-size:35px'>✦</div>
        </foreignObject>
      </svg>"
    ),
    repeating-linear-gradient(
      to right, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    repeating-linear-gradient(
      to bottom, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    linear-gradient(45deg, #f8a5c2, #6c5ce7);
}

拆开来看,repeat 关键字告诉浏览器这张SVG小图要像墙纸一样平铺。紧接着的 left -17px top -22px / 55px 55px 分成了两截:斜杠左边是背景图的起始位置(向左偏移17像素,向上偏移22像素),斜杠右边是每张平铺单元的尺寸(宽55像素,高55像素)。为什么偏移量是 -17px-22px?因为星星图案本身有35像素大小,而格子交叉点位于网格线的交汇处。经过反复试错,把星星往左上挪一点,才能让它的中心对准白色线框的十字交叉口。偏移数值跟星星的 font-size 以及格子尺寸直接挂钩,换不同大小的星星需要重新微调。

SVG 部分用了 foreignObject 在里面塞了一个HTML的 div,这个 div 只放了一颗黑色小星星的字符实体 。通过 style="font-size:35px" 控制星星的大小,这个尺寸越大,覆盖的圆角范围就越大——实际上星星的边缘会遮住底层方格的尖角,视觉上相当于给格子磨了圆角。颜色设为白色,这样在深色渐变背景上能跳出来。注意整个SVG的 viewBoxforeignObject 的宽高都写成35像素,跟 font-size 保持一致,避免缩放变形。

鼠标滑过变半透

想要加点交互效果,可以在鼠标悬停时把白色线框变成半透明,同时把星星图层撤掉。这里不删除星星图层,而是重新写一套 background 属性,只保留渐变层,星星那行直接省略。白色线条的颜色从纯白 white 换成带透明通道的 rgb(255 255 255 / 0.5),半透明值0.5让底下的渐变底色能透上来。

.box:hover {
  background:
    repeating-linear-gradient(
      to right, transparent,
      transparent 50px,
      rgba(255, 255, 255, 0.5) 50px,
      rgba(255, 255, 255, 0.5) 55px
    ),
    repeating-linear-gradient(
      to bottom, transparent,
      transparent 50px,
      rgba(255, 255, 255, 0.5) 50px,
      rgba(255, 255, 255, 0.5) 55px
    ),
    linear-gradient(45deg, #f8a5c2, #6c5ce7);
  box-shadow: 10px 10px 20px rgba(108, 92, 231, 0.3);
}

悬停时还加了一个外发光 box-shadow,让整个模块浮起来。注意 repeating-linear-gradient 里的透明段和白色段的位置数字(50px, 55px)必须跟之前完全一致,否则网格线会错位。半透明的白色在深色背景上会呈现一种类似磨砂玻璃的效果,跟星星消失后的干净画面挺搭。

调参避坑表

参数位置常见取值作用说明
透明段终点50px控制方格边长
白色段终点55px控制网格线粗细
星星偏移X-17px微调水平对位
星星偏移Y-22px微调垂直对位
星星字体大小35px决定圆角覆盖范围

调试的时候最容易翻车的是星星跑偏。如果发现星星不在十字交叉点上,可以单独把渐变层注释掉,只看星星的平铺效果,然后一点点调整偏移量。偏移量用负数表示向左或向上移动星星的起始绘制点。还有一个细节:白色线条的宽度(5像素)加上偏移量,必须保证星星的直径能盖住方块的尖角,否则圆角效果会露馅。如果想换其他符号,比如实心圆点 或者五角星 ,直接在SVG的 div 里替换字符就行,注意某些特殊符号在不同操作系统下的显示可能不太一样。