DEV Community

Cover image for The RGB split effect with css and a bit of javascript
John Kapantzakis
John Kapantzakis

Posted on

19 7

The RGB split effect with css and a bit of javascript

While developing my personal website, I came accross this amazing library, Blotter.js, which exposes several methods (materials) that apply various effect on texts.

ChannelSplitMaterial is one of those effects that piqued my interest.

The idea behind this effect is simple, just split up the red, green and blue pixels and place them in different location from the original one. And that's just what we are going to do!

But first, lets see what the final result looks like

Lets start with the HTML

<div id="wrapper">
<div id="text" class="channel-split-wrapper">
RGB
</div>
</div>
view raw index.html hosted with ❤ by GitHub

The #wrapper element just holds the affected element, the #text div. The #text div holds the text that we are going to apply the RGB effect to.

Now, we need to create a function that takes one argument, the HTML element to be affected. Lets call this function channelSplit. channelSplit will take the innerHTML of the element passed as the first argument and clone it 3 times, one for each primary color (red, green and blue).

function channelSplit(elem) {
if (elem) {
const inner = elem.innerHTML;
elem.innerHTML = "";
const spanHidden = document.createElement("span");
spanHidden.classList.add("channel-split-static");
spanHidden.innerHTML = inner;
elem.appendChild(spanHidden);
["red", "green", "blue"].forEach(x => {
const span = document.createElement("span");
span.classList.add("channel-split");
span.classList.add(`channel-split-${x}`);
span.innerHTML = inner;
elem.appendChild(span);
});
}
}
view raw main.js hosted with ❤ by GitHub

As you can see, we are placing a .channel-split-static span inside the initial element. .channel-split-static has zero opacity and its use is to preserve the initial dimentions of the text holder element.

Summarizing the functionality of the channelSplit function:

  • Takes one argument, the text holder element
  • Clones the innerHTML of the text holder and appends 3 .channel-split elements, one for each primary color (red, green, blue)
  • Places one .channel-split-static span with zero opacity

We are now done with Javascript 😁!

Now, all we have to do is to apply some css in order to achieve the desired effect.

In order to stack each of the three .channel-split elements one above the other, we set their position property value to absolute.

Another important change we need to make, is to set mix-blend-mode: difference to the .channel-split elements in order to blend their colors. If we don't apply this rule, the final result will display the font color of the elemnt stacked on top of all.

Here are the main css rules that help us achieve the rgb split effect

.channel-split-static {
opacity: 0;
}
.channel-split {
position: absolute;
top: 0;
left: 0;
mix-blend-mode: difference;
}
.channel-split-red {
color: #f00;
}
.channel-split-green {
color: #0f0;
}
.channel-split-blue {
color: #00f;
}
view raw style.css hosted with ❤ by GitHub

Finally, we are going to apply some animation in order to separately move each of the .channel-split elements away from each other in order to illustrate the effect.

.channel-split-red {
color: #f00;
animation: ANIMATE-RED 2000ms infinite;
}
.channel-split-green {
color: #0f0;
}
.channel-split-blue {
color: #00f;
animation: ANIMATE-BLUE 2000ms infinite;
}
@keyframes ANIMATE-RED {
0% {
transform: translate(0, 0)
}
50% {
transform: translate(5px, 5px)
}
100% {
transform: translate(0, 0)
}
}
@keyframes ANIMATE-BLUE {
0% {
transform: translate(0, 0)
}
50% {
transform: translate(-5px, -5px)
}
100% {
transform: translate(0, 0)
}
}
view raw style2.css hosted with ❤ by GitHub

And that's it!

Thanks for reading this post and I hope you liked it!

Image of Docusign

Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (4)

Collapse
 
raigo profile image
rudotriton

Great work, a small inconsistency I noticed in the effect on the hero image at the top and your code. The hero image uses mix-blend-mode: screen which means that red, green and blue add up to white, while you use difference which gets a tint based on the background color.

Collapse
 
kinduff profile image
Alejandro AR

Very interesting. Thanks for sharing.

You can skip Javascript if you want to do it with CSS only, you can use before & after pseudo-classes. Check it out here jsfiddle.net/kinduff/r70ve5bd/1/

Collapse
 
kapantzak profile image
John Kapantzakis

Thanks Alejandro! Very interesting approach!

Collapse
 
diegoweissel profile image
Weissel Design • Edited

Hate to break the 21st like but this is awesome, thanks

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs