Creating CSS capable of rendering multi-lingual content and right-to-left languages.

Choosing the Fonts

An important step in making sure your document is published properly in different scripts (languages) is choosing a font that covers the entire set of characters from that script (language).

However, you can specify a series of font families (using the CSS font-family property) that are used as fall-backs. Once a word cannot be rendered using the first specified font, the next font family is tried. The following example uses some common fonts available on Windows to make a CSS stylesheet capable of properly displaying a large number of languages, from all European to Asian languages:

* {
	font-family: Calibri, SimSun, "Malgun Gothic";	
Assigning a font for all the elements, and not relying on basic fonts, makes the document accessible.
Note: If your CSS does not assign a font to a part of your document, then the following sequence of fonts are used: Serif, Times, Times New Roman, Symbol, MingLiU, MS Mincho, Arial Unicode MS. This combination covers a wide character range, but might be different from what you need.

Support for Right to Left Languages

The Unicode BIDI algorithm is applied automatically. For best result in HTML, make sure you mark the right-to-left content, or the left-to-right content embedded in right-to-left, with proper direction attributes:

<p dir='rtl'>SOME ARABIC TEXT <p dir='ltr'>Some latin words.</p>.</p>

For arbitrary XML, use the unicode-bidi and direction CSS properties:

<para dir='right-to-left'>SOME ARABIC TEXT.</p>


para[dir='right-to-left'] { 
    direction: rtl; 
    unicode-bidi: embed; 
Note: There are built-in rules in Oxygen PDF Chemistry that automatically match the dir attribute in any XML vocabulary, with the same semantic as for HTML. The accepted values are: ltr, rtl, auto. If you use other attribute names or other values for this attribute, you should add CSS rules similar to the one above.

For elements in a right to left context, Oxygen PDF Chemistry automatically switches the left borders, paddings, and margins with the ones from the right. This keeps your CSS as simple as possible.

In the following example, the p element has a left border.

p {
    border-left: 1pt solid orange;

Suppose it is placed in a div with the default ltr direction. The orange line is painted in its left border. But if it is placed in a div with the rtl direction, the orange line will be painted in its right border because that is where the text begins. In a sense, "left" becomes "start".

Note: To disable this behavior, you may use the -no-rtl-mirroring command line parameter.


Ligatures for the Latin scripts are disabled by default. To enable them, see the -enable-latin-ligatures command line parameter.

Other non-Latin scripts have the ligatures enabled.

Changing Labels Depending on Language

When developing a CSS that will apply to output localized to a number of countries, you must consider changing the static text (CSS generated) depending on the language.

Note: Your document must use the xml:lang or lang attributes to specify the content language, ideally on the root element. The value must be specified using a language identifier (such as "en", "en-US", "en-CA", "fr", "fr-CA").

Consider a case where all the chapter titles are prefixes with the word "Chapter", followed by the figure counter. Depending on the language of the XML/HTML document, you need this word to change to: "Kapitel" for German, or to "Chapitre" for French.

<div class='chp'>

The CSS may be written starting with a default rule that will be used when the content has other language than the ones that are expected. This rules will also be used for English content:

div.chp > h2:before{
    content: "Chapter " counter(chp);

Next, write rules for each of the languages:

div.chp > h2:lang(de):before{
    content: "Kapitel " counter(chp);
div.chp > h2:lang(fr):before{
    content: "Chapitre " counter(chp);

A good practice is to keep all the static text for a specific language in a separate CSS.

To make the maintenance easier, you can separate the strings from the counter value by using one of the advanced features of Oxygen PDF Chemistry (the :before and :after pseudo elements) with multiple levels. So you could write the default rule as:

div.chp > h2:before(2){
    content: "Chapter ";
div.chp > h2:before(1){
    content: counter(chp);

Now, the more specific rules are more simple:

div.chp > h2:lang(de):before(2){
    content: "Kapitel ";
div.chp > h2:lang(fr):before(2){
    content: "Chapitre ";
Note: The multiple-level pseudo elements is a non standard feature, and might not work if you switch to another processor.