skip navigation

Styling blockquotes

Adding CSS to jazz up blockquotes is often far harder than it should be. Take for example adding oversize quotes at the beginning and end. These can be added using the pseudo elements ::before and ::after along with a special content properties content: open-quote and content: close-quote.

blockquote::before {
    content: open-quote;
}
blockquote::after {
    content: close-quote;
}

This is simple enough but even here things can go awry.

Blockquote or blockquote > p ?

The first problem is whether or not you’re applying this to the right element. If you’re writing in markdown and having your blockquotes parsed to HTML it could be that the blockquote is rendered with a paragraph tag inside.

<blockquote>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Exercitationem.</p>
</blockquote>

In that case you may want to target that paragraph element instead. If it has a margin-top value other than zero it could leave the quotation mark high above the first line.

So instead of blockquote::before it might need to be blockquote:first-child::before. Use the :first-child pseudo-selector in case the quote has multiple paragraphs.

The problem

See the Pen This Pen by Synphod (@Synphod) on CodePen.

Styling the quotes

Since the opening quote and closing quote will probably share many of the same values let’s start with that:

blockquote>p:first-child::before,
blockquote>p:last-child::after {
    font-size: 4em;
    font-family: georgia, serif;
    color: green;
    vertical-align: -0.4em;
    line-height: 0.1em;
}

Because a 4em sized character naturally has a greater line-height you can adjust that using line-height and vertical-align. This will require some trial and error to get it how you like it.

Next add the quotes using the CSS values open-quote and close-quote. Note: unlike most content values these are NOT enclosed in speech marks: content: open-quote

blockquote>p:first-child::before {
    content: open-quote;
}
blockquote>p:last-child::after {
    content: close-quote;
}

Finally the opening quote will make it appear the paragraph is indented. If you don’t want that then you can add an outdent using a text-indent with a negative value:

blockquote>p:first-child {
    text-indent: -1.6em;
}

Final code

This generally works but if you change the font size of the pseudo elments you’ll probably have to fiddle with other values like line-height too. This is a modified version based on an article in CSS Tricks. The article suggests setting a child paragraph to display: inline. However that won’t work if the blockquote contains multiple paragraphs.

It’s certainly not the only way to do this. Other methods use absolute positioning for instance. If I find a use for the other methods I’ll add them in due course.

However this method is reasonably succinct. For both quote marks you’ll need at least two declarations. If you’re styling both of them then it’s more succint to add the first one. The last one is optional and targets the first paragraph.

The one thing I don’t like is the guesswork needed for the vertical-align and text-indent values. I think the line height would be consistent regardless of the font-size of the quotation marks.

blockquote>p:first-child::before,
blockquote>p:last-child::after {
    line-height: 0.1em;
    font-family: georgia, serif;
    font-size: 4em;
    color: orange;
    vertical-align: -0.4em;
}
blockquote>p:first-child::before {
    content: open-quote;
}
blockquote>p:last-child::after {
        content: close-quote;
}
/* Optional but you might prefer a hanging outdent */
blockquote>p:first-child {
    text-indent: -1.6em;
}