This document describes Turbine 1.0. You can find documentation for Version 1.1 (which is currently in beta state) in the new docs.
Turbine is a PHP-powered tool that introduces a new way for writing CSS. It's syntax and features are designed to decrease css development time and web developer headache. Turbine takes this …
// Welcome to Turbine! @media screen #foo, #bar color:#FF0000 margin-left, margin-right: 4px div.alpha, div.beta font-weight:bold border-radius:4px… and turns it into …
@media screen { #foo, #bar { color: #FF0000; margin-left: 4px; margin-right: 4px; } #foo div.alpha, #foo div.beta, #bar div.alpha, #bar div.beta { font-weight: bold; border-radius: 4px; } }
…or, if you like fast-loading websites, directly into this (which is automatically cached, gezipped and served with the correct expires headers):
@media screen{#foo,#bar{color:#F00;margin-left:4px;margin-right:4px}#foo div.alpha,#foo div.beta,#bar div.alpha,#bar div.beta{font-weight:bold;-moz-border-radius:4px;-webkit-border-radius:4px;-khtml-border-radius:4px;border-radius:4px}}
Turbine can save you a lot of typing and time and allow you to focus on a website's design and functionality instead of css's limitations, page performance or your least favourite browser's latest bugs. Think jQuery for CSS. Being fully extensible, you can customize Turbine to your liking.
Turbine's basic features include:
While Turbine's basic features may save you some keystrokes, it's plugins automate and simplify some of the more tedious and complicated aspects of writing css. See the plugins section for details.
Simply download the latest public release from Github and unpack it to a directory on your web server. There are no requirements beside PHP 5.2.
Turbine has two sets of configuration options - one on a per-file-basis and one on a global level. These global configuration options
are set in the file config.php
. The following settings are availiable:
Option | Effect | Default |
---|---|---|
debug_level |
Disable all error messages (0 ), enable web developer debugging messages (1 ) or enable all error messages
(2 ). Setting this to anything but 0 also disables Turbine's server-side cache. |
1 |
css_base_dir |
Sets the base directory for the css and cssp files | |
minify_css |
Leave css files unchanged by Turbine (false ) or minify them (true ) |
true |
Security notice: As of version 1.0.5 Turbine can only access files in the css_base_dir
to prevent directory traversal.
Turbine files are simple text files with the extension .cssp
.
To use Turbine, embed css.php
in your HTML like a normal css file and add the files
argument containing
a list of Turbine files separated by semicolons.
<link rel="stylesheet" href="path/to/turbine/css.php?files=file1.cssp;file2.cssp" />
The base path for the files can be changed in the file config.php
(css_base_dir
).
You can also include regular css files, which will be output unchanged (or minified, if the minify_css
configuration option is set to true
).
The files as processed in sequence and don't influence each other in any way. For example,
constants defined in file1
won't apply to code in file2
. If
you want share code between files, use the loader plugin.
There's basic Turbine support for Dreamweaver, UltraEdit and GtkSourceView.
You can find an extension for Dreamweaver in resources/editors/dreamweaver
. This extension adds
.cssp-files to Dreamweaver's list of supported filetypes, puts in place some code highlighting and autocompletion (code hinting)
for Turbine files. To install the extension, just double click turbine.mxp
, or open the Extension Manager and select
File → Install Extension…, browse for turbine.mxp
and select it.
Follow this guide on how to add
the Turbine wordfile resources/editors/ultraedit/turbine.uew
to UltraEdit. Use the tags listed in
resources/editors/ultraedit/turbine.txt
to complete your tag list.
The language file for GtkSourceView adds syntax highlighting to editors like Gedit and Anjuta. Simply copy the
file turbine.lang
from resources/editors/gtksourceview-2.0/language-specs
to either
~/.local/share/editors/gtksourceview-2.0/language-specs
or
/usr/local/share/editors/gtksourceview-2.0/language-specs
.
The Turbine.tmbundle
adds syntax highlighting with a small property and plugin documentation for TextMate. Simply copy the
file Turbine.tmbundle
from resources/editors/textmate
to
~/Library/Application Support/TextMate/Bundles
. Now select Bundles → Bundle Editor → Reload Bundles from within TextMate.
The one important thing about Turbine's syntax is that it is all about lines. The context of any statements in the code depends of the context of the statement's line.
Turbine's syntax works a bit like Python – the level of indentation instead of curly braces decides the context of a given line. A simple rule looks like this:
#foo div > p // Selector color:red // Property and value font-weight:bold // Property and value
The way Turbine determines if a given line is a selector or a property-value-pair is the indentation level of the following line:
#foo div > p // Next line is indented = this is a selector color:red font-weight:bold span // Next line is indented = this is a selector color:blue
This behavior allows nested selectors, which can be quite powerful (see nested selectors). You can use any number or combination of spaces and tabs for indentation, but be careful to keep your indentation constistent in the whole file.
Semicolons at the end of values are not required, but you can use them to put multiple declarations in one line:
#foo div > p color:red; font-weight:bold span color:blue; font-style:italic
There a two kinds of comments available: single line comments that start with //
…
// Hello world
… and block comments that start with a line containing nothing but --
and end with the same:
-- Hello world This is a block comment --
@media
-rules in Turbine a simple switches. Each @media
line ends the previous @media
block
and opens a new one.
@media screen // Open screen block #foo background:red @media print // Close screen block, open print block #foo background:green @media projection // Close print block, open projection block #foo background:blue @media screen // Close projection block, open screen block #bar font.weight:bold
@media
block of the same type will be merged, so the resulting css looks like the following:
@media screen { #foo { background: red; } #bar { font.weight: bold; } } @media print { #foo { background: green; } } @media projection { #foo { background: blue; } }
If you need to end an @media block without opening a new one, you can do so using @media none
.
@media screen #foo color:red @media none #bar color:green
Result:
#bar { color: green; } @media screen { #foo { color: red; } }
There a a few reserved prefixes for properties, values and selectors:
Prefix | Context | Effect |
---|---|---|
$ | Selector | Selector alias, will be replaced by the selector defined in @aliases (see Constants and aliases) |
Value | Constant, will be replaced by the value defined in @constants (see Constants and aliases) |
|
$_ | Value | Special constant ($_SCRIPTPATH , $_FILEPATH , see Constants and aliases) |
? | Selector | Template - whole element will be removed before output but properties can be inherited from it (see Templating) |
& | Value | Expression (currently not used by Turbine or any plugin) |
The configuration options of Turbine can be set in the stylesheets themselves &ndash a @turbine
block (called
configuration block) allows for options to be set like properties and values in normal CSS code. There are
at the moment two things that can be controlled there: compression and plugins.
Turbine can output CSS code in a minified form.
@turbine compress:1 #foo color:red background:blue
Becomes
#foo{color:red;background:blue}
That's a good thing to have since everybody likes smaller downloads and the CSS code generates tends to be more verbose than
handwritten CSS anyway. To enable compression simply add compress:1;
to your configuration block.
To active a plugin, simply add it's name to the plugins
property (the order doesn't matter):
@turbine plugins:resetstyle, datauri, borderradius
Turbine has a set of core plugins that greatly enhance the functionality of Turbine. If you know a bit of PHP you can easily build your own plugins.
if you want to use multiple properties with the same value inside a selector, you can take advantage of expanding properties. This allows you to use properties as a comma-separated list …
#foo position:absolute top, left:4px
which Turbine expands into multiple css rules:
#foo { position: absolute; top: 4px; left: 4px; }
Turbine implements nested css selectors using a simple principle: whenever the next line is indented, to current line is used as a selector and combined with it's parent selectors.
#foo div > p color:red font-weight:bold a:link, a:visited text-decoration:underline a:hover, a:active text-decoration:none a:focus outline:1px dotted #CCC
The nested code above compiles to the following css:
#foo div > p { color: red; font-weight: bold; } #foo div > p a:link, #foo div > p a:visited { text-decoration: underline; } #foo div > p a:hover, #foo div > p a:active { text-decoration: none; } #foo div > p a:focus { outline: 1px dotted #CCC; }
Without nested selectors you would have to have typed a lot more #foo div > p
. Nested selectors can become a
bit confusing if you overuse them, but with a bit of moderation they can save quite a bit of typing. Consider this example:
#header, #footer ul, ol, p a:link, a:visited text-decoration:underline a:active, a:hover text-decoration:none
Result:
#header ul a:link, #header ul a:visited, #header ol a:link, #header ol a:visited, #header p a:link, #header p a:visited, #footer ul a:link, #footer ul a:visited, #footer ol a:link, #footer ol a:visited, #footer p a:link, #footer p a:visited { text-decoration: underline; } #header ul a:active, #header ul a:hover, #header ol a:active, #header ol a:hover, #header p a:active, #header p a:hover, #footer ul a:active, #footer ul a:hover, #footer ol a:active, #footer ol a:hover, #footer p a:active, #footer p a:hover { text-decoration: none; }
A selector can span multiple lines if each line except the last one ends with a comma:
#header, #footer, #foobar color:red
To avoid confusion it is recommended to use aliases for complex selectors instead.
In case you need to insert css without Turbine messing with it, you can use the @css
prefix. Any lines that begin with
@css
will appear in the output completely unchanged (except for the @css
prefix which is removed).
@css @-moz-document url-prefix(http://), url-prefix(https://), url-prefix(ftp://){ #foo color:red @css }
Result:
@-moz-document url-prefix(http://), url-prefix(https://), url-prefix(ftp://){ #foo { color: red; } }
If you have to use css hacks, this is the way to go.
If you want to use images or embed fonts, please note that all paths are relative to css.php! You can define constants or use the
special constants $_SCRIPTPATH
and $_FILEPATH
to work with this. See below for a detailed explaination of constants.
Constants (also known as "css variables") allow you to define your own easy-to-remember shortcuts for complicated hex colors or long font stacks. They can be used for any css property and are case-sensitive.
@constants myRed:#C02222 imagePath:/assets/images #foo color:$myRed background:url($imagePath/foo.png) top left no-repeat
#foo { color: #C02222; background: url(/assets/images/foo.png) top left no-repeat; }
The constants defined in in an @turbine
block only apply to the current .cssp file. There are two special constants
that apply globally and that are always made availiable by Turbine:
$_SCRIPTPATH
: The path to css.php
$_FILEPATH
: The path to the current .cssp file
Aliases are constants applied to selectors insted of values. Don't want to remember the complicated #wrapper #header > div ul
?
You don't have to:
@aliases mainNavigation: #wrapper #header > div ul $mainNavigation list-style:none
The @aliases
block defines mainNavigation
as an alias of #wrapper #header > div ul
, which
results us to the following css code:
#wrapper #header > div ul { list-style: none }
Aliases, like constants, are case-sensitive.
All .cssp
are processed completly independent from each other. Inside the files, constants and aliases apply only to
the @media
-block they are defined in. The exception is the set of constents defined outside of any block –
they apply to the whole file.
Example:
@constants mycolor:#F00 // Defined outside of any @media block = applies _globally_ @media screen @constants myothercolor:#00F // Defined in @media block = applies _only_ in the screen block #foo color:$mycolor background:$myothercolor @media print #foo color:$mycolor background:$myothercolor // Won't work as "myothercolor" is only defined for the "screen" block, but not for "print"
Result:
@media screen { #foo { color: #F00; background: #00F; } } @media print { #foo { color: #F00; background: $myothercolor; } }
Turbine's inheritance, prototyping and copying features allow you to pass around chunks of properties and values between elements in
your code. Note that @font-face
and @import
elements can copy and interit properties from other elements,
but they cannot be copied or inherited from.
To simply copy a value from a property in another selector, you can use the copy(selector property)
syntax:
#foo color:#F00 #bar color:copy(#foo color)
Result:
#foo { color: #F00 } #bar { color: #F00 }
The copied and copying properties don't have to be the same:
#foo background:#F00 #bar color:copy(#foo background)
Result:
#foo { color: #F00 } #bar { background: #F00 }
Copying works with aliases too. If you want to copy the color
value from $foo to #bar, you can simple use
copy($foo color)
:
@aliases foo: #header > div.foobar $foo color:blue #bar background:copy($foo color)
Result:
#header > div.foobar { color: blue; } #bar { background: blue; }
Turbine's extends
let elements inherit complete sets of properties from other elements, which are merged with the
element's own properties:
#parent color:red font-weight:bold div.child extends:#parent margin:4px
Result:
#parent { color: red; font-weight: bold; } div.child { margin: 4px; color: red; font-weight: bold; }
If a property is already defined in a element extends
will not overwrite it:
#parent color:red font-weight:bold div.child extends:#parent font-weight:normal
Result:
#parent { color: red; font-weight: bold; } div.child { font-weight: normal; color: red; }
For inheritance from multiple sources, the parent elements must be quoted because of the comma character (which otherwise might be part of a selector as well as a list sepperator):
#parent1 color:red #parent2 font-weight:bold div.child extends:"#parent1", "#parent2"
Result:
#parent1 { color: red; } #parent2 { font-weight: bold; } div.child { color: red; font-weight: bold; }
The ?
prefix allows you to define elements that will be removed before output but from which properties can be inherited
or copied from (see prefixes). These elements can be used to declare complete
building blocks for your real css elements:
// Prototypes ?box margin, padding:4px ?blackBox background:#000 ?whiteBox background:#FFF ?roundedBox border-radius:8px // "Real" elements div.whiteSqare extends:"?box", "?whiteBox" div.blackRound extends:"?box", "?blackBox", "?roundedBox"
Result:
div.whiteSqare { margin: 4px; padding: 4px; background: #FFF; } div.blackRound { margin: 4px; padding: 4px; background: #000; border-radius: 8px; }
The loader plugin allows you (among other things) to build a library of prototypes, store them in an external file and include them when you need them. The code for the black and white boxes above could then be shortend to the following:
@load url(myBoxTemplates.cssp) div.whiteSqare extends:"?box", "?whiteBox" div.blackRound extends:"?box", "?blackBox", "?roundedBox"
An additional bonus of building external libraries is that you can re-use them in all of your coming projects.
Generates @font-face declarations from a simplified syntax.
Bulletproof @font-face syntax is a syntax for embedding web fonts in a manner that works for all browsers and takes care of numerous browser quirks. Its only downside is that it's rather complicated:
@font-face { font-family: 'Graublau Web'; src: url('GraublauWeb.eot'); src: local('Graublau Web Regular'), local('Graublau Web'), url("GraublauWeb.woff") format("woff"), url("GraublauWeb.otf") format("opentype"), url("GraublauWeb.svg#grablau") format("svg"); }
The @font-face syntax plugin generates browser-specific @font-face declarations from a very simplified syntax.
fontface
to @turbine
plugin listSaginaMedium
":
@font-face
-rule with a single src
-property pointing not to a real
file but to the common basename, e.g. "src:url('fonts/SaginawMedium')
".eot, .woff, .otf, .ttf
and .svg
.
fonts/SaginawMedium.eot
.@turbine plugins:fontface @font-face font-family:'SaginawMedium' src:url('fonts/SaginawMedium') font-weight:bold font-style:italic
Result for IE <= 8:
@font-face { font-family: 'SaginawMedium'; src: url("fonts/SaginawMedium.eot"); font-weight: bold; font-style: italic; }
Result for all other browsers:
@font-face { font-family: 'SaginawMedium'; src: url("fonts/SaginawMedium.woff") format("woff"), url("fonts/SaginawMedium.ttf") format("truetype"), url("fonts/SaginawMedium.svg#SaginawMedium") format("svg"); font-weight: bold; font-style: italic; }
Converts proprietary gradient code into vendor-specific gradient code.
This plugin creates a cross-browser linear vertical or horizontal background gradient
(angles or radial gradient not supported). As this CSS3 property is still very alpha
we pick up W3C's current draft's syntax for a simple two-colored linear gradients.
For Mozilla, WebKit and Konquror we use their very differing vendor-specific gradient
implementation syntax, for Opera we assign a dynamically created SVG-file as background-image,
and for IE we make use of a gradient-filter.
Add backgroundgradient
to your @turbine
plugins rule and start using
linear-gradient
following W3C's current draft's syntax for a simple two-colored
linear gradient within a background-image
or background
property:
background: linear-gradient(<direction>,<startcolor>,<endcolor>);
top
: Gradient starting at the top, going to the bottomleft
: Gradient starting at the left, going to the right#FFF
rgb(255,255,255)
rgba(255,255,255,0.3)
@turbine plugins:backgroundgradient #foo background-image: linear-gradient(top,#FFF,#000)
Result for Mozilla:
#foo { background-image: -moz-linear-gradient(top,#FFF,#000); }
Result for WebKit:
#foo { background-image: -webkit-gradient(linear,left top,left bottom,from(#FFF),to(#000)); }
Result for Konqueror:
#foo { background-image: -khtml-gradient(linear,left top,left bottom,from(#FFF),to(#000)); }
Result for Opera:
#foo { background-image: url(/turbine/plugins/backgroundgradient/svg.php?direction=top&startcolor=#fff&endcolor=#000) 0 0 repeat; }
Result for IE 6 & 7:
#foo { background-image: linear-gradient(top,#FFF,#000); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFFFFFFF,endColorstr=#FF000000,gradientType=0); }
Result for IE 8:
#foo { background-image: linear-gradient(top,#FFF,#000); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFFFFFFF,endColorstr=#FF000000,gradientType=0)"; }
Automatically adds vendor-specific versions of border-radius
and implements some shortcuts.
Webkit and Mozilla browsers require vendor-specific prefixes for the CSS3 property border-radius
. This plugin
automatically inserts all of them wherever a border-radius
property is found. Additionally, the plugin provides
shortcuts for adding rounded corners only on the left, right, top or bottom side of an element: border-left-radius
,
border-right-radius
, border-top-radius
, border-bottom-radius
.
Add borderradius
to your @turbine
plugins rule and start using border-radius
like the
standard border-radius
CSS3 property.
@turbine plugins:borderradius #foo border-radius:4px
Result:
#foo { -moz-border-radius: 4px; -khtml-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
#foo border-left-radius:4px;
Result:
#foo { -moz-border-radius-topleft: 4px; -moz-border-radius-bottomleft: 4px; -khtml-border-top-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; -webkit-border-top-left-radius: 4px; -webkit-border-bottom-left-radius: 4px; border-top-left-radius: 4px; border-bottom-left-radius: 4px; }
Automatically adds vendor-specific versions of box-shadow
.
Webkit and Mozilla browsers require vendor-specific prefixes for the CSS3 property box-shadow
. This plugin automatically
inserts them wherever a box-shadow
property is found and also adds proprietary filters for Internet Explorer.
Add boxshadow
to your @turbine
plugins rule and start using box-shadow
like the
standard box-shadow
CSS3 property.
@turbine plugins:boxshadow #foo box-shadow:2px 2px 8px #000
Result:
#foo { box-shadow: 2px 2px 8px #000; -moz-box-shadow: 2px 2px 8px #000; -webkit-box-shadow: 2px 2px 8px #000; -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Color='#000000',Direction=135,Strength=2)"; filter: progid:DXImageTransform.Microsoft.Shadow(Color='#000000',Direction=135,Strength=2); }
Automatically adds vendor-specific versions of box-sizing
.
Webkit and Mozilla browsers require vendor-specific prefixes for the CSS3 property box-sizing
. This plugin automatically
inserts them wherever a box-sizing
property is found and also adds a proprietary behavior for Internet Explorer.
Add boxshadow
to your @turbine
plugins rule and start using box-shadow
to declare which box model
to use. The following values are available:
content-box
: Standard W3C box modelborder-box
: The width and height properties of an element include the padding and border, but not the margininherit
: Same as the parant element (default)@turbine plugins:boxsizing #foo box-sizing:border-box
Result:
#foo { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; behavior: url(plugins/boxsizing/boxsizing.htc); box-sizing: border-box; }
Includes or excludes css rules based on the viewer's browser, operating system or platform.
The browser and platform sniffer allows you to use Turbine's build-in browser sniffer for your cssp files. It allows you to include or exclude css rules based on the viewer's browser, operating system or platform, precisely targeting browser, engine or os versions (windows only).
Warning: Browser sniffing is always a complicated, messy and unreliable business. Don't use this plugin unless you think you really know what you're doing!
Add add sniffer
to your @turbine
plugins rule and use the browser
, engine
, os
and
device
properties.
@font-face
from Windows XP to circumvent XP's rendering problems with non-windows fontsUpdate your browser!messages to IE6 users
device
property
The device
property allows you to target mobile devices or desktop computers:
// Show red text only for dektop computers #foo device:desktop color:red // Show green text only for mobile devices #foo device:mobile color:green
To exclude devices, use the ^
operator at the beginning of the value of a device
property:
// No red text for mobile devices #foo device:^mobile color:red
You can use the following values for the device
property:
desktop
mobile
os
property
The os
property allows you to target operating systems:
// Show red text only for windows #foo os:windows color:red // Show green text only for mac os #foo os:mac color:green
You can target the different versions of windows (and only windows) too:
// Show red text only for windows versions equal or newer than vista #foo os:windows>=vista color:red // Show green text only for windows xp #foo os:windows=xp color:green
To exclude operating systems, use the ^
operator as usual:
// No red text for linux #foo os:^linux color:red
You can use the following values for the os
property:
windows
mac
linux
unix
(Includes FreeBSD, OpenBSD etc)os
but this is really unreliable.The following windows versions can be targeted:
95
nt4
98
me
2000
or 2k
xp
2003
or 2k3
vista
windows7
or win7
or 7
browser
property
The browser property doesn't target individual browsers but rather browser families. For example Flock, Songbird, Minefield and Firefor are all members
of the firefox family. To target one or multiple families, simply add their names to the browser
property of an element:
// Show red text only for firefox and opera #foo browser:firefox opera color:red
You can target browser versions too:
// Show red text only for firefox versions newer than 3.5 #foo browser:firefox>3.5 color:red // Show green text only for safari 4 #foo browser:safari=4 color:green
This also works for all browsers from the Firefox family with engine versions that are on par with firefox versions newer than 3.5. Version numbers must be
floats (e.g. to target Firefox 3.6.4 you have to write browser:firefox=3.64
).
To exclude browsers, use the ^
operator as usual:
// No red text for chrome #foo browser:^chrome color:red
The device browser
property can, like all properties of this plugin, also be used inside the @turbine
element. This will affect the
stylesheet as a whole:
// We don't want to bother with IE6, so we simply hide ALL STYLES from it. // That makes the page somewhat useable without much work @turbine browser:^ie<7
engine
property
Engine detection is a messy business because not all browsers anounce their engine and engine versions in the user agent string. To make the engine
property work, in some cases it has to be passed the browser name an version number instead of the actual engine!
// Webkit browsers usually tell us their engine, so we can target them easily #foo engine:webkit<525 color:red // IE7 doesn't tell us that it uses an engine called Trident 3.1, so we have to use the browser name and version number as a fallback #foo engine:ie=7 color:green
As with browser versions, engine version numbers must be floats too. To target WebKit 525.27.1 you have to write engine:webkit=525.271
.
To exclude engines, use the ^
operator as usual:
// No red text for webkit #foo engine:^webkit color:red
You can use the following values for the engine
property:
gecko
webkit
khtml
For all other engines (like Presto in Opera and Trident in IE) you have no choice but to target the Browser and its Version.
Tries to fix some common browser rendering and behavior bugs automatically.
min-height
:hover
on all elements (Source)<button>
styleability (Source)Note: there is no guarantee that the plugin will catch all cases in which a bug from the above list will occour. The goal is to reduce the time spent on fixing css, not to do away with manual bugfixing completly.
Just add bugfixes
to your @turbine
plugins rule. Done!
Smart color models for older browsers
The colormodels plugin enables the CSS color declarations rgba()
, hsl() and hsla()
for browsers
that usually don't support them. It works by transforming the original declarations to somthing the browser that is currently used
can understand.
Just add colormodels
to your @turbine
plugins rule. Done!
The following turbine code …
p background:hsla(200, 20%, 20%, 0.5)
… is recalculated to RGBA for Opera 9, which doesn't support hsla()
:
p { background: rgba(40, 54, 61, 0.5); }
For IE, the HSLA declaration is transformed into a proprietary filter:
p { background: none; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#8028363D,endColorstr=#8028363D); zoom: 1; }
If neither filters nor anything else would work (e.g. in really prehistoric browsers or in IE for non-background properties), a solid color is used:
p { background: rgb(40, 54, 61); }
Background transparency in IE works with Microsoft's proprietary filter
property which may cause unwanted effects
in some scenarios. Consider the following:
p background:rgba(200, 0, 0, 0.5) p.foo background:rgb(200, 0, 0)
Turbine will insert filter
property for p
:
p { background:none; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#80C80000,endColorstr=#80C80000); } p.foo { background: rgb(200, 0, 0); }
The problem is that in the browser the filter will also affect p.foo
because the p
selector of course also matches p.foo
. The solution is to explicitly remove any filters from p.foobar
:
p background:rgba(200, 0, 0, 0.5) p.foobar background:rgb(200, 0, 0) filter:none
Inlines images into the css output.
The Data URI plugin inlines all images smaller than 24kb as base64 encoded as a data URI or, for Internet Explorer, as MHTML. This significantly reduces the number of HTTP requests.
Just add datauri
to your @turbine
plugins rule. Done!
@turbine plugins:datauri #foo background:#FFF url(test.png) top left
Result:
#foo { background: #FFF url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAMAAADXEh96AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAGUExURf///8zjYPWWfS0AAAARSURBVHjaYmAAAUYiSIAAAwAAqAAH4ng45wAAAABJRU5ErkJggg==') top left; }
Adds the correct default styles for HTML5 elements
The HTML5 plugin adds most of the correct default styles for HTML5 elements according to the specifications. Some parts of the specifications (like the font size for headlines in sectioning content) are ignored because they would require an insane amount of css code to implement correctly. Note that for this plugin to work in Internet Explorer you still have to enable HTML5 elements via javascript.
Just add html5
to your @turbine
plugins rule. Done!
Enables display:inline-block
in older Browsers
This plugin enables display:inline-block
in older IE and Gecko Browsers by automatically setting display
to
-moz-inline-stack
rule for Gecko or setting display
to inline
and adding zoom:1
for IE < 8.
Just add inlineblock
to your @turbine
plugins rule. Done!
@turbine plugins:inlineblock #foo display:inline-block
Result in browsers using Gecko < 1.9:
#foo { display: -moz-inline-stack; }
Result in IE < 8:
#foo { display: inline; zoom: 1; }
Loads another .cssp file.
Loader loads the contents of another .cssp file at the exact location where @load
ist placed. It inserts the
code of the loaded file before parsing anything, so the contents of the file is subject to all of Turbines operations in
the file it is inserted into.
The plugin will automatically take care of any differences in indentation style between the loaded code and the code it is loaded into.
Add load
to your @turbine
plugins rule and add a @load url(path/to/file.cssp)
line
where you want a file to be included. Done!
This is an example of using the loader plugin to create a module to create a module that contains all the colors used in a project.
File style.cssp
:
@load url(/modules/colors.cssp) #foo color:$textcolor background:$bgcolor
File /modules/colors.cssp
:
@constants textcolor:#C00000 bgcolor:#EEE
Result:
#foo { color: #C00000; background: #EEE; }
Performs a number of micro-optimizations.
The minifier plugins shortens hex color declarations, replaces hex colors with shorter named colors when possible, removes units from zero values, removes
leading zeros from floats, shortens long margin and padding notation (8px 4px 8x 4px
is turned into 8px 4px
) and removes whitespace
from comma-sepparated strings, saving a bit of space and loading time.
Just add minifier
to your @turbine
plugins rule. Done!
#foo font-family: Georgia, "Times New Roman", serif color: #FF0000 background: #F0FFFF margin: 0.5em 0em padding: 8px 4px 8px 4px
Result (pretty-printed):
#foo { font-family: Georgia,"Times New Roman",serif; color: #F00; background: azure margin: .5em 0; padding: 8px 4px; }
Compressed result:
#foo{font-family:Georgia,"Times New Roman",serif;color:#F00;background:azure;margin:.5em 0;padding:8px 4px}
Automatically adds vendor-specific versions of opacity
.
This plugin automatically inserts all existing vendor prefixed opacity-properties, as well as the corresponding alpha-filter for IE.
Add opacity
to your @turbine
plugins rule and start using opacity
like the
standard opacity
CSS3 property.
@turbine plugins:opacity #foo opacity:0.3
Result:
#foo { -moz-opacity: 0.3; -khtml-opacity: 0.3; -webkit-opacity: 0.3; opacity: 0.3; }
plus, for IE 8:
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(opacity=30)";
or for IE 6 & 7:
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=30);
Inserts language- and country-specific quotation marks.
Different languages and countries use different quotation marks. The quote style plugin allows you to set
the contents for the quotes
property by language and/or country.
Include quotes
in your @turbine
plugins rule and start using the quotes
property with
the values listed below.
quotes
valuesValue | Result | Glyphs |
---|---|---|
german |
#foo { quotes:'\201E \201C \201A \2018'; } |
„ “ ‚ ‘ |
german-alt |
#foo { quotes:'\00BB \00AB \203A \2039'; } |
» « › ‹ |
swiss |
#foo { quotes:'\00AB \00BB \2039 \203A'; } |
« » ‹ › |
english-uk |
#foo { quotes:'\2018 \2019 \201C \201D'; } |
‘ ’ “ ” |
english-us |
#foo { quotes:'\201C \201D \2018 \2019'; } |
“ ” ‘ ’ |
Includes a reset stylesheet.
Auto-includes a handy set of css rules that unset the default styling for all elements.
Just add resetstyle
to your @turbine
plugins rule. Done!
To use a custom reset stylesheet, rename _custom.css
in the directory plugins/resetstyle
to
custom.css
and add your own reset rules there.
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { color: inherit; margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent; font-weight: normal; text-decoration: none; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } :focus { outline: 0; } ins { text-decoration: none; } del { text-decoration: line-through; } table { border-collapse: collapse; border-spacing: 0; }
Automatically adds vendor-specific versions of transform
.
Webkit, Opera and Mozilla browsers require vendor-specific prefixes for the CSS3 property transform
. This plugin automatically
inserts them wherever a transform
property is found and also adds a proprietary filter in conjunction with a behavior for Internet Explorer.
For it to work in Internet Explorer the transformed object needs to have width
and height
set. Also, if you queue up transforms,
limit yourself to a maximum of one of each sort (translate, rotate, scale), e.g. transform: rotate(25deg) translate(100px,0) scale(0.5)
.
Add transform
to your @turbine
plugins rule and start using transform
to declare a single one, or a sequence of
transforms. The following values are available:
rotate(angle)
Rotates the element clockwise around its center by the specified angle, e.g. rotate(30deg)
. Accepted values: positive and negative integers and floats. Accepted units: deg
, rad
or grad
.
scale(sx[, sy])
Specifies a 2D scaling operation on X and Y axes as described by [sx, sy]
, e.g. scale(2.1,4)
. If sy
isn't specified, it is assumed to be equal to sx
, e.g. scale(2.1)
. Accepted values: positive integers and floats. Accepted units: no unit needed.
scaleX(sx)
Specifies a 2D scaling solely on the X axis, e.g. scaleX(2.7)
. Accepted values: positive integers and floats. Accepted units: no unit needed.
scaleY(sy)
Specifies a 2D scaling solely on the Y axis, e.g. scaleY(0.3)
. Accepted values: positive integers and floats. Accepted units: no unit needed.
translate(tx[, ty])
Specifies a 2D translation as described by [tx, ty]
, e.g. translate(100px,20px)
. Accepted values: positive and negative integers and floats. Accepted units: px
, em
, %
, pt
or ex
.
translateX(tx)
Translates the element by the given amount along the X axis, e.g. translate(100px)
. Accepted values: positive and negative integers and floats. Accepted units: px
, em
, %
, pt
or ex
.
translateY(ty)
Translates the element by the given amount along the Y axis, e.g. translate(20px)
. Accepted values: positive and negative integers and floats. Accepted units: px
, em
, %
, pt
or ex
.
skew(ax[, ay])
Skews the element around the X and Y axes by the specified angles, e.g. skew(30deg,-10deg)
. If ay
isn't provided, no skew is performed on the Y axis., e.g. skew(30deg)
. Accepted values: positive and negative integers and floats. Accepted units: deg
, rad
or grad
.
skewX(angle)
Skews the element around the X axis by the given angle., e.g. skewX(30deg)
. Accepted values: positive and negative integers and floats. Accepted units: deg
, rad
or grad
.
skewY(angle)
Skews the element around the Y axis by the given angle., e.g. skewY(-10deg)
. Accepted values: positive and negative integers and floats. Accepted units: deg
, rad
or grad
.
matrix(a, c, b, d, tx, ty)
Specifies a 2D transformation matrix comprised of the specified six values
Multiple transforms may be queued together, separated by a whitespace, e.g. transform: rotate(25deg) translate(100px,0) scale(0.5)
. Note that the parts will get processed one by one from left to right. So in the mentioned example the translation won't happen along the X axis but on a virtual axis that is rotated 25 degrees clockwise.
@turbine plugins:transform #foo width: 200px; height: 100px; transform: rotate(25deg) translate(100px,0) scale(0.5)
Result for non-IE-browsers:
#foo { width: 200px; height: 100px; -moz-transform: rotate(25deg) translate(100px,0) scale(0.5); -o-transform: rotate(25deg) translate(100px,0) scale(0.5); -webkit-transform: rotate(25deg) translate(100px,0) scale(0.5); transform: rotate(25deg) translate(100px,0) scale(0.5); }
Result for IE8-browsers:
#foo { width: 200px; height: 100px; position: relative; transform: rotate(25deg) translate(100px,0) scale(0.5); left: 91px; top: 38px; behavior: url(/Turbine/plugins/transform/transform.htc); -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(Dx=1.0,Dy=1.0,M11=0.453153895,M12=-0.21130913,M21=0.21130913,M22=0.453153895,sizingMethod='auto expand')"; zoom: 1; }
Result for IE6/7-browsers:
#foo { width: 200px; height: 100px; position: relative; transform: rotate(25deg) translate(100px,0) scale(0.5); left: 91px; top: 38px; behavior: url(/Turbine/plugins/transform/transform.htc); filter: progid:DXImageTransform.Microsoft.Matrix(Dx=1.0,Dy=1.0,M11=0.453153895,M12=-0.21130913,M21=0.21130913,M22=0.453153895,sizingMethod='auto expand'); zoom: 1; }
Meta plugins enable a group of other plugins.
Meta plugins enable a group of related plugins. If, for expample, you wanted to use lots of CSS3 properties, you don't have to
write plugins:boxshadow, borderradius, transform, transistion
and simply use plugins:css3
, which will
enable all plugins from the previous list. There are four core meta plugins available: CSS3, Performance, Legacy and Utility.
Activates all other plugins that enable advanced CSS properties:
Activates all other plugins that improve performance:
Activates all other plugins that help you to support older browsers:
Activates all other plugins that add helpful utilities:
Turbine is free open source software (LGPL) and development takes place on GitHub, a hosting platform for the excellent distributed version control system Git. Github membership is free and makes helping your favourite open source project really easy. See the following video for details.
Tom Preston-Werner, Chris Wanstrath and Scott Chacon — Git, GitHub and Social Coding
Everybody is welcome to fork Turbine and start contributing!
Plugin development for Turbine is rather simple. All you need is a file called plugin_name.php
containing
a function of some sort (usually named plugin_name()
), located in the plugins directory. The function must
accept only one argument, which is passed as a reference (see the PHP manual on references).
The contents of this argument depends on the hook the plugin is assigned to:
Hook | Time of execution | Argument |
---|---|---|
before_parse |
Before the .cssp files are parsed | Reference to an array containing the lines of the original .cssp files |
before_compile |
After parsing, before applying Turbine core features (inheritance and the like) | Reference to an array containing the parsed Turbine code |
before_glue |
After compilation and cssp magic, just before the output ist generated | Reference to an array containing the parsed Turbine code |
before_output |
After generating the output of one .cssp file, before combining the output with other files | Reference to a string containing the final css output from the current .cssp file |
To hook into Turbine you need to call the register_plugin()
function using three arguments: the hook, an
execution priority and your plugin function's name:
<?php register_plugin('before_compile', 0, 'mypluginfunction'); ?>
It is recommended to leave the execution priority at 0 unless early oder late execution of the plugin is really important. A higher priority means earlier execution.
When using before_compile
or before_glue
the array recieved as the argument for the plugin
function will look like this:
Array ( [@media foo] => Array ( [#bar] => Array ( [property1] => Array ( [0] => value ) [property2] => Array ( [0] => value ) ) ) [@media bar] => Array ( [#bar] => Array ( [property1] => Array ( [0] => value ) [property2] => Array ( [0] => value1 [1] => value2 [2] => value3 ) ) ) )
CSS rules that are not part of any @media
block a stored in the global
block. A property may contain more
than one value. Properties that start with an underscore are considered hidden/special properties. They will usually not apprar in
the final css output like normal properties.
@font-face
and @import
statements are stored in sepperate arrays in the global
block.
@cssp
statements appear in their respective blocks as @css-X
elements with X
being a
consecutive number. All @css-X
elements have only one property, _value
, which contains the raw CSS code
from the@cssp
statement.
Given the following Turbine input code …
@import url(foobar.css); span.test color:blue span.test color:green @font-face font-family:"Example" src:url("example.otf") @media screen #foo div.bar margin, padding:4px
… the array that plugin functions recieve on before_compile
will be the following:
Array ( [global] => Array ( [@import] => Array ( [0] => Array ( [0] => url(foobar.css); ) ) [@font-face] => Array ( [0] => Array ( [font-family] => Array ( [0] => "Example" ) [src] => Array ( [0] => url("example.otf") ) ) ) [span.test] => Array ( [color] => Array ( [0] => blue [1] => green ) ) ) [@media screen] => Array ( [#foo div.bar] => Array ( [margin, padding] => Array ( [0] => 4px ) ) ) )
The array that plugin functions recieve on before_glue
will most likely be slightly different because Turbine and some
plugins will by then have already done their work. The margin, padding
property would for example already be expanded to
two sepperate properties:
[@media screen] => Array ( [#foo div.bar] => Array ( [margin] => Array ( [0] => 4px ) [padding] => Array ( [0] => 4px ) ) )
In case you wanted your plugin to remove all occurences of background-image
from your stylesheets,
this would be the code:
<?php /** * remove_background_image.php * Remove all occurences of background-image */ function remove_background_image(&$parsed){ // Loop through the @media blocks foreach($parsed as $block => $css){ // Loop through the selectors foreach($parsed[$block] as $selector => $styles){ // Look for background-image in the styles if(isset($parsed[$block][$selector]['background-image'])){ // Be gone! unset($parsed[$block][$selector]['background-image']); } } } // No need to return anything } // Hook into Turbine $cssp->register_plugin('before_compile', 0, 'remove_background_image'); ?>
Don't be afraid to do anything CPU- or memory consuming in your plugins - in production mode, everything is calculated only once and is served from the cache afterwards.
$cssp->report_error(string $message)
Reports a big ugly error message when in debug mode.
$cssp->report_error('Something went wrong!');
static CSSP::comment(array $element, string $property, string $comment)
Adds a css comment to an element when not compressing. If $property
is null
, the comment is added to the selector, otherwise to
the property $property
.
CSSP::comment($parsed['global']['#foo'], 'color', 'Changed by my plugin!');
Result:
#foo { color: red; /* Changed by my plugin! */ }
$cssp->get_final_value(array $values [, string $property [, bool $compressed]])
From an array of css values this method returns the value with the highest rank, i.e. the last value or the last value with !important
.
// Returns "green" $cssp->get_final_value(array( 'red', 'blue', 'green' )); // Returns "blue !important" $cssp->get_final_value(array( 'red', 'blue !important', 'green' ));
The property parameter can be used to handle special cases like -ms-filter
where values must be combined:
// Returns "foo bar" $cssp->get_final_value(array( 'foo', 'bar' ), '-ms-filter');
If $compressed
is true, the method will return a minified output.
$cssp->insert(array $elements, string $block [, string $before[, string $after]])
Inserts $elements
in the block $block
before the element with the selector $before
or after the element with the
selector $after
.
$example_element = array( '#foo' = array( 'color' => array('red') ) ); // Insert before "#bar" in the global block $cssp->insert($example_elements, 'global', 'bar'); // Insert after "#bar" in the "@media print" block $cssp->insert($example_elements, '@media print', null, 'bar');
This only works directly with $cssp->parsed
and not with the reference passed to the plugin function!
$browser
instanceTurbine's browser sniffer is developed as a subproject. By the time any plugin in Turbine gets executed, the browser sniffer will already have parsed the visitor's user agent string. The following variables might be useful:
Variable | Contains | Possible values |
---|---|---|
$browser->browser |
Browser name (Lowercase string) | A browser name (e.g. "safari") or the name of the larger family the browser belogs to. For example Flock and Songbird would be detected as "firefox" |
$browser->browser_version |
Browser version (Float) | The browser's version number as a float value. Firefox 3.6.4 would be detected as "3.64". |
$browser->engine |
Browser engine (lowercase string) | Contains the browser's engine if this information is available from the user agent string (usually the case in Webkit and Gecko browsers) or otherwise the browser's family name (Opera, IE) |
$browser->engine_version |
Browser engine version (Float) | The browser's engine version number as a float value. Gecko 1.9.2.3 would be detected as "1.923". |
$browser->platform |
OS name (lowercase string) | Contains the user's operating system name (e.g. "Windows", "Mac", "Linux" or "Unix") |
$browser->platform_version |
OS version (Float) | Contains the user's operating system version if this information is available from the user agent string (eg. "5.1" for Windows XP or "10.5" for OS X Leopard) |
$browser->platform_type |
Platform type (Lowercase string) | Either "Desktop" or "Mobile" |
When the browser sniffer failes to detect one of the above properties, the lowercase string "unknown" is used.
<?php /** * example * A great example. Does something cool. * @param array $param1 The first param * @param int $param2 The second param * @return bool */ function example($param1, $param2){ global $g1, $g2; $length = count($param1); for(i = 0; i < $length; $i++){ // A helpful comment explaining why the sub function is called example_subfunction($param1[$i]); } return false; } /** * example_subfunction * A secondary example. Related to example somehow * @param string $param Some explanation * @return void */ function example_subfunction($param){ if($param == 1){ foo(); } else{ bar(); } } ?>
The CSS to Turbine Converter transforms normal CSS code into ready-to-use Turbine code. Note that the converter is a rather simple script and only changes the syntax of the input code! It doesn't use any of the more sophisticated Turbine features. It can help you migrate a project to Turbine but should not be used for more as a starting point.
Paste code, change indentation settings, click "Convert!". Done!
The Turbine Shell is a simple playground for Turbine. Simply enter some HTML and Turbine code, configure the browser variables, click "Go!" and see the results! You can use all turbine plugins, constants, aliases and all other features. After checking the "Interactive mode" checkbox at the bottom the result frames will be updated after every keystroke.
Add code, change browser variables, click "Go!". Done!
Turbine speeds up your CSS development and increases your productivity. It allows you to build more websites in less time, charge more for less work or just concentrate on things that are more important than tweaking CSS code, like design or content. And that's pretty much it.
Turbine would problably work to some extend but many of it's operations (mostly plugins) depend on user-agent sniffing and on devlivering slightly different css code to different user agents.
For most cases, Turbine does more good to your website's performance than it does have a negative impact on it. Not only can Turbine output compressed CSS code, but all the calculations in Turbine only happen once per file and user agent. This result is then cached and used for as long as you don't change the source file, and if it already served that particular user agent. The resulting files are served compressed using Zlib output compression in 2KB chunks if available, or alternatively Gzip. Additionally Turbine checks whether a user agent already downloaded our current styles and, if that's true, tells it to use its cached version. This way Turbine uses as little processing time on the server as possible, reduces transfer times and saves traffic.
In order to improve performance even more, you can minify CSS with the Minifier plugin, and replace all images referenced in your CSS code with embedded data URIs using the DataURI plugin.
In short: unless you are a complete performance nerd that knows every trick by heart and has too much time at hands, Turbine will improve your website's performance.
Of course! The following websites all use Turbine:
Set debug_level
in your config.php to anything but 0
to disable the cache.
CSSP stands for "CSS Plus", Turbine's rather unimaginative working title.