CSS text-emphasis: emphasis marks over and under text

Japanese, Chinese and Korean often stress a word with a small mark on every character instead of italics. One CSS property draws those marks.

To put dots over Japanese, Chinese or Korean text, use the CSS text-emphasis property. It draws one small mark, such as a sesame shape or a circle, on every character of the element.

Put it on an em or a span around the words you want to stress.

em { text-emphasis: filled sesame red; }

Try the shapes and colors below. The code line under the text updates as you change them.

Live exampletry it here, then copy the code
Share it as a link
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CSS text-emphasis</title>
<style>
  body {
    margin: 0; padding: 18px; font-family: system-ui, sans-serif;
    background: #f4f5f7; color: #1d2330;
  }
  .text {
    font-family: "Yu Gothic", "Hiragino Sans", "Noto Sans CJK JP", sans-serif;
    font-size: 24px; line-height: 2.2; margin: 0 0 14px;
    padding: 6px 16px; background: #fff; border-radius: 10px;
  }
  /* the whole feature: one property on the words you want to stress */
  .mark {
    text-emphasis: filled sesame #e11d48;
  }
  .controls { display: flex; flex-wrap: wrap; gap: 8px; font-size: 14px; }
  select, input { font: inherit; }
  code {
    display: block; margin-top: 12px; padding: 8px 10px; border-radius: 8px;
    background: #1d2330; color: #e5e7eb; font-size: 13px;
  }
</style>
</head>
<body>
<p class="text" lang="ja">これは<span class="mark">大事</span>な点です。</p>
<p class="text" lang="en">This is the <span class="mark">key</span> point.</p>

<div class="controls">
  <select id="fill" aria-label="Fill">
    <option>filled</option><option>open</option>
  </select>
  <select id="shape" aria-label="Shape">
    <option>sesame</option><option>dot</option><option>circle</option>
    <option>double-circle</option><option>triangle</option>
  </select>
  <input id="color" type="color" value="#e11d48" aria-label="Color">
</div>
<code id="out">text-emphasis: filled sesame #e11d48;</code>

<script>
  const fill = document.getElementById('fill');
  const shape = document.getElementById('shape');
  const color = document.getElementById('color');
  const out = document.getElementById('out');

  function update() {
    const value = `${fill.value} ${shape.value} ${color.value}`;
    document.querySelectorAll('.mark').forEach((el) => {
      el.style.textEmphasis = value;
    });
    out.textContent = `text-emphasis: ${value};`;
  }
  [fill, shape, color].forEach((el) => el.addEventListener('input', update));
</script>
</body>
</html>
The same property on a Japanese and an English word. Pick a fill, a shape and a color.

The property has three parts: the shape, the color and the side. The first two share a shorthand. The side has its own property.

Shape and fill: text-emphasis-style

text-emphasis-style takes a fill word and a shape word. The fill is filled or open. The shape is one of five keywords.

The five shape keywords, each drawn filled and open.
The five shape keywords, each drawn filled and open.
Keyword Filled mark Open mark
sesame A short slanted stroke, the Japanese goma dot An outlined stroke
dot A small round dot A small ring
circle A larger round dot A larger ring
double-circle A dot inside a ring Two rings
triangle A solid triangle An outlined triangle

Write both words. With only filled, the browsers we tested drew different shapes: Chromium drew a small dot, Firefox and WebKit drew a circle. Naming the shape, as in filled sesame, gives every browser the same instruction.

A quoted string works as a custom mark, such as "★". Give it one character. Given "ab", Chromium, Firefox and WebKit all drew only the a.

Color and the shorthand

text-emphasis-color sets the mark color. Leave it out and the marks take the text color, currentcolor. The shorthand text-emphasis takes a style and a color in any order:

.key {
  text-emphasis: filled dot #e11d48;
  text-emphasis-position: under right;
}

The shorthand does not include the position. That is why the example above sets it on a second line. Writing the shorthand later does not reset a position set earlier.

Over or under: text-emphasis-position

text-emphasis-position takes over or under for horizontal text, and right or left for vertical text. You can write both, such as under right, and each writing mode uses the part that applies to it.

Live exampletry it here, then copy the code
Share it as a link
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>text-emphasis-position</title>
<style>
  body {
    margin: 0; padding: 16px; font-family: system-ui, sans-serif;
    background: #f4f5f7; color: #1d2330;
  }
  .row { display: flex; gap: 12px; align-items: flex-start; }
  .box {
    background: #fff; border-radius: 10px; padding: 14px;
    font-family: "Yu Gothic", "Hiragino Sans", "Noto Sans CJK JP", sans-serif;
    font-size: 22px; line-height: 2.2;
  }
  .horizontal { flex: 1; min-width: 0; }
  .vertical { writing-mode: vertical-rl; height: 200px; }
  .box span { text-emphasis: filled circle #2563eb; }
  /* the same position value is used by both boxes */
  .box span { text-emphasis-position: var(--pos, over right); }
  .label { font-size: 12px; color: #6b7280; margin: 0 0 4px; }
  .controls { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 6px; }
  button {
    font: 14px system-ui, sans-serif; padding: 7px 10px; border-radius: 8px;
    border: 1px solid #cbd5e1; background: #fff; cursor: pointer;
  }
  button[aria-pressed="true"] { background: #2563eb; color: #fff; border-color: #2563eb; }
</style>
</head>
<body>
<div class="row">
  <div class="horizontal">
    <p class="label">horizontal-tb</p>
    <div class="box" lang="ja"><span>重要</span>な<span>点</span></div>
  </div>
  <div>
    <p class="label">vertical-rl</p>
    <div class="box vertical" lang="ja"><span>重要</span>な<span>点</span></div>
  </div>
</div>

<div class="controls" id="controls">
  <button aria-pressed="true">over right</button>
  <button aria-pressed="false">under right</button>
  <button aria-pressed="false">over left</button>
  <button aria-pressed="false">under left</button>
</div>

<script>
  const buttons = document.querySelectorAll('#controls button');
  buttons.forEach((btn) => {
    btn.addEventListener('click', () => {
      // one custom property feeds text-emphasis-position in both boxes
      document.body.style.setProperty('--pos', btn.textContent);
      buttons.forEach((b) => b.setAttribute('aria-pressed', b === btn));
    });
  });
</script>
</body>
</html>
The same position value on a horizontal and a vertical box. Press a button to move the marks.
  • Japanese and Korean: marks go over horizontal text and to the right of vertical text. That is the default, so over right needs no rule.
  • Chinese: marks go under horizontal text. Set under right on it. In our test Firefox and WebKit already put them under for lang="zh-CN" text, but Chromium put them over.
  • Vertical text: over and under do nothing. Only right or left moves the marks.
over and under choose the side in horizontal text. right and left choose it in vertical text.
over and under choose the side in horizontal text. right and left choose it in vertical text.

If one page mixes languages, scope the rule by the lang attribute:

:lang(zh) em { text-emphasis-position: under right; }

What gets a mark, and line spacing

Each character gets its own mark, including Latin letters and digits. Spaces and punctuation such as 、 and 。 get none.

Marks skip spaces and punctuation. They also need room, so tight lines grow.
Marks skip spaces and punctuation. They also need room, so tight lines grow.

The marks take space above or below the line, like ruby text. We measured a two-line block of 20px text with line-height: 1. It was 40px tall without marks and 78px tall with them in Chromium, Firefox and WebKit.

So a paragraph with a few emphasised words can have uneven line gaps. A looser line height leaves room for the marks.

In our 20px Yu Gothic test, the marked line stopped growing at line-height: 2 in Firefox and at 3 in Chromium and WebKit. At 2 those two added 6px. The exact value depends on the font, so check your own text.

Numbers in vertical text: text-combine-upright

Vertical Japanese text often carries dates. In writing-mode: vertical-rl, a number like 26 lies on its side by default. text-combine-upright: all sets the digits side by side inside one character square:

<p class="card">9月<span class="num">26</span>日</p>
.card { writing-mode: vertical-rl; }
.num  { text-combine-upright: all; }

Keep the span to two or three digits. all squeezes everything into one square, so longer numbers get cramped. The property does nothing in horizontal text, so you can leave it on when the layout switches. CSS writing-mode covers vertical layout in full.

A finished example: a reading card

This card uses both properties. The emphasis marks use over right, so they sit above the words in horizontal mode and move to the right side when the card turns vertical. The date digits use text-combine-upright.

Live exampletry it here, then copy the code
Share it as a link
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Reading card with emphasis marks</title>
<style>
  body {
    margin: 0; padding: 16px; font-family: system-ui, sans-serif;
    background: #efe9dc; color: #2b2118;
  }
  .card {
    background: #fffdf7; border-radius: 12px; padding: 18px 20px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .1);
    font-family: "Yu Mincho", "Hiragino Mincho ProN", "Noto Serif CJK JP", serif;
    font-size: 21px; line-height: 2.1;
  }
  .card.vertical { writing-mode: vertical-rl; height: 260px; overflow-x: auto; }
  .card p { margin: 0; }
  em {
    font-style: normal;                       /* no fake italic on Japanese */
    text-emphasis: filled sesame #b91c1c;
    text-emphasis-position: over right;       /* above in horizontal, right in vertical */
  }
  .num { text-combine-upright: all; }         /* only affects vertical text */
  .controls { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 12px; font-size: 14px; }
  button {
    font: 14px system-ui, sans-serif; padding: 7px 12px; border-radius: 8px;
    border: 1px solid #b8a98f; background: #fff; cursor: pointer;
  }
</style>
</head>
<body>
<div class="controls">
  <button id="flip" type="button">Switch to vertical</button>
  <label><input id="tcy" type="checkbox" checked> text-combine-upright</label>
</div>

<div class="card" id="card" lang="ja">
  <p>令和<span class="num">8</span>年<span class="num">9</span>月<span class="num">26</span>日</p>
  <p>本文の<em>要点</em>だけに点を打つ。</p>
  <p>全部に打つと、<em>どこも</em>目立たない。</p>
</div>

<script>
  const card = document.getElementById('card');
  const flip = document.getElementById('flip');
  const tcy = document.getElementById('tcy');

  flip.addEventListener('click', () => {
    const vertical = card.classList.toggle('vertical');
    flip.textContent = vertical ? 'Switch to horizontal' : 'Switch to vertical';
  });

  tcy.addEventListener('change', () => {
    document.querySelectorAll('.num').forEach((el) => {
      el.style.textCombineUpright = tcy.checked ? '' : 'none';
    });
  });
</script>
</body>
</html>
Switch the card between horizontal and vertical. Untick the box to see the date without text-combine-upright.
  • Semantic tag: the stressed words are em elements, so the stress is in the HTML, not only in the look.
  • No italics: font-style: normal removes the slanted look that em has by default, which suits Japanese type poorly.
  • One rule for both modes: the position value has a part for each writing mode.

Emphasis marks, em, bold and ruby

text-emphasis is paint only. It adds no meaning to the HTML, so assistive technology gets nothing from it. For stress that carries meaning, use the em tag and style it with emphasis marks, as the card does.

Emphasis marks are not ruby either. Ruby adds a reading, different for each word. Emphasis puts the same mark on every character. For readings such as furigana, use the ruby tag.

When it does not work

What you see Cause Fix
No marks at all Only a color was given, so the style is none Add a shape, such as filled dot
Marks above Chinese text The default puts them over (Chromium, any language) Set under right
Vertical text ignores under Vertical text uses right and left Write under left or over left
A different shape in each browser Only filled or open was given Name the shape too
Line gaps jump around The marks need room above the line A looser line-height
A custom string shows one letter Only the first character is used Use a single character
Commas and spaces have no mark This is intended Nothing to fix

Emphasis marks depend on the fonts and the writing mode on the reader's screen. A screenshot hides how they move when the layout turns vertical, and an .html attachment may open as plain code on a phone.

To send the working version, paste the page into a NOS document and choose Create share link. HTML to link walks through it.

The page renders as written and its scripts run, so the people you send it to can switch the card and try the shapes themselves. If you change the code later, the same link shows the new version.

Questions people ask

What is CSS text-emphasis for?

It draws a small mark, such as a dot or a sesame shape, next to every character of the text it applies to. East Asian typography uses these marks to stress words, the way English uses italics. It works on Latin text too.

Why do my emphasis marks show up above the text when I want them below?

The default puts marks over horizontal text, and in Chromium it does so for every language. Chinese text usually puts the marks under, so set text-emphasis-position: under right on it.

Does the text-emphasis shorthand set the position?

No. The shorthand only sets text-emphasis-style and text-emphasis-color. Set text-emphasis-position on its own line, and it is inherited, so one rule on a parent covers every emphasised word inside.

Why are there no marks on commas and spaces?

That is intended. Browsers skip spaces and punctuation such as 、 and 。, so the marks sit only on letters, digits and ideographs.

Does text-emphasis make text bold or change its meaning?

No. It is only a visual mark. To mark the stress in the HTML itself, wrap the word in em or strong, then style that element with text-emphasis.

Keep reading