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

Themes, jQuery plugins and all sorts of widgets from outside of concrete5 often come with CSS that interferes with other aspects of a site or the concrete5 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 concrete5 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.

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

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 concrete5 5.7, a Less compiler is included with concrete5 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:

Less

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

Sass

.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.

Loading Conversation