10

I'd like to use HTML <ruby> to mark up Japanese text with its pronunciation. However, I've found that at large font sizes, the baseline of the <rt> text is well above the top of the characters it's marking up. Here's an example which shows what I mean:

ruby {
  font-size: 72pt;
}
<ruby>遅<rt>おそ</rt>い</ruby>

For reference, this is how it appears in my current browser (Firefox on Linux), though I've seen similar behavior in other browsers:

incorrectly-formatted ruby text

What I would like is to adjust the height of the ruby text to be something more like this:

correctly-formatted ruby text

However, nothing I try seems to have any effect on the positioning of the ruby text. These are all things that I have tried which did not work:

  • vertical-align: -10px
  • postion: relative and top: 10px
  • transform: translateY(-10px)

Is there any way that I can adjust the positioning of this text?

Rose Kunkel
  • 3,102
  • 2
  • 27
  • 53
  • Which browsers are you aiming for? It looks like the text shows up quite differently in Chrome vs Firefox (even if you change the text to `font-family: sans-serif` to match your example output), and it seems like only Firefox has any real support for ``-related attributes for styling. By the way, I found [this blog entry](https://www.chenhuijing.com/blog/html-ruby/#) useful when looking into all this. – Paul Fioravanti Aug 03 '16 at 22:50
  • @Paul Fioravanti I'm most interested in how to do this in WebKit-based browsers. If you've got a Firefox solution, though, feel free to post it! I didn't see a way to do it even with support for the ruby-specific CSS rules. – Rose Kunkel Aug 03 '16 at 22:54
  • No solution from me, unfortunately :( On Chrome, I tried tweaking all sorts of CSS properties, but just couldn't seem to bring the furigana closer to the kanji. When I opened up your code in Firefox though, the distance between the two looked pretty much as it does in your screenshot, so that's why I asked. – Paul Fioravanti Aug 03 '16 at 23:04

4 Answers4

13

I think I've found a solution which allows for styling <ruby> elements while preserving their semantics. Here's a demonstration, and then a few key insights:

body {
  font-size: 72pt;
}

ruby {
  display: inline-flex;
  flex-direction: column-reverse;
}

rb, rt {
  display: inline;
  line-height: 1;
}
<ruby><rb>遅</rb><rt>おそ</rt></ruby>い

Set the <rt> element to be display: inline.

Chrome seems to have some special behavior when <rt> is display: block, which prevents styling it as a normal block-level element. That special behavior appears to be disabled when using display: inline.

Use a separate <ruby> element for each annotation.

While there are several valid ways to mark up ruby text, using a new <ruby> element for each annotation gives us a nice container element and makes styling much easier. This is semantically equivalent to using a single ruby element with multiple <rt> and <rb> elements.

Use flexbox to position ruby text.

Flexbox is by far the simplest and most powerful way to position ruby text. If your browser doesn't yet support flexbox, you can try using inline-table, but I didn't have much success in styling content using it. Users of older browsers might also want to see Paul Fioravanti's answer.

I used display: inline-flex to treat the ruby elements as if they were normal text while still having flex contents, and then flex-direction: column reverse to position the text vertically with the <rt> on top.

Set line-height: 1 in the <ruby> element.

A lot of the extra space between the text and its ruby markup can be attributed to the fact that the line height is not the same as the text height by default. Setting line-height: 1 will ensure they are the same.

If the spacing between elements is still not the desired spacing, setting margin-bottom on the <rt> element can adjust it. It can be set to a positive or negative value.

Community
  • 1
  • 1
Rose Kunkel
  • 3,102
  • 2
  • 27
  • 53
  • 1
    Excellent answer and definitely worthy of an accept. Thanks for going into so much detail! – Paul Fioravanti Aug 10 '16 at 20:54
  • I found a problem with this answer. Try this: `小鳥遊たかなしたかなしたかなし`. In the default behavior, the characters in are separated when the text in is very long, but after applying the CSS in this answer the characters in are next to each other. – Eric Stdlib Mar 11 '21 at 07:37
5

In order to attempt to provide an answer to this question, I went to https://japanese.stackexchange.com/ to see how actual experts in this would do it. There, they seem to have dispensed with the <rb> and <rt> tags and instead changed them to <span>s and styled them appropriately.

Based on the styles I found there, I came up with this CSS jiggery-pokery that seems to get at least in the ballpark of what is needed to take some control of the sizing and positioning of furigana text.

ruby {
  font-size: 72pt;
  display: inline-block;
  line-height: 1em;
  position: relative;
}

span.rb {
  display: inline-block;
  padding-top: 0.6em;
}

span.rt {
  font-size: 0.55em;
  position: absolute;
  display: block;
  line-height: 1.3em;
  top: 0;
}
<ruby>
  <span class="rb">遅</span>い
  <span class="rt">おそ</span>
</ruby>
Community
  • 1
  • 1
Paul Fioravanti
  • 16,423
  • 7
  • 71
  • 122
  • Great answer! I found a way to do it while still using the `` and `` elements, but your solution is probably better for older browsers. – Rose Kunkel Aug 10 '16 at 15:33
  • Great answer. This is the CSS rule I finally got the ruby elements to align, when using the PrinceXML HTML to PDF conversion utility. – Kanuj Bhatnagar Apr 05 '21 at 11:42
0

For me, simply using <rt>'s margin-bottom works on Firefox:

<html>
<head>
  <style>
    div {
        float: left;
        border: solid;
        margin: 1em;
    }
    ruby {
        font-size: 5em;
        background-color: rgba(255, 0, 0, 0.3);
    }
    rt {
        font-size: 1em;
        background-color: rgba(0, 255, 0, 0.3);
    }
  </style>
</head>
<body>
<div>
  <ruby>
    <rb>数多く</rb>
    <rt style="margin-bottom: 0em;">kazuooku</rt>
  </ruby>
</div>
<div>
  <ruby>
    <rb>数多く</rb>
    <rt style="margin-bottom: -0.4em;">kazuooku</rt>
  </ruby>
</div>
<div>
  <ruby>
    <rb>数多く</rb>
    <rt style="margin-bottom: -0.4em; margin-top: -0.2em">kazuooku</rt>
  </ruby>
</div>
</body>
</html>

This solution makes sure that if <rt> is wider than <rb>, the characters in <rb> will be separated (notice the space between "数" and "多" below).

Firefox: Firefox

However it doew not work so well on Chrome (I am using Chromium, though): Chromium

Eric Stdlib
  • 1,292
  • 1
  • 18
  • 32
0

Some fonts have this problem and others don't. We can try to trick the browser into thinking the ascent and descent are different by first loading a font "emptied" with unicode-range, and then falling back to the font we actually want. Some trial and error may be needed in figuring out what fonts have the best or most compatible metrics, and if they are too short letters like g might collide.

@font-face {
    font-family: "Empty";
    font-weight: 400;
    font-style: normal;
    unicode-range: U+000A;
    src: local("Webdings"), local("Times New Roman"), local("Arial");
}

ruby {
    font-size: 72pt;
    font-family: "Empty", "My Font Here", sans-serif;
}
<ruby>遅<rt>おそ</rt>い</ruby>
<ruby>語<rt>go</rt></ruby>
gnucchi
  • 189
  • 10