Skin Development Primer
This article will teach you what you need to know to be able to develop your own b2evolution skins as quickly as possible.
Note: if you only are looking for a quick & dirty hack to change your CSS, try this: How to add custom CSS. The current page you’re looking at is much more interesting though ;)
If you hare coming here as a professional skin/theme designer and you have never actually used b2evolution before, we recommend you browse through our guided tours in order to get a general overview of what b2evolution does and how it’s laid out. Especially look at:
You should probably always use the very latest cutting edge beta or even alpha version of b2evolution – get it from the GitHub reprository here – when developing skins, because extended features are added all the time (especially regarding Containers and Widgets).
The screenshots below are for b2evolution version 6.2.1-alpha. This article is currently being updated for b2evolution version 6.4.0-alpha.
Below, we will guide you through the following phases:
- X-raying a skin through the browser
- Understanding the skin files
- Starting your own skin
- Changing the skin design
A skin (or a "theme" as others call it) is a certain "look & feel" applied to a b2evolution Collection.
In the default b2evolution installation with demo contents, each collection uses a different skin.
In the following paragraphs we will examine the collection named "Blog A" which is installed by default in b2evolution and which happens to use the skin named "Bootstrap Blog".
As a skin developer you should do one of the following:
- either turn on debugging. (The previous link will basically show you how to set
$debug = 1in the right config file).
- or turn on the Dev menu by seting
$dev_menu = 1in a similar way (This second way is cleaner)
Once you have done one of the above, a "Dev"==!#DEL#!==Dev menu will appear in the Evo Bar.
When you browse through different pages of a collection, look at the Dev menu and notice how the value of "$disp" changes. This is a direct mirror of the PHP
$disp variable used internally by b2evolution. This is a key concept because the value of
$disp will determine which "template" (which PHP file) of the current skin will be called to display the current page.
Here are some examples of different "disps" as we call them:
Each disp will actually try to call a different template, that is: a different PHP file in the skin folder to display the page. Each template can in turn include sub-templates. We’ll go into details later but you should know that you can actually see what happens by turning on "Show includes" in the "Dev" menu:
You will then see all the includes wrapped in a green box:
Note that if you have "Site skin" turned on (it is enabled by default), then you will also see the global "site-wide" header and footer wrapped in purple boxes.
Each disp/template of a skin will display some hardcoded HTML and some dynamic PHP but the bulk of the content will come from Containers.
Inside the Containers you will find Widgets. The administrator of a b2evolution website can easily move widgets around inside a container or even from one container to another.
To better grasp the concept of Containers and Widgets, you can activate the "Show containers" option in the "Dev" menu or in the "Collection" menu:
You will then see a red box around each Container and a blue box around each Widget:
Your challenge as a skin designer will be to build designs that work well with a variety (not to say an infinity) of possible arrangements of widgets in your containers. Fortunately, the current trends in responsive "block" design makes this easier than it used to.
If you click "Edit" in a red box or if you use the "Collection > Widgets…" menu, you will access the Widget manager screen in the Back-office:
The above shows all the containers of the current skin and the widgets they contain. It may even show containers that are not in the current skin but that still contain widgets (which you might have added in a previous skin you used for this collection). This way you are sure never to lose a widget which may contain fine tuned customizations.
Note the small link "Reload containers" at the top right. You will need this when you add a new container to one of your skin templates. When you click this, b2evolution will scan all the templates of the current skin and look for newly added containers. (It will also notice removed containers):
Note: in future versions of b2evolution, skins will explicitly declare a list of the containers they want to use with some added benefits, but this is not fully implemented at the time of this writing.
Widgets are under the control of the site administrator. At the time of developing a skin you don’t really know what widgets will be put into which containers… but you should definitely experiment with a variety of combinations that make sense!
By default b2evolution installs demo widgets in a series of "common Containers" which are used by almost all skins. This is not only a good starting point for testing a skin design, you should absolutely positively make sure that your skins display correctly out of the box with these default widgets. Otherwise your skins will look broken to most users who test them.
Of course you can and should also let your skins support more elaborate widgets combinations!
Here are the basics to manipulate widgets and try different combinations:
Move widgets by simply dragging and dropping them at another place (including a different container):
Each Widget has a properties panel to configure the level of details that it will display:
Each Container has an "Add widget" button that can be used to add a widget to that container:
Note: At this time, the list of available widgets is long and difficult to grasp without trial & error. If you are a graphic designer and think you could design one expressive icon to identify each widget, please talk to us ;)
Here we will go into details about the files and folders that make the skins work…
In b2evolution’s root directory, you should find a folder named
skins with contents similar to this:
Each of the sub-folders of the skins directory represents (and contains) an actual skin.
In the example above the skin we were looking at is the one in the
bootstrap_blog_skin folder. Let’s open that folder:
There are 4 kind of files heres:
- Red: these are "main" templates. These are files that b2evolution will call to display some specific disps. The universal fallback template that will be called if no better one is found is
index.main.php. This is a key file to know.
- Blue: the "skin.class" file. This file gives b2evolution some information about the skin. For example the full name of the skin is defined in there.
- Green: CSS files.
- No color: various screenshots to showcase the skin before it’s installed.
When b2evolution wants to display
$disp = front, it will look for a file named
front.main.php. When b2evo wants to display
$disp = posts, it will look for
posts.main.php. And so on for any
However, in the case of this skin, the templates above don’t exist! Because of this, b2evolution will resort to calling
index.main.php instead. This is the universal fallback. This file must exist for every skin.
index.main.php will be used until you define more specific
.main.php template is basically what lays out a Header container, a Sidebar container, a Footer container… and a main area.
In the main area, it will then hand-off display to a
xyz.disp.php template. Here again, the name will match
$disp. When b2evolution wants to display
$disp = front, it will now try to include a file named
_front.disp.php. When b2evo wants to display
$disp = posts, it will now try to include a file named
Here again, you will notice that these files are not defined for this skin. Furthermore, there is no such thing as
_index.disp.php! Actually, in this case, b2evolution will resort to using a fallback template. We’ll tell you more about fallback templates in the next section.
For now, let’s have a quick look at the other templates we have in the "Boostrap Blog Skin" directory:
access_denied.main.php: this will be called for
$disp= access_denied (in case of private blogs). We want to use this instead of
index.main.phphappens to define a Sidebar container which we don’t want to show in case of denied access!
access_requires_login.main.php: You can probably guess this one (very similar case).
- As a convention, each skin should define all its CSS in a file named
- Ideally, that CSS should be minified into a file called
style.min.css. If you don’t want to use minification in your skin, you can disable it (see below).
- Of course the CSS may actually be pre-processed (b2evolution uses Grunt for this). In this case we use LESS and the source file is
Remember the missing
_posts.disp.php file we mentioned above?
When b2evolution doesn’t find a template it needs in the directory of the skin, it will look for it in the fallbacks folders named
Let’s look at
Can you see it has
_posts.disp.php for example?
These fallback templates will be used when your skin doesn’t define its own variant of one of these templates. This means that your skin doesn’t need to implement every single feature and especially every new feature of the latest b2evolution version. There will almost always be a fallback mechanism to include a default template when your skin doesn’t have it. In many cases the fallback template will integrate well with your design. In other cases, of course, the visual aspect may not be optimal.
Notice there are basically 3 kinds of templates:
- Red: the ".main" templates – these are deprecated files that are no longer used as of b2evolution 6.5.1. If you still have them after upgrading to 6.5.1, you can delete them.
- Orange: the ".disp" templates (this is the second level.)
- Yellow: the ".inc" (sometimes ".form") templates (these are basically snippets of code that may be included in other templates, either ".main" or ".disp")
Now, how do we know for sure which template is used when?
Quite simple actually… do you remember the "Show includes" feature we introduced earlier:
If you look closely you will see that each green (or purple) box shows you the exact template being included. In this case, for example, you can see that when b2evolution is trying to include
_font.disp.php it falls back to the version it finds in
So what about this
Each skin can define which skin API version it’s using. If it doesn’t define anything it will use version 5. If you want version 6, you need to define it in
- If a skin uses the API version 5, then b2evolution will always search for fallback templates in
- If a skin uses the API version 6, then b2evolution will first try to find fallback templates in
/skins_fallback_v6/. And only if this fails will it fall back to
Note there are no versions 1, 2, 3 and 4. They are all equal to 5. Before b2evolution version 6, there was no multi-step fallback mechanism. All skins had to share the same fallbacks.
We very much recommend that you always start with an existing skin that somehow approaches what you’re trying to do and progressively modify it. In our experience it’s the most productive way to reach your goal, with the added benefit of always having a working work-in-progress instead of keeping all the integration problems for the end.
If you would build a static HTML version of your skin first, you would quickly find that once you integrate real widgets into the containers you would need to rework all your margins and paddings. You would also find that you made some design decisions that are not desirable in the context of containers and widgets.
A least for your first time, we recommend you start with a stock skin that ships with b2evolution (so you’re sure that your reference point actually goes "by the book" and is not a variation of a variation of a variation with lots of obsolete code in it). Furthermore, we actually recommend you start with
bootstrap_blog_skin which is the most stable reference point.
For the purpose of this primer, let’s start by duplicating the
bootstrap_blog_skin skin folder. Let’s call our new skin
Note: if you know a little bit about GitHub, there is an even better option: start by cloning (or forking if you wish) the starter skin: https://github.com/b2evolution/starter_skin . This is the same as the
bootstrap_blog_skin but it has some additional support files that will come in handy later.
So no matter what option you chose, you should now have a directory called
Once you’ve renamed the folder, you also need to edit the
_skin.class.php file that it contains. Open it in your favorite editor and make the following changes:
class starter_Skin) to
class custom_Skin. Note that your skin folder ends in
_skinwhereas the class name ends in
_skinwith an uppercase S. This is a very important distinction. Please make sure you follow this.
- Change the skin name from
return 'Bootstrap Blog';to
return 'My Custom Skin';
- Optionally change the
@subpackagecomment at the top.
The resulting file should look something like this:
(Only the beginning of the file is quoted above.)
Use the evobar Menu "Collection > Skin…" to see the param screen of the currently installed skin:
Click "Choose a different skin":
Here you could select one of the other installed skins. However, since your new skin hasn’t been installed yet, it doesn’t appear here.
In order to install your new skin, click "Install new skin". (You only need to do this once.)
The following screen shows you all the skin folders that have not yet been installed:
Choose the "custom" skin/folder and click "Install NOW!".
Once the skin is installed, you will be taken back to the screen where you can pick from all installed skins:
Select "My Custom Skin" by clicking on its thumbnail. (This thumbnail comes straight from
You’re now back on the current skin’s param screen, except you are now using the new "My Custom Skin":
To get your feet wet, you could start by changing a little bit of CSS.
Like most modern web designs, b2evolution Skins use compiled CSS. This means that there are several different files involved:
style.scss, which is LESS or SASS code and which has been compiled (processed) into:
style.css, which is normal CSS code, which in turn has been compressed (minified) into:
style.min.css, which is the optimal, best performance CSS file your website can load.
The skins that come with b2evolution use Grunt for compiling. Other skins, may have used other tools.
Using LESS or SASS and Grunt is outside the scope of this primer but we’ll give you a quick example of how you can customize the CSS file of the skin.
So let’s start by getting the LESS/SASS and minified files out of the way, before they interfere with your CSS edits: Delete
style.scss if it exists) as well as
style.min.css from your skin’s folder.
Now, check that the skin still works. It should automatically resort to loading
style.css instead of
style.min.css. Should this not be case, please check the following line in your skin’s
Note that you may actually be able to do a lot more CSS-only customizations than you might think. This is made possible because the
<body> tag is supercharged with contextual classes that will allow you to use very context specific CSS selectors in a number of situations. Learn more here: Targeted CSS Selectors.
We recommend you take a walk through your
/skins/custom/index.main.php by opening it in your text/PHP editor.
See how it lays out some structural
<div>s and fills them with Containers. Also note how it’s including sub-templates.
Note how an array of parameters is passed to each container as well as to each included sub-template. By modifying these parameters you can radically influence the HTML code that will be generated by Widgets as well as by Fallback Templates without needing to edit them.
This is the main reason why most skins have so few templates and why fallback templates are called so much – because it’s easy to pass parameters to customize the output of the fallback templates.
Here we will show you how to add a
single.main.php controller in order to have a completely different layout for a single post view (disp=single) than for the home page and everything else (all other disps).
In this example we will keep the original layout with a sidebar for most pages but for disp=single, we’ll make a template that has no sidebar in order to remove distractions at the time of reading.
Start by duplicating the file
index.main.php and name the new one
single.main.php. This new file will now automatically be called for all disp=single pages.
Let’s start customizing this new template…
You can remove the Sidebar container (from the
single.main.php template in this case) by removing the following PHP code:
Save the template and try it out.
Now you have an empty column on disp=single. You may also want to remove the div for that column:
In order to get rid of the "empty column", let’s deal with the main column. The code that currently sets its div is like this:
Since we don’t have a sidebar any more, we don’t need to deal with the multiple settings possible in the skin params any more either. So we don’t need the PHP code that determines the width and position. Let’s go for a full width main area:
But when you look at it, it’s not very classy… is it?
So let’s make the main area narrower and with margins on the sides:
But we don’t want the margins on small screens. So let’s make this responsive:
This of course if far from perfect. We’re just quickly demonstrating the concept here.
Remember you can override any fallback template just by duplicating the file into the folder of your skin. This new version will then the called instead of the fallback.
We’d love to answer your questions so they can benefit everyone else!
Please post any question you have at this point into the comment form below.
We’ll update this primer as needed.
Created by • Last edit by on Jun 20, 2019