14

I am looking for a way to create the following effect with CSS.

1 dot at each char

I found some solutions for putting dots below the text (white dots below HTML text), but I don't want "dotted underlining", I want every character to have just a single dot below it. Also the dot should increase with the font-size of the text (although if needed, I could mess with JS to fix that).

How could I achieve that?

Avatar
  • 14,622
  • 9
  • 119
  • 198
matthy
  • 8,144
  • 10
  • 38
  • 47

3 Answers3

25

CSS Text Decoration Module Level 3 defines those properties:

  • text-emphasis-style

    This property applies emphasis marks to the element's text. [...]
    The marks are drawn once for each character.

  • text-emphasis-position

    This property describes where emphasis marks are drawn at.

When browsers support that, you will be able to use

text-emphasis-style: dot;
text-emphasis-position: under left; /* or `under right` */

body {
  text-emphasis-style: dot;
  text-emphasis-position: under left;
  -webkit-text-emphasis-style: dot;
  -webkit-text-emphasis-position: under;
  font-size: 300%;
}
ieuw

However, it is not widely supported yet. See caniuse for full details.

Firefox supports it since version 46, or since version 45 if you enable layout.css.text-emphasis.enabled flag.

Chrome supports it since version 25, but needs the -webkit- vendor extension.

Note the standard text-emphasis-position uses a 2-value syntax (for horizontal and vertical writing modes, respectively), but there is a suggestion to allow 1-value syntax too. However, -webkit-text-emphasis-position doesn't allow the 2-value syntax, only the 1-value one.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • That's genuinely beautiful. – David Thomas Dec 15 '14 at 00:59
  • 4
    In Japanese, this style is widely used and known as "kenten" (圏点) or "bouten" (傍点). In fact, I believe that is what motivated the CSS features described in this answer. –  Dec 15 '14 at 18:11
19

You cannot style a continuous block of text on per-character basis using CSS yet.

(There might be support for that in the future, as @Oriol points out in his answer. I'm only dealing with the current situation here.)

You can style your code on per-element basis, so if you enclose each and every one of your characters in a separate element (with char class), you could add the dot using something like:

.char {
    display: inline-block;
    position: relative;
}
.char::before {
    content: '.';
    display: inline-block;

    /* position the dot underneath the character */
    position: absolute;
    bottom: -0.5em;
    left: 0;

    /* center the dot horizontally */
    text-align: center;
    width: 100%;

    /* ... (style the dot to your liking) */
}

This would make the DOM incredibly messy, but it would meet your requirements (scale with font-size, etc).

hon2a
  • 7,006
  • 5
  • 41
  • 55
  • You can create a simple JS code to split them into spans: `$('#wrap').html( ""+ $('#wrap').html().split("").join("")+"" )` – Martijn Dec 14 '14 at 19:09
  • @Martijn This will only work if `#wrap` only contains text nodes. – Oriol Dec 14 '14 at 19:12
  • 1
    Splitting DOM text into characters is a separate exercise with a variety of solutions. I wouldn't worry about it here. – hon2a Dec 14 '14 at 19:16
  • @Oriol: You are right, but writing a 100% solution as a omment would've been a bit much :P Just showing the concept of the idea :) – Martijn Dec 15 '14 at 08:11
0

Just a summary of both solutions above:

1. Using modern CSS that sets a dot below each letter

HTML:

0,<span class="dotunderletter">1</span> = 
<br>
0,<span class="dotunderletter">01</span> = 
<br>
0,001 = 1 · 1/1.000 = 

CSS:

.dotunderletter {
    text-emphasis-style: dot;
    text-emphasis-position: under left;
    -webkit-text-emphasis-style: dot;
    -webkit-text-emphasis-position: under;
}

Result:

text-emphasis-style css

Issue: The line height changes.


2. Using a CSS before element for each single char

HTML:

0,<span class="char">1</span> = 
<br>
0,<span class="char">0</span><span class="char">1</span> =
<br>
0,001 = 1 · 1/1.000 = 

CSS:

.char {
    display: inline-block;
    position: relative;
}
.char::before {
    content: '.';
    display: inline-block;
    position: absolute;
    bottom: -0.5em;
    left: 0;
    text-align: center;
    width: 100%;
}

Result:

CSS single char

Issue: Each char needs to be put into a span element. But the line height does not change and it works in most of the browsers.

Thanks to hon2a and Oriol for their helpful answers!

Avatar
  • 14,622
  • 9
  • 119
  • 198