A line of Japanese has no spaces between words, and yet a Japanese paragraph set by LaTeX comes out flush on both margins. The trick is a glue called \kanjiskip whose natural width is zero but which stretches — measured under jsarticle at 10pt it is 0.0pt plus 0.92473pt minus 0.0924pt. Most of the time it is not there at all; the moment a line has to be tightened or loosened, a little of it wells up between every pair of characters. The job Western typesetting hands to the interword space, Japanese distributes thinly across every character boundary in the line. This page walks through that machinery — the Japanese glue, the kinsoku line-break prohibitions, vertical writing and ruby — the apparatus TeX had to grow for Japanese and that has no Western counterpart, with measured numbers throughout.
\kanjiskip and \xkanjiskip: the space you never typed
Japanese layout inserts two different glues automatically. \kanjiskip goes between two Japanese characters; \xkanjiskip goes at the boundary between Japanese and Latin. The decisive difference is their natural width: under jsarticle at 10pt, \kanjiskip is 0.0pt plus 0.92473pt minus 0.0924pt and \xkanjiskip is 2.5pt plus 1.49994pt minus 0.59998pt. The first is zero by default and only stretches when it must — which is why the character grid stays intact while the lines still justify. The second is always 2.5pt wide — which is why writing 日本語 and abc opens a gap on both sides of the Latin word although nobody typed a space. Once you hold these two apart, most arguments about Japanese spacing reduce to "which glue are we talking about?"
% measure it yourself: put this in the body and read the .log
\typeout{kanjiskip = \the\kanjiskip}
\typeout{xkanjiskip = \the\xkanjiskip}
\sbox0{日本語テキスト}\typeout{plain = \the\wd0}
\sbox0{日本語ABCテキスト}\typeout{mixed = \the\wd0}
\sbox0{ABC}\typeout{latin = \the\wd0}Measure it and the numbers line up. Under jsarticle at 10pt, 日本語テキスト is 64.72778pt wide and ABC is 21.8056pt. Add them and you expect 86.53338pt, but 日本語ABCテキスト measures 91.53339pt. The 5.00001pt difference is 2.5pt of \xkanjiskip inserted at two places: between 語 and A, and between C and テ. As proof, declare \noautoxspacing and measure the same box again: it returns to 86.53339pt, exactly the sum. And one more: 日本語 measures 27.74048pt, precisely three times the 9.24683pt of a single kanji — \kanjiskip sits between those characters and adds nothing to the width, because its natural size is zero.
| Parameter | On the pTeX side | On the LuaTeX-ja side | Default in jsarticle at 10pt |
|---|---|---|---|
kanjiskip | \kanjiskip=... | \ltjsetparameter{kanjiskip=...} | 0.0pt plus 0.92473pt minus 0.0924pt |
xkanjiskip | \xkanjiskip=... | \ltjsetparameter{xkanjiskip=...} | 2.5pt plus 1.49994pt minus 0.59998pt |
prebreakpenalty | \prebreakpenalty on a character | \ltjsetparameter{prebreakpenalty={...}} | 10000 for punctuation and closing brackets |
postbreakpenalty | \postbreakpenalty on a character | \ltjsetparameter{postbreakpenalty={...}} | 10000 for opening brackets |
jcharwidowpenalty | \jcharwidowpenalty=... | \ltjsetparameter{jcharwidowpenalty=...} | 500 |
inhibitxspcode | \inhibitxspcode on a Japanese character | \ltjsetparameter{jaxspmode={...}} | 2 on the full-width opening bracket, 1 on closers and 。, 3 on kanji |
xspcode | \xspcode on a Latin character | \ltjsetparameter{alxspmode={...}} | 3 for A, 2 for ., 1 for ( |
Those defaults change with the class, and that is what gives a page its character. Run the same measurement under jlreq and \kanjiskip is 0.0pt plus 2.5pt, \xkanjiskip is 2.5pt plus 2.5pt minus 1.25pt. Since a kanji in jlreq at 10pt is exactly 10pt wide, the stretch amounts to a quarter of a full-width character — two and a half times the tenth of a character that jsclasses allows. jlreq is therefore designed to justify by opening the character spacing considerably more, and the way lines pull in or push out at the right margin visibly changes. If a document "feels different" after a class change, print those two values with \typeout and compare them first.
Why full-width brackets get no extra gap: widths and \inhibitxspcode
Because the bracket itself declares "no gap on this side". \inhibitxspcode assigns each Japanese character a value from 0 to 3 controlling how \xkanjiskip may attach to it, and in jsarticle the full-width opening bracket ( carries 2, the closing bracket ) and the full stop 。 carry 1, and an ordinary kanji carries 3. Measurement settles it: 日本語(ABC)テキスト comes to 105.02704pt, which is nine full-width characters (9 × 9.24683pt) plus the 21.8056pt of ABC — not one \xkanjiskip anywhere. Full-width brackets already carry white space inside their own square, so adding another 2.5pt would visibly overdo it, and the bracket therefore forbids it. Keeping to the manuscript convention — Latin letters and digits half-width, Japanese punctuation and brackets full-width — is not only about appearance; it is what makes this spacing logic apply correctly. Drop a half-width ( into Japanese text and the \xspcode rules take over instead (( carries 1), producing quite different spacing.
% (u)pLaTeX: inspect and change how xkanjiskip attaches to one character
\typeout{open paren = \the\inhibitxspcode`(} % 2 in jsarticle
\typeout{close paren = \the\inhibitxspcode`)} % 1 in jsarticle
\inhibitxspcode`(=3 % allow the gap on both sides after all
% LuaLaTeX: same idea, other name -- and NO space after the comma
\ltjsetparameter{jaxspmode={`(,preonly}}Here is the trap when porting settings between pLaTeX and LuaLaTeX: the values 1 and 2 of \inhibitxspcode are numbered the other way round in LuaTeX-ja's jaxspmode. Measurement proves it. Set \inhibitxspcode to 1 for the kanji 語 on the pTeX side and the gap disappears from A語 (19.24684pt down to 16.74684pt) while it survives in 語A. Set jaxspmode to 1 for the same character in LuaTeX-ja and the opposite happens: the gap goes from 語A (19.24713pt down to 16.74713pt) and survives in A語. LuaTeX-ja's source gives its modes names — 1 is preonly and 2 is postonly, meaning "allow the gap only before / only after this Japanese character". pTeX's 1 means "only after". The two systems agree in words and disagree in numbers. Copy the settings mechanically and the gap lands on the wrong side. When porting, write the names preonly and postonly rather than the digits. One caution on the LuaTeX-ja side: do not put a space after the comma. With a space, TeX Live 2024 reports ! Missing number, treated as zero. and then applies 0 anyway — the gap vanishes on both sides instead of one.
Kinsoku: line-break prohibition with \prebreakpenalty and \postbreakpenalty
Kinsoku is the rule that keeps certain characters off the start or end of a line. Punctuation 。、, closing brackets )」』 and the small kana ゃ ぁ may not begin a line; opening brackets (「『 may not end one. Which character dislikes which side is supplied by the Japanese font metrics (JFM) together with the class, and TeX implements it not as a ban but as a penalty. Break the line just before the full stop 。 or the closing bracket ) and that character falls to the head of the next line — so jsarticle sets both \prebreakpenalty。 and \prebreakpenalty) to 10000. Break just after the opening bracket ( and the bracket is stranded at the line end, so \postbreakpenalty( is 10000 too. By TeX convention 10000 is an infinite penalty, that is, an outright prohibition. The virtue of building it this way is that prohibition becomes a matter of degree: write 10000 for "never", or 200 for "rather not", and the line-breaking algorithm weighs it against everything else. Western typesetting has no concept of kinsoku at all; this is machinery pTeX added to TeX.
% read the shipped values, then relax one of them
\typeout{full stop = \the\prebreakpenalty`。} % 10000
\typeout{open paren = \the\postbreakpenalty`(} % 10000
\prebreakpenalty`〜=200 % discourage, do not forbid
\jcharwidowpenalty=1000 % dislike a lone character on the last line
% the LuaTeX-ja spelling of the same three settings
\ltjsetparameter{prebreakpenalty={`〜, 200}}
\ltjsetparameter{jcharwidowpenalty=1000}Because it is expressed as a penalty, Japanese typesetting could grow a parameter with no Western counterpart at all: \jcharwidowpenalty, whose default is 500 in both jsarticle and ltjsarticle. It is the weight placed against leaving a single Japanese character stranded on the last line of a paragraph — the Japanese equivalent of a widow. The point is that 500 is a moderate value: not an absolute ban, but "worth tightening the other lines a little to avoid, though not worth wrecking the page for". In practice, when you meet a paragraph that insists on ending with one lonely character, try \jcharwidowpenalty=1000 before you rewrite anything. If that still does not settle it, adding or removing a single character of prose is often the faster fix.
How to switch on vertical writing: the tate option and plext
Today you switch it on with a class option. \documentclass[tate]{jlreq} runs under both uplatex and lualatex, and \documentclass[tate]{ltjsarticle} runs under LuaLaTeX. The pLaTeX family also ships dedicated vertical classes, utarticle and utbook, which compile under uplatex as they stand. Vertical writing is special for TeX not merely because the direction of the line and the direction of stacking swap over, but because the same character demands a different glyph. Punctuation and brackets have to be repositioned and rotated for vertical setting. That is why pTeX carries two families of font encoding from the outset — JY for horizontal and JT for vertical — and inside a box declared \tate the JT side is selected automatically. Western typesetting has no counterpart to any of this.
% vertical writing, three ways that all compile on TeX Live 2024
\documentclass[tate,uplatex]{jlreq} % uplatex; also works under lualatex
\documentclass[tate]{ltjsarticle} % lualatex
\documentclass[uplatex]{utarticle} % uplatex, dedicated vertical class
% tate-chu-yoko: a short horizontal run inside vertical text
平成\tatechuyoko{31}年 % jlreq only -- under uplatex or lualatex
平成\rensuji{31}年 % plext (pLaTeX) and lltjext (LuaTeX-ja)
% zw is the width of one full-width character, zh its height;
% \begin{minipage}<t>{10zw} sets a vertical box ten characters wideSetting two-digit numbers or units upright and side by side inside vertical text is called tate-chu-yoko. The spelling differs by route. \tatechuyoko{31} is defined by jlreq alone, and works under uplatex and lualatex so long as you are using jlreq; ltjsarticle does not have it, so writing \tatechuyoko there gives ! Undefined control sequence. The LuaTeX-ja spelling is \rensuji{31}, supplied by lltjext (or by the vertical classes ltjtarticle and ltjtbook), and pLaTeX has the same \rensuji{31} from the plext package. plext was ASCII's extension for vertical setting, and besides \rensuji it handles tables, boxes and their writing direction — its signature is the angle-bracket argument, as in \begin{minipage}<t>{10zw}, which states the direction explicitly and is what you need to drop a horizontal table into a vertical document. lltjext is the LuaTeX-ja counterpart, near enough a transcription in both names and argument conventions. When vertical setting misbehaves, check first whether the class accepts a tate option, then whether plext or lltjext is loaded.
Ruby (furigana) and emphasis dots: which package to choose
The current answer is pxrubrica on (u)pLaTeX and luatexja-ruby on LuaLaTeX. Both spell it \ruby{...}{...}, but pxrubrica distinguishes the two kinds of ruby that JIS X 4051 and JLReq define — and it makes you choose. A vertical bar splits the reading character by character: \ruby{漢字}{かん|じ} is mono ruby, one reading over each kanji. Group ruby, a single run of kana across the whole compound, has to be asked for: \ruby[g]{漢字}{かんじ}. Give a two-character word an unsplit reading with neither bar nor option and you get ! Package pxrubrica Error: Group count mismatch between the ruby and the body (2 <> 1). Emphasis dots come from the same package as \kenten{重要}. For something quick and light, the \ruby in okumacro, shipped with jsclasses, is enough — it is always group ruby, so \ruby{漢字}{かんじ} simply works. Be aware that CTAN also carries a package simply called ruby — Werner Lemberg's ruby from the CJK package, version 4.8.5 in TeX Live 2024 — a separate lineage altogether.
| Package | Route | What it gives you |
|---|---|---|
pxrubrica | pLaTeX / upLaTeX / LuaLaTeX / XeLaTeX | mono versus group ruby, control over overhang, and emphasis dots via \kenten |
luatexja-ruby | LuaLaTeX only | ruby integrated into LuaTeX-ja, so it interferes less with line breaking |
okumacro | pLaTeX / upLaTeX | shipped with jsclasses; a quick \ruby and \kenten, with no splitting syntax |
ruby | the CJK package family (pdfLaTeX and friends) | Werner Lemberg's separate lineage; not part of the Japanese TeX stack, so do not mix it in |
\usepackage{pxrubrica}
...
\ruby{漢字}{かん|じ} % mono ruby: the bar splits the reading per character
\ruby[g]{漢字}{かんじ} % group ruby: one run over the word -- [g] is required
\kenten{重要} % emphasis dots beside each characterHere is one accident that breaks without producing an error. Both pxrubrica and okumacro define \ruby, and loading both raises not even a warning — whichever comes second silently wins. Load okumacro after pxrubrica and then set \ruby{漢字}{かん|じ}, and the bar in かん|じ is no longer read as a mono-ruby separator but printed as a full-width vertical line (with pxrubrica alone, the reading splits properly over the two kanji). Nothing appears in the log, so you cannot know until you look at the PDF. Load exactly one package that defines \ruby. If you are on jsclasses and already load okumacro, delete that line when you switch to pxrubrica.
What JLReq is: the W3C "Requirements for Japanese Text Layout" and the jlreq class
JLReq is the W3C document "Requirements for Japanese Text Layout", a systematic written account — readable by implementers — of Japanese page design, line composition, line-break prohibition, ruby and the handling of punctuation. Until it appeared, this knowledge lived as the accumulated craft of printing houses, so publishing it mattered: web browsers and e-book readers alike now refer to the same document. The jlreq class is that document implemented in LaTeX, written by Noriyuki Abe. The class file shipped with TeX Live 2024 states the edition it follows in its opening comments: (based on JLReq 20200811). Choosing jlreq is therefore not merely "picking a newer class" — it is putting the justification for your page design in a public document.
The practical consequence is that you stop writing the fine adjustments yourself. Vertical writing is a single tate option, \jlreqsetup lets you set line-composition parameters by name, and the defaults for kinsoku and ruby already follow JLReq. Conversely, swapping an existing jsarticle document to jlreq unchanged widens the \kanjiskip stretch, changes how lines pack, and can move the page count. A sensible line to draw: jlreq for a document you are starting now, jsclasses when you must preserve the look of an existing manuscript. Either way, \kanjiskip, \xkanjiskip, \prebreakpenalty and \jcharwidowpenalty exist under the same names, so the last turn of the screw is always yours.