DEVseo

Making It Your Web

Vertically Split Coloured Text

Please note: This example currently only works in Chrome

That's a hard title to think of. To explain a little further: have you ever required text on the page that needs to be half one colour and half another, vertically? It's not something I've ever had to think about before but when I did the obvious thing that spread to mind was gradients. That makes sense, and sounds quite easy. But then a spanner in the works: "without using gradients" was spoken.

Thinking caps on.

As with most CSS problems I come across, the first thought that came to mind was pseudo-elements. :before and :after are two of the most handy things to come to CSS3. They can be used to make stuff appear that isn't actually there! CSS3 arrows are probably the most widely used of these, but you can also use them to create page curls. In fact just read this post to see what amazing things they bring to web page designs.

So, on to the problem at hand. First things first, here's an example of this in action:

Example Text

And the CSS for this?

.gradient {
	font-family: Arial;
	font-size: 5em;
	line-height: 1em;
	text-align: center;
	background: #CCC;
	-webkit-background-clip: text;
	-moz-background-clip: text;
	background-clip: text;
	color: rgba(0,0,0,0);
	position: relative;
}
.gradient:after {
	background: #C05DA5;
	content: attr(data-text);
	-webkit-background-clip: text;
	-moz-background-clip: text;
	background-clip: text;
	height: 50%;
	left: 0;
	position: absolute;
	top: 5px;
	width: 100%;
	-webkit-transition: all .25s ease;
	   -moz-transition: all .25s ease;
	    -ms-transition: all .25s ease;
	     -o-transition: all .25s ease;
	        transition: all .25s ease;
}

So how did I do this?

As you can see above in the CSS I'm using the :after pseudo-element to basically create a "copy" of the text and set it's height to 50% of the original size so that only half of it shows and then adding a background colour and the background-clip CSS3 property so that the colour only 'bleeds' onto the text. Simple!

You may have noticed that I have added transitions to the :after pseudo-element too. Doing this you can actually animate the height of the second colour by changing the height value. Here's an example that shows this:

Example Text

Unfortunately JavaScript doesn't let you interact with the pseudo-elements themselves so I've had to add a load of classes to the CSS and then change the class of the element to change the height of the :after pseudo-element. Here's the JavaScript I'm using:

$(function()
  {
      var objButton = $(".add10");
      var objButton2 = $(".take10");
      var objButton3 = $(".tonum");
      var objEl = $(".gradient2");
      var intNum = 0;
      objButton.on("click", function()
      {
          intNum = intNum + 10;
          if(intNum > 100)
          {
              intNum = 100;
          }
          objEl.removeClass(function (index, css) {
                return (css.match (/\bstart\S+/g) || []).join(' ');
            }).addClass("start" + intNum);
      });
      objButton2.on("click", function()
      {
          intNum = intNum - 10;
          if(intNum < 0)
          {
              intNum = 0;
          }
          objEl.removeClass(function (index, css) {
                return (css.match (/\bstart\S+/g) || []).join(' ');
            }).addClass("start" + intNum);
      });
      objButton3.on("click", function()
      {
          intNum = $(this).data("to");
          objEl.removeClass(function (index, css) {
                return (css.match (/\bstart\S+/g) || []).join(' ');
            }).addClass("start" + intNum);
      });
  });

Fairly simple stuff. The removeClass function just removes any class that matches start*, which is the class I used in my CSS. This is what I added to the CSS for this to work:

.gradient.start10:after {
	height: 10%;
}
.gradient.start20:after {
	height: 20%;
}
.gradient.start30:after {
	height: 30%;
}
.gradient.start40:after {
	height: 40%;
}
.gradient.start50:after {
	height: 50%;
}
.gradient.start60:after {
	height: 60%;
}
.gradient.start70:after {
	height: 70%;
}
.gradient.start80:after {
	height: 80%;
}
.gradient.start90:after {
	height: 90%;
}
.gradient.start100:after {
	height: 100%;
}

It's certainly not as clean as I would have liked but you might have a better way. If so please comment below!

One final thing I wanted to try was using the :before pseudo-element to see if it was possible to add two colours to the text. It turns out that you can! See below:

Two-Toned

All I added to the CSS was the following:

.gradient:before {
	background: #5090D0;
	content: attr(data-text);
	-webkit-background-clip: text;
	-moz-background-clip: text;
	background-clip: text;
	height: 66%;
	left: 0;
	position: absolute;
	top: 5px;
	width: 100%;
}

Pretty cool stuff.  Here's an example combining the animation with the double colours, just for fun. Have a play and let me know what else you can come up with!

A Few Caveats

For this to work there are a couple of small annoyances that must be fulfilled. Firstly, the element must have a data attribute of "text" that contains the same text as in the element. This is so that the pseudo-elements know which text to overlay and the easiest way is to use the value: attr(data-text), which uses whatever the value of the data attribute 'text' is as the content for the pseudo-element.

Also, line-heights cause a slight problem. Because the line-height changes the position of the text relative to it's own container, you have to change the top value in the CSS to line up the pseudo-element text with the actual text. No big issue, but might get annoying if you want to use this for various pieces of text having various line-heights.

It's also not widely supported. The background-clip property is pretty well supported in modern browsers, but the 'text' value of this property is not. I think this example will only work in later versions of Chrome at the moment.

Comments (be the first)

Add A Comment

Please note: all comments are moderated before they are published on this page.


8bmnsk
Cancel Reply

Loading

Complete!