Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Theme changes in 2.0

From MoodleDocs

Moodle 2.0


Please note this is a work in progress, do not edit - use page comments instead if needed, thanks.

Goals

The main goals are:

  1. general simplification of code
  2. easier theme customizations
  3. allow themes to be stored in dataroot
  4. improved performance
  5. solve all caching problems
  6. base all themes on YUI CSS foundation
  7. easy customisation of theme images (similar to smartpix)

Design overview

All theme files will be served through two files /theme/styles.php and '/'theme/image.php. If more advanced themes need extra javascript files we could add optional /theme/javascript.php file.


All CSS style sheets (including YUI, plugin CSS and parents) would be merged into single large CSS file served via the /theme/styles.php file, it would have several parameters:

  • theme - string, theme name
  • rtl - bool, modified style sheet for RTL languages
  • iehack - 6/7, IE would include special IE6/7 incompatibility fixes (this means IE 6 and 7 loads two styles.php instead of one)
  • rev - int, theme revision number stored in main config table, solves all caching problems


The theme config.php would be significantly simplified, the complete list of available options would be:

  • $THEME->parents = array('standard', 'purple'); lists all parents top-down, each theme contains full list of parents, this is non-recursive and more flexible specification without any limits
  • $THEME->sheets = array('styles_layout', 'styles_fonts', 'styles_color'); the same as before, lists files from current theme directory
  • $THEME->parents_exclude_sheets('standard'=>array('styles_moz'), 'purple'=>array('styles_fonts.css')); it would be also posssible to use true instead of array in order to specify all sheets or all sheets in all parents
  • $THEME->plugins_exclude_sheets('mod_book', 'gradereport_grader'); - specify individual components that should be excluded from this theme
  • $THEME->layouts = array(...); - the same as before, cascades through parent themes
  • resource and filter hacks $THEME->resource_mp3player_colors, $THEME->filter_mediaplugin_colors


Implementation

One huge CSS sheet

Each page would only include only one huge style sheet. The URL would be returned from theme_get_url($themename, $rtl, $iehack) function. All theme URL would be served by a /theme/styles.php script. Page parameters specifying theme name and RTL flag, rev parameter is used for invalidating of browser caches.

The CSS concatenation is done from the YUI CSS, styles.css from all plugins and theme CSS. Algorithm is following:

  1. YUI CSS
    1. merge all YUI CSS into one file, respect correct order of files
    2. put image placeholders instead of relative links {{yui|someimage}}
  2. Plugins CSS
    1. go through all plugins and search for styles.css - put the list into array, use component names as keys, locations as values
    2. filter out excluded sheets specified in current $THEME->plugins_exluded_sheetes
  3. Theme CSS
    1. go through all sheets defined in all parents and store all #THEME->sheets in array
    2. filter out excluded sheets specified in current $THEME->parent_exluded_sheetes
  4. Resolve real image locations
    1. regex search for {{component|image}}
    2. priority is: current theme, parent themes, then plugin or YUI fodlers
    3. images in web accessible areas are linked directly, images in dataroot would have to go through /theme/image.php?theme=xxx

Please note that the current $PAGE->requires->css() does not fit this approach, because we can not put it into correct place.

IE6/7 are an exception, they use one extra sheet that tries to work around Internet Explorer incompatibilities.

Theme caching

Potential problems are:

  • server performance - the merging of all CSS, parent themes and image resolving is relatively expensive
  • bandwidth - longer caching, fewer files and optional gzip compression
  • stale data in browser caches - different file needs to be served when anything in CSS changes


The theme CSS content depends on:

  • current theme
  • current language RTL flag
  • theme revision

The theme revision is stored in $CFG->themerevision, it is an integer counter incremented after installation/upgrade of any plugin or core. The revision is also bumped up right after switching on/off theme designer mode or even manually.

Theme caching may work in three modes - no caching, browser caching only, server&browser caching. The large merged CSS files may be stored in dataroot, the file caches would be deleted after each theme revision change.

IE CSS hacks

Old meta.php was used for conditional loading is IE specific hacks. These hacks did not cascade properly. New alternative solution is to use _ie6.css and _ie7.css suffixes. The exclusions and cascading rules are used the same as for normal sheets.

The IE compatibility sheets are served by theme/styles.php file.

Hopefully IE6 and IE7 will die out before the Moodle 2.1 release...

YUI

Moodle started using YUI framework around 1.7, until 2.0dev we did not use any UI widgets that required CSS. The problem is that the YUI needs to be loaded before theme and plugin CSS, second problem is that standard YUI CSS requires reset CSS which greatly improves A-grade browser compatibility and helps theme designers.

In 2.0dev there was an option to use external YUI library, unfortunately we can not use external CSS because we need to recalculate image links (this allows easy overriding of YUI images without actually overriding the CSS definition.

YUI CSS foundation

Why should we base our themes on YUI CSS foundation? Why not? The benefits are:

  • eliminates some different HTML defaults (margins, paddings, font sizes, etc.) (YUI CSS Reset)
  • consistent font sizing and better font-family degradation (YUI CSS Fonts)
  • incredibly simple table-less page layouts that include nesting (YUI CSS Grids)
  • the standard YUI CSS is already built on top of this foundation

I do not think we should expect any problems related to the use of YUI CSS foundation, it looks like the current themes need only minor tweaking to make it compatible (already tested).

Core and custom themes could use the extremely simple and powerful YUI CSS Grids framework for page layout. I do not think we could quickly develop anything as reliable and compatible before the release of 2.0.

If we do not use this foundation we have to write all CSS for standard YUI widgets, this could be very time consuming and the results/timeframe are not predictable.

YUI widgets customisation

The standard YUI CSS has to be loaded after YUI CSS Base (Reset+Fonts+Grids), but before our own CSS. The CSS may be overridden through plugin styles.css or theme styles. YUI standard images could be simply changed by adding different images with the same name into theme/standard/pix/yui/.. or any other theme. The image resolver would first look into current theme, all parents and the last option would be standard YUI library

YUI versioning

In 1.9 we store all YUI files in /lib/yui/ folder, this may be a potential problem when upgrading YUI version from upstream because the old files could be still cached in browsers. Solution could be to add version number /lib/yui/x.yy/.

Image resolver

Images are used in html code and in CSS style sheets. The problem is easy to solve in PHP code, partial solution was already present in Moodle 1.9 - see $CFG->pixpath

In 2.0dev there was implemented new icon_finder class, it can be replaced by much simpler rules, we can also add pix support into all plugins.

Image locations:

  • /lib/yui/
  • /mod/modulename/pix/, blocks/blockname/pix/ - in all plugins
  • /theme/themename/pix/ - standard theme images
  • /theme/themename/yui_pix/ - overriding of yui images from themes
  • /theme/themename/plugin_pix/component_name - overriding of plugin images in themes


The standard API is $OUTPUT->get_image_url($componentname, $imagename) when used from PHP and {{image:componentname|imagenamewithpathwithoutextension}} if used in CSS.

There are a few exceptions like theme favicon, screenshots and module icons, all other images should be placed in pix directories.


Image resolved allows us to also serve images from dataroot via /theme/image.php script


Themes in dataroot

Backwards compatibility

Limited, the themes would have to be updated. Old themes can be detected by searching for /theme/oldtheme/styles.php, this file will not be present in new themes any more. Moodle core would simply use parent theme if already updated or standard theme.

Upgrade steps

  1. delete styles.php
  2. redefine all config.php options - in majority of cases change parent value to parents array
  3. rename styles_ie6.css and styles_ie7.css to styles_layout_ie6.css and styles_layout_ie7.css - each normal sheet may have an extra sheet with _ieX suffix now, these are loaded automatically, excluding is applied based on $THEME->parents_exclude_sheets() info from the current theme
  4. rename rtl.css to styles_layout_rtl.css - again each normal style sheet may have extra sheet with _rtl suffix similar to IE hacks sheets
  5. delete header.html, footer.html and meta.php - obsoleted by $THEME->layouts option and new layout files

In order to minimize confusion during the upgrade, the old themes will be ignored and will be listed os "Incompatible" on the theme selection page - this page is probably the first place admins go in order to diagnose theme problems.

Removed features

  1. sometheme/meta.php - used mostly for IE6/7 hacks, custom layouts may be used instead
  2. smartpix - completely obsoleted by the new image location resolution algorithm
  3. $CFG->themewww, $CFG->themedir and friends - themes can be stored in dataroot, web hosting companies may use shared dirroot without custom themes, the styles.php URLs would be always constructed via some helper functions
  4. styles.php replaced by styles.css, supported in all plugin types - the PHP is not needed because images are specified using {{image:component|dir/image}} syntax
  5. $PAGE->requires->css() replaced by styles.css in each plugin