4
\$\begingroup\$

I'm doing a hobby project for fun recently, it's a GitHub webpage using Jekyll.

One of the main component of my site is displaying Chinese characters with their Sino-Vietnamese pronunciation. I use <ruby> elements to render these texts, for those who don't know, you can read its MDN docs

The problem with that is word spacing is broken when a <rt> element is longer than its associated <rb> element. So I created a jQuery function to dynamically adjust spacing.

A minimal example here:

const stdSpace = "1em"; // for ruby annotation spacing
$(function () {
    $("rb").each(rubyAdjust);
});
function rubyAdjust(i, el) { // for each ruby base
    const rbW = $(el).width(), // take its width
          rtW = $(el).next("rt").width(), // its associated ruby text width
          diff = (rtW - rbW).toFixed(0), // excess amount
          addSpace = diff > 0
                     ? `calc(${stdSpace} + ${diff.toString()}px)`
                     : stdSpace;
    $(el).css("margin-right", addSpace);
}
rb {
    display: inline-block /* fluid word spacing with margin using JS */
}

rt {
    text-align: left /* to work together with rb margin */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ruby>
    <rb>是</rb><rt>Thị</rt>
    <rb>故</rb><rt>cố</rt>
    <rb>空</rb><rt>không</rt>
    <rb>中</rb><rt>trung</rt>
</ruby>

My function rubyAdjust works as expected, but becomes a UI blocking point when I have a very long text. For a full fledged example, you can visit a page of my project which shows the Diamond Sutra.

So what I want is to improve the rendering speed:

  1. Is there a better way to adjust word spacing of <ruby>? The official docs of <ruby> doesn't have much, maybe because the feature is still uncomplete and fews people are using it?
  2. I've also searched for a multi thread execution of jQuery, but it seems like DOM manipulation isn't possible. Do you guys have any idea?

Many thanks,

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Some improvements:

  • completely remove the JS function and replace with CSS (thanks to this SO answer); this greatly reduces loading time
  • wrap one ruby for each pair rb & rt with ruby, instead of having multiple pairs of them inside ruby
  • use flex to render rather than the default display: block

The improved code:

ruby {
    display: inline-flex;
    flex-direction: column-reverse;
    margin-right: 0.5em; /* additional spacing */
}

rb, rt {
    display: inline;
    line-height: 1; /* spacing between rb & rt can be changed */
    text-align: left; /* my personal preference */
}
<ruby><rb>是</rb><rt>Thị</rt></ruby>
<ruby><rb>故</rb><rt>cố</rt></ruby>
<ruby><rb>空</rb><rt>không</rt></ruby>
<ruby><rb>中</rb><rt>trung</rt></ruby>

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.