Structure of Custom Blogger Themes

GeekThis remains completely ad-free with zero trackers for your convenience and privacy. If you would like to support the site, please consider giving a small contribution at Buy Me a Coffee.

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="" xmlns:b="" xmlns:data="" xmlns:expr="">
		<title><data:blog.pageTitle /></title>
		<b:include data="blog" name="all-head-content" />
		<b:include data="blog" name="google-analytics" />


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

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

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: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" />

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">
				<li>Page List Here, When I Know How To Loop</li>

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">
				<b:loop var="item" values="data:links">
						<a expr:href=""><data:item.title /></a>

<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:includable id="post" var="post">
				Title: <data:post.title />

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 cond='data:blog.url != data:blog.homepageUrl'>
	<div>Home Page: False</div>
<b:else />
	<div>Home Page: True</div>

<b:if cond='data:blog.isMobileRequest'>
	<div>Mobile: True</div>
<b:else />
	<div>Mobile: False</div>

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.


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.

			<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" />
		* {
			padding: 0px;
			margin: 0px;
		body {
			background: $(siteBackground);
			font: $(siteFont);
		#navigation {
			color: $(navigationFontColor);
			font: $(navigationFont);
			background: $(navigationBackground);

More Resources

External Resources

Related Posts

Blogger Customize AdSense Advertisements

How to customize the appearance of Blogger advertisements to improve your earnings and website appearance.

Blogger Theme Data Tags for Widgets

A list of template tags for Blogger Widgets available to add to your custom Blogger template and design.

Custom Blogger Domain with Namecheap

How to add a custom domain to Blogger that is registered with Namecheap to give your blog a unique name.