,世界杯正在进行中,也不要忘记学习 CSS(得想办法蹭一波热度)。比如,用 CSS 绘制一个足球场?,
,CSS 足球场,一眼望去,这里的形状只有圆形和矩形,在不借助其他标签的情况下(包括伪元素),其实很容易联想到渐变,一起看看如何绘制的吧,有非常多的渐变小技巧~,首先来看一下足球场的构造,下面是在网上找到的一张设计图。,
,球场设计图,主要有以下几个部分:,以世界杯比赛场地为例,长度115码(105m),宽度74码(68m)。,假设 HTML结构如下,这里用到的标签仅仅只有一个。,为了尺寸计算方便,采用em相对单位进行换算,数值就可以采用真实的“码”,好处是都是整数,简单绘制一下外围边线和底线,如下:,注意这里实现的小细节:这里外层的线框是通过outline实现的,还预留了一个5em的透明边框,这是因为背景的位置和尺寸百分比计算是根据内容区域的,并不包含边框。比如,background-postion:0 0表示的就是线框内的左上点,background-postion: 100% 100%表示的就是线框内的右下点,,background-size: 100%表示的就是线框内最大尺寸,如下:,
,透明边框的好处,还有一个好处,透明边框仍然是可以绘制背景的,比如深浅不同的草皮就可以绘制在边框之外,这个后面再说。,准备工作完成了,下面是具体的绘制过程。,在绘制之前,可以简单规划一下,通过 CSS 变量将各部分分离开来,这样看起来会更加清晰,例如:,首先是中线,使用线性渐变linear-gradient。,可能有些同学还不太清楚上面这一段 background的简写,可以看下面这张图(下面只列举了常用的,实际上还有更多属性)。,
,背景的简写,效果如下:,
,中线,然后是开球点和中圈。,这是一个半径为10码的圆,可以通过一个径向渐变radial-gradient实现。,注意,这里使用了关键词closest-side,表示最近的边,可以根据背景尺寸直接控制圆的大小,默认值是farthest-side,其他选项详细如下:,当然,对于完全对称的容器,closest-* 和 farthest-*是完全相同的,各自的区别如下所示:,
,径向渐变关键词,绘制效果如下:,
,中圈,罚球区通常也叫大禁区,是一个44码*18码的矩形线框。,线性渐变不像径向渐变那样,并不能直接画出这种矩形线框,我采用的方式是覆盖的方式,也就是一块绿色的覆盖在一块白色的背景之上,实现如下:,动态演示如下:,
,大禁区实现演示,两边半场都有罚球区域,而且长的也完全一样,需要再重新绘制一份一模一样的吗?,️️️当然不需要!,仔细观察,两边的罚球区域正好可以通过水平平铺repeat-x实现,只需要改变背景大小就行了,示意如下:,
,平铺实现演示,你也可以查看动态演示:,
,平铺实现动态演示,用代码实现就是:,这样就能在不增加渐变数量的情况下实现多份相同的背景,效果如下:,
,大禁区,然后是球门区,通常叫小禁区,是一个20码*6码的矩形线框。,这个和罚球区绘制方法一致,就不多描述了。,效果如下:,
,小禁区,最后是球门。球门在底线后面,由于是俯视图,只需要知道长度8码就行了,宽度可以随便给一个。,这个和上面绘制方法一致,不过需要注意background-position的位置,是负数。,这里就体现出前面透明的好处了,可以将背景绘制在边框上,效果如下:,
,球门,这样就完成了所有矩形线框的绘制。,最后是几条比较重要的圆弧。,首先是罚球点,又称点球点,距离球门12码。,这是一个圆点,直接通过一个径向渐变radial-gradient绘制,这个我们等会再来绘制,先画下面的。,然后是罚球弧,它是以罚球点为圆心,半径为10码的圆弧,和中圈一样。,和中圈大小是一样的,只是位置不同,注意圆心距离左侧的距离是12码,由于左右都是一样的,可以用前面提到的repeat-x方式实现(当然这里不写也行,因为默认就是平铺的),示意如下:,
,平铺实现演示,你也可以查看动态演示:,
,平铺实现动态演示,用代码实现就是:,效果如下:,
,最上层的罚球弧,现在这个圆弧覆盖在最上面,由于罚球区是通过覆盖的方式实现的,所以可以将罚球弧放在罚球区下面,通过改变background的先后顺序就可以了,如下:,这样就正常了。,
,罚球弧,然后用同样的方式把罚球点补上。,效果如下:,
,罚球点,最后是角球弧。位于球场四角,是半径为1m的 1/4 圆弧。,如果按照一般的思路,肯定是绘制 4 个 1/4 圆弧就行了,不过这里还可以采用另一种方式。仔细想一下,这4个圆弧合在一起是不是刚好就是一个完整的圆?经过位移、平铺就可以了,思路演示如下,
,1/4圆平铺原理演示,用代码实现就是:,这样用一个渐变就同时绘制出了4个圆,效果如下:,
,4个完整角球弧,可以看到,4个圆弧已经均匀分布在4个角落了,但是已经超出了线外,这个也非常好解决,默认情况下背景是可以绘制在border-box范围内的,只需要通过background-clip裁剪到content-box内就行了,如下:,这样就完美了。,
,使用background-clip裁剪后的角球弧,到目前位置,球场的所有部分基本已经完成了,最后再铺上深浅相间的草坪。,关于草坪的条纹间隔貌似不是很统一?这里就大概给一个数值,用线性渐变即可,如下:,由于前面罚球区等用到了覆盖的方式,所以这里不能直接将草坪绘制在最底下,需要绘制在最上层,效果如下:,
,直接覆盖的草坪,可以看到,仅仅通过半透明的覆盖还是很不自然的,所以需要将颜色混合一下,需要用到background-blend-mode,比较复杂,这里就不展开了,设置如下:,效果如下:,
,混合模式,有点奇怪...原因是上面设置的是所有图层的background-blend-mode,我们其实只需要设置最顶层的草坪,那怎么处理呢?我起初以为background缩写是包含background-blend-mode的,这样的话可以单独给某一层设置了,可惜这个不支持(我猜测这个属性出现的稍晚一些,没有统一到背景里)。,没办法,只能逐层设置了,第1层设置 soft-light,剩下的全部都是normal,如下:,后面的normal可以多,但是不能少,原因在于,会根据背景数量自动补充,如果数量不足,会重新开头循环(这个补充规则其实跟其他背景属性,例如 background-size是一样的)。,
,混合模式自动填充规则,这样就非常自然了,效果如下:,
,最终效果,下面是完整代码(其实没多少行):,你也可以访问以下任意链接:,渐变是 CSS 中非常强大但比较繁琐的功能了,几乎是万能的,能够设计出来的都可以通过渐变绘制出来,只是实现的复杂度问题,擅于发现图形的规律也能有效地减少渐变的复杂度,下面简单总结一下。,当然实际工作中肯定是不推荐的,更多是学习掌握渐变相关知识,这样绘制一些活动小图标,或者在某些不方便改变 HTML 结构时可以有更多的思路和方案,不是吗?,[1]CSS football filed - 码上掘金 (juejin.cn): https://code.juejin.cn/pen/7172148336886022175。,[2]CSS football filed (codepen.io): https://codepen.io/xboxyan/pen/BaVqogP。,[3]CSS football filed (runjs.work): https://runjs.work/projects/8f18caa4fb1248dc。
© 版权声明
文章版权归作者所有,未经允许请勿转载。