Inspired by Rachel Smith's #postAboutYourPen!

Earlier this year I started experimenting with CSS text effects. One of the first pens I created was the editable fractured text effect.

What I love about this example is that it makes use of all the base techniques which can be used to form the foundation of many other text effects. So let's look at how it's created.

First we set up our HTML element, in our case a h1 and we add a data-attribute. These are custom attributes that allow information to be exchanged between the HTML and the DOM. In our case it will also allow us to share the content of our element with our CSS.

For most effects, and in this case we want the text in our data-attribute to be the same as the text in our h1. Using a data-attribute instead of duplicating our markup results in cleaner HTML which is easier to maintain and more accessible. 🙌

      <h1 data-heading="Fracture">Fracture</h1>

Next up we need to set up our CSS. (There is a bunch of CSS at the bottom for positioning that isn't super relevant to the effect so you can ignore that.) Let's focus on the text itself.

First we need to setup a CSS pseudo-element, this combined with our data-attribute is going to give us the layers we need for our text effects. We have access to two pseudo-elements per HTML element, the ::before and the ::after. Combine this with the base element (in our case the h1) we now have three layers to work with. You wont always need the three layers, but it's nice to know your options.

The most important step here is telling the pseudo-elements to use the data from the data-attribute on our h1. We do this in our CSS by passing the value of the data-attribute into the content property of the pseudo-element

Instead of hard coding a string, or leaving it blank we need to specify the name of the data-attribute. e.g. content: attr(data-heading); This will create a new layer with the same text as our h1.

Importantly, to ensure they are layered over the top of each other we'll add position: absolute on the pseudo-elements and include left: 0;.

The CSS will look something like this:

      h1::after {
        content: attr(data-heading);
        position: absolute;
        left: 0;
    }

Now we have it all set up let's get to the fun part where we actually start to make the effect. The way this works is really cool, essentially we mask the top half of the h1 with the top half of the ::before. This is achieved by setting the text colour to the same value as the background.

As the bottom colour of our text is black and our background is white we'll set the text colour of the ::before to white, making it appear as though the top half of the text was never there!

You may be able to see a slight black outline behind the white, the way I dealt with this was adding a text-shadow to hide it. This doesn't always happen but if you can use it text-shadow is a good way to get around the issue.

The CSS will look something like this:

  h1::before {
    content: attr(data-heading);
    position: absolute;
    left: 0;
    overflow: hidden;
    height: 50%;
    color: white;
    text-shadow: 3px -2px 5px white, -3px 3px 4px white;
}

So once we have our base we want to create the top mis-aligned layer using the ::after pseudo-element . It will include the same base properties and values we set for the ::before pseudo-element specifically the content, position, left and overflow properties.

However, with this layer we need to hide the bottom half of the text so we'll add a height (I went with 49%) and add overflow: hidden;. Finally we add a negative X offset with a translateX on the transform property to offset the top layer.

  h1::after {
    content: attr(data-heading);
    position: absolute;
    left: 0;
    overflow: hidden;
    transform: translateX(-10px);
    height: 49%;
    color: black;
}

All together it looks like this:

As you can see in the example above my demo is animated this is done by adding in a simple keyframe animation.

   .animated:after {
    transform: translateX(0);
    animation: fracture 5s infinite ease;
 }

 @keyframes fracture {
    0% {transform: translateX(0);}
    50% {transform: translateX(-20px);}
 }

What I love about this is that we aren't really using anything fancy or complicated and it's got pretty amazing browser support. We get new shiny things every day, sometimes it pays to see what we already have in our tool belt.

Of course, if you want something a little fancier for your fractured text you can look at using something like clip-path to create the same thing, but on an angle.

If you are interested in other cool text effects you can explore my collection here: https://codepen.io/collection/DamKJW (Note: some are a little broken while I work out font trial issues).

Enjoy! ☺️


6,713 1 105