Styling the Code and Pre Elements


Styling <code> and <pre> tags in CSS seems pretty straightforward. However, there are two issues that usually crop up, in my experience.

  1. The content of <code> shouldn't be wrapping, if screen with allows it. On mobile screens it should wrap, but there should also be a hint that indicates the start and end of the long code line that's wrapping. This is pretty easy to achieve.
  2. If your text is within a parent container with a set width, sometimes the content of the <pre> tag will overflow. Usually, it's easy to just set overflow-x:auto; and let the user scroll left/right within the tag. The problem is, most contemporary OSs (or DEs, if you're on Linux) now hide the scroll bar by default when it's not in use, so it can be hard to tell if the area is scrollable. Alternatively, you can do nothing and just deal with weird line breaks, but that can lead to confusion, especially if there is indentation.

Below is a minimalistic solution that doesn't use any external libraries, just vanilla CSS and JavasScript. You can see it in action throughout my website, although it's slightly modified to fit with the site's theme.

HTML

Here's an example of how your HTML might be structured.

<article>
    <p>Some text with <code>a piece of code</code> within it.</p> 
    <pre>
        Some preformatted text here,
        perhaps on multiple lines. 
        Perhaps with lines that are way, way too long to fit in the parent container without overflowing.
    </pre>
</article>

CSS

The <article> container has a set width.

article {
    width: 700px;
    margin: 0 auto;
}

Basic styles for <code> and <pre> tags.

code, pre {
    color: #fff;
    border-radius: 5px;
    background: #000;
}
code {
    white-space: nowrap;
    padding: 1px 5px;
}
pre {
    box-sizing: border-box;
    margin-bottom: 20px;
    padding: 10px 15px;
    overflow-x: auto;
}

Next, we create a class called "overflowing", which will be added by JavaScript only on <pre> elements that are detected to be overflowing. A dashed border added and rounded borders are removed from the right side to hint at the fact that the block is truncated. <pre> elements that are not overflowing remain untouched.

pre.overflowing {
    border-right: 2px dashed #fff;
    border-radius: 5px 0 0 5px;
}

Once the user hovers over (or taps) over the element, the dashed border is removed and rounded corners are re-applied.

pre.overflowing:hover,
pre.overflowing:active {
    width: max-content;
    border-right: none;
    border-radius: 5px;
}

Use media query to pre-wrap the <code> element if user is on a small screen or mobile. The border-radius property applied before hints at where the line starts and ends.

@media only screen and (max-width: 767px) {
    code {
        white-space: pre-wrap;
    }
}

JavaScript

// Function that checks if an element is overflowing.
function isOverflowing(element) {
    return element.scrollWidth > element.clientWidth;
}

// Go through all pre elements and see if they're overflowing.
// If so, add class "overflowing" to them.
var elements = document.getElementsByTagName("pre");
for(var i = 0; i < elements.length; i++) {
    var element = elements[i];
    if(isOverflowing(element)) {
        element.classList.add("overflowing");
    }
}

Examples

Short text doesn't get truncated:

Lorem ipsum dolor sit amet, consectetur adipiscing elit

Long text overflows, but gets styled appropriately:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.