Concrete CMS Coding Guideline (5.7.x and later)

This is a community-contributed tutorial. This tutorial is over a year old and may not apply to your version of Concrete CMS.
Feb 4, 2016

Creative Commons License

Pull requests are welcome! Please help fix any misspell, grammar error and others to improve!

Translations

Language URL
English https://github.com/katzueno/concrete5-Coding-Guideline/tree/english
Japanese (日本語) https://github.com/katzueno/concrete5-Coding-Guideline/tree/japanese

Additional translation are welcome! Please fork it, make a branch for the language, translate and send me the pull request!

About This Guideline

Purpose

This guideline was made for front-end engineers who are creating an original Concrete block for client specific work.

Concrete is front-end flexible CMS. But it also means that it be could easily result in CSS and/or JS conflict between site's CSS and interface UI.

This coding guideline is made to help avoid the conflict for Concrete Japan, Inc. partners.

Concrete Japan, Inc. is helping various company's Concrete project. Please feel free to contact us at any time for your project needs. We can work internationally.

http://concrete5.co.jp/

Target

This coding guildeline targets to the following:

  • Have the knowledge of HTML + CSS + JS
  • Have the basic knowledge of Concrete
  • Building an original Concrete theme based on the client's request
  • Design is usually provided via Photoshop PSD, Illustrator's AI or other design data. And then crete HTML+CS+JS template

Additionally, we recommend the front-end engineer to closely get in touch with the designer during design process.

License

This work is licensed under a Creative Commons Attribution 4.0 International License.

Creative Commons License

Use this guideline "as is". We hold no responsibility against any damages caused by this guideline.

By using this guideline, you have agreed that Concrete Japan, Inc and its affiliate hold no responsibility or liability against any damages caused by using this guideline.

Disclaimer

This guideline will always be work-in-progress.

There is no perfect way to code.

Please use this guideline "as is". We are not responsibile for any damages caused by this guideline.

Credit

  • Katz Ueno (Concrete Japan, Inc) - http://concrete5.co.jp
  • Remo Laubacher (Ortic Solutions GmbH) - [http://www.ortic.com}(http://www.ortic.com)

Example: Basic Specification

This is an example table for a project before you start coding.

Example: Basics

Name Content
Theme Handle ***
Framework used Bootstrap / Foundation / 960Grid / Original

Example: Libraries Using

Please indicate which libraries you are planning to use

Libraries Version
Bootstrap 3.1.1
jQuery 1.11.3
Bxslider TBA

Example: Page Template List

These page template handles are used for Body Wrapper Class in Concrete. So we recommend that you determine the following Page Template list before starting to code.

Name Handle
p0_0 Home p0_0_top
p0_1 Department Top p0_0_top_dept
p1_0 Default default
p2_0 Product Top p2_0_product_top
p2_1 Product Index p2_1_product_index
p2_2 Product Detail p2_1_product_detail
  • You can only use letters, numbers and underscore (_)
  • Underscore (_) will be converted to hyphen (-) when printed to the Body Wrapper Class automatically

Example: Page Type List

These page type handles are used for Body Wrapper Class in Concrete. So we recommend that you determine the following Page Type list before start coding.

Name Handle Page Template used
pt0_0 Home pt0_0_top p0_0_top
pt0_1_1 A Deaprtment Top pt0_0_1_top_XX_dept p0_0_top_dept
pt0_1_2 B Department Top pt0_0_2_top_XX_dept p0_0_top_dept
pt0_1_3 C Department Top pt0_0_3_top_XX_dept p0_0_top_dept
pt1_0_1 Default Index default_index default
pt1_0_2 Default Detail default_page default
pt2_0 Product Top pt2_0_product_top p2_0_product_top
pt2_1_1 Product Index Category A pt2_1_1_product_index_XXX p2_1_product_index
pt2_1_2 Product Index Category B pt2_1_2_product_index_XXX p2_1_product_index
pt2_1_3 Product Index Category C pt2_1_3_product_index_XXX p2_1_product_index
pt2_2_1 Product Detail Category A pt2_1_1_product_index_XXX p2_1_product_detail
pt2_2_2 Product Detail Category B pt2_1_2_product_index_XXX p2_1_product_detail
pt2_2_3 Product Detail Category C pt2_1_3_product_index_XXX p2_1_product_detail
  • You can only use letters, numbers and underscore (_)
  • Underscore (_) will be converted to hyphen (-) when printed to the Body Wrapper Class automatically

Basic Rules

  • You must use UTF-8 encoding
  • You must use LF (UNIX) line break

Where to Save

Concrete saves the theme related files under the following locations.

Version Destination
Concrete 5.6.x /themes/XXX/
Concrete 5.7.x /application/themes/XXX
  • XXX should be replaced to your desired theme handle
  • You can only use small letters, numbers and underscore (_). You CANNOT use CAPITAL letters.

The above locations are for your own theme. If you want to make your theme as 'package', You must follow it own rules. Please visit Concrete offocial documentatio section on concretecms.org

Images, CSS and JS assets that are embedded onto theme

Images, CSS and JS assets should be saved onto the following locations. (These are files that are fixed onto the theme only.)

  • /application/themes/XXX/css/
  • /application/themes/XXX/js/
  • /application/themes/XXX/images/

or

  • /application/themes/XXX/assets/css/
  • /application/themes/XXX/assets/js/
  • /application/themes/XXX/assets/images/

We recommend to put everything onto "assets" folder

HTML Coding Location

We recommend you to save HTML mock ups under:

  • /application/themes/XXX/html/

Please refer the same CSS, JS and images files that used for Concrete themes files, so that it would be easier to debug.

Library Set

Each Concrete instance is installed with the following libraries.

If you plan to use the same libraries, you should try to use the same version of libraries to avoid conflict

Especially, you should use same version of jQuery that Concrete use

Library Name c5.6.3.3 c5.7.3.1 c5.7.5.2 c5.7.5.3 c5.7.5.6
ace N/A 1.1.8 1.2.0 1.2.2 1.2.2
backbone TBA TBA TBA TBA 1.1.2
backstretch TBA 2.0.4 2.0.4 2.0.4 2.0.4
bootstrap 2.0.3 3.1.1 3.1.1 3.1.1 3.1.1
dropzone N/A 4.0.1 4.1.0 4.2.0 4.2.0
dynatree N/A 1.2.6 1.2.8 1.2.8 1.2.4
font-awesome N/A TBA 4.2.0 4.2.0 4.2.0
html5shiv N/A N/A 3.7.2 3.7.2 3.7.2
respond N/A N/A 1.4.2 1.4.2 1.4.2
jquery 1.7.2 1.11.1 1.11.3 1.11.3 1.11.3
jquery/awesome-rating N/A TBA 0.1.1 0.1.1 0.1.1
jquery/cookie N/A 1.4.1 1.4.1 1.4.1 1.4.1
jquery/fileupload N/A TBA 5.39.0 5.39.0 5.39.0
jquery/form N/A TBA 2.87 2.87 2.87
jquery/live-update N/A TBA TBA TBA TBA
jquery/magnetic-pop-up N/A TBA TBA 1.0.0 1.0.0
jquery/mousewheel N/A TBA TBA 3.1.12 3.1.12
jquery/pep N/A TBA TBA TBA TBA
jquery/placeholder N/A TBA TBA 2.0.8 2.0.8
jquery/textcounter N/A N/A N/A N/A 0.3.4
jquery/tristate N/A TBA TBA TBA TBA
jquery/touch-punch N/A TBA 0.2.3 0.2.3 0.2.3
jquery/ui TBA 1.10.3 1.11.4 1.11.4 1.11.4
jquery/visualize N/A TBA TBA TBA TBA
kinetic N/A TBA 4.7.2 4.7.2 4.7.2
Modernizr N/A TBA 2.8.3 2.8.3 2.8.3
packery N/A TBA TBA 1.0.2 1.0.2
picturefill N/A TBA 2.3.1 2.3.1 2.3.1
redactor N/A TBA 10.2.1 10.2.1 10.2.1
select2 N/A TBA 3.5.1 3.5.1 3.5.1
spectrum N/A TBA TBA 1.3.4 1.3.4
swfobject N/A TBA TBA TBA 2.1
TinyMCE 3.5.11 N/A N/A N/A N/A
underscore N/A TBA 1.6.0 1.6.0 1.6.0
  • N/A: not included in the core
  • TBA: To be announced / currently checking its version.

If you want to specify how to load and unload these assets onto your theme, read the Concrete documentation.

CSS/JS Framework

If you want to make a (responsive) Concrete theme, concerte5 supports the following framework

  • Bootstrap
  • Foundation
  • 960Grid

If you are not sure which framework to use, we highly recommend to use Bootsrap. In Concrete.7.x., most of the basic blocks and page are built with Bootstrap. So you may be able to reduce the number of hours.

However, Concrete use different version of Bootstrap. Be careful.

When using Foundation, you may need to be careful. But you don't get affected by the Bootstrap version.

CSS Coding Guideline

Do-nots & Cautions

body Do-nots

Don't add ID and class to body (Required)

Don't add ID and class to body tag.

Don't apply Position to body (Required)

Don't add position to body.

No background (Recommended)

Don't add background to body. Please apply background to the following Body Wrapper Class

don't use ccm-* classes (Required)

Except ccm-page, don't set any class naming ccm-* These are used for Concrete UIs and dashboard.

Body Wrapper Class (Required)

From Concrete 5.7.x, the <div> tag with following CSS classes are inserted right after the <body> tag; and it closes right before the end of <body> tag.

  • ccm-page
  • page-template-XXX (XXX is the handle of Page Templates)
  • page-type-XXX (XXX is the handle of Page Type)

If you would like to apply certain overall design change depends on the Page Template and Types, you may use the above classes.

If you are not sure what to do, just ignore page-template-XXX and page-type-XXX classes but just ccm-page.

  • To name Page Template and Page Type handles, you can use alphabet, number and underscore(_)
  • However, underscore(_) will be converted to hyphen (-) automatically when printing it to the body wrapper class
  • The user may leave the Page Type blank. Therefore, page-type-xxx may not be printed out to HTML sometime.

Don't apply CSS style to HTML elements or Bootstrap class directly

Concrete prints out the HTML as the part of its control panel. So you don't want to cause the conflict between your own CSS and Concrete.

Therefore, you don't want to apply CSS style directly to HTML elements, such as <a> or <input>, and Bootstrap class such as .btn .btn-success and etc without specifying .ccm-page as the parent class.

If you're converting the existing HTML+CSS Template, I recommend to use LESS and wrap with .ccm-pages class

BAD EXAMPLE: Don't make the CSS like the following

/* HTML elements that will also affect Concrete dashboard */
a { /* CSS  */ }
input { /* CSS  */ }

/* Bootstrap classes that will also affect Concrete dashboard */
.btn { /* CSS  */ }

GOOD EXAMPLE 1: Specify CSS under .ccm-page class

/* Make sure to wrap HTML elements with Page Wrapper class */
.ccm-page a { /* CSS  */ }
.ccm-page input { /* CSS */ }

/* Make sure to wrap Bootstrap class with Page Wrapper */
.ccm-page .btn { /* CSS */ }

GOOD EXAMPLE 2 : Using LESS

/* Specify all CSS within .ccm-pages class */

.ccm-page {

    a { /* CSS */ }
    input { /* CSS */ }

    .btn { /* CSS */ }
}

Z-index (Required)

Z-index, for all of your CSS, must be set to less than 1000.

  • In Concrete 5.6.x z-index must be set less than 5

Don't do anything to depends on file upload location (Required)

Don't code anything that rely on uploading the images to the same directory where a Concrete editor can freely edit and change.

  • In Concrete, images and other assets are uploaded onto the directory which are randomly generated.
  • For example, you won't be able to execute auto mouse over image effects by adding _over postfix to the file name. (unless the image assets are stored in theme folder and the image filename are hard-coded.)

Don't add ID to blocks (Strongly Recommended)

Try to avoid any coding that uses ID.

Meta title, description, keywords, OGP tag is not needed (Recommended)

Meta Title, Description, Keywords, OGP tags will be inserted. It's not necessary to implement for HTML coding.

Coding Requirement

Provide ALL patterns of blocks

  • Based on the spec and design data, provide all design patterns of coding.
  • Example: Left aligned, center, and right aligned image.

Provide the patterns when the text, image and/or data is empty

  • Consider the coding when elements are empty.
  • Example: When thumbnail image of Page List is not present, the position, margin and padding of page title won't be messed up and etc.

Consider the Pattern of Repeated Elements

  • When showing the repeating elements, don't break the design layout by increasing and decreasing the number of elements.
  • When showing the grid style elements, don't messed up the layout by increasing and decreasing the number of elements.
  • When showing the grid style coding, don't wrap the elements by each row but entire section of the block.
  • Make sure to provide coding with repeating elements of various patterns.
  • If necessary, provide the coding when elements are empty or 1 entries when multiple entries are expected.
    • Example: When there is no result in Page List block, do you want to show other stuff or simply blank?
    • Example: When a slideshow block only has one image, do you still want to display pagination interface or transition effects?

Consider the Size of Repeated Elements

  • When coding grid content and must match the height of each elements, provide JavaScript to adjust the height of each element
  • If JavaScript option is not available, consider to create a block that has one (1) row. And if you want to have multiple rows, add more blocks.
  • Exmaple: There is a grid design Page List with thumbnail, date and page title elements. When the length of page title differ, the height of each block differs and messes up the layout.

Consider the Volume of Text

Consider the patterns when text is shorter and longer than expected.

  • Example: When you have a aligned image + text block without proper clearfix, the layout could messed up when you have shorter text.
  • Exmaple: There is a Page List block with thumbnail, date and title. If the page title become two-lines, it could messed up the layout.

Consider Edit Bar on top when you have fixed navigation or anchor link

When a user with edit permission comes to Concrete site, Concrete will place 49px height edit bar on top. This may cause some inconvenience to the editor. She or he may not be able to see the global navigation or the anchor link will be right behind the edit bar.

Therefore, you may want to prepare the special CSS and JS code that will ONLY be inserted when the user see the edit bar.

SAMPLE

<?php $cp = new Permissions($c); if($cp->canViewToolbar()){?>
    <style media="screen">
        .header {top:48px;}
        /* Other CSS Style */
    </style>

    <script type="text/javascript">
        /* Additional setting such as smooth scrolling */
    </script>

<?php } ?>

Coding Recommendation

Try to make the block coding as generic as possible so that it can be used for other pages

  • Blocks can be placed anywhere in the area (unless you resrtict via permission settings)
  • Try to avoid the coding that can only be used at certain area. For example, the certain area is wrapped with certain div. The block is inheriting the CSS from it. (There may be some exception such as header, footer or the area with different background color)

BEM (Block Elements Modifier)

We recommend to embrace BEM method.

https://en.bem.info/

Use of LESS

From Concrete 5.7.x, it equipped with LESS compiler. Except when previewing HTML template, there is no need to compile LESS.

We recommend to use LESS, But not necessary as long as you can provide compiled CSS file.

Coding Guideline for Each Block

Content

Content block uses Redactor JS library, and print out the following coding. It print out the code without class and ID. You may want to adjust your CSS by the following two patterns.

Default

Content block won't wrap any div.

You may want to wrap the certain div in Area.

Recommended

Make each Content block wrap with <div class="wysiwyg"></div>. In this case, you must override Content Block.

You should try to avoid the situation that a Concrete user has to manually type CSS class or ID by going into code view of Content Block. If there is a certain pattern such as adding additional <span> tag to H tags, consider making a custom JS.

The following is the sample HTML coding of Content Block.

You should make CSS based on the following sample. Or we recommend to create the sample pattern by yourself by making a actual content block in Concrete, and provide those coding to the coder to adjust CSS>

<div class="wysiwig"> <!-- This div tag is not generated via Concrete default content block, but Concrete Japan, Inc recommend this way. In order to achieve this, you must override Content Block. -->
    <p>P</p>

    <h1>H1</h1>

    <blockquote>
        Blockquote
    </blockquote>

    <p><strong>Strong</strong></p>

    <p><em>Italic</em></p>

    <p><u>Underscore</u></p>

    <p><del>Strikethrough</del></p>

    <p>UL List</p>

    <ul>
        <li>UL List</li>

        <li>UL List</li>

        <li>UL List</li>
    </ul>

    <p>OL List</p>

    <ol>
        <li>OL List</li>

        <li>OL List</li>

        <li>OL List</li>
    </ol>

    <p>No Indent</p>

    <p style="margin-left: 20px;">1 Indent</p>

    <p style="margin-left: 40px;">2 Indent</p>

    <p>Image</p>

    <p><img src="/index.php/download_file/view_inline/1"></p>

    <p>Align Left</p>

    <p>Align Right</p>

    <p>Table</p>

    <table>
        <thead>
            <tr>
                <td>Head</td>

                <td>Head</td>

                <td>Head</td>
            </tr>
        </thead>

        <tbody>
            <tr>
                <td>1</td>

                <td>2</td>

                <td>3</td>
            </tr>

            <tr>
                <td><p>Paragraph tag may get inserted upon certain situation</p>
                <p>When you happened to have the multiple lines text within a cell like this.</p></td>

                <td><p>Paragraph tag may get inserted upon certain situation</p>
                <p>When you happened to have the multiple lines text within a cell like this.</p></td>

                <td><p>Paragraph tag may get inserted upon certain situation</p>
                <p>When you happened to have the multiple lines text within a cell like this.</p></td>
            </tr>
        </tbody>
    </table>

    <p><a href="/index.php?cID=1" data-concrete5-link-type="ajax">Internal Link</a></p>

    <p><a href="/index.php/download_file/view/1" data-concrete5-link-type="image" data-concrete5-link-launch="lightbox-image">Light box Link - Image</a></p>

    <p><a href="/index.php?cID=1" data-concrete5-link-type="ajax" data-concrete5-link-launch="lightbox-image">Light box Link - AJAX</a></p>

    <p><a href="/index.php/download_file/view/1" data-concrete5-link-type="image">File Download Link</a></p>

    <p>Align Text to the Left</p>

    <p style="text-align: center;">Center text</p>

    <p style="text-align: right;">Align text to the right</p>

    <p style="text-align: justify;">Justify Text</p>
    <hr>

    <p><span style="color: rgb(192, 80, 77);">Font color</span></p>
</div>
<!-- This div tag is not generated via Concrete default content block, but Concrete Japan, Inc recommend this way. In order to achieve this, you must override Content Block. -->

HTML Block

Default

By default, HTML Block is wrapped with the following div

<div id="HTMLBlockXXX" class="HTMLBlock">

XXX is block ID.

Recommended

Sometime, you don't want those HTMLBlock class or ID. Therefore, you may want to override HTML Block not to output div tag.

Autonav

This is the navigation block based on list tag.

  • You can add levels
  • Commonly used for global navigation menu
  • You could create mega menu via additioanl customization
  • Breadcrumb is generated by this block

You could add additional div or span for each designated levels of navigation. However, it could be complicated. So please try to code with simple ul li structure.

Page List

Available elements

  • Page Title
  • Published Date
  • Thumbnail Imae
  • Other Page Attributes
    • Topics
    • eyc

Wrap the entire block with div, and then create the repeatable elements

Pagination

Although pagination has variety of options, it is recommended to code as the following.

Default Code of Pagination

Here is the sample code of pagination.

<div class="ccm-pagination-wrapper">
    <ul class="pagination">
        <li class="prev"><a href="#">← Previous</a></li>
        <li><a href="#">1</a></li>
        <li class="disabled"><span>…</span></li>
        <li><a href="#">17</a></li>
        <li><a href="#">18</a></li>
        <li><a href="#">19</a></li>
        <li><a href="#">20</a></li>
        <li><a href="#">21</a></li>
        <li><a href="#">22</a></li>
        <li class="active"><span>23 <span class="sr-only">(current)</span></span></li>
        <li class="next disabled"><span>Next →</span></li></ul></div>

The sample coding use Bootstrap 3.

1. div wrapper

Please wrap with <div class="ccm-pagination-wrapper">

2. ul

Please wrap with <ul class="pagination">.

3. "Previous" Link

FORMAT

<li class="prev"><a href="#">← Previous</a></li>

  • Use prev class
  • If there is no link, add disable class (If you don't want to display the previous link when it's not linked, please adjust CSS by using these classes.)
  • Add <span></span>
  • The text ← Previous can be configurable to any text
4. Numbering: Basic

<li><a href="#">7</a></li>

  • list tag
  • a tag
  • page number
5. Numbering: Active Page

When displaying the page that you're currenltly viewing

<li class="active"><span>23 <span class="sr-only">(current)</span></span></li>

  • active class added to the list tag
  • wrap with span
  • <span class="sr-only">(current)</span> is sample coding if you want to add additional coding for the current page. You could simply choose to leave ie blank.
6. Numbering: Skip

<li class="disabled"><span>…</span></li>

  • li tag with disabled class
  • <span>…</span> to display '...'
7. "Next"

<li class="next disabled"><span>Next →</span></li></ul></div>

  • list tag
  • with next class
  • If there is no link, disabled class is added. (If you don't want to display the previous link when it's not linked, please adjust CSS by using these classes.)
  • "Next →" is default text. But it can be configurable,

CSS File

In Page List block, it will load the /concrete/css/frontend/pagination.css

But you sometime don't want to load extra css file. You can either do any of the 2 steps

1. Set page_theme.php to tell Concrete that you're not using

This is highly recommended option.

You are probably going to make new theme. So make sure to create page_theme.php and tell Concrete that you won't be using any of frontend CSS files.

Example

<?php
public function registerAssets() {
    $this->providesAsset('css', 'core/frontend/pagination');
}

Then it won't load pagination CSS.

2. Override /concrete/css/frontend/pagination.css

Create a CSS file like /application/css/frontend/pagination.css If you don't want anything, you can simply make a blank CSS file

3. Override /concrete/blocks/page_list/controller.php

Create a controller override of Page List block at /application/blocks/page_list/controller.php, then remove or comment the following line

$this->requireAsset('css', 'core/frontend/pagination'); is.

Related Document of customizing Pagination

In addition, you can entirely customize the pagination format.

Image Slider

Available Elements

  • Image
  • Title (Text)
  • WYSIWYG (Similar to Content Block)
  • Link

You can apply the similar coding to the page list block. If you want to use any particular slideshow JS library, make sure it won't cause any conflict against Concrete's JS and other theme's JS.

If you want to create a image slideshow that has a thumbnail navigation, you must print out all thumbnail images in HTML, then use JS to create thumbnail navigation. Example: http://memocarilog.info/memocarilog-demo/galleriffic-demo/

Image Block

<picture>
    <!--[if IE 9]><video style='display: none;'><![endif]--><!--[if IE 9]></video><![endif]-->
    <img src="/index.php/download_file/view_inline/1" alt="#" class="ccm-image-block img-responsive bID-XXXX">
</picture>
  • 'bID-XXXX' will have its bID.

FAQ Block

Available Elements

  • Navigation Link Text
  • Title Text
  • Description

Page Title

Working / help wanted

Page Attribute

Working / help wanted

YouTube

Working / help wanted

Google Map

Working / help wanted

Form Block

Working / help wanted

Recent Tutorials
Create custom Site Health tasks
Apr 19, 2024
By myq.

This tutorial will guide you through the creation of a new Site Health task

Reusing the same Express entity in multiple associations
Apr 11, 2024
By myq.

How to create and manage multiple associations in Express

Express Form Styling
Apr 11, 2024
By myq.

Different ways to style Express forms

Setting addon/theme version compatibility in the marketplace
Jan 9, 2024

For developers worn out with setting the latest addon or theme version manually across too many core versions, here is a JavaScript bookmarklet to do it for you.

How to get the locale of a page
Jan 8, 2024
By wtfdesign.

Now, why don't we just have a getLocale() method on Page objects beats me, but here's how you work around it

Using a Redis Server
Jun 16, 2023
By mlocati.

How to configure Concrete to use one or more Redis servers to persist the cache.

Improvements?

Let us know by posting here.