This document is licensed under a Creative Commons Attribution 3.0 License.
The ruby markup model currently described in the HTML specification is limited in its support for a number of features, notably jukugo and double-sided ruby, as well as inline ruby. This specification addresses these issues by introducing new elements and changing the ruby processing model. Specific care has been taken to ensure that authoring remains as simple as possible.
This document was largely developed to address the shortcomings listed in Use Cases & Exploratory Approaches for Ruby Markup.
This document is merely a public working draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organisation.
This specification is a proposed extension specification to HTML and has no official standing whatsoever.
The following changes are made to HTML by this document:
ruby
nested inside ruby
now represents its children;rb
and rtc
elements have been introduced;ruby
elementHTMLElement
.The ruby
element allows one or more spans of phrasing content to be marked with
ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily
used in East Asian typography as a guide for pronunciation or to include other annotations. In
Japanese, this form of typography is also known as furigana.
The content model of ruby
elements consists of one or more of the following
sequences:
rb
elements.
rt
or rtc
elementsrp
element followed by one or more rt
or rtc
elements,
followed by an rp
element.
The ruby
, rb
, rtc
, and rt
elements can be used for
a variety of kinds of annotations, including in particular (though by no means limited to) those described
below. For more details on Japanese Ruby in particular, and how to render Ruby for Japanese, see
Requirements for Japanese Text Layout. [JLREQ]
At the time of writing, CSS does not yet provide a way to fully control the
rendering of the HTML ruby
element. It is hoped that CSS will be extended to support
the styles described below in due course.
Annotations (the ruby text) are associated individually with each ideographic character (the base text). In Japanese this is typically hiragana or katakana characters used to provide readings of kanji characters.
<ruby>B<rt>annotation</ruby>
When no rb
element is used, the base is implied, as above. But you can also make
it explicit. This can be useful notably for styling, or when consecutive bases are to be treated
as a group, as in the jukugo ruby example further down.
<ruby><rb>base<rt>annotation</ruby>
In this example, notice how each annotation corresponds to a single base character.
<ruby>日<rt>に</rt></ruby><ruby>本<rt>ほん</rt></ruby> <ruby>語<rt>ご</rt></ruby>で<ruby>書<rt>か</rt></ruby> いた<ruby>作<rt>さく</rt></ruby><ruby>文<rt>ぶん</rt></ruby>です。
Ruby text interspersed in regular text provides structure akin to the following image:
This example can also be written as follows, using one ruby
element with two
segments of base text and two annotations (one for each) rather than two back-to-back
ruby
elements each with one base text segment and annotation (as in the markup
above):
<ruby>日<rt>に</rt>本<rt>ほん</rt>語<rt>ご</rt></ruby>で<ruby>書<rt>か</rt></ruby> いた<ruby>作<rt>さく</rt>文<rt>ぶん</rt></ruby>です。
Group ruby is often used where phonetic annotations don't map to discreet base characters, or for semantic glosses that span the whole base text. For example, the word "today" is written with the characters 今日, literally "this day". But it's pronounced きょう (kyou), which can't be broken down into a "this" part and a "day" part. In typical rendering, you can't split text that is annotated with group ruby; it has to wrap as a single unit onto the next line. When a ruby text annotation maps to a base that is comprised of more than one character, then that base is grouped.
Which can be marked up as follows:
<ruby>今日<rt>きょう</ruby>
Jukugo refers to a Japanese compound noun, ie. a word made up of more than one kanji character. Jukugo ruby is a term that is used not to describe ruby annotations over jukugo text, but rather to describe ruby with a behaviour slightly different from mono or group ruby. Jukugo ruby is similar to mono ruby, in that there is a strong association between ruby text and individual base characters, but the ruby text is typically rendered as grouped together over multiple ideographs when they are on the same line.
The distinction is captured in this example:
Which can be marked up as follows:
<ruby>法<rb>華<rb>経<rt>ほ<rt>け<rt>きょう</ruby>
In this example, each rt
element is paired with its respective
rb
element, the difference with an interleaved rb
/rt
approach being that the sequences of both base text and ruby annotations are
implicitly placed in common containers so that the grouping information is captured.
For more details on Jukugo Ruby rendering, see Appendix F in the Requirements for Japanese Text Layout [JLREQ] and Use Case C: Jukugo ruby in the Use Cases & Exploratory Approaches for Ruby Markup [RUBY-UC].
In some contexts, for instance when the font size or line height are too small for ruby to be readable, it is desirable to inline the ruby annotation such that it appears in parentheses after the text it annotates. This also provides a convenient fallback strategy for user agents that do not support rendering ruby annotations.
Inlining takes grouping into account. For example, Tokyo is written with two kanji characters, 東, which is pronounced とう, and 京, which is pronounced きょう. Each base character should be annotated individually, but the fallback should be 東京(とうきょう) not 東(とう)京(きょう). This can be marked up as follows:
<ruby>東<rb>京<rt>とう<rt>きょう</ruby>
Note that the above markup will enable the usage of parentheses when inlining for browsers
that support ruby layout, but for those that don't it will fail to provide parenthetical fallback.
This is where the rp
element is useful. It can be inserted into
the above example to provide the appropriate fallback when ruby layout is not supported:
<ruby>東<rb>京<rp>(</rp><rt>とう<rt>きょう<rp>)</rp></ruby>
Sometimes, ruby can be used to annotate a base twice.
In the following example, the Chinese word for San Francisco (旧金山, i.e. “old gold mountain”) is annotated both using pinyin to give the pronunciation, and with the original English.
Which is marked up as follows:
<ruby><rb>旧<rb>金<rb>山<rt>jiù<rt>jīn<rt>shān<rtc>San Francisco</ruby>
In this example, a single base run of three base characters is annotated with three
pinyin ruby text segments in a first (implicit) container, and an rtc
element
is introduced in order to provide a second single ruby text annotation being the city's
English name.
We can also revisit our jukugo example above with 上手 ("skill") to show how it can be annotation in both kana and romaji phonetics while at the same time maintaining the pairing to bases and annotation grouping information.
Which is marked up as follows:
<ruby><rb>上<rb>手<rt>じよう<rt>ず<rtc><rt>jou<rt>zu</ruby>
Text that is a direct child of the rtc
element implicitly produces
a ruby text segment as if it were contained in an rt
element.
In this contrived example, this is shown with some symbols that are given names in
English and French with annotations intended to appear on either side of the base symbol.
<ruby> ♥<rt>Heart<rtc lang=fr>Cœur</rtc> ☘<rt>Shamrock<rtc lang=fr>Trèfle</rtc> ✶<rt>Star<rtc lang=fr>Étoile </ruby>
Similarly, text directly inside a ruby
element implicitly produces a ruby
base as if it were contained in an rb
element, and rt
children of
ruby
are implicitly contained in an rtc
container. In effect, the
above example is equivalent (in meaning, though not in the DOM it produces) to the
following:
<ruby> <rb>♥</rb><rtc><rt>Heart</rt></rtc><rtc lang=fr><rt>Cœur</rt></rtc> <rb>☘</rb><rtc><rt>Shamrock</rt></rtc><rtc lang=fr><rt>Trèfle</rt></rtc> <rb>✶</rb><rtc><rt>Star</rt></rtc><rtc lang=fr><rt>Étoile</rt></rtc> </ruby>
Within a ruby element, content is parcelled into a series of ruby segments. Each ruby segment is described by:
rb
element.
rtc
elements, or to sequences of rt
elements implicitly recognised as containers.
Each ruby text container is described by zero or more ruby text annotations each of which is a
DOM range that may contain text nodes or an rt
element, and an annotations range
that is a range including all the annotations for that container.
Furthermore, a ruby element contains ignored segments. Ignored segments do not form part of the
document's semantics (they consist of some inter-element whitespace and rp
elements, the latter of which are used for legacy user agents that do not support ruby at all).
Each ruby text annotation in each ruby text container of a ruby segment is paired with the base at the same offset. If there are more bases than ruby text annotations for a given container, then its last annotation spans the remaining bases. If there are more ruby text annotations than there are bases, they are not paired.
Informally, the segmentation and categorisation algorithm below performs a simple set of
tasks. First it processes adjacent rb
elements, text nodes, and non-ruby elemtns
into a list of bases. Then it processes up to two rtc
elements
or sequences of rt
elements that are considered to automatically map to an
"anonymous rtc
". Put together these data items form a ruby segment as detailed
in the data model above. It will continue to produce such segments until it reaches the end of
the content of a given ruby
element. The complexity of the algorithm below compared
to this informal description stems from the need to support an author-friendly syntax and
being mindful of inter-element white space.
At any particular time, the segmentation and categorisation of content of a
ruby
element is the result that would be obtained from
running the following algorithm:
ruby
element for which the algorithm is being run.ruby
element ancestor, then abort these steps.rp
element, then increment index by one and
jump to the step labelled process a ruby child.
rt
element, then run these substeps:
rtc
element, then run these substeps:
rtc
element and a DOM
range whose start is the
boundary point (root, index)
and whose end is the
boundary point (root, index plus one).
Append this new annotation container at the end of current annotation containers.
Text
node and is inter-element whitespace,
then run these substeps:
Text
node and is inter-element whitespace,
then jump to the step labelled peek ahead.
rt
element, an rtc
element,
or an rp
element, then set index to the value of lookahead index
and jump to the step labelled process a ruby child.
rb
element, then run these substeps:
When the steps above say to commit a ruby segment, it means to run the following steps at that point in the algorithm:
When the steps above say to commit the base range, it means to run the following steps at that point in the algorithm:
When the steps above say to commit current annotations, it means to run the following steps at that point in the algorithm:
When the steps above say to commit an automatic base, it means to run the following steps at that point in the algorithm:
Text
nodes, or Text
nodes that are not inter-element whitespace, then
run these substeps:
rb
elementruby
element.HTMLElement
.The rb
element marks the base text component of a ruby annotation. When it is the
child of a ruby
element, it doesn't represent anything itself,
but its parent ruby
element uses it as part of determining what it
represents.
An rb
element that is not a child of a ruby
element
represents the same thing as its children.
rt
elementruby
or of an rtc
element.HTMLElement
.The rt
element marks the ruby text component of a ruby annotation. When it is the
child of a ruby
element or of an rtc
element that is itself the child of
a ruby
element, it doesn't represent anything itself,
but its ancestor ruby
element uses it as part of determining what it
represents.
An rt
element that is not a child of a ruby
element
or of an rtc
element that is itself the child of a ruby
element
represents the same thing as its children.
rtc
elementruby
element.HTMLElement
.The rtc
element marks a ruby text container for ruby text components in a ruby annotation.
When it is the child of a ruby
element it doesn't represent
anything itself, but its parent ruby
element uses it as part of determining what it
represents.
An rtc
element that is not a child of a ruby
element
represents the same thing as its children.
When an rtc
element is processed as part of the segmentation
and categorisation of content for a ruby
element,
the following algorithm defines how to process an rtc
element:
rtc
element for which the algorithm is being run.rt
element, then run these substeps:
When the steps above say to commit an automatic annotation, it means to run the following steps at that point in the algorithm:
Text
nodes, or Text
nodes that are not inter-element whitespace, then
create a new DOM range whose start is the
boundary point (root, current automatic annotation
range start) and whose end is the
boundary point (root, index), and
append it at the end of annotations.
rp
elementruby
element, either immediately before or immediately after an
rt
or rtc
element.
HTMLElement
.The rp
element can be used to provide parentheses around a ruby text component of
a ruby annotation, to be shown by user agents that don't support ruby annotations.
An rp
element that is a child of a ruby
element represents nothing. An rp
element
whose parent element is not a ruby
element represents its
children.
The example above, in which each ideograph in the text 漢字 is annotated with its
phonetic reading, could be expanded to use rp
so that in
legacy user agents the readings are in parentheses (please note that
white space has been introduced into this example in order to make it
readable):
...
<ruby>
漢
<rb>字</rb>
<rp> (</rp>
<rt>かん</rt>
<rt>じ</rt>
<rp>) </rp>
</ruby>
...
In conforming user agents the rendering would be as above, but in user agents that do not support ruby, the rendering would be:
... 漢字 (かんじ) ...
When there are multiple annotations for a segment, rp
elements can also be placed
between the annotations. Here is another copy of an earlier contrived example showing some
symbols with names given in English and French using double-sided annotations, but this time
with rp
elements as well:
<ruby> ♥<rp>: </rp><rt>Heart</rt><rp>, </rp><rtc><rt lang=fr>Cœur</rt></rtc><rp>.</rp> ☘<rp>: </rp><rt>Shamrock</rt><rp>, </rp><rtc><rt lang=fr>Trèfle</rt></rtc><rp>.</rp> ✶<rp>: </rp><rt>Star</rt><rp>, </rp><rtc><rt lang=fr>Étoile</rt></rtc><rp>.</rp> </ruby>
This would make the example render as follows in non-ruby-capable user agents:
♥: Heart, Cœur. ☘: Shamrock, Trèfle. ✶: Star, Étoile.
In Usage summary,
add rb
and rtc
to the table.
Changes are required to [WEBVTT] in order to match this model.
In the parsing algorithm, “A start tag whose tag name is one of: "rp", "rt"” needs to include
"rb" and "rtc". Closing tag handling for rt
and rp
need be complemented
with the new elements, and they need to be added to
Closing
elements that have implied end tags. There are several other occurrences of "rp" and "rt"
in the parsing algorithm that need to see these elements added.
The CSS for Phrasing content
needs to include style for rb
and rtc
, and the following prose
needs to take them into account. Note that the CSS Ruby Module
[CSS3RUBY] is currently in sore need of fixing such that any reliance on it is hazardous at best.
rb
needs to be removed from
Non-conforming features.
The Elements appendix needs updating to include the new elements, as will the Element interfaces appendix.
Much of this document is deeply indebted to Fantasai and Richard Ishida.
Indicate document conformance problems better (e.g. more than two rtc
s).
Take text-level elements into account rather than just text nodes.