Let me elaborate. This is a way to render a text without using any font at all. A 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 characters, only this time the result is not an actual font.

Yes, this is just a HTML controlled with CSS, but still, it is a software, 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.

How it Works

CSS Character
1. Main shape;
2. Extra element;
3, 4. Pseudo elements.

This is a hybrid of web and font design, a 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. Using a SVG to build on would make this task much easier, but a SVG doesn't have the flexibility of a raw HTML element, and all the process would fall back to the conventional font design.

The font design is based on the elements border width, which makes it extremely versatile. Excepting 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 (Fig. 01.A.2.) are generated when the ::before and ::after pseudo-element is not enough to form a character.

extra elements

As usual, a sans font will have fewer elements to deal with, the file is smaller and will load faster. This is not really an issue and it's only logical, the CSS is read before a font embedded with the @font rule.

Design First

The idea behind the project is to get the maximum out of the most basic resources, to simplify the setup process if possible and get rid of dependencies, just to make sure that the design is the same on devices with disabled scripts. A script free solution should eliminate annoying flickers on load and render actual characters instead of system alternatives or empty squares.

Function Later

The idea works for situations when the design is more important than the function. Without a solid script support this means giving up on dynamic content.
On digital displays accurate sizes resulted from elaborated mathematical formulas are not always reproduced as expected. Logical values were replaced with optical sizes, but even so, the design relies on the pixel ratio and can hide a few surprizes.

Good and bad points found so far are listed in the .


The font is not created to replace or minimize standard systems and the result is far from a final solution. This is an experiment and should be treated as such. Bugs are mandatory.

Language Support

The CSS font covers European, American and most of the African languages:

  1. Afar
  2. Afrikaans
  3. Albanian
  4. Alsatian
  5. Azeri
  6. Bambara
  7. Bari
  8. Basque
  9. Bislama
  10. Bosnian
  11. Breton
  12. Catalan
  13. Cebuano
  14. Chamorro
  15. Chichewa
  16. Corsican
  17. Croatian
  18. Czech
  19. Danish
  20. Dutch
  21. English
  22. Esperanto
  23. Estonian
  24. Faroese
  25. Fijian
  26. Filipino
  27. Finnish
  28. Flemish
  29. French
  30. Friulian
  31. Gagauz
  32. Galician
  33. German
  34. Greenlandic
  35. Haitian Creole
  36. Hausa
  37. Hawaiian
  38. Hmong
  39. Hungarian
  40. Icelandic
  41. Indonesian
  42. Irish
  43. Italian
  44. Javanese
  45. Khasi
  46. Kiribati
  47. Kirundi
  48. Kurdish
  49. Latin
  50. Latvian
  51. Lombard
  52. Luxembourgish
  53. Machame
  54. Malagasy
  55. Malay
  56. Maltese
  57. Manx
  58. Maori
  59. Moldavian
  60. Norwegian
  61. Papiamento
  62. Piedmontese
  63. Pinyin
  64. Polish
  65. Portuguese
  66. Provençal
  67. Romanian
  68. Romansh
  69. Romany
  70. Rotokas
  71. Sami
  72. Samoan
  73. Sango
  74. Sardinian
  75. Scottish
  76. Sediq Taroko
  77. Serbian Latin
  78. Sesotho
  79. Shona
  80. Slovenian
  81. Soga
  82. Somali
  83. Spanish
  84. Sundanese
  85. Swahili
  86. Swedish
  87. Tagalog
  88. Tatar
  89. Turkish
  90. Türkmen
  91. Welsh
  92. West Frisian
  93. Wolof
  94. Xhosa
  95. Zulu

HTML Syntax

Any HTML element can include the CSS font, as long it has the "css" class, next to the weight of the font. To select a weight, the "thin", "light", "regular" or "bold" class is used, something like <pre class="regular css"> … (the <pre> tag here is just a safety measure, to avoid any style interference).

Available weights: Thin, Light, Regular and Bold.

The PHP function removes extra spaces and creates matching groups for every word and letter. An angle bracket (<) is ignored if this has a closing correspondent (>), leaving every tag intact. URLs, file paths or other additional infos found in the tag are encoded just the same by the browser.


The characters are recognized by unicode, without worrying about the charset attribute, which means that special characters set in the function will be displayed as they are supposed to.

Character Entities

Characters generated as typed.

HTML entities and URL Escape Codes are not decoded, the PHP function generates each character as typed. This is not an accidental feature and won't limit the use of a text in HTML format, but inline HTML codes must be avoided or replaced with alternatives, for example non-breaking spaces (&nbsp;) can be wrapped in the <nobr> tag.


Depending on layout preferences, specific tags can be treated as objects (a, u, ins, del), to emulate and customize their native appearance and behaviour.

Redesigned underline tag.

Except for text formatting elements (h1-h6, strong, em, small, sup, sub, etc.) that will need new rules to have the right effect on the text, most of the semantic elements (form, ol, li) work with their custom settings.

Dynamic text inside active forms.

Dynamic Content

A dynamic text change ideally would require the PHP function again. Unless the whole structure of a word/letter is recreated and inserted afterwards, scripts have a limited power in manipulating the CSS text content. Most of the characters have nested elements and rely on the character recognition to render properly. A simple class change is not enough.

For demonstration parts of the PHP function are reproduced with Javascript and used in the testarea.

Ids and Classes

HTML elements ids and classes are used to create alternates instantly. Special characters may have a matching Unicode, but sometimes these are far from reach to have a practical use, especially in web.

Default system font.
p {font-size: 50px}

Conventional sans-serif font size.

CSS font size matching average values.


The font-size is set in the CSS file, the same as every font, using viewport, percentage, pixels, em or rem. Values set in pixels works with decimals.


Since this is not really a font, in order to have a sharper display, some browsers instead of blurring the elements, will move them to the closest integer value or even change their dimensions. This is more obvious on small sizes, when the pixel ratio is usually a decimal number.

To avoid weird shape shiftings the font-size should have integer values, but sometimes not even this can guarantee a perfect alignment.


Letter Spacing

The PHP function works with different options, depending on the desired format. For letter spacing this will insert a span after each letter, this way blocking the ligatures and creating extra options for spacing. Letter-spacing is increased or decreased using the span width or its positive/negative margins.
This won't limit the use of a span tag outside the words.

The letter margins are reserved for kerning, and padding would interfere with the design. If a spacing is used globally, the best option is to rewrite the kerning for every letter in the CSS file.

Word Spacing

The word spacing depends on the space character width. This works independently and must be adjusted with every letter-spacing, to fit the new setup.

Line Height

Because the font is ten times bigger, usual values are multiplied with ten. The minimum line height is 7 since the base heights of the characters are 7em. For smaller heights than 100% the words need negative top and bottom margins.

Default system text.
p {line-height: 1.8}

Random line height set for texts.

Equivalent line height for the CSS text.

Font Style

The font-style rule in CSS has no effect on the font. The metrics take the component elements into account, global transformations to get Italics, Condensed or other versions have inconsistent results.

Text Alignment

The text-align and the text-indent works by default. The CSS text will align to any setup even without a text content.

Line Breaks

Block-level elements (e.g. div, p, ol) placed inside the CSS text will cause a line break, as it would normally. The <br> tag works as expected.

Word Break

The word break is adjustable, depends on the text length or personal preferences. It's a matter of inline or inline-block setting.


Cutout effect using CSS variables.

CSS Variable

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 are matched with the background).

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 to the font design.


Mix-blend-mode on image backgrounds.


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 and rotate on heart symbol).


Where a background cannot be used (2, 3), the solution is {mix-blend-mode: lighten} on dark backgrounds and darken on light backgrounds. The inner element needs a dark background in this case.

Standard Ligatures

Characters replaced with standard ligatures.

The PHP function is set to recognize pairings and render different characters for each case. Characters in standard ligatures have fixed positions and behave as groups to avoid weird appearances on word breaks or letter spacing. Because of that, text editing will not affect the component characters of a standard ligature.

Standard ligatures are limited to the fi, fj and fl pairings. The f+f, f+t, t+t or s+t pairing is breakable, characters can be used separately, therefore considered a contextual ligature.

Contextual Ligatures

Hyphen and More sign reshaped inline.

Contextual ligatures in the CSS font are not stand-alone characters and doesn'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.

Ligatures work by default and can be deactivated in the CSS file. The "tracking" option of the PHP function disables ligatures by adding a span element after each character.

OpenType Features

The features are activated with a specific class added to the parent container. This is valid also for Subscripts (subs), Enclosed Alphanumerics (circ) and the Optical size (size).

Alternates are rendered in any circumstances, regardless if a character is registered or not, in every browser, with or without font feature support.

Default lowercase.
<pre class="regular css">
Stylistic alternates.
<pre class="regular css salt">
Default css text.
<pre class="bold css">
Ordinal indicators.
<pre class="bold css ordn">
Inline figures.
<pre class="regular css">
Oldstyle numbers and slashed zeros.
<pre class="regular css onum slsh">
Figures and slash dividers.
<pre class="bold css">
Figures and slashes as fractions.
<pre class="bold css frac">
Default css text.
<pre class="regular css">
<pre class="regular css sups">
White symbols.
<pre class="light css">
Negative correspondent symbols.
<pre class="light css blck">

0 Words 0 Characters  Selected

*Test limited to keyboard characters.

Project in progress.