Three20's CSS feature has the potential to be an incredibly powerful feature, making it possible to theme and style native applications using CSS. Three20's implementation is tightly bound to the TTStyle framework and this adds far more weight to the framework than is necessary.
Nimbus Stylesheets
A clean Nimbus implementation would port the CSS grammar and parser that were built for Three20 and make it incredibly easy to import css files and then apply them to standard views.
The interface I'm imaging would look something like this:
// Loads a stylesheet from disk and parses it. This would probably be done at
// app initialization. Because this is necessary for styling views, these style sheets
// should always be immediately available.
// If processing the stylesheet takes a lot of time, it may be worth breaking the
// stylesheets up into separate files and loading them on-demand.
NIStylesheet* stylesheet = [NIStyleSheet stylesheetFromFilePath:<path to css file>];
// This method would apply styles to the given view and all of its subviews.
// This is useful if you want to quickly style a controller's view hierarchy on
// viewDidLoad. This method should be *fast*.
[stylesheet applyRecursivelyTo:self.view];
One method of styling could be to use class names to apply styles to a type of view. For example:
/* All toolbar instances would have this style applied */
UIToolbar {
tint-color: #000099; /* tint the toolbar red */
translucent: true;
}
/* All network image views will have a white border */
NINetworkImageView {
border-color: rgba(255, 255, 255, 0.5); /* semi-transparent white border */
border-width: 1px;
}
Styling Specific View Instances
It's important to be able to target specific views and style them accordingly. Below are just two ways one could explore the implementation for this.
Four-letter IDs
We could also get fancy with ids in a couple of ways. One could use the tag property on all views to define a unique id using the four character id method. For example:
In code:
photoView.tag = 'ppic'; // This photo view is a profile picture.
In CSS:
#ppic {
background-color: blue;
}
Pros:
- Easy to use (effectively automatic with the applyRecursivelyTo: method)
- Interface builder integration (you can set tags for views very easily)
Cons:
- Restricted to four letter domain for ids.
- Requires use of the tag property.
Manual Style Application
We could provide a method that allows us to pick a style and apply it directly to any view. An example use of this method would probably look something like this:
[stylesheet applyStyleToView:photoView withID:@"photoView"];
Pros:
- Allows full-length names for style IDs.
Cons:
- Requires manual application of style to every view.
Pseudo-Comprehensive List of Nimbus CSS Properties
color => [#xxxxxx|#xx|rgba(xx, xx, xx, xx.xx)|rgb(xx, xx, xx)|color-name]
dimension => [xx(px)]
font-size => [xx(pt)]
box-dimensions => [<dimension>|<dimension> <dimension>|<dimension> <dimension> <dimension> <dimension>]
UIView {
border-color: <color> {view.layer.borderColor}
border-width: <dimension> {view.layer.borderWidth}
background-color: <color> {view.backgroundColor}
border-radius: <dimension> {view.layer.cornerRadius}
opacity: xx.xx {view.layer.opacity}
}
UILabel {
color: <color> {label.textColor}
font: <font-size> <font-name> {label.font}
font-weight: [bold|normal] {label.font}
text-shadow: <color> <x-offset> <y-offset> {label.shadowColor label.shadowOffset}
text-align: [left|right|center] {label.textAlignment}
line-break-mode: [wrap|character-wrap|clip|head-truncate|tail-truncate|middle-truncate] [label.lineBreakMode]
number-of-lines: xx {label.numberOfLines}
minimum-font-size: <font-size> {label.minimumFontSize}
adjusts-font-size: [true|false] {label.adjustsFontSizeToFitWidth}
baseline-adjustment: [align-baselines|align-centers|none] {label.baselineAdjustment}
}
UILabel:highlighted {
color: <color> label.highlightedTextColor;
}
UIButton {
padding: <box-dimensions>; {button.contentEdgeInsets, button.titleEdgeInsets, button.imageEdgeInsets}
color: <color> {[button titleColorForState:]}
text-shadow: <color> {[button titleShadowColorForState:]}
}
UIButton:[highlighted|disabled|selected] {
color: <color> {[button titleColorForState:]}
text-shadow: <color> {[button titleShadowColorForState:]}
}
UITableView {
separator-style: [none|single-line|single-line-etched] {tableView.separatorStyle}
separator-color: <color> {tableView.separatorColor}
}