Chapter 4. Styling XOOPS and Creating a Theme from 960
This chapter mainly deals with how to add more styles to your themes. We will continue to use the theme you converted in Chapter 3. Also, we will discuss how to create a theme from the 960 CSS Framework for XOOPS (found online at http://code.google.com/p/insraq/source/browse/#svn%2Ftrunk%2F960) to save you time and coding.
More on Styling XOOPS
If you find an existing XOOPS theme and open the style.css file for that theme, you will find lots of CSS definitions. If the file is not well commented, though, you can hardly decipher what they actually do. It is the same when you write your own CSS file: if you do not follow a certain procedure, you will confuse others (and maybe even yourself).
There are lots of ways to categorize the definitions. I will introduce a method that I use when I am writing XOOPS themes.
Global Style
These definitions regard general tags, like body
, a
,
img
, h1-h6
, etc. They will be used extensively on
every page. Only include those styles that are applicable to every page
(for example, if you want a link on a specific page to be red, do
not write color:
red;
here).
Theme-Specific Style
These definitions are usually CSS definitions used by theme.html (for example, header, content, footer, slideshow, block, and so on). These styles are not used by XOOPS by default; they are used by your theme.
Warning
I originally used some general naming conventions like “nav
” and “menu
”. Then I found out that this may cause
conflict between theme style (your style.css) and module style (some
module-specific styles defined by module developers).
It is best to add a prefix to these names, like “inspire10-nav
” and “inspire10-menu
”. This way, even though we have
longer names, there will be fewer conflicts and more distinction.
XOOPS System Template Style
These definitions are used by the XOOPS system template and are supposed to be used by modules—for example, the System menus and User menus. Others include very detailed table style definitions and form definitions. (Strictly speaking, forms are not really in this category, but for convenience, we will include them here.)
Dealing with XOOPS Template Style
Global style and theme-specific style are not XOOPS-specific, meaning that you should write them by the time you finish your XHTML and CSS templates. To include them in your theme, simply copy and paste.
The XOOPS system template style (referred to as required style therein) is generally not defined in your original template, but is required by XOOPS. This is what you need to work on.
XOOPS has many historical versions. Each version might have different requirements for required styles. I will introduce the common ones and leave those that are rarely used for you to discover on your own later.
#MainMenu
This group of style definitions is used by the system module on
the main menu (usually used as the
navigation menu). They are all under
#mainmenu
ID, and have different
classes:
style.css (excerpt)
#mainmenu {}
#mainmenu a {
display: block;
}
#mainmenu a:hover {}
#mainmenu a:active, #mainmenu a.current {}
#mainmenu a:visited {}
#mainmenu a.menuTop {}
#mainmenu a.menuMain {}
#mainmenu a.menuSub {
padding: 0 0 0 10px;
}
#mainmenu a.menuSub:hover {}
#mainmenu a.maincurrent {}
Above is the necessary definition. As you can see, I only added
two definitions (a
and a.menuSub
) and left the others blank. The
display: block;
is used to make the
menu item displayed in the block, and the definition in #mainmenu a.menuSub
is used to differentiate
subitems from main items. I added a 10px
left padding
to achieve this.
#Usermenu
usermenu
is quite similar to mainmenu
, except that there is no “subitem” in
usermenu
:
style.css (excerpt)
#usermenu {}
#usermenu a {
display: block;
}
#usermenu a:hover {}
#usermenu a:active, #usermenu a.current {}
#usermenu a:visited {}
#usermenu a.menuTop {}
#usermenu a.highlight {}
Table and Cells
This is the most complex part. XOOPS has a complicated definition of table style, and different modules might use themes differently. I always try to maintain a minimum definition that works well in most situations, and let the modules set their styles. But the problem remains unsolved:
style.css (excerpt)
table {
width:100%;
margin: .5em 0 1em 0;
border-collapse: collapse;
}
th {
font-weight: bold;
text-align: center;
vertical-align : middle;
background: #e7eef7;
padding: 5px;
}
tr {
border: 1px solid #eee;
}
td {
padding: 5px;
}
.outer {
border-collapse: collapse;
padding: 5px;
}
.head {
font-weight: bold;
vertical-align: top;
background: #f8f8f8;
}
.even {
padding: 5px;
border: 1px solid #eee;
}
.odd {
padding: 5px;
border: 1px solid #eee;
background: #e7eef7;
}
The above code is the style I use in the 960 CSS framework for
XOOPS. I make a lot of assumptions about styles here. The border of the
table is #eeeeee
, and for th
(which defines a style for table headers)
and .head
(which defines a style for
the head
class), I add a background
to differentiate them. I also add a padding of 5px
to
td
(which defines a style for
standard table cells) and additional classes.
I do it this way because I think table definitions should not be the focus of theme design, and shouldn’t bother designers so much. When I first designed for XOOPS, I was quite confused by those table definitions. They seemed too overwhelmed with details. Even if you do not define style for most of the selectors, you will be fine.
Another problem is that different module designers will use
different markup for their modules. For example, some will use <th>
as a table header, while others use
<th class="header">
. So my
current approach is to define a set of minimum styles. But a better way
to tackle this would be for the XOOPS community to work out a standard
for module templates. If all the designers and developers followed this
standard, differing markup would no longer be a problem.
Smarty: I Want to Know More
XOOPS provides a lot of Smarty variables to help designers achieve their goals. Here, I’ve made a list of the commonly used Smarty variables according to my experience over the past few years. I’ve categorized them for easy reference.
Header Tags
<{$xoops_charset}>
Output the character set information (e.g., “iso-8859-1”, “UTF-8”).
<{$xoops_langcode}>
Output content language (e.g., “DE”, “EN”).
<{$xoops_meta_keywords}>
Output the keyword list from the Meta/Footer settings.
<{$xoops_meta_description}>
Output the meta tag site description.
<{$meta_copyright}>
Output the meta tag copyright text.
<{$meta_robots}>
Output the W3C robot meta tag info.
<{$meta_rating}>
Output the meta tag rating information.
<{$xoops_js}>
Output XOOPS JavaScript.
<{$xoops_module_header}>
Output the module header. Usually, the module’s own JavaScript will be outputted. Details will be explained later.
XOOPS General
<{$xoops_sitename}>
Output the site name.
<{$xoops_slogan}>
Output the site slogan.
<{$xoops_pagetitle}>
Output the page title.
<{$xoops_theme}>
Output theme’s name in directory “/themes/” (e.g., “default”, “suico”).
<{$xoops_dirname}>
Output the name of the current module directory. If no module is displayed, this value is set to “system”.
<{$xoops_themecss}>
Inserts the style.css file (e.g., “http://www.xoops.org/themes/default/style.css”).
<{xoImgUrl}>
This is the XOOPS resource locator. It is often used if you want to link to an image or a CSS. Detailed usage will be explained throughout the book.
<{$xoops_url}> or <{xoAppUrl}>
Output the site URL (e.g., “http://www.xoops.org”), without the final slash.
<{$xoops_banner}>
Display banners.
<{$xoops_contents}>
Display the news and other content.
<{$xoops_footer}>
Display the footer.
<{$xoops_requesturi}>
Request URL provided by XOOPS (e.g., /modules/news/article.php?storyid=1).
XOOPS User-Related
<{$xoops_isadmin}>
Test if the visitor is Administrator—return TRUE if yes.
<{$xoops_isuser}>
Test if the visitor is a logged in user—return TRUE if yes.
<{$xoops_userid}>
User ID of the member.
<{$xoops_uname}>
Username for the member.
Smarty Flow Control
<{if $smarty_variable}>
...
<{elseif}>
...
<{else}>
...
<{/if}>
The
if-else
control.<{foreach item=block from=$xoBlocks.canvas_left}>
<{/foreach}>
The
foreach
loop.There is also a
foreachq
, described next.<{foreachq item=block from=$xoBlocks.canvas_left}>
...
<{/foreach}>
Note that the closing tag is
<{/foreach}>
instead of<{/foreachq}>
.
Include and Assign
<{include file=PATH}> or <{includeq file=PATH}>
Used to include a file in theme.html; the difference is that the latter is more efficient (but less secure).
<{assign var=NAME value=SOME_VALUE}>
Assign a value to a Smarty variable. For example:
<{assign var=theme_name value=$xoTheme->folderName}> <{assign var=theme_name value=$xoTheme->folderName|cat:'/tpl'}>
Then you could use:
<{includeq file="$theme_name/tpl.html"}>
This would include XOOPS/themes/yourtheme_tpl.html or XOOPS/themes/
tpl
/yourtheme_tpl.html.
More on Smarty: Tricks and Examples
Module-Based Navigation
Now suppose you have a typical site navigation markup:
<ul class="nav">
<li class="current"
><a href="#">Home</a></li>
<li><a href="#">News</a></li>
<li><a href="#">Forum</a></li>
<li><a href="#">Blogs</a></li>
<li><a href="#">Contact</a></li>
</ul>
You want the navigation panel to tell the visitor which section of
the website they are currently in. The most common way is to add a
current
class to the current item.
Then you can style the class in your CSS file.
The trick is to add a current
class to the current item. How does one achieve that in XOOPS? It’s
easy:
<ul class="nav"> <li<{if $xoops_dirname == "system"}> class="current"<{/if}>> <a href="#">Home</a> </li> <li<{if $xoops_dirname == "news"}> class="current"<{/if}>> <a href="#">News</a> </li> <li<{if $xoops_dirname == "forum"}> class="current"<{/if}>> <a href="#">Forum</a> </li> <li<{if $xoops_dirname == "xpress"}> class="current"<{/if}>> <a href="#">Blogs</a> </li> <li<{if $xoops_dirname == "contact"}> class="current"<{/if}>> <a href="#">Contact</a> </li> </ul>
As mentioned earlier, $xoops_dirname
outputs the current module
directory name. Suppose you are using News module; the corresponding
directory name is news. So we can use an if
clause in Smarty to test whether $xoops_dirname
equals the current module name.
If yes, then we add a current
class.
What About a Block Without a Title?
Usually, a block consists of a block title and block content. However, for some blocks, you may think the block title is meaningless and you probably do not want to display it. Take a look at our previous markup. If the block does not have a block title, the output will look like this:
<div class="title"><h2></h2></div> <div class="entry">This is the block content</div>
This does not look nice. If you define some style for the title, it will simply give a blank result.
A better way to handle this is to only show the markup for the block title when the block has a title:
<{if $block.title}> <div class="title"><h2></h2></div> <{/if}> <div class="entry">This is the block content</div>
Use the above markup, and if a block has no title (i.e., the block title is empty), the output will look like this:
<div class="entry">This is the block content</div>
The markup for a block title will not be output.
Custom Block Filter
This sounds like rocket science, but it really isn’t. This trick follows the previous workaround. Suppose you want to have a special markup or style for some specific blocks—for example, the Search block. You have two choices. The first is the block anywhere technique, which will be covered in Chapter 7. This is fairly complex and is suitable for a situation in which your whole website is made of custom-designed blocks.
The second choice is to create a custom block filter. This is easy, and applies to situations in which you only have one or two custom-designed blocks.
To illustrate, look at the original code for blocks:
<{foreach item=block from=$xoBlocks.page_topcenter}> <div class="title"><h2><{$block.title}></h2></div> <div class="entry"><{$block.content}></div> <{/foreach}>
A block filter is simply an if
clause:
<{foreach item=block from=$xoBlocks.page_topcenter}> <{if $block.title == "Search"}> <div class="block-search"> <{else}> <div class="block-general"> <{/if}> <div class="title"><h2><{$block.title}></h2></div> <div class="entry"><{$block.content}></div> </div> <{/foreach}>
With the above code, if the block title is
"Search"
, then we will apply a block-search
class to the block, and then
apply the block-general
class.
To add more than one filter, use an if-elseif
clause:
<{foreach item=block from=$xoBlocks.page_topcenter}> <{if $block.title == "Search"}> <div class="block-search"> <{elseif $block.title == "Welcome"}> <div class="block-welcome"> <{elseif}> <div class="block-general"> <{/if}> <div class="title"><h2><{$block.title}></h2></div> <div class="entry"><{$block.content}></div> </div> <{/foreach}>
Blocks can be filtered not only by names, but also by
id
s, a technique which is less commonly used:
<{foreach item=block from=$xoBlocks.page_topcenter}> <{if $block.id == 5}> <div class="block-search"> <{elseif $block.id == 6}> <div class="block-welcome"> <{elseif}> <div class="block-general"> <{/if}> <div class="title"><h2><{$block.title}></h2></div> <div class="entry"><{$block.content}></div> </div> <{/foreach}>
“What is my block ID?” you may ask.
The ID of a block can be found out in the following way: edit a block, and in the address bar of your browser, you will see a URL like this:
http://example.com/modules/system/admin.php?fct=blocksadmin&op=edit&bid=1
The bid part of the query string is your block ID.
Create a Theme with 960
To create a theme from scratch takes a lot of time, which is why the concept of a framework is so handy. There are two types of framework, and both have their pros and cons. One is very rigid and strict, with lots of rules and conventions. The learning curve is very steep, but once you master it, you can write very concise and beautiful code.
Another type is loosely organized. It provides lots of functions to help your design. But even if you don’t follow all of the conventions, it’s fine. The learning curve is flat, but you’ll probably need to write more code than with the first type.
When I first decided to create a theme framework for XOOPS, there were already many other good frameworks. (One of the most famous is Morphogenesis, created by Chris (kris_fr in the forums). It is very powerful, concentrating on the file structure and functions. It does have some documentation, but is a little difficult for beginners.)
I decided to create a theme framework that focuses on design itself. I did not provide a lot of functions within it. The framework includes a theme.html to set home page structure using the 960 CSS Framework; some CSS files with definitions necessary to create a theme; and some other must-have JavaScript libraries.
To create a theme with 960, just copy the folder, rename it, and it’s done!
Then, open theme.html and you can see that the home page structure is written in 960, which assumes a width of 960 pixels and provides a grid system based on frequently used dimensions. If you are familiar with this system, you can easily modify it. If not, just leave it there, because the default grid layout will work 90% of the time.
The next step is to add some selectors in theme.html and add the corresponding styles to
style.css. Your style definitions
should be added in the /* Theme Specific Style
*/
section. Assuming you are already used to designing in CSS,
you will have no trouble dealing with rest of the stuff in the
template—it’s just like designing pure XHTML and CSS templates, except for
some Smarty syntax. If the syntax throws you at all, refer back to Chapter 2.
Get Designing for XOOPS now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.