Tutorials Bugs Masterclass Free stuff Test pages Proposals

Basic concepts

Advanced concepts

RichInStyle.com CSS2 tutorial - Language styles


Language selectors

Language of family



Non-right-to-left text



Language selectors

CSS-2 provides two selectors for selecting elements according to their language:

Language is of specified family

P[lang|="en"] matches <P lang="en-us"> as well as "en" or "en-*".

:lang(x) selector

This pseudo-class matches an element in human language x - e.g., P:lang(en) matches <P lang="en"> (English), and a document with a Content-Language HTTP header of pt is matched by :lang(pt). Note that it is matched in the same way as above in that :lang(en) matches en-us.

It matches more elements than the [lang|=] selector insofar as it matches according to language, which is inherited (in HTML), rather than attribute value, which can only be specified on a tag.


This states the encoding method of the document, may only appear in external style sheets, and must be the very first thing of the file, with not so much as a space before it:

@charset "ISO-8859-1"; /* This is the only character set most Western authors need */

Non-left-to-right text

Non-left-to-right text has often been difficult to achieve. With CSS-2, however, two properties are provided to cope with this.


The direction property is used to specify the direction of text. Direction: ltr (initial value) specifies that text goes left-to-right, and direction: rtl, right-to-left. Direction is inherited. However, it only affects inline-level elements if their unicode-bidi is embed or override.

Note that of itself direction does not affect the direction of text because directionality is implicit to the text. For example, this paragraph has dir=rtl. This will not affect the direction of the text in the paragraph because the paragraph's characters are implicitly left-to-right. The exception to this is when unicode-bidi is set to bidi-override, which overrides this default behavior.


It is very common that (mainly right-to-left) text has text going in multiple directions within it. The unicode-bidi property specifies the behavior in this case.

Valid values are normal (initial value), embed and bidi-override.

Unicode-bidi is not inherited.

The values specify behavior with respect to the Unicode bidirectionality algorithm. Normal means that the element does not open a new embedding level. Implicit (that based on characters rather than elements) reordering is effective across inline-level element boundaries.

If specified on an inline-level element, embed means that the element opens a new embedding level. The direction of the level is supplied by direction.

Bidi-override creates an override if specified on an inline-level or block-level element that only has inline-level descendants. This overrides implict reordering.

Bidi examples

Although the initial value for unicode-bidi is normal, in the browser style sheet all block-level elements are given unicode-bidi: embed.

Thus you have by default [Inline-level elements] {unicode-bidi: normal} [Block-level elements] {unicode-bidi: embed}.

As a result, say you have:

<P style="direction: rtl">
Left-to-right text AND THIS IS RIGHT-TO-LEFT

There is no problem here - the P element has unicode-bidi: embed (because of the UA style sheet), which means that it can cope with one level of text with different directionality, and the text will be correctly rendered.

However, say you have:

<SPAN>THIS IS RIGHT-TO-LEFT <Q>this is left-to-right within that SPAN</Q></SPAN>

Because the SPAN has unicode-bidi: normal, it cannot cope with implict reordering, and the rendering will not be correct. To override this, it is necessary to add unicode-bidi: embed to the SPAN element. This will create a new embedding level so that implicit reordering can take place.

If the text has already been placed in visual order, you might wish to suppress reordering. For example, if you have this piece of text: 'WERBEH' that has already been placed in visual order, to stop reordering according to the implicit directionality of the text you must add a bidi-override. Thus <SPAN style="unicode-bidi: bidi-override">WERBEH</SPAN> would prevent reordering and simply render the text in the direction specified (or inherited) by the direction property. In this case the appropriate direction is direction: ltr, because it is appropriately ordered for that.

Differences between CSS and HTML bidi

  1. In HTML, direction is only inherited to block-level descendants. In CSS direction is inherited to all elements, the differences between block-level and inline-level descendants is made by means of the unicode-bidi property.
  2. In HTML specifying direction automatically opens a new level in the bidi algorithm; in CSS you have to specify unicode-bidi: embed to achieve this.
  3. In HTML the dir attribute is required when you specify a bidi-override; in CSS because direction is inherited, this isn't necessary.

This is the end of the CSS2 guide. I would strongly recommend that you now read the master class so that you can hone your skills to true style sheet mastery, the bug guides, so that you can make sure that your styles work, or simply the front page so you can access it all.