Easily scope/namespace theme and block CSS using Less and Sass to prevent CSS conflicts

Mar 31, 2017

This tutorial is an updated legacy how-to by JohntheFish.

Themes, jQuery plugins and all sorts of widgets from outside of Concrete CMS often come with CSS that interferes with other aspects of a site or the Concrete dashboard. You can easily use a Less or Sass compiler to quickly limit the scope of such CSS. Even if you have not spotted any conflicts yet, limiting the scope of CSS is generally a good design practice that can help avoid trouble in the future. Limiting the scope of CSS is actually recommended in Concrete theme and block making guidelines.

When deciding on what CSS selector to scope your theme CSS to, an easy choice is to use .ccm-page. The .ccm-page wrapper class is conveniently part of every theme because of the required getPageWrapperClass() method.

<!-- Concrete and theme header stuff -->
    <div class="<?php echo $c->getPageWrapperClass(); ?>">
        <!-- page type layout for theme -->
    <!-- Concrete footer stuff -->

That is just background. If you look through the documentation and tutorials there is plenty more to read about structuring themes.

Suppose you already have a mass of CSS, from a theme you are importing or from a framework you are building a theme from. It may contain hundreds or thousands of styles. You don’t really want to have to go through all those styles one-by-one and prefix them with .ccm-page. It’s a tedious and error prone task that can only become a maintenance nightmare.

The trick is to use Less or Sass to add scope. Less and Sass are extensions to CSS that, when processed by a respective compiler, output pure CSS. Take all the CSS you want to scope, wrap it in a single scope declaration and apply the Less or Sass compiler. The output will be fully scoped CSS.

There are many ways to implement the details. If the theme is already built from Less or Sass, you can usually just create another file with the scope declaration that includes all the various component files within the scope declaration. Or you could edit the outermost file to add a line to open the scope at the top and another close it at the end. You may also need to change the extension of all the files you are compiling to end in .less or .scss so the compiler will know to process them.

Do some Googling and you will soon find Less and Sass compilers that you can run from the desktop, run online from a web site or build directly into your site to compile on demand. Starting with Concrete 5.7, a Less compiler is included with Concrete and allows you to use .less files in your theme.

Let’s begin with the trivial case of a simple style sheet for the "Monster Font" theme that inconveniently globally over-sizes all paragraphs. That may be what the theme wants, but it turns out some parts of the dashboard are also suffering monster sizing.

p {
    font-size: 50px;

To limit the scope you can wrap it in your scope class:

.ccm-page {
    p {
        font-size: 50px;

When you then compile the Less or Sass, the resulting CSS will be:

.ccm-page p {
    font-size: 50px;

The over-sized paragraph font is now constrained to only apply to paragraphs inside .ccm-page and cannot interfere with anything outside that container.

That was just a trivial example. The technique extends to wrapping many styles in one go. What you are aiming for is an outer wrapper for all the styles that looks like:

.ccm-page {
    // wrap all styles inside here

You aren't limited to wrapping individual styles, you can wrap entire files using @import:


.ccm-page {
    @import "grid.less";
    @import "blocks.less";
    @import "typography.less";


.ccm-page {
    @import "grid";
    @import "blocks";
    @import "typography";

After compiling, all the styles in the imported files would be scoped to .ccm-page.

The same approach for scoping theme CSS is used for scoping block CSS, the only difference is the class you use for scoping. A general recommendation for naming the block scope class is to use the class prefix of "ccm-block-" followed by the block handle. For example, if your block handle was "my_block_name", then your block scope class would be .ccm-block-my-block-name. This class would then be applied to the element that wraps your block HTML, or depending on the type of block and structure, it would be applied to parent elements in your block HTML.

When you compile the Less or Sass, the output will be CSS that is all instantly scoped to your container. Styles that argue with the dashboard, with other themes, other block templates or other jQuery widgets should be a thing of the past.

Recent Tutorials
Generate a report with author information and form summaries in Concrete CMS.
May 9, 2022

In Concrete CMS, you can use a form to initiate contact between logged-in users and then create helpful reports. After form submissions are collected, they can be searched, sorted, and exported as a spreadsheet. This tutorial will detail how to add author information to a report using the advanced search.

How to clone and customize Atomik theme
Feb 14, 2022
By linuxoid.

How to clone and customize Atomik theme

Update jQuery to 3.5 on Concrete CMS version 8.5.x
Dec 1, 2021
By hissy.

If you have to take some time to fix your site to work with version 9 and want to update jQuery immediately, you can override it.

Add-On Developers: Get Your Add-Ons Ready for Concrete CMS 9.0
Aug 6, 2021
By andrew.

Concrete CMS 9.0 is coming! But there are some changes in version 9 that might affected your add-ons and themes. This document aims to answer questions about the most common ways that your add-ons might need to be changed, and common problems you'll run into.

Permissions for editors in a multilingual site
Jun 2, 2021
By myq.

How to set up a multilingual Concrete CMS site for groups of language-specific editors

Getting Started with Doctrine in Concrete CMS
Jan 20, 2021
By linuxoid.

Doctrine is a very flexible, simple (once you get to know it better) and powerful PHP library for database interactions primarily focused on the ORM = Object Relational Mapping and DBAL = DataBase Abstraction Layer.

Was this information useful?
Thank you for your feedback.