Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

The Making (and Potential Benefits) of a CSS Font


Not a typical one, at least. Each Character is an HTML element, built with CSS. A true web font!

Let me elaborate. This is a way to render text without using any font at all. Random text is split with PHP into words and letters, then rendered as HTML Elements with classes. Every element is styled with CSS to create the characters. This is “just” HTML controlled with CSS, but still, it is software and it gets the message through. It has all the properties a conventional font does, so we’ll call it a font. A font without a format.

Disclaimer: I’m not an expert in HTML, CSS, or PHP. I’m willing to bet there is a shortcut or an easier solution to achieve what I’ve done here, but since I’m happy with the results, I will present the process and my experience. The presentation is not a tutorial; it is an experiment based on my limited skills and should be treated as such.

The idea

The project was never meant to last for five months, but that’s what it took! It all started with having a play with a CSS icon, using pseudo-elements to make shapes. Once the first S letter was finished, the rest were relatively easy. I checked to see if there were other similar projects but didn’t find much, so I was motivated to see how far I could get.

Initially, an SVG font controlled with CSS seemed like a good idea. It would make this task much easier (SVG is made for drawing) and could focus on design-specific effects, but it doesn’t have the flexibility of a raw HTML element. An SVG cannot be modified depending on context, and the process falls back to the conventional font design, where every character has a fixed shape and code.

How it works

This is a hybrid of web and font design. Each character is built like any web element and used inline to behave like a font. Metrics, Weights, OpenType Features and all the other font properties are controlled exclusively with the CSS file.

The font design is based on the border width of the elements, which makes it extremely versatile. With the exemption of script fonts, several styles and weights can result just from border variations, using the same shape. On more complex characters the clip-path and the background is used to create the cutout effect.

Nested elements are generated when the ::before and ::after pseudo-element is not enough to form a character. Using em values for width, height and border widths will help later in controlling the font size. This is one of the golden rules.

A character (left) is built like any CSS icon (right). There are no major differences. Sometimes a letter is easier to build, just like a stickman, based on circles and lines. But here is when you can really appreciate the role of the border-radius property. Personally, I never was a fan of rounded borders, but this experience changed my mind. Basically, there’s no limit for what a radius can do.

Below are the only two “real” examples of the CSS font in this article, the rest of the example figures are converted to SVG for easier display in a blog post.

1. Gray – main shape
2. Red – pseudo elements
3. Blue – Extra element
Most of the times you have to insist for the desired effect, but in the end you want to carry this icon in your wallet. Icon created with a single shape, the pseudo-element is used only to avoid the rotation of the main element, in case it is used inline.

The serif preview presents a more complex situation, but as usual, a sans font will have fewer elements to deal with, making the file is smaller and load faster. This is not really an issue and it’s only logical — the CSS is read before a font embedded with the @font-face rule.

The challenge

Naive start, putting all the math and the logic to use. None of the values work if a pixel decides so. The final solution in this case was to include a second parent that will keep the “children” tidy.

The hardest part is to beat the pixel ratio, or align the pseudo elements to the base shape. Elaborated mathematical formulas failed when the charater was resized. A browser will treat each element separately and shift them to the closest integer value.

A solution to this was to create as many pseudo-elements as possible (even including extra elements), and use a single reference for a pair of ::before and ::after, not related to the main shape. In this case, the browser will render the elements more or less to the same position.

A character without a point of reference is illustrated with the S letter below. The top and bottom section of the letter are two pseudo elements, without a base shape to rely on (e.g. the gray area in the serif above or here in the digit two).

After creating a few hundred characters, you realize that a character cannot support inline transformation (i.e. skew(), rotate(), and such) because it won’t align to siblings. This becomes more obvious visually on text selection. Because of that, a pseudo-element makes perfect sense. I would say essential: the second golden rule.

The graphic shows the basic principle of construction. When apertures cannot be controlled simply with the {border: 0;} rule, clip-path is used.
In this case, the S letter needs a smaller aperture, so the border eventually is kept and cut at the desired distance with clip-path.

CSS custom properties

It seems easier to create a style in CSS than it is in font softwares. You have the option to control shapes and sizes for multiple characters at once. In CSS, more characters are grouped together in the same ruleset.

CSS custom properties are extremely handy in this situation, especially for controlling borders, widths, and positions. The different weights are the result of changes in the variable, with adjustments afterwards. Fine tuning is unavoidable because character shapes and sizes take the border width into account and may not display proportionally with different borders, especially on asymmetrical shapes.

Cutout effect created by adding the same background color to the overlaying element. Combination of colors and effects using the mix-blend-mode.

The cutout effect is created by adding the same background color to the overlaying element, then using a combination of colors and effects using mix-blend-mode.

A global color variable is required in CSS to create a cutout effect for nested elements that otherwise would follow the parent color (overlaying elements match the background).

The background-image property won’t work on characters built exclusively with borders and the background is changed if the element has size or position transformations (scale, rotate, or other).

Where a background cannot be used, the solution is mix-blend-mode: lighten; on dark backgrounds and mix-blend-mode: darken; on light backgrounds.

Side effects

The downside is that some effects can have unexpected or even opposite results on elements with variable properties. Usually, a filter will read elements as full objects. To prevent any conflict, borders and transformation effects are reserved for the font design.

Font to text

A font won’t make a text. The idea in the first place was to create a text that will load along with the CSS, without any dependencies. For that the best option is PHP (my rookie opinion). Besides rendering HTML with inline functions, it is up to almost any task imaginable. Without PHP this project would not be possible.

Naturally, the first task with PHP was to split a random text, remove extra spaces and create matching groups for every word and letter, each one with its own class. So far, so good. I won’t insist on the part that went smoothly, it is a basic function, using split, explode and all the other words borrowed from a video game.

Still, since I never worked on this before, I had to learn the hard way. Nobody told me that PHP considers the “0” (zero) as null, so there’s a day gone. I couldn’t figure out why my zeros are not displayed.

For anyone with this issue maybe it’s helpful. Instead of using the empty() function, I used the one below:

function is_blank( $value ) {  
  return empty( $value ) && !is_numeric( $value );
}

The other major issue was the character range. It seems that there are way too many settings in HTML, the .htaccess file, and on the server itself just to recognize special characters. The solution was found after a few days in the PHP Documentation, posted by qeremy [atta] gmail [dotta] com, obviously somebody living in a diacritic-heavy area.

function str_split_unicode( $str, $length = 1 ) {
  $tmp = preg_split( '~~u', $str, -1, PREG_SPLIT_NO_EMPTY );
  if ( $length > 1 ) {
    $chunks = array_chunk( $tmp, $length );
    foreach ( $chunks as $i => $chunk ) {
        $chunks[$i] = join( '', ( array ) $chunk );
    }
    $tmp = $chunks;
  }
  return $tmp;
}

A lot of chunks, if you ask me, but it works like a charm and solves every issue. The function basically overlooks the language settings and will read any character, even the non-standard ones. Characters buried deep in the Unicode tables will be recognized if the PHP function includes that character.

This function will only create the possibility to generate each character as typed, without the need for HTML entities. This option won’t limit the use of text in HTML format, but inline codes must be avoided or replaced with alternatives. For example, instead of using non-breaking spaces ( ), elements can be wrapped in the tag.

The HTML entities are not decoded, which is an advantage from my point of view.
Default system font on the left. On the right is CSS text rendered without any changes.

Structure

With this solved, the next step is to create a specific structure for each character. The class of the HTML elements and the positions of the nested element depends on a long list of characters that correspond with one or more classes. Some of the most basic characters are not excluded from this list (e.g. the small “a” letter needs a finial and that means an extra element/class).

The basic structure looks something like this, just to get the idea …

'Ć' => 'Cacute C acute'

…which will render three elements: the parent Cacute, the C letter, and the acute accent.The result is below, where the red square represents the parent element, containing the other two preset elements.

Cacute — a classic combination between a basic letter and an accent.

The technique is very similar to the way diacritics (sometimes ligatures) are built in font software, based on pairings. When a component element is changed, every other will adjust.

Because any element can have multiple applications, the IDs are avoided and only classes are used.

OpenType features

The PHP function is set to behave differently depending on context. The character recognition is set to replace pairings and create ligatures when rendering the CSS text.

Contextual ligatures in the CSS text are not standalone characters and don’t have specific classes. Different from conventional OpenType features, the characters are restyled, not replaced. The interaction is controlled in CSS by styling the second element, to merge or form a new character.

The features are activated with a specific class added to the parent container. Alternates are rendered in any circumstance, regardless if a character is registered or not, in every browser, with or without font feature support.



This post first appeared on Nexstair | Creative Website Design And Wordpress T, please read the originial post: here

Share the post

The Making (and Potential Benefits) of a CSS Font

×

Subscribe to Nexstair | Creative Website Design And Wordpress T

Get updates delivered right to your inbox!

Thank you for your subscription

×