使用CSS实现《声生不息》节目Logo

声明:本文涉及图文和模型素材仅用于个人学习、研究和欣赏,请勿二次修改、非法传播、转载、出版、商用、及进行其他获利行为。
背景

《声生不息》 是芒果TV、香港电视广播有限公司和湖南卫视联合推出的港乐竞唱献礼节目,听着音乐仿佛回到了那个令人怀念的港风席卷整个亚洲的年代。
该节目 Logo 采用经典红蓝配色,无限符号 ∞ 造型,满满的设计感。本文在仅采用原生 CSS 的情况下,尽量还原实现该 Logo 造型,本文内容虽然非常简单,但是用到的知识点挺多的,比如:repeating-linear-gradient、clip-path、background-clip、Window.getComputedStyle()、CSSStyleDeclaration.getPropertyValue() 等。
效果
先来看看实现效果吧。

点击右上角的 半圆 形状,页面主体可切换为白色。

在线预览
Github:https://dragonir.github.io/shengshengbuxi/
Codepen:https://codepen.io/dragonir/full/OJQRBad
实现
开始之前,先把 Logo 中用到的主要颜色作为CSS变量,后续会在多处用到这几种颜色,并要通过变量实现页面主体颜色切换功能。
:root {
--black: #010101;
--red: #F66034;
--blue: #0A68DF;
}
步骤0:第一个圆
观察 Logo 原型可以发现,第一个 是纯红色条纹样式效果,可以通过 repeating-linear-gradient 实现条纹背景效果,并设置伪元素 ::after 为背景黑色实现圆环样式。
<div class="logo">
<div class="cycle cycle_1"></div>
</div>
.cycle {
height: 500px;
width: 500px;
border-radius: 50%;
position: relative;
box-sizing: border-box;
}
.cycle_1 {
z-index: 2;
background: var(--red);
background: repeating-linear-gradient(180deg,var(--red),var(--red) 12px, var(--black) 0, var(--black) 22px);
border: 12px solid var(--black);
}
.cycle_1::after {
content: '';
display: inline-block;
height: 200px;
width: 200px;
background: var(--black);
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
border-radius: 50%;
z-index: 3;
}

repeating-linear-gradient
repeating-linear-gradient 创建一个由重复线性渐变组成的 <image>,和 linear-gradient 采用相同的参数,但它会在所有方向上重复渐变以覆盖其整个容器。
语法:
repeating-linear-gradient([ <angle> | to <side-or-corner> ,]? <color-stop> [, <color-stop>]+ )
\---------------------------------/ \----------------------------/
渐变轴的定义 色标列表
<side-or-corner>:描述渐变线的起始点位置。它包含两个关键词:第一个指出垂直位置left或right,第二个指出水平位置top或bottom。关键词的先后顺序无影响,且都是可选的。to top,to bottom,to left和to right这些值会被转换成角度0度、180度、270度和90度。其余值会被转换为一个以向顶部中央方向为起点顺时针旋转的角度。渐变线的结束点与其起点中心对称。<angle>:用角度值指定渐变的方向或角度。角度顺时针增加。<color-stop>:由一个<color>值组成,并且跟随着一个可选的终点位置,可以是一个<percentage>或者是沿着渐变轴的<length>。
示例:
// 一个倾斜45度的重复线性渐变, 从蓝色开始渐变到红色
repeating-linear-gradient(45deg, blue, red);
// 一个由下至上的重复线性渐变, 从蓝色开始,40%后变绿,最后渐变到红色
repeating-linear-gradient(0deg, blue, green 40%, red);
每次重复,色标位置的偏移量都是基准渐变长度(最后一个色标和第一个之间的距离)的倍数。因此,最后色标的色值应该与第一个色标的色值保持一致;如果不一致的话,会导致非常突兀的渐变效果。
与其他渐变一样,线形重复渐变没有提供固定的尺寸;即, 它没有原始尺寸或首选尺寸,也没有首选的比例。它将自适应于对应元素的尺寸。
步骤1:第二个圆
添加第二个圆 置于第一个圆 的底层,它的样式是从左到右的径向渐变,通过 linear-gradient 即可实现。
<div class="logo">
<div class="cycle cycle_1"></div>
<div class="cycle cycle_2"></div>
</div>
.cycle_2 {
margin-left: -160px;
background: linear-gradient(to right, var(--red), var(--blue));
border: 12px solid var(--black);
}
.cycle_2::after {
content: '';
display: inline-block;
height: 200px;
width: 200px;
background: var(--black);
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
border-radius: 50%;
z-index: 3;
}

步骤2:两个圆的重叠部分
底部重叠部分,使用 clip-path 裁切出一个半圆效果,置于所有最顶层。
.cycle_2::before {
position: absolute;
box-sizing: border-box;
top: -12px;
left: -12px;
content: '';
display: inline-block;
height: 500px;
width: 500px;
background: var(--red);
border-radius: 50%;
-webkit-clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0 100%);
clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0 100%);
z-index: 3;
border: 12px solid var(--black);
}

clip-path
clip-path 使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏。
语法:
// 关键字 值
// none
clip-path: none;
// <clip-source> 值
clip-path: url(resources.svg#c1);
// <geometry-box> 值
clip-path: margin-box;
clip-path: border-box;
clip-path: padding-box;
clip-path: content-box;
clip-path: fill-box;
clip-path: stroke-box;
clip-path: view-box;
// <basic-shape> 值
clip-path: inset(100px 50px);
clip-path: circle(50px at 0 100px);
clip-path: ellipse(50px 60px at 0 10% 20%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: path('M0.5,1 C0.5,1,0,0.7,0,0.3 A0.25,0.25,1,1,1,0.5,0.3 A0.25,0.25,1,1,1,1,0.3 C1,0.7,0.5,1,0.5,1 Z');
// 盒模型和形状值结合
clip-path: padding-box circle(50px at 0 100px);
// 全局值
clip-path: inherit;
clip-path: initial;
clip-path: revert;
clip-path: revert-layer;
clip-path: unset;
<clip-source>:用url()引用SVG的<clipPath>元素<basic-shape>:一种形状,其大小和位置由<geometry-box>的值定义。如果没有指定<geometry-box>,则将使用border-box用为参考框。取值可为以下值中的任意一个:inset():定义一个inset矩形。circle():定义一个圆形,使用一个半径和一个圆心位置。ellipse():定义一个椭圆,使用两个半径和一个圆心位置。polygon():定义一个多边形,使用一个SVG填充规则和一组顶点。path():定义一个任意形状,使用一个可选的SVG填充规则和一个SVG路径定义。
<geometry-box>:如果同<basic-shape>一起声明,它将为基本形状提供相应的参考框盒。通过自定义,它将利用确定的盒子边缘包括任何形状边角(如被border-radius定义的剪切路径)。几何框盒的可选值:margin-box:margin box作为引用框。border-box:border box作为引用框。padding-box:padding box作为引用框。content-box:content box作为引用框。fill-box:利用对象边界框object bounding box作为引用框。stroke-box:使用笔触边界框stroke bounding box作为引用框。view-box:使用最近的SVG视口viewport作为引用框。如果viewBox属性被指定来为元素创建SVG视口,引用框将会被定位在坐标系的原点,引用框位于由viewBox属性建立的坐标系的原点,引用框的尺寸用来设置viewBox属性的宽高值。
none:不创建剪切路径。
步骤3:重叠部分优化
将重叠部分设置为与第二个圆 相同的渐变色,可以产生由第一圆 过渡为第二圆 的错觉。
.cycle_2::before {
background: linear-gradient(to right, var(--red), var(--blue));
}

步骤4:文字
Logo 文字是从左到右由蓝到红的渐变效果,可以通过将文字的盒背景设置为渐变色,然后通过 background-clip: text 将背景被裁剪成文字的前景色来实现。
<h1 class="text">声生不息</h1>
.text {
background: linear-gradient(to right, var(--blue), var(--red));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
font-style: italic;
}

background-clip
background-clip 设置元素的背景图片或颜色是否延伸到边框、内边距盒子、内容盒子下面。如果没有设置background-image 或 background-color,那么这个属性只有在 border 被设置为非 soild、透明或半透明时才能看到视觉效果,否则本属性产生的样式变化会被边框覆盖。
语法:
// 关键字 值
background-clip: border-box;
background-clip: padding-box;
background-clip: content-box;
background-clip: text;
// 全局值
background-clip: inherit;
background-clip: initial;
background-clip: unset;
border-box:背景延伸至边框外沿,但是在边框下层。padding-box:背景延伸至内边距padding外沿。不会绘制到边框处。content-box:背景被裁剪至内容区content box外沿。text:背景被裁剪成文字的前景色(实验性属性)。
步骤5:点击切换效果
点击右上角的的半圆形图案 ⌒,可以实现将 Logo 从彩色切换为纯白色,该功能是通过切换定义在 :root 下的 CSS变量 值实现的,可以通过以下方法实现 CSS变量 值的切换。
<span class="toggle" id="toggle" title="点击切换颜色"></span>
半圆形图案 ⌒ 的噪点背景效果是通过添加一张噪点图实现。
.toggle {
background: linear-gradient(to left bottom, var(--blue), rgba(0, 0, 0, 0)), url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAAADFBMVEUvLy9eXl6AgICoqKhWH7o7AAAABHRSTlMSEhIS3WyPCwAAA1hJREFUOMsN0M3rDHEcwPH3d3y/4zcr67s1s3bIU62y8nBxcVCf79pZ4WBWsx6TVbvyEKUolJrxmBTj4SecVqE4OTjgIP6D5eC8DkouOJAj19fxhXJCWn811mk1Sp1q0J0q6AoNF7ZQ0uD+74CBj3otoUUEmJc0wqVEr2Ulatp1/6HYA9SGwfn+s6ftD8zsbic1idsPVrfcoQRYSrvbd7PdA7TY6cKcbfrwRXaJaqgTXSfDKd625S7XGB1YraJ0yuatOJmJvf5aqIwYINvBGIr+gZiDl80Qdoh3M1GTfuCzf1+yEetme3loJ3Hf6yijG5S9rRa7XI7Nzu1AYGF5Bd1cNeplTmN8yJpV8kYrpKEIAzXDgbBK2QhhTb37NP4P1aqRZ3ua6DVLb2AKjVpgBkbHie4QGFVqxDcpgL4tlTUMNKKgazpmWC+CkBBkTu59dpl+XikMg+U5izd/9z+KpxcFYvxxs01Vtho32XLZBNRmy8YWQBszOV6ES9r7cvQdshRbKVdfOrDKeyB+MeXsWvMmI95/Pdsp7J5MydZHR9MonithyhIllnSppjGaQRkb7vVyTaqNhLUsVI5I/HEDi3JYWdu+KEgsmkzJXGPZ97wQyqPREfp+vmAvzo3AfhF9HvZS1SiZL9H4pVgfhmofCltJ3wxq9/961Aaqq3HpzsFroqtPe9SVm3Ol5yd3f99TueB46l+9lB/drm4PxXs/4j4j5k6pAzS88njnDp72JijRYlYFRMaxfY8q20pWZjGLdKsCP2YoVYXl9RK1Kp7Xpx8MLYEe+gIWlUDwJNABR0AVAGQ4rfcCrci5YQYZonhi9ckLVrkTeCTeL5+0H7+Lw1baYjGu+6ddepc6qeLc8EhvL3dvf5Xi9maHyrGnCmFXXo7bk83O3C6FFYVDURtfLD4YVUpO011EfYvktpukxpKogevhPViJPC6tmWnOcxkaJYnwOw2zyoYKeAmKIlfpILLxBmOo3yLlkzh5+yTKmkvtrsc3oP8Tx7t8YTms2Be9a0TJNJ21Gb6k5mwY9Vn/P2vRSHu7tiZ2kx6mrMtCoqPG+9w3YWxOw5EZDcszz+tUQhZlq8j8Rw77ynqzi7XaV3kH8x62ScfWdhZpkgX3wWdZcibtbFASgOEfZmfZzbdc/O0AAAAASUVORK5CYII=');
}
// 获取根元素
const root = document.querySelector(':root');
// 创建获取变量值的函数
const getCssVariable = (key) => {
return getComputedStyle(root).getPropertyValue(key);
}
// 创建设置变量值的函数
const setCssVariable = (key, value) => {
root.style.setProperty(key, value);
}
// 点击切换CSS变量值
document.getElementById('toggle').addEventListener('click', () => {
if (getCssVariable('--blue') === '#FFFFFF') {
setCssVariable('--blue', '#0A68DF');
setCssVariable('--red', '#F66036');
} else {
setCssVariable('--blue', '#FFFFFF');
setCssVariable('--red', '#FFFFFF');
}
}, false);
Window.getComputedStyle()
Window.getComputedStyle() 方法返回一个对象,该对象在应用 active 样式表并解析这些值可能包含的任何基本计算后,返回元素的所有 CSS 属性的值。
语法:
let style = window.getComputedStyle(element, [pseudoElt]);
- 参数:
element:用于获取计算样式的Element。pseudoElt:可选,指定一个要匹配的伪元素的字符串。必须对普通元素省略或null。
- 返回值:返回的
style是一个实时的CSSStyleDeclaration对象,当元素的样式更改时,它会自动更新。
getComputedStyle可以从伪元素拉取样式信息,如::after,::before,::marker,::line-marker。
CSSStyleDeclaration.getPropertyValue()
CSSStyleDeclaration.getPropertyValue() 接口返回一个 DOMString ,其中包含请求的 CSS 属性的值。
语法:
var value = style.getPropertyValue(property);
- 参数:
property是一个DOMString,是需要查询的CSS属性名称。 - 返回值:
value是DOMString,包含查找属性的值。若对应属性没有设置,则返回空字符串。

步骤6:噪点背景
仔细观察的话,页面背景并不是单纯的黑色,而是会有轻微的类似电视机 雪花 的噪点效果,通过以下样式即可实现噪点效果。
<div class="bg"></div>
背景是一张噪点图片,设置背景时将 background-repeat 设置为 repeat 并添加通过translate 实现位移的动画实现噪点晃动效果。
.bg {
position: fixed;
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
width: 200%;
height: 200vh;
background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAAADFBMVEUvLy9eXl6AgICoqKhWH7o7AAAABHRSTlMSEhIS3WyPCwAAA1hJREFUOMsN0M3rDHEcwPH3d3y/4zcr67s1s3bIU62y8nBxcVCf79pZ4WBWsx6TVbvyEKUolJrxmBTj4SecVqE4OTjgIP6D5eC8DkouOJAj19fxhXJCWn811mk1Sp1q0J0q6AoNF7ZQ0uD+74CBj3otoUUEmJc0wqVEr2Ulatp1/6HYA9SGwfn+s6ftD8zsbic1idsPVrfcoQRYSrvbd7PdA7TY6cKcbfrwRXaJaqgTXSfDKd625S7XGB1YraJ0yuatOJmJvf5aqIwYINvBGIr+gZiDl80Qdoh3M1GTfuCzf1+yEetme3loJ3Hf6yijG5S9rRa7XI7Nzu1AYGF5Bd1cNeplTmN8yJpV8kYrpKEIAzXDgbBK2QhhTb37NP4P1aqRZ3ua6DVLb2AKjVpgBkbHie4QGFVqxDcpgL4tlTUMNKKgazpmWC+CkBBkTu59dpl+XikMg+U5izd/9z+KpxcFYvxxs01Vtho32XLZBNRmy8YWQBszOV6ES9r7cvQdshRbKVdfOrDKeyB+MeXsWvMmI95/Pdsp7J5MydZHR9MonithyhIllnSppjGaQRkb7vVyTaqNhLUsVI5I/HEDi3JYWdu+KEgsmkzJXGPZ97wQyqPREfp+vmAvzo3AfhF9HvZS1SiZL9H4pVgfhmofCltJ3wxq9/961Aaqq3HpzsFroqtPe9SVm3Ol5yd3f99TueB46l+9lB/drm4PxXs/4j4j5k6pAzS88njnDp72JijRYlYFRMaxfY8q20pWZjGLdKsCP2YoVYXl9RK1Kp7Xpx8MLYEe+gIWlUDwJNABR0AVAGQ4rfcCrci5YQYZonhi9ckLVrkTeCTeL5+0H7+Lw1baYjGu+6ddepc6qeLc8EhvL3dvf5Xi9maHyrGnCmFXXo7bk83O3C6FFYVDURtfLD4YVUpO011EfYvktpukxpKogevhPViJPC6tmWnOcxkaJYnwOw2zyoYKeAmKIlfpILLxBmOo3yLlkzh5+yTKmkvtrsc3oP8Tx7t8YTms2Be9a0TJNJ21Gb6k5mwY9Vn/P2vRSHu7tiZ2kx6mrMtCoqPG+9w3YWxOw5EZDcszz+tUQhZlq8j8Rw77ynqzi7XaV3kH8x62ScfWdhZpkgX3wWdZcibtbFASgOEfZmfZzbdc/O0AAAAASUVORK5CYII=') repeat 0 0;
background-repeat: repeat;
animation: bg-animation .2s infinite;
}
@keyframes bg-animation {
0% { transform: translate(0,0) }
10% { transform: translate(-5%,-5%) }
// ...
100% { transform: translate(5%,0) }
}
总结
本文包含的知识点主要包括:
repeating-linear-gradient条纹背景clip-path形状裁切background-clip设置元素的背景延伸Window.getComputedStyle()获取计算后元素的所有CSS属性的值CSSStyleDeclaration.getPropertyValue()获取请求的CSS属性的值
想了解其他前端知识或
WEB 3D开发技术相关知识,可阅读我往期文章。转载请注明原文地址和作者。如果觉得文章对你有帮助,不要忘了一键三连哦 。
附录
- [1]. 前端实现很哇塞的浏览器端扫码功能
- [2]. 前端瓦片地图加载之塞尔达传说旷野之息
- [3]. 仅用CSS几步实现赛博朋克2077风格视觉效果
...
- [1]. Three.js 实现3D开放世界小游戏:阿狸的多元宇宙
- [2]. Three.js 火焰效果实现艾尔登法环动态logo
- [3]. Three.js 实现2022冬奥主题3D趣味页面,含冰墩墩
...
参考
- https://developer.mozilla.org/zh-CN/docs/Web/CSS/gradient/repeating-linear-gradient
- https://developer.mozilla.org/zh-CN/docs/Web/CSS/clip-path
- https://developer.mozilla.org/zh-CN/docs/Web/CSS/background-clip
- https://developer.mozilla.org/zh-CN/docs/Web/API/Window/getComputedStyle
- https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration/getPropertyValue
作者:dragonir 本文地址:https://www.cnblogs.com/dragonir/p/16265984.html
使用CSS实现《声生不息》节目Logo的更多相关文章
- 纯css实现扁平化360卫士logo demo
前几天在w3ctech上看到有人用纯css写出了360卫士的logo,感觉蛮好玩的. 因为自己用css以来,还没有写过这种玩意,出于娱乐,我也来试着尝试一下. 开始也不知到怎么下手,最棘手的是那两个像 ...
- 43.纯 CSS 绘制一个充满动感的 Vue logo
原文地址:https://segmentfault.com/a/1190000015177284 感想: 又有点回到boder的三角形 HTML code: <div class="v ...
- 如何用纯 CSS 绘制一个充满动感的 Vue logo
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/zaqKPx 可交互视频教 ...
- 前端每日实战:43# 视频演示如何用纯 CSS 绘制一个充满动感的 Vue logo
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/zaqKPx 可交互视频教程 此视频 ...
- CSS常见技巧
一.CSS Sprite(雪碧图|精灵图)指什么? 有什么作用? CSS雪碧 即CSS Sprite,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法是将小图像和背景图片合并到一张图片上,然后利 ...
- 网站logo正确写法,个人拙见,不喜勿喷
网站logo既要考虑seo又需要用图片代替网站名字,所有H1标签带来的权重还是需要使用 有些人喜欢直接把<H1></H1>标签直接hidden掉,个人喜欢使用css Text- ...
- CSS应用心得
单纯Html配合CSS网页 下面用程序来实际总结一下 首先,在写程序的应该具有一个良好的编程习惯. 第一:排版,拥有一个良好的排版,有助于我们能够快速的理解以及阅读程序: 第二:注释,就如以下程序,作 ...
- 160907、CSS 预处理器-Less
CSS 预处理器是什么?一般来说,它们基于 CSS 扩展了一套属于自己的 DSL,来解决我们书写 CSS 时难以解决的问题: 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器: ...
- web的各种前端打印方法之CSS控制网页打印样式
来源:http://www.jb51.net/web/70358.html CSS控制网页打印样式: 使用CSS控制打印样式,握刚刚使用时一塌糊涂,根本不知道CSS中的midia的作用是什么,问到别人 ...
随机推荐
- 你对 Spring Boot 有什么了解?
事实上,随着新功能的增加,弹簧变得越来越复杂.如果必须启动新的 spring 项 目,则必须添加构建路径或添加 maven 依赖项,配置应用程序服务器,添加 spring 配置.所以一切都必须从头开始 ...
- Atomic 的实现原理
1.直接操作内存,使用Unsafe 这个类 2.使用 getIntVolatile(var1, var2) 获取线程间共享的变量 3.采用CAS的尝试机制(核心所在),代码如下: public fin ...
- 使用salt-cloud创建openstack虚拟机
salt-cloud也是基于openstack来做的,它可以支持多种云的使用.比如:Aliyun.Azure.DigitalOcean.EC2.Google Compute Engine.HP Clo ...
- AGENS算法
3.2 层次方法 下图,上面是从左到右由5个簇逐渐合并成1个簇的过程,下面是从右到左由一个簇逐渐分裂成5个簇的过程 AGENS算法 最后面一句话是重点,假设有<A,B>,<C,D&g ...
- Azure DevOps 中 Dapr项目自动部署流程实践
注:本文中主要讨论 .NET6.0项目在 k8s 中运行的 Dapr 的持续集成流程, 但实际上不是Dapr的项目部署到K8s也是相同流程,只是k8s的yaml配置文件有所不同 流程选择 基于 Dap ...
- 探讨:微信小程序应该如何设计
微信小程序公测后,开发者非常热情,都有很高的期待,都想抓住这一波红利.但是热情背后需要冷静,我们需要搞清楚两个问题: 微信想要我们做什么?微信小程序可以做什么? 微信想要我们做什么? 首先来弄清楚微信 ...
- 浏览器视图层级中的“根”:<html>和<body>的属性研究
做前端开发的同学都会知道,每一个UI系统(比如IOS或Android)中都会有一个view hierarchy(视图层级)的概念,即所有的可视元素(大到一个页面,小到一个button)都在一个树形结构 ...
- JavaScript作用域链与闭包的理解
作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域 链的工作原理. 1. 全局作用域(Global Scope) (1)最外层函数和 ...
- 将对象push到数组中组成对象数组
let items = { key:'', value:'' } for(let i = 0;i<len;i++){ items.value = _this.ills[i].sName; ite ...
- 模拟FCFS调度算法(先来先服务)
文章目录 一.FCFS的介绍 二.代码演示 三.代码分析 1.使用节点模拟进程 2.SimulateFCFS(核心模拟FCFS类) 3.创建一个节点为n的队列(模拟就绪队列) 4.核心计算分析 5.输 ...