ionfish / stylish

Write CSS with Ruby

This URL has Read+Write access

stylish / index.html
100644 265 lines (215 sloc) 8.649 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
---
layout: default
title: Stylish, a CSS generator in Ruby
article_link: http://extralogical.net/2009/05/generating-css-with-stylish/
---
 
<p>
  Stylish is a tool that lets you generate
  <abbr title="Cascading Stylesheets">CSS</abbr> code with a minimum of fuss.
  Its aim is to make writing certain kinds of stylesheet much simpler. Common
  examples include those with a lot of duplication, or which are just
  variations on the same basic structure.
</p>
 
<p>
  The following tutorial assumes you have Ruby and RubyGems installed. Ruby
  programming knowledge helps, but should not be essential.
</p>
 
<div class="section">
  <h1>Why would you want to write CSS in Ruby?</h1>
  
  <p>
    Because CSS doesn&#8217;t have loops or variables, and can be very
    repetitive. Stylish allows you to eliminate a lot of redundancy in your
    code. There are other reasons too, as we will see throughout this tutorial.
For a more comprehensive explication,
read <a href="{{ page.article_link }}">Generating CSS with Stylish</a>.
  </p>
</div>
 
<div class="section">
  <h1>Installing Stylish</h1>
  
  <p>The simplest way to install Stylish is via RubyGems:</p>
  
  <pre class="code terminal"><code>sudo gem install stylish</code></pre>
  
  <p>
    You&#8217;ll need to have the <a href="http://gemcutter.org/">Gemcutter
    gem</a> installed, but Stylish has no other gem dependencies. Ruby 1.8.6
    and Ruby 1.9 are both supported, but <a href="ruby19.html">using 1.9 is
    recommended</a> since it makes developing with Stylish that bit more
    pleasant.
  </p>
</div>
 
<div class="section">
  <h1>Creating simple stylesheets</h1>
  
  <p>
    The foundation of the stylesheet generation <abbr title="Domain-Specific
Language">DSL</abbr> is the <code>Stylish.generate</code> method. This
    takes a block, and returns a <code>Stylesheet</code> object.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  # Your rules here
end{% endhighlight %}
  
  <p>
    Now to construct some rules. This is done with the <code>rule</code>
    method, which must be passed one or more selectors, a hash of
    declarations and/or a block.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  rule "div.section", :margin_bottom => "1em"
end{% endhighlight %}
 
  <p>
    Note that selectors are strings, and declarations are hashes where the keys
    are symbols and the values are strings. The rule method can be a bit
    verbose, so selectors which consist of a single <abbr title="Hypertext
Markup Language">HTML</abbr> element can be used directly as methods.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  p :line_height => 1.5
  a :text_transform => "uppercase"
end{% endhighlight %}
 
  <p>
    Rules can also take a block, which creates a new selector scope. This means
    that rules with repetitive CSS namespacing using descendant and child
    selectors can be refactored into simple tree structures.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  rule "div.section" do
    p :line_height => 1.5
    a :text_transform => "uppercase"
  end
end
 
style.to_s # => div.section p {line-height:1.5;}
           # div.section a {text-transform:uppercase;}{% endhighlight %}
  
  <p>
    Once you&#8217;ve created your stylesheet object, you&#8217;ll probably
    want to serialise it to a file. The <code>Stylesheet</code> class includes
a <code>print</code> method for just this eventuality.
  </p>
  
{% highlight ruby %}style.print('my_style.css'){% endhighlight %}
</div>
 
<div class="section">
  <h1>Using variables</h1>
  
  <p>
    Variables allow property values to be determined when the stylesheet is
    serialised, rather than when it&#8217;s declared. A hash (in other words, a
    symbol table) containing the variables&#8217; names and values should be
    passed to the stylesheet&#8217;s <code>to_s</code> method.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  a :color => :bright
end
 
style.to_s :bright => "f00" # => a {color:#f00;}
style.to_s :bright => "0f0" # => a {color:#0f0;}
style.to_s :bright => "00f" # => a {color:#00f;}{% endhighlight %}
  
  <p>
    Variables are represented by Ruby symbols, and can be used in place of
    selectors as well as properties.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  rule :wrapper do
    a :color => :bright
  end
end
 
style.to_s :wrapper => "#wrapper", :bright => "f00"
  # => #wrapper a {color:#f00;}{% endhighlight %}
  
  <p>
    Variables allow the same simple template to be used multiple times.
    Creating different colour schemes is the classic use case, but there are
    plenty of others.
  </p>
</div>
 
<div class="section">
<h1>Compound values</h1>
  
<p>
Most declaration values are simple strings or numbers. Some, however, have
a more complex internal structure. The most common example is
<code>background</code> declarations.
</p>
  
{% highlight ruby %}style = Stylish.generate do
  body :background => {:color => "fafafa", :image => "bg.png",
                       :repeat => "no-repeat", :position => ["50%", "10px"],
                       :compressed => true}
end
 
style.to_s
  # => body {background:#fafafa url('bg.png') no-repeat 50% 10px;}
{% endhighlight %}
  
  <p>
    The <code>compressed</code> flag tells Stylish to use the shorthand form of
    the various <code>background-</code> properties; omitting it will generate
    the more specific longhand declarations.
  </p>
{% highlight css %}body {
  background-color:#fafafa;
  background-image:url('bg.png');
  background-repeat:no-repeat;
  background-position:50% 10px;
}{% endhighlight %}
  
  <p>
    Variables will work both as a replacement for compound values, substituting
    the entire hash or array when serialising the stylesheet.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  body :background => :bodybg
end
 
style.to_s(:bodybg => {:url => "/images/eyewatering.gif"})
  # => body {background-image:url('/images/eyewatering.gif');}
{% endhighlight %}
  
  <p>
    However, they can also be used within the body of the compound value,
    nested as deeply within the data structure as necessary.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  body :background => {:color => "000", :image => :fruit}
end
 
style.to_s({:fruit => "apple.jpg"})
  # => body {background-color:#000; background-image:url('apple.jpg');}
{% endhighlight %}
  
  <p>
    Combining compound values and variables in this way can be very powerful,
    as often one will only want to make minor changes between different
    stylesheets, and picking out a particular value with a variable simplifies
    the mappings between variables and values considerably.
  </p>
</div>
 
<div class="section">
  <h1>Multiple background images</h1>
  
  <p>
    Stylish attempts to build in forward-compatibility with powerful features
    of CSS3 such as
    <a href="http://www.w3.org/TR/css3-background/#layering">multiple
    background images</a>. When using these features in Stylish, two simple
    rules of thumb should be followed:
  </p>
  
  <ul>
    <li>Singular declarations have singular names and take singular values</li>
    <li>Multiple declarations have plural names and take arrays of values</li>
  </ul>
  
  <p>
    To illustrate this, let&#8217;s look at two different background
    declarations.
  </p>
  
{% highlight ruby %}style = Stylish.generate do
  body :background => {:image => "single.png"}
  rule ".wrap", :background => {:images => ["first.png", "second.png"]}
end
 
style.to_s # => body {background-image:url('single.png');}
           # .wrap {background-image:url('first.png'), url('second.png');}
{% endhighlight %}
  
  <p>
    In other words, to give a rule one background image, use
    <code>:image</code>; to give it several, use <code>:images</code> (and an
    array of values). This applies to all background properties which may take
    multiple values:
  </p>
  
  <ul>
    <li><code>background-image</code>, use <code>:images</code></li>
    <li><code>background-origin</code>, use <code>:origins</code></li>
    <li><code>background-clip</code>, use <code>:clips</code></li>
    <li><code>background-repeat</code>, use <code>:repeats</code></li>
    <li><code>background-size</code>, use <code>:sizes</code></li>
    <li><code>background-position</code>, use <code>:positions</code></li>
  </ul>
  
  <p>
    Note that the singular and plural versions are incompatible with one
    another; if you use <code>:image</code> in a background declaration you
    can&#8217;t use <code>:images</code> in the same declaration, and vice
    versa.
  </p>
</div>