Rendering Quotes – CSS

Rendering Quotes – CSS

The W3C recommends that visual user agents render quotation marks according to the specified language attribute, since many languages adopt different styles for quotations. Yet no user agent I have tried will render quotations in a language-specific manner in their default style sheet. Let’s change that.

When building tripoli, one of the goals was to ensure language-specific quotation marks through CSS. But that turned out to be a difficult task to achieve, since many user agents either simply ignore the specs or make up their own way of rendering quotes. Even so called “modern” browsers like safari.

CSS 2.1 includes a property called quotes. The quotes property specifies quotation marks for any number of embedded quotations. It’s a tricky property, so before continuing make sure you read the entire section at W3C and understand how the content property defines what type of marks to produce and the quotes property how they will look.

Before getting on with the CSS, let’s start with some basic HTML for testing purposes:

  1. <p><q>Generic quote and <q>another quote</q> inside</q></p>
  2. <p lang="sv"><q>Swedish quote and <q>another quote</q> inside</q></p>
  3. <p lang="da"><q>Danish quote and <q>another quote</q> inside</q></p>
  4. <p><q lang="sv">Swedish quote and <q>another
    quote</q> inside with the lang attribute set in the parent
    <code><q></code> tag</q></p>
  5. <blockquote><p>This is a generic paragraph with a
    <q>quote element</q> inside a
  6. <div lang="sv"><blockquote><p>This is a
    swedish paragraph with a <q>quote element</q> inside a
  7. <div lang="da"><blockquote><p>This is a
    danish paragraph with a <q>quote element</q> inside a

All set. Now try rendering that in a user agent without any quotation CSS applied: Example 1

Judging from the results, we can make the following conclusions:

  • IE 6 and 7 simply ignores the quotes, no matter what. Probably due to that they do not understand the :before and :after selectors.
  • Opera, Safari 2 and Safari 3 render default double quotes (0022) in all languages, even for nested or inner quotes.
  • Firefox and other gecko browsers render correct US-EN quotes for all languages, regardless of the lang attribute.

Internet Explorer will be ignored from now on since they require a javascript to dynamically insert quotes. Instead, let’s focus on the “modern” browsers who supports proper CSS.

W3C recommends the following CSS code to correctly render language-spceific quotations, in this example we focus on the danish and swedish quotes:

  1. :lang(sv) { quotes: '\201D' '\201D' '\2019' '\2019'; }
  2. :lang(da) { quotes: '\00BB' '\00AB' '\203A' '\2039'; }
  3. q:before { content: open-quote; }
  4. q:after { content: close-quote; }

Note: I used some ISO 10646 quotation mark characters for rendering.

Very well, let’s try that in your browser suite: Example 2. By looking at the results we can make the following conclusions:

  • Firefox now render language-specific quotations where specified and defaults US-EN quotations elsewhere
  • Opera also render correct quotations where specified but resorts to double quotes (0022) elsewhere
  • Safari 2 and 3 is unchanged since the quotes property is unsupported

Why is safari not following standards? Besides officially not supporting the quotes property, it is also worth taking a look inside the default style sheets when it comes to quotations. Opera and Firefox have the following rules:

  1. q:before { content: open-quote; }
  2. q:after { content: close-quote; }

… which is good enough, while safari has this:

  1. q:before { content: '"' /* FIXME: content: open-quote; */ }
  2. q:after { content: '"' /* FIXME: content: close-quote; */ }

My point exactly, FIX ME!. Obviously not yet.

Let’s start with fixing Opera’s default quotes by adding the following CSS rule:

  1. q { quotes: '\201C' '\201D' '\2018' '\2019'; }

Ok, now Opera and Firefox gets it right. But what about Safari? Well, the problem is that Safari ignores the quotes property and manually inserts quotation marks via the :before and :after selectors. So we need to use them as well. But we cannot simply define generic quotes by using something like q:before { content: "\201C"; } for safari, since they will override the language-specific quotes properties in firefox. Instead, let’s try this CSS code:

  1. *[lang~='da'] q:before, q[lang~='da']:before { content: '\201E'; }
  2. *[lang~='da'] q:after, q[lang~='da']:after { content: '\201C'; }
  3. *[lang~='da'] q q:before, q[lang~='da'] q:before { content: '\2019'; }
  4. *[lang~='da'] q q:after, q[lang~='da'] q:after { content: '\2019'; }
  5. *[lang~='sv'] q:before, q[lang~='sv']:before { content: '\201D'; }
  6. *[lang~='sv'] q:after, q[lang~='sv']:after { content: '\201D'; }
  7. *[lang~='sv'] q q:before, q[lang~='sv'] q:before { content: '\2019'; }
  8. *[lang~='sv'] q q:after, q[lang~='sv'] q:after { content: '\2019'; }

Since Safari has pretty good support for the attribute selector we can use the [lang~=val] selector to target any element with the lang attribute whose value is a whitespace-separated list of language. If Safari was following the specs it would be enough with one simple line to define language-specific quotes. Now we need four heavy lines for each language. Anyway, now we only have one more thing to do for Safari to get this perfect: add some nice generic quotes if no language is specified:

  1. q:before { content: '\201C'; }
  2. q:after { content: '\201D'; }
  3. q q:before { content: '\2018'; }
  4. q q:after { content: '\2019'; }

Here is how it looks now: Example 3

Now Opera, Safari and firefox render the quotations correctly. Please be aware of that the CSS above will override the quotes property defined for firefox earlier, so you could simply remove those if you like. But it might be a good idea to keep them as a reference to what should have been the correct way to render quotes. In Tripoli, I did not bother to render language-specific quotes for Safari since it would require a lot of redundant CSS code. Instead, I would recommend to stick to the actual language you will use for the specific project.

There are several ways to add quotation marks to the blockquote element. But first we need to ask ourselves: Should we add quotations to blockquotes? This is what the specs say:

We recommend that style sheet implementations provide a mechanism for inserting quotation marks before and after a quotation delimited by BLOCKQUOTE in a manner appropriate to the current language context and the degree of nesting of quotations. However, as some authors have used BLOCKQUOTE merely as a mechanism to indent text, in order to preserve the intention of the authors, user agents should not insert quotation marks in the default style. The usage of BLOCKQUOTE to indent text is deprecated in favor of style sheets.

So, W3C recommends that we add quotation marks to the blockquote, as long as we use it in a correct way (not to indent text). So let’s find out how we can do this. One way is to add double quotes around any element that is the first descendants of the blockquote and then single quotes around any q element inside by using some fancy selectors:

  1. blockquote * { quotes: ''; }
  2. blockquote > *:before { content: '\201C'; }
  3. blockquote > *:after { content: '\201D'; }
  4. blockquote q:before { content: '\2018'; }
  5. blockquote q:after { content: '\2019'; }

This should work in all modern browsers, including safari. The code will insert quotes before and after any element that is a direct child of the blockquote and then single quotes around any q element that are descendants to the blockquote. The first rule is necessary to reset the quotes in firefox before inserting them.

Now we just have to make language specific blockquote quotations! I didn’t bother to do it for all languages but you can check out the source code to get an idea about how it can be done.

I have collected all the CSS and HTML into a complete final example file (source) that you can use as a reference when creating quotes. I only added support for swedish and danish quotations besides the generic EN-US ones. The main problem as I can see it is that it requires a lot of code to get the quotes right, and then I haven’t even begun with Internet Explorer yet. So a general advice: stick to the actual language for the specific project and be aware of browser glitches. Quotation marks is probably one of the least developed areas in web typography, but it might add that little extra attention to details in your designs.