Classy supports all UIAppearance properties and methods. It also supports alot of properties that are not covered by UIAppearance. Wherever possible Classy uses the same naming used by UIKit, so you don't need to wonder which style properties map to which objective-c properties.

For example the following UIPageControl properties

@property (nonatomic,retain) UIColor *pageIndicatorTintColor;
@property (nonatomic,retain) UIColor *currentPageIndicatorTintColor;

Can be styled using exactly the same property names

UIPageControl {
  pageIndicatorTintColor black
  currentPageIndicatorTintColor purple
}
        

Properties can also be defined using kebab case

UIPageControl {
  page-indicator-tint-color black
  current-page-indicator-tint-color purple
}
        

Sometimes UIAppearance requires you to pass additional arguments when setting a property. For example the following UIToolBar UIAppearance setters

- (void)setBackgroundImage:(UIImage *)backgroundImage 
        forToolbarPosition:(UIBarPosition)topOrBottom
                barMetrics:(UIBarMetrics)barMetrics;
                
- (void)setShadowImage:(UIImage *)shadowImage
    forToolbarPosition:(UIBarPosition)topOrBottom;

Format

Classy allows you to specify these argument values with the following format

<propertyName> [<argumentName> : <argumentValue>, ... ]
  • Order of arguments is not important
  • Remove any "for" prefix from the argument name. ie forToolbarPosition becomes toolbarPosition

Examples

Heres an example of the UIToolBar UIAppearance methods with all the arguments set

UIToolBar {
  background-image[barMetrics:landscape-phone, toolbarPosition:top] test_image_4
  shadow-image[barMetrics:landscape-phone, toolbarPosition:bottom] test_image_3
}
        

If you leave out any arguments, the first enum value will be used

UIToolBar {
  background-image[toolbarPosition:top] test_image_4
  shadow-image[barMetrics:landscape-phone] test_image_3
}
        

It's always a good idea to avoid repeating yourself. Classy enables you to avoid repeating common style property values by defining them as a variable, which can then be used throughout the stylesheet.

A variable must be named according to the following rules

  • Must begin with upper/lower case letter OR $
  • Can contain _, -, or any alphanumeric char
// prefix with '$' to help distinguish variables
$brand-color = #e1e1e1

// OR not
insets = 5, 10, 5, 10

UIButton {
  background-color $brand-color
  contentEdgeInsets insets
  background-image[state:selected] bg_button insets
}
        

Variables and style property values can contain simple math expressions.

$corner-radius = 2 + 2
$insets = 5, 10, 5, 10

UIButton {
  layer @{
    border-width 10 - 5
    corner-radius $corner-radius + 2
  }
  contentEdgeInsets $insets * 2
}
        

Classy allows you to style properties of nested object keypaths, for example "view.layer.borderWidth" or "navigationBar.titleTextAttributes.font". To disambiguate between nested selectors and nested properties you must use the @ after the property name.

UINavigationBar {
  title-text-attributes: @{
    font: HelveticaNeue 21
    foreground-color: magenta
    background-color: red
    ligature: 6
    kern: 0.6
    strikethrough-style: single
    underline-style: double
    stroke-color: blue
    paragraph-style: @{
      line-spacing: 20
      paragraph-spacing: 15
      line-break-mode:truncatingTail
      alignment:center
    }
    shadow: @{
      shadow-offset: 1,2
      shadow-blur-radius: 10
      shadow-color: purple
    }
  }
}
        

TextAttributes Special Case

Any property that has a type of NSDictionary and suffix of "TextAttributes" will be treated as a CASTextAttributes

As always { and } are optional

UIView
  background-color #A2A2A2
  layer @
    border-width   2
    border-color   #A1A1A1
    corner-radius  8
    shadow-color   black
    shadow-offset  9,3
    shadow-opacity 0.6
    shadow-radius  4

        

Type Example Value Converted Value
NSInteger 12 12
CGFloat 5.5 5.5
BOOL YES YES
NO NO
true YES
false NO
UIEdgeInsets 20 { .top = 20, .left = 20, .bottom = 20, .right = 20 }
20, 10 { .top = 20, .left = 10, .bottom = 20, .right = 10 }
5, 10, 15, 20 { .top = 5, .left = 10, .bottom = 15, .right = 20 }
UIOffset 99 { .horizontal = 99, .vertical = 99 }
6, 7 { .horizontal = 6, .vertical = 7 }
CGSize 11 { .width = 11, .height = 11 }
14, 15 { .width = 14, .height = 15 }
CGPoint 10 { .x = 10, .y = 10 }
4, 5 { .x = 4, .y = 5 }
CGRect 3, 12, 15, 80 { .origin.x = 3, .origin.y = 12, .size.width = 15, .size.height = 80 }

, Value Seperator

The command value seperator character is optional. Which means that 12, 13 and 12 13 will both produce the same value

Class Example Value Converted Value
UIImage bg_button_selected [UIImage imageNamed:@"bg_button_selected"]
bg_home 4,6,8,10 [[UIImage imageNamed:@"bg_home"] resizableImageWithCapInsets:insets]
"image with spaces" [UIImage imageNamed:@"image with spaces"]
UIColor #e1e1e1 [UIColor cas_colorWithHex:@"#e1e1e1"]
supports #rgb or #rrggbb or #rrggbbaa
rgb(160, 180, 220) [UIColor colorWithRed:160/255.0 green:180/255.0 blue:220/255.0 alpha:1]
rgb(180, 200, 220, 0.2) [UIColor colorWithRed:180/255.0 green:200/255.0 blue:220/255.0 alpha:0.2]
hsl(200, 60%, 100%) [UIColor colorWithHue:200/360.0 saturation:60/100.0 brightness:100/100.0 alpha:1]
hsl(200, 60%, 100%, 0.2) [UIColor colorWithHue:200/360.0 saturation:60/100.0 brightness:100/100.0 alpha:0.2]
red [UIColor redColor]
supports your own colors
UIFont Avenir-Light 12 [UIFont fontWithName:@"Avenir-Light" size:12]
check iosfonts.com for a list of fonts available
20 [UIFont systemFontOfSize:20]
NSString 'single quote string' @"single quote string"
"double quote string" @"double quote string"
Wherever possible Classy uses the following method to map enum values.
Given enum constant value (UIControlStateNormal), remove enum name (UIControlState), convert to lowercase, which results in normal
Enum Value Converted Value
UIControlState normal UIControlStateNormal
highlighted UIControlStateHighlighted
disabled UIControlStateDisabled
selected UIControlStateSelected