Skip to content Get in touch

Contact form

Scoped rich text styling in SASS

When developing content related sites, we often need to style body content of various entries on the site (blog posts? pages? events? etc.) in accordance with the styleguide of the project. And indeed, if you take a look at this very text you’ll see a variety of different styles applied to code, links, lists etc. within it.

Areas with rich text editable by content managers usually are styled with type selectors such as em or strong since content managers most often style their copy in a WYSIWYG editor.

However, in component-based front end methodologies (one of which I hope you use) usage of type selectors is usually not recommended or disallowed altogether. They are against the spirit of component based development, being too penetrating.

Why? If you have a common styling for all <h2> headings on the page, that means that it can easily apply to any element there, be it a simple h2 tag in page rich content, that heading you use for the site logo, or an h2 employed to denote a section of sidebar. This forces us to create a hard to sustain equilibrium of overrides. Design in a FE system built with components in mind must be completely separated from semantics, and HTML tags shouldn’t usually have their own styling being a white canvas for us to draw any picture on them. That’s why there exist linting rules that can limit type selectors usage.

Users may want to insert blocks with readymade styling into rich body content, and this is where the problem manifests itself clearly. The design of such a block can be easily torn apart by the ubiquitous type selectors, forcing us to use overrides. For example, in a div containing post body you make all links green — .body-text a {color:green}. Post body, however, contains a component of an image gallery with button-like, gray-colored pagination links. Those also become green because of inheritance, and this is not what we look for.

What is the best way then to apply project styling to such content while being able to insert usual front end components inside?

A mixin can provide the solution. We would include it inside every element on site front end which has rich content that is editable by content managers — page body, rich text custom fields such as ACF’s WYSIWYG editor field, etc. To avoid leaking of the type selectors’ styles into nested components we will employ the child combinator >:

@mixin textcontent {
& > {
    blockquote {
      font-style:italic; 
    }
    p, ul, ol {
      &:not(:only-child) {
        margin-top:$unit-y;
        margin-bottom:$unit-y;
      }
    }
    h2, h3, h4, h5, h6, p, ul, ol {
      &:first-child {
        margin-top:0; 
      }
      &:last-child {
        margin-bottom:0; 
      }
    }
    ul li {
      list-style-type:disc; 
    }
    ul, ol {
      li li {
        padding-left:$unit-x; 
      }
    }
  }
  img {
    display:block; 
  }
  iframe {
    width:100%; 
  }
}

Note how we use parent selector of SASS (&) to denote the element inside which the mixin is applied.

This way a complex component inserted in the middle of post body will still have its styling intact and not be affected by type selectors used to style the body text itself. The mixin will also allow us to add any other elements to style within rich text area without having them leaked.

More about this topic

Other thoughts

More thoughts