concrete5 – use LESS files for block templates

If you built a couple of block templates, you’ll probably have had some nasty CSS code. Quite often you’ll have block specific options, a background color for example, which has to change the CSS file. You can easily do that, no doubt, just use addHeaderItem or put a style tag in your view.php. The block controller code might look like this:

1
2
3
public function on_page_view() {
   $this->addHeaderItem('<style type="text/css">#my-block-' . $this->bID . ' { background: ' . $this->backgroundColor . '; }</style>');
}

In most cases you’ll find situations where the developer mixed a code like shown above with an external CSS file.

That certainly works but it’s usually much more elegant to keep all the block related CSS rules in a single file. We can use the great LESS language to achieve a much more elegant solution. Wouldn’t it be great if you could put all the CSS rules in a file like this:

1
2
3
4
5
6
#my-block@{bID} {
   background: @backgroundColor;
   display: block;
   width: 100px;
   height: 100px;
}

That’s possible, it just takes a bit more code. You’ll need lessphp available here http://leafo.net/lessphp/. In your block controller, you can use a method like this to compile a LESS file like the one shown above into a static CSS with all variables replaced on the fly if required. Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public function on_page_view() {
    // get current block template
    $template = $this->getCurrentTemplate();
 
    $bv = new BlockView();
    $bv->setController($this);
    $bv->setBlockObject($this->getBlockObject());
 
    // build path to less file
    $blockPath = $bv->getBlockPath();
    if ($template == '') {
        $blockTemplateLessPath = $blockPath . DIRECTORY_SEPARATOR . 'view.less';
    } else {
        $blockTemplateLessPath = $blockPath . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $template . DIRECTORY_SEPARATOR . 'view.less';
    }
 
    // there's a less file, check if we have to rebuild it
    if (file_exists($blockTemplateLessPath)) {
        $lessFileHash = md5($blockTemplateLessPath . $this->bID . filemtime($blockTemplateLessPath));
        $cacheFile = DIR_FILES_CACHE . '/my-block-' . $lessFileHash . '.css';
 
        // cache file doesn't exist, rebuild it
        if (!file_exists($cacheFile)) {
            $lessc = Loader::library('3rdparty/lessc.inc', 'my_block');
            $lessc = new lessc();
            $lessc->setVariables(
                    array(
                        'backgroundColor' => $this->backgroundColor,
                        'bID' => $this->bID
                    )
            );
            $lessc->compileFile($blockTemplateLessPath, $cacheFile);
        }
 
        // include generated css file
        $this->addHeaderItem('<link rel="stylesheet type="text/css" href="' . REL_DIR_FILES_CACHE . '/cover-picture-' . $lessFileHash . '.css' . '"/>');
    }

If these instructions were a bit short, you can find a working example in one of my github repositories, check this: https://github.com/Remo/concrete5-cover-picture/blob/master/blocks/cover_picture/controller.php#L43-L81.

I hope this helps you to clean up your code!




1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *