Here’s the trick: by combining the Turkish letter “ı” and the period “.” we can create something that looks like the letter “i,” but is made from two separate elements. This opens us up to some fun options to style or animate the dot of the letter independently from the stalk. Worried about accessibility? Don’t worry, we’ll cover that the best way we know how.
Let’s look at how to create and style these separate “letters,” and find out when they can be used, and when to avoid them.
Check out some examples
Here are some different styles and animations we can do with this idea:
See the Pen
Styles and animations by Ali C (@alichur)
on CodePen.
Because both parts of the letter are regular Unicode characters, they will respect font changes and page zoom the same as any other text. Here’s some examples of different fonts, styles, and zoom levels:
See the Pen
Different fonts and zoom by Ali C (@alichur)
on CodePen.
Step-by-step through the technique
Let’s break down how this technique works.
Choose the Unicode characters to combine
We are using the dotless “i” character (ı) and a full stop. And, yes, we could use other characters as well, such as the dotless “j” character (ȷ) or even the accents on characters such as “ñ” (~) or “è” (`).
Stack the characters on top of each other by wrapping them in a span and setting the display
property to block
.
<span class="character">.</span>
<span class="character">ı</span>
.character {
display: block;
}
Align the characters
They need to be close to each other. We can do that by adjusting the line heights and removing the margins from them.
.character {
display: block;
line-height: 0.5;
margin-top: 0;
margin-bottom: 0;
}
Add a CSS animation to the dot element
Something like this bouncing animation:
@keyframes bounce {
from {
transform: translate3d(0, 0, 0);
}
to {
transform: translate3d(0, -10px, 0);
}
}
.bounce {
animation: bounce 0.4s infinite alternate;
}
There’s more on CSS animations in the CSS-Tricks Almanac.
Checking in, here’s where we are so far:
See the Pen
Creating the letter by Ali C (@alichur)
on CodePen.
Add any remaining letters of the word
It’s fine to animate the “i” on its own, but perhaps it’s merely one letter in a word, like “Ping.” We’ll wrap the animated characters in a span to make sure everything stays on a single line.
<p>
P
<span>
<span class="character">.</span>
<span class="character>ı</span>
</span>
ng
</p>
There’s an automatic gap between inline-block elements, so be sure to remove that if the spacing looks off.
The final stages:
See the Pen
Adding the letter inside a word by Ali C (@alichur)
on CodePen.
What about SVG?
The same effect can be achieved by creating a letter from two or more SVG elements. Here’s an example where the circle element is animated independently from the rectangle element.
See the Pen
SVG animated i by Ali C (@alichur)
on CodePen.
Although an SVG letter won’t respond to font changes, it opens up more possibilities for animating sections of letters that aren’t represented by Unicode characters and letter styles that don’t exist in any font.
Where would you use this?
Where would you want to use something like this? I mean, it’s not a great use case for body content or any sort of long-form content. Not only would that affect legibility (can you imagine if every “i” in this post was animated?) but it would have a negative impact on assistive technology, like screen readers, which we will touch on next.
Instead, it’s probably best to use this technique where the content is intended for decoration. A logo is a good example of that. Or perhaps in an icon that’s intended to be described, but not interpreted as text by assistive technology.
Let’s talk accessibility
Going back to our “Ping” example, a screen reader will read that as P . ı ng
. Not exactly the pronunciation we’re looking for and definitely confusing to anyone listening to it.
Depending on the usage, different ARIA attributes can be added so that text is read differently. For example, we can describe the entire element as an image and add the text as its label:
<div role=img aria-label="Ping">
<p>P<span>.</span><span>ı</span>ng</p>
</div>
This way, the outer div element describes the meaning of the text which gets read by screen readers. However, we also want assistive technology to skip the inner elements. We can add aria-hidden="true"
or role="presentation"
to them so that they are also not interpreted as text:
<div role=img aria-label="Ping">
<p role="presentation">P
<span>.</span>
<span>ı</span>
ng</p>
</div>
This was only tested on a Mac with VoiceOver in Safari. If there are issues in other assistive technology, please let us know in the comments.
More Unicode!
There’s many more “letters” we can create by combining Unicode characters. Here’s a full outline of common glyphs, or you can have some fun with the ones below and share your creations in the comments. But remember: no cool effect is worth compromising accessibility on a live site!
First Glyph | Second Glyph | Combined |
---|---|---|
ı | . | i |
ȷ | . | j |
n | ~ | ñ |
a | e | æ |
a | ` | à |
You forgot all the umlaut characters, a huge range of possibilities here:
a + ¨ = ä
u + ¨ = ü
o + ¨ = ö
a + ° = å
o + / = Ø (kinda)
Those aren’t common usage in English though, so their use cases are much more limited on an effect with an already extremely limited use case.
I suppose a more resilient and somewhat more authentic approach to semantics would be
A. to remove altogether the image semantics,
B. to visually hide an unstyled copy of the full strings from sighted users
C. to hide the fragmented strings from screen reader users with aria-hidden, as demoed here
I was just thinking this. People on screen readers would have been pretty confused but I guess the point was to just demonstrate the new shiny.
Neil has given the better approach to hiding the content from screen reader users. Use his example.
Allow me to explain why. Using
aria-label
on a<div>
or<span>
is poorly supported and will be deprecated as an option in ARIA 1.2. Casting it as an image withrole="img"
will just confuse the issue (and some users) since it is not an image. Note thataria-label
overrides the text node of a thing, so therole="presentation"
oraria-hidden="true"
would be unnecessary in that example. That override is also a factor if your users are non-native English speakers since it may not auto-translate.Generally, VoiceOver has so many quirks that another screen reader is needed to confirm findings. I suggest starting with NVDA or JAWS.
Also, since this is looping and not a single micro-animation, I recommend wrapping it in a
prefers-reduced-motion
feature query to disable the animation for users who do not want it.looks interesting :—)
Inspired by gradient text color found here on CSS Tricks I hid the dot (made it transparent), and then added a pseudo-class with “.” as content. There was no need for extra characters and no need for ARIA attributes. If you select the text you’ll see the original dot behind the bouncing dot.
<p class="text">P<span>i</span>ng</p>
span {
display: inline-block;
background: linear-gradient(rgba(0, 0, 0, 0) 30%, #ff8a00 30%);
background-clip: border-box;
-webkit-background-clip: text;
-webkit-text-fill-color: rgba(0, 0, 0, 0);
position: relative;
}
span::before {
content: ".";
-webkit-background-clip: none;
-webkit-text-fill-color: gba(0, 0, 0, 0);
-webkit-background-clip: text;
-webkit-text-fill-color: #ff8a00;
position: absolute;
top: -44%;
left: 7%;
z-index: 10;
}
There are some magic numbers used here for positioning and for gradient color stop. They depent on font family, size, and some other properties so be careful. This is just a proof of concept.
Wouldn’t it be easier to use a psedo element to create the dot?
This yould give a simpler reference point to position it I think
Like this https://codepen.io/schoenwaldnils/pen/jOOppxa
FYI: The dot on the i (and j) is called a tittle.
Why does the comment in the HTML remove the spacing?