Structure of Custom Blogger Themes
The documentation for Blogger Themes is lacking and incorrect in many spots, making it really difficult to get started on your own. You could of course rip code segments from existing themes but that is hardly the best method to go about creating your own theme. This document will cover the basic structure of the Blogger theme. In future posts (linked at the end) I will cover more parts about Blogger Themes.
Blogger Themes are created using an XML Document (only one file). This single document specifies all cases of the website (index / archive / item) along with special styles for the “Widgets” you add to each section of your blog under the Layout section of Blogger Administration Panel. With all of this content in a single document, organization is key and understanding what everything does is even more important.
Basic Layout
Below is a very stripped down frame of the beginning layout of the XML document for a theme.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html b:version="2" expr:dir="data:blog.languageDirection" xmlns="http://www.w3.org/1999/xhtml" xmlns:b="http://www.google.com/2005/gml/b" xmlns:data="http://www.google.com/2005/gml/data" xmlns:expr="http://www.google.com/2005/gml/expr">
<head>
<title><data:blog.pageTitle /></title>
<b:include data="blog" name="all-head-content" />
<b:include data="blog" name="google-analytics" />
</head>
<body>
</body>
</html>
For the most part, you will not need to change or remove anything that is displayed in the above code. The first line just creates the XML document and specifies it’s version and encoding. After that we just declare the DOCTYPE to html and set up the HTML namespaces.
The HTML namespaces required are for b
, data
and expr
. The b
namespace is used for nearly every call to process various information.
As for the expr
namespace, it’s use as “expression” to include data
inside of HTML attributes. And as you can probably guess, the data
namespace allows you to display dynamic and stored data onto the page.
In the HTML tag, you will also note the expr:dir
. This creates a
normal dir
attribute but Blogger handles the attribute as data from
Blogger instead of text because it’s prefix is expr:
. The data
included is data:blog.languageDirection
, which if you can’t guess is
LTR or RTL but in lowercase. If you would like to add plain text along
with data for an attribute, wrap your plain text in quotations and
include a plus symbol between the data and the string.
In the head tags, we set the title and include a data tag. These data
tags will pull data from the required resource in Blogger. The one
inside of the title tags is referencing the global blog
resource
which stores various global information you will need (see other posts
at the bottom of the page for all data types).
After setting and escaping the data tag, we have two b:include
tags
which will load the required resources we need. The attributes for
b:include are data
which tells Blogger what data we should pass to
that b:includable
along with name, which lists the includeable to
include at that location. An includable is a resource that can be
included. The two listed in the header are global and cannot be
modified. You will create an includable when customizing widgets for
your theme.
The rest of the document is laid out as a normal HTML template and acts just like one. Even when you add the following Blogger Tags in the HTML document, they will mostly turn into div’s or include another part of a template that will turn into div elements.
Working with b:section
Inside of your HTML body
tag, you will have XML tags of b:section
These tags specify a section inside of the Layout for Blogger that
users can add widgets to. Section tags cannot contain HTML elements or
more sections, it can only contain b:widget
tags. Below are the
attributes you can set for a section.
- id: (required) A unique identifier for the section. Will be added to the final HTML code for the ID attribute.
- class: (optional) A class attribute in the HTML Final Code. Using common class names, Blogger will attempt to transfer the correct widgets and gadgets to these sections when you switch themes later on. For example using “navbar”, “header”, “main”, “sidebar” and “footer” will successfully move the widgets to the correct locations.
- maxwidgets: (optional) The integer of the maximum widgets this section can contain. If no limit is specified of the attribute is omitted there will be no limit.
- showaddelement: (optional) A value of “yes” or “no” having “yes” as the default value. This determines if the section in the layout page will show a box to add new elements.
- growth: (optional) A value of “horizontal” or “vertical” with the value of “vertical” being the default. This value specifies how each widget will stack next to each other in a section.
<!-- Allow user to add more widgets / gadgets to this section with showaddelement -->
<b:section class="sidebar" id="sidebar" showaddelement="yes" growth="vertical">
<!-- Nothing can go here except b:widgets -->
</b:section>
<!-- Only have widgets here that the programmer defined since showaddelement is no -->
<b:section class="main" id="main" showaddelement="no" growth="vertical">
<!-- Nothing can go here except b:widgets -->
</b:section>
Working with b:widget
Widgets have to be placed inside of b:section
tags and are used to
display content on your blog. A few examples of the widgets available
are “Blog”, “PageList”, “Header”, “Navbar” to list a few. Widgets
placed inside of sections are the default template widgets and can be
removed if not locked (check attributes below). You do not need to
modify widgets and can use them “as-is” by making the b:widget
tag
close at the end of it’s declaration and not having any child elements.
Widgets that are customized are only customized to that section and for
that instance of the widget (as far as I can tell). Customized widgets
contain b:includable
tags which tell Blogger how to display the
widget.
- id: (required) The ID for the widget. Has to be identical to the type plus trailing with a numeric value that is unique. Type Blog would have an id of Blog1 or Blog2.
- type: (required) The type of the widget. All types are listed under this attribute section.
- locked: (optional) A value of “yes” or “no” indicating if the widget can be moved or deleted from the specified section. The default value is “no”.
- title: (optional) The display title for the Widget. Will show up in the Widget Layout screen in Blogger. If omitted, will use the global Blogger titles for each widget.
- pageType: (optional) Declares what pages the widget should appear. Can have a value of “archive”, “main”, “item”, or “all”. With “all” being the default value. The widget will always appear in the Layout section of Blogger no matter what the pageType is set to.
- mobile: (optional) A value of “yes”, “no”, “default” or “only” declaring if the widget can appear on mobile devices. Only the Header, Blog, Profile, PageList, AdSense, Attribution will display on mobile devices when the value is set to default.
Widget Types
- Blog
- Feed
- Header
- HTML
- Image
- LinkList
- TextList
- BloggerButton
- BlogProfile
- Navbar
- VideoBar
- NewsBar
- PageList
- BlogList
- Text
- PopularPosts
- Stats
- PlusBadge
- PlusFollowers
- PlusOne
- Translate
- Label
- Poll
- Slideshow
- CustomSearch
- FollowByEmail
- BlogArchive
<b:section class="sidebar" id="sidebar" showaddelement="yes" growth="vertical">
<b:widget type="PageList" id="PageList" locked="no">
<!-- Have Includables here for custom widget layout and styles -->
</b:widget>
</b:section>
<b:section class="main" id="main" showaddelement="no" growth="vertical">
<!-- Have Blogger use the Default Layout for the widget since no children -->
<b:widget type="Blog" id="Blog1" locked="yes" />
</b:section>
Working with b:includable
This tag specifies how it should be handled if called upon to be
“included”. The tag has two attributes which can be id
, a required
attribute and can be the same if exists inside of a different widget
tag. There has to be a includable with the id of “main” inside of each
b:widget
. The main includable is what is called for the processing of
the widget. All other id’s can be named whatever they want since you
will manually code the call to them. The other attribute is var
. This
attribute holds the data
that is passed when you call b:include
with a data attribute. The var attribute is optional.
Inside the b:includable
element, can be plain HTML along with calls
to include and data tags. Referencing a data
tag while inside an
includable, will cause the reference of data to be changed to the
callers passed data (widget data). If the var
is not set, the passed
data to the includable will be the root of data calls. If the var
is
set, the root data will point to the widgets data instead and the var
will point to the passed data.
<b:section class="sidebar" id="sidebar" showaddelement="yes" growth="vertical">
<b:widget type="PageList" id="PageList" locked="no">
<b:includable id="main">
<ul>
<li>Page List Here, When I Know How To Loop</li>
</ul>
</b:includable>
</b:widget>
</b:section>
Working with b:loop
Looping in blogger is very important since a lot of data is in arrays, such as posts, labels, comments and lists. The loop will navigate through each of those elements in the array and give you a new data variable to reference that element.
The b:loop
contains two attributes, one of which is values
that
holds the full array of values you wish to loop through. Inside of the
Blog widget, you can loop through data:posts
Since the b:loop element
isn’t plain HTML, you don’t have to call onto an expr to reference the
data.
The other attribute for b:loop
is var
The var will be a keyword you
will reference inside the loop to request the current element you are
on during the loop.
<b:section class="sidebar" id="sidebar" showaddelement="yes" growth="vertical">
<b:widget type="PageList" id="PageList" locked="no">
<b:includable id="main">
<ul>
<b:loop var="item" values="data:links">
<li>
<a expr:href="data:item.links.target"><data:item.title /></a>
</li>
</b:loop>
</ul>
</b:includable>
</b:widget>
</b:section>
<b:section class="main" id="main" showaddelement="no" growth="vertical">
<b:widget type="Blog" id="Blog1" locked="yes">
<b:includable id="main">
<b:loop var="item" values="data:posts">
<b:include name="post" data="item" />
</b:loop>
</b:includable>
<b:includable id="post" var="post">
<div>
Title: <data:post.title />
</div>
</b:includable>
</b:widget>
</b:section>
Working with b:if and b:else
You also are able to have if / else statements in Blogger Themes using
the XML tags of b:if
and b:else
. There is no else if statement so
you will have to create extra if tags to accomplish what you need. When
you use a b:else
tag, make sure you escape it, since there is no
closing tag for it.
The b:if
tag has one attribute of cond
which is the if statement
query or condition. Inside of cond
you can compare values using ==
,
!=
, >=
, <=
, >
, and <
. If you are comparing a data variable
with a string, the string has to be wrapped with double quotes. You
will often have to set the double quotes to the HTML Entities of a
quote instead of the ascii text of a quote. Also, the greater-than and
less-than symbols will need to be html encoded also since XML doesn’t
allow those symbols inside of attributes.
<b:if cond='data:blog.pageType == "item"'>
<div>Page Type: Item</div>
<b:else />
<div>Page Type: Else</div>
</b:if>
<b:if cond='data:blog.url != data:blog.homepageUrl'>
<div>Home Page: False</div>
<b:else />
<div>Home Page: True</div>
</b:if>
<b:if cond='data:blog.isMobileRequest'>
<div>Mobile: True</div>
<b:else />
<div>Mobile: False</div>
</b:if>
Working with b:skin
All of your styles and Advanced Variables will be defined in the
b:skin
tag, located in the head
tag of the document. The data
inside of b:skin
has to be CDATA and cannot be a style tag like some
Google documentation mentions.
Inside of the CDATA you can place all of your CSS for the page. You can have external CSS loaded also by using a link tag outside of the skin tag, but then you won’t be able to reference the user defined styles and variables.
Before your CSS begins, but while still in the CDATA, you can create a
CSS comment /* comment */
that defines Variable
’s that the user can
modify in the Blogger template editor. These variables will setup the
type of variable, the value, the default value, variable name, variable
description and the variants of that variable.
To setup variant color themes you need to have a variable that has the
name
of “keycolor”. If you do not have this variable, the variants
will not appear under the “Background” customize tab in Blogger.
Variable Attributes
- name: The name of the attribute that at a later date will be used to reference the variables value. You can reference the name by adding
$(name)
inside of your style declarations. - description: A description or headline of what the element will modify. Only appears inside the Blogger Advanced color settings.
- type: The type of variable to set. Can either be font or color. There are rumored to be more but there is no documentation or hidden codes to show otherwise.
- default: The default value for the variable. If the value isn’t set or the user resets all variables, this is what the color will end up becoming.
- value: The value of the variable. Should be omitted or set to the default value when releasing or publishing your theme so the end user will get the true value.
- variants: A comma separated list of the variants for different themes / color schemes.
Groups
Along with variables, you can also place the variables inside of
Group
tags which will highlight a section of the page of where you
are editing and group multiple variables together. Groups have two
attributes, a description
and a selector
. The description is what
describes to the user what they are editing, such as Blog Titles or
Post Links. The selector will tell Blogger which section of the page to
highlight to give the user a visual representation of what they are
editing.
<b:skin>
<![CDATA[
/*
<Variable name="keycolor" description="Theme KeyColor" type="color" default="#eeeeee" variants="#ff0000,#00ff00" />
<Variable name="siteFont" description="Font Style" type="font" default="14px 'Open Sans',sans-serif" />
<Variable name="siteBackground" description="Background" type="color" default="#eeeeee" variants="#ff0000,#00ff00" />
<Group description="Navigation" selector="#navigation">
<Variable name="navigationBackground" description="Background" type="color" default="#c14545" />
<Variable name="navigationFont" description="Font Style" type="font" default="18px 'Open Sans',sans-serif" />
<Variable name="navigationFontColor" description="Font Color" type="color" default="#ffffff" />
</Group>
*/
* {
padding: 0px;
margin: 0px;
}
body {
background: $(siteBackground);
font: $(siteFont);
}
#navigation {
color: $(navigationFontColor);
font: $(navigationFont);
background: $(navigationBackground);
}
]]>
</b:skin>