Recreating the “声生不息” Logo Using Pure CSS with Gradient, Clip‑Path, and Variable‑Based Color Switching
This article demonstrates how to recreate the “声生不息” program logo using only native CSS and a small amount of JavaScript, covering gradient stripes, clip‑path shaping, background‑clip text effects, CSS variables for color toggling, and detailed code snippets for each implementation step.
Background
The TV show "声生不息" is a music competition produced by Mango TV, Hong Kong TVB, and Hunan TV. Its logo uses a classic red‑blue color scheme with an infinity symbol, giving a strong sense of design.
This tutorial reproduces the logo using only native CSS , demonstrating many techniques such as repeating-linear-gradient , clip-path , background-clip , Window.getComputedStyle() , and CSSStyleDeclaration.getPropertyValue() .
Result
First, see the effect of the implementation.
Click the semi‑circular shape at the top‑right corner to switch the page theme to white.
Online preview:
👁🗨 Github: https://dragonir.github.io/shengshengbuxi/ 👁🗨 Codepen: https://codepen.io/dragonir/full/OJQRBad
Implementation
Before starting, define the main colors used in the logo as CSS variables, which will be reused for color switching.
:root {
--black: #010101;
--red: #F66034;
--blue: #0A68DF;
}Step 0: First Circle 🔴
The first circle is a pure red stripe created with repeating-linear-gradient and a pseudo‑element ::after for the black ring.
<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 creates an image composed of repeated linear gradients. It works like linear-gradient but repeats the pattern to fill the entire container.
Syntax:
repeating-linear-gradient([ <angle> | to <side-or-corner> ,]? <color-stop> [, <color-stop>]+ )<side-or-corner> defines the start point of the gradient line (e.g., to top , to right ).
<angle> specifies the direction in degrees, increasing clockwise.
<color-stop> is a color value optionally followed by a position.
Examples:
// 45° repeating linear gradient from blue to red
repeating-linear-gradient(45deg, blue, red);
// Vertical repeating gradient: blue → green at 40% → red
repeating-linear-gradient(0deg, blue, green 40%, red);Each repetition’s color‑stop offset is a multiple of the base gradient length, so the final stop should match the first to avoid abrupt changes.
Step 1: Second Circle 🔵
Add a second circle beneath the first, using a left‑to‑right 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;
}Step 2: Overlapping Area 🔴🔵
Use clip-path to cut a semi‑circle from the second circle and place it on top.
.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 defines a visible region for an element; everything outside is hidden.
Syntax:
clip-path: none;
clip-path: url(resources.svg#c1);
clip-path: margin-box;
clip-path: inset(100px 50px);
clip-path: circle(50px at 0 100px);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);inset() defines a rectangular clipping area.
circle() defines a circular clipping area.
ellipse() defines an elliptical clipping area.
polygon() defines a polygonal clipping area.
path() defines an arbitrary SVG path.
Step 3: Overlap Optimization 🔴🔵
Set the overlapping part to the same gradient as the second circle, creating the illusion of a smooth transition.
.cycle_2::before {
background: linear-gradient(to right, var(--red), var(--blue));
}Step 4: Text 🅰
The logo text uses a left‑to‑right gradient and background-clip: text to show the gradient inside the letters.
<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 controls how far a background extends (border‑box, padding‑box, content‑box, or text).
Syntax:
background-clip: border-box;
background-clip: padding-box;
background-clip: content-box;
background-clip: text;Step 5: Click‑to‑Toggle Effect 🔲
Click the semi‑circular toggle element to switch the logo from colorful to pure white by changing the CSS variable values defined in :root .
<span class="toggle" id="toggle" title="点击切换颜色"></span>The toggle’s background includes a noise image for a TV‑static effect.
.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=') 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); }
}JavaScript toggles the CSS variables:
const root = document.querySelector(':root');
const getCssVariable = (key) => getComputedStyle(root).getPropertyValue(key);
const setCssVariable = (key, value) => { root.style.setProperty(key, value); };
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() returns a CSSStyleDeclaration object containing the computed values of all CSS properties for an element.
let style = window.getComputedStyle(element, [pseudoElt]);💡 CSSStyleDeclaration.getPropertyValue()
Retrieves the value of a specific CSS property from a CSSStyleDeclaration object.
var value = style.getPropertyValue(property);Summary
The article covered the following key points:
repeating-linear-gradient for striped backgrounds
clip-path for shape clipping
background-clip for extending backgrounds to text
Window.getComputedStyle() for obtaining computed CSS values
CSSStyleDeclaration.getPropertyValue() for reading specific property values
For more front‑end knowledge or Web 3D development topics, check my previous articles. Please credit the original source and author if you repost, and don’t forget to give a “three‑click” like 👍.
Appendix
[1] 📷 Front‑end implementation of a cool browser‑side QR code scanner
[2] 🌏 Front‑end tile map loading – Zelda: Breath of the Wild
[3] 🆒 CSS‑only cyber‑punk 2077 visual effect
3D References
[1] 🦊 Three.js – 3D open‑world mini‑game: Ali’s Multiverse
[2] 🔥 Three.js – Elden Ring dynamic logo flame effect
[3] 🐼 Three.js – 2022 Winter Olympics themed 3D page with Bing Dwen‑Dwen
References
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
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.