Themes and templates
7 February 2018 921 views | Documentation v1
Themes
The 'look and feel' of a Tuskfish site is determined by the template sets or themes that are in use. Themes, unsurprisingly, live in the 'themes' directory. Each theme occupies a subdirectory bearing its name, for example 'default' and 'admin' are the default themes for the front end and the administrative area, respectively (there is also an additional 'rss' theme to format your feeds and a 'gallery' to view images on your site).
To add a new theme to your site upload it into the /themes directory and it will immediately be available for use. The default theme contains:
- theme.html: This file sets the main layout of the page, for example the basic column / grid structure and elements such as navigation menu and footer, if present. It also includes links to all the CSS and Javascript libraries in use.
- main.html: A template representing the main content area of the page. It slots into theme.html.
- singleStream.html: A template representing an index page, displaying a mixed list of the latest content teasers from all content types.
- For each content type, there is a specific template eg. 'article.html', 'image.html' and 'video.html', which display the full description of an object in single view mode.
- form.html: A wrapper template for forms.
- A few other HTML files for components such as the login form, select boxes, etc.
- style.css: This contains custom CSS classes specific to this theme or that override the standard Bootstrap classes.
Templates are hierarchical. In the above example, theme.html is the outermost template dictating overall page structure; main.html slots into it to display the main page element such as page title, tag select box, and pagination controls. Either singleStream.html (index view) or an individual object template (single item view) slots into the central area of main.html to display the actual page content. Templates must be rendered in reverse order (innermost first) so that they can be assigned to the next level template.
For the default set up of a Tuskfish theme you need (at a minimum) theme.html, main.html, form.html and singleStream.html. But you could cut it down to just theme.html, depending on the type of content you were displaying and on how you set up your controller scripts. These patterns are just convenient defaults; you can of course create your own templates that display content in different ways.
Assigning themes to pages
Template sets are assigned at the individual page level using a single line of code. In this example the 'admin' template set is in use:
// Specify template set, otherwise 'default' will be used.
$tfTemplate->setTheme('admin');
You could assign a different template set to this page by changing 'admin' to the name of some other template set you have installed on the site. For example, let's assign a custom admin theme that you designed yourself:
// Specify template set, otherwise 'default' will be used.
$tfTemplate->setTheme('custom');
You could, if you wanted to, have a completely different theme for every single page or different sections of your site. You could even change the theme of a single page dynamically. Pretty easy, right?
Switching themes conditionally
By adding some conditions you can make a page switch themes dynamically. In the example below a visuals-heavy landing page theme is set as default, but if parameters are available requesting a specific page view (ie. indicating that content has been requested) then a more text-friendly theme is used.
// Theme switcher. Use Agency for home page, Marketing for everything else.
if ($cleanId || $cleanStart || $cleanTag) {
$tfTemplate->setTheme('marketing');
} else {
$tfTemplate->setTheme('agency');
}
Cloning an existing theme
You can easily create a new theme from an existing one:
- Make a copy of the theme with a different directory name.
- Edit the <head> section of the theme and update the links to style.css and any specific scripts and fonts, to match the new folder name.
The new theme is fully independent and you can modify it without any fear of damaging the old one.
Modifying a third-party Bootstrap theme to work with Tuskfish
It's not hard to convert a third-party theme to work with Tuskfish. Basically, you need to insert placeholders where you want Tuskfish to dynamically insert content:
- Modify the <head> section to draw on Tuskfish site preferences / metadata and to point to the local Bootstrap and jQuery libraries. Just take a look at the default theme as an example; you can copy the meta tags directly and they will work just fine.
- Insert placeholders into the template, as relevant, eg. $tfMainContent for the main page area and any blocks you have.
- Possibly, depending on the nature of the template set, you may need to apply some of its CSS styles to content-specific templates, to make them consistent with the overall look and feel. The default templates that ship with Tuskfish only contain vanilla HTML, so you (might) need to apply classes to style them.
Be aware that while designers often bundle the Javascript libraries they have used with their themes, these are often out of date by the time you download them and may contain security vulnerabilities. It is best to delete bundled standard libraries such as jQuery and Bootstrap, and substitute links to the versions bundled with Tuskfish.
Templates
The template system is managed by the TfTemplate class. An instance of TfishTemplate is initialised by tfHeader.php, so it is available on every page as the variable $tfTemplate.
$tfTemplate is used to i) store data that you want to insert into HTML templates, and ii) renders the HTML templates for display.
Assigning data to templates
Simply assign your data to $tfTemplate as a property:
$someData = 'x';
$tfTemplate->someData = $someData;
You should assign all of the data you want to display in a given template before rendering it. Note that $tfTemplate does *not* do output escaping; you must handle that yourself. Tuskfish convention is to handle output escaping within the actual templates.
Rendering templates
Render a HTML template for display by passing in its filename (without extension) to the render() method:
// Render the full description of a single article using the article.html template.
$tfTemplate->contentObject = $articleObject;
$output = $tfTemplate->render('article');
But since every type of content object knows what its default template is (they have a 'template' property), you could also write:
$tfTemplate->article = $articleObject;
$output = $tfTemplate->render($articleObject->template);
When you call render() the properties of $tfish_template are extracted into variables of the same name, thereby populating the variables in the specified template file.
The output of a template can in turn be assigned to a higher-level template, and usually is. For example, after rendering an article we would usually assign it to $tfTemplate->tfMainContent, which by convention represents the main content area of a page, defined in the main layout file for a given template set:
// Render an article object within the main layout template.
$tfTemplate->article = $articleObject;
$tfTemplate->tfMainContent = $tfTemplate->render($article->template);
The main layout file for a template set is rendered within tfFooter.php, which is included at the bottom of a page as the last order of business.
// Include the relevant page template, or the default if not set.
if ($tfTemplate && !empty($tfTemplate->getTheme())) {
include_once TFISH_THEMES_PATH . $tfTemplate->getTheme() . "/theme.html";
} else {
include_once TFISH_THEMES_PATH . "default/theme.html";
}
So basically $tfTemplate->tfishMainContent is in turn extracted and rendered, along with any other content placeholders you may have prepared, such as blocks. As blocks are typically inserted into the main layout template, you should render blocks and assign them to $tfTemplate just before finishing your script. Your main layout template should contain matching variables in the positions where you want to display the blocks.
// Call a static block and prepare it for display in the main layout template.
$someBlock = TfishBlockHandler->getObject(42);
$tfTemplate->someBlock = $tfTemplate->render($someBlock->template);
// Script ends, footer is included and main template file rendered.
If you try to render a template that does not exist in your template set an error will be thrown.
Bootstrap
Tuskfish uses the excellent Bootstrap framework for front end presentation. If you already know Bootstrap you can skip to the next sub-section. Tuskfish uses Bootstrap 5.
Bootstrap borrows the 'layout grid' metaphor from print publishing as the basis for designing sites. It is first-rate for developing responsive, mobile-friendly designs that work across different sized displays. Bootstrap provides a library of useful CSS styles, and components including controls, menus and vector icons. It is very well documented with free starter themes and code examples.
Simply applying Bootstrap styles to some vanilla HTML will give you highly polished output. Since vanilla HTML is what I can do and highly polished output is what I want, that's why we are using it :) At its heart Tuskfish is just a back-end data entry and retrieval system; when it comes to actual presentation of that data the show is handed over to the HTML templates, which just contain vanilla mark up. And Bootstrap.
There are loads of (really) beautiful, mobile-friendly Bootstrap themes available for free (you can also buy themes from Bootstrap's creators or from a wide range of commercial providers). Wiring one up to work with Tuskfish only takes a few minutes; essentially Tuskfish generates placeholders containing your content and you just need to insert them into a template were appropriate and possibly, depending on the nature of the template, apply some CSS classes to your HTML.
Good places to look for free (no strings attached) themes are listed below (yes, they may also sell themes, it's not a crime). There are many more sites offering quality work for "nearly free" if you are prepared to tolerate a few strings such as providing a mandatory backlink to the designer's site (AKA free advertising, for them) and not being able to redistribute the themes to anyone else. To me a work with such conditions is not actually free, but designers seem to have a different idea about what this word means.
As a developer I need themes that I can redistribute with my code, if I can't redistribute a theme then it is useless to me. Also, it is one thing to ask that your name be credited via a comment in the code (no problem), but it is another to require people to publicly display your name on the face of their website as a licensing condition. Many business and corporate users simply can't do that, and again, themes that come with such conditions should not be described as "free". Of particular annoyance are people that expect public attribution for every little form icon and button - all it does is ensure that nobody uses their work.
While I'm in rant mode the fact that the GNU General Public License does not cover artwork that ships with GPL code is a constant source of annoyance to me. Why is it that the graphic designer gets paid, but the programmer doesn't?
Sites with good quality, truly free themes:
- BlacktTie.
- Start Bootstrap.
- Get Bootstrap (basic themes and code examples).
For royalty-free photos that you can use without having to plaster ugly attributions all over your website, sign up to Death To The Stock Photo.
Copyright, all rights reserved.