Module: Sass::Script::Functions

Included in:
EvaluationContext
Defined in:
lib/sass/script/functions.rb

Overview

Methods in this module are accessible from the SassScript context. For example, you can write

!color = hsl(120, 100%, 50%)

and it will call #hsl.

The following functions are provided:

#hsl : Converts an hsl(hue, saturation, lightness) triplet into a color.

#hsla : Converts an hsla(hue, saturation, lightness, alpha) quadruplet into a color.

#rgb : Converts an rgb(red, green, blue) triplet into a color.

#rgba : Converts an rgb(red, green, blue, alpha) triplet into a color.

#red : Gets the red component of a color.

#green : Gets the green component of a color.

#blue : Gets the blue component of a color.

#alpha / #opacity : Gets the alpha component (opacity) of a color.

#opacify / #fade-in : Makes a color more opaque.

#transparentize / #fade-out : Makes a color more transparent.

#percentage : Converts a unitless number to a percentage.

#round : Rounds a number to the nearest whole number.

#ceil : Rounds a number up to the nearest whole number.

#floor : Rounds a number down to the nearest whole number.

#abs : Returns the absolute value of a number.

These functions are described in more detail below.

Adding Custom Functions

New Sass functions can be added by adding Ruby methods to this module. For example:

module Sass::Script::Functions
  def reverse(string)
    assert_type string, :String
    Sass::Script::String.new(string.value.reverse)
  end
end

There are a few things to keep in mind when modifying this module. First of all, the arguments passed are Literal objects. Literal objects are also expected to be returned. This means that Ruby values must be unwrapped and wrapped.

Most Literal objects support the value accessor for getting their Ruby values. Color objects, though, must be accessed using rgb, red, green, or blue.

Second, making Ruby functions accessible from Sass introduces the temptation to do things like database access within stylesheets. This temptation must be resisted. Keep in mind that Sass stylesheets are only compiled once at a somewhat indeterminate time and then left as static CSS files. Any dynamic CSS should be left in <style> tags in the HTML.

Within one of the functions in this module, methods of EvaluationContext can be used.

Defined Under Namespace

Classes: EvaluationContext

Instance Method Summary collapse

Instance Method Details

#abs(value) ⇒ Number

Finds the absolute value of a number. For example:

abs(10px) => 10px
abs(-10px) => 10px

Parameters:

  • value (Number)

    The number

Returns:

  • (Number)

    The absolute value

Raises:



390
391
392
# File 'lib/sass/script/functions.rb', line 390

def abs(value)
  numeric_transformation(value) {|n| n.abs}
end

#alpha(color) ⇒ Number Also known as: opacity

Returns the alpha component (opacity) of a color. This is 1 unless otherwise specified.

Parameters:

Returns:

Raises:

  • (ArgumentError)

    If color isn't a color



271
272
273
274
# File 'lib/sass/script/functions.rb', line 271

def alpha(color)
  assert_type color, :Color
  Sass::Script::Number.new(color.alpha)
end

#blue(color) ⇒ Number

Returns the blue component of a color.

Parameters:

Returns:

Raises:

  • (ArgumentError)

    If color isn't a color



260
261
262
263
# File 'lib/sass/script/functions.rb', line 260

def blue(color)
  assert_type color, :Color
  Sass::Script::Number.new(color.blue)
end

#ceil(value) ⇒ Number

Rounds a number up to the nearest whole number. For example:

ciel(10.4px) => 11px
ciel(10.6px) => 11px

Parameters:

  • value (Number)

    The number

Returns:

  • (Number)

    The rounded number

Raises:



364
365
366
# File 'lib/sass/script/functions.rb', line 364

def ceil(value)
  numeric_transformation(value) {|n| n.ceil}
end

#floor(value) ⇒ Number

Rounds down to the nearest whole number. For example:

floor(10.4px) => 10px
floor(10.6px) => 10px

Parameters:

  • value (Number)

    The number

Returns:

  • (Number)

    The rounded number

Raises:



377
378
379
# File 'lib/sass/script/functions.rb', line 377

def floor(value)
  numeric_transformation(value) {|n| n.floor}
end

#green(color) ⇒ Number

Returns the green component of a color.

Parameters:

Returns:

Raises:

  • (ArgumentError)

    If color isn't a color



250
251
252
253
# File 'lib/sass/script/functions.rb', line 250

def green(color)
  assert_type color, :Color
  Sass::Script::Number.new(color.green)
end

#hsl(hue, saturation, lightness) ⇒ Color

Creates a Color object from hue, saturation, and lightness. Uses the algorithm from the CSS3 spec.

Parameters:

  • hue (Number)

    The hue of the color. Should be between 0 and 360 degrees, inclusive

  • saturation (Number)

    The saturation of the color. Must be between 0% and 100%, inclusive

  • lightness (Number)

    The lightness of the color. Must be between 0% and 100%, inclusive

Returns:

  • (Color)

    The resulting color

Raises:

  • (ArgumentError)

    if saturation or lightness are out of bounds



187
188
189
# File 'lib/sass/script/functions.rb', line 187

def hsl(hue, saturation, lightness)
  hsla(hue, saturation, lightness, Number.new(1))
end

#hsla(hue, saturation, lightness, alpha) ⇒ Color

Creates a Color object from hue, saturation, and lightness, as well as an alpha channel indicating opacity. Uses the algorithm from the CSS3 spec.

Parameters:

  • hue (Number)

    The hue of the color. Should be between 0 and 360 degrees, inclusive

  • saturation (Number)

    The saturation of the color. Must be between 0% and 100%, inclusive

  • lightness (Number)

    The lightness of the color. Must be between 0% and 100%, inclusive

  • alpha (Number)

    The opacity of the color. Must be between 0 and 1, inclusive

Returns:

  • (Color)

    The resulting color

Raises:

  • (ArgumentError)

    if saturation, lightness, or alpha are out of bounds



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
# File 'lib/sass/script/functions.rb', line 205

def hsla(hue, saturation, lightness, alpha)
  assert_type hue, :Number
  assert_type saturation, :Number
  assert_type lightness, :Number
  assert_type alpha, :Number

  unless (0..1).include?(alpha.value)
    raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1")
  end

  original_s = saturation
  original_l = lightness
  # This algorithm is from http://www.w3.org/TR/css3-color#hsl-color
  h, s, l = [hue, saturation, lightness].map { |a| a.value }
  raise ArgumentError.new("Saturation #{s} must be between 0% and 100%") unless (0..100).include?(s)
  raise ArgumentError.new("Lightness #{l} must be between 0% and 100%") unless (0..100).include?(l)

  h = (h % 360) / 360.0
  s /= 100.0
  l /= 100.0

  m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s
  m1 = l * 2 - m2
  Color.new(
    [hue_to_rgb(m1, m2, h + 1.0/3),
      hue_to_rgb(m1, m2, h),
      hue_to_rgb(m1, m2, h - 1.0/3)].map { |c| (c * 0xff).round } +
    [alpha.value])
end

#opacify(color, amount) ⇒ Object Also known as: fade_in

Makes a color more opaque. Takes a color and an amount between 0% and 100% and returns a color that's that much closer to opaque.

For example, 50% will make the color twice as opaque:

opacify(rgba(0, 0, 0, 0.5), 50%) => rgba(0, 0, 0, 0.75)
opacify(rgba(0, 0, 0, 0.8), 50%) => rgba(0, 0, 0, 0.9)
opacify(rgba(0, 0, 0, 0.2), 50%) => rgba(0, 0, 0, 0.8)

Specifically, opacify(color, n%) will make the color n% closer to fully opaque.



289
290
291
292
293
294
295
296
297
298
299
# File 'lib/sass/script/functions.rb', line 289

def opacify(color, amount)
  assert_type color, :Color
  assert_type amount, :Number
  unless (0..100).include?(amount.value)
    raise ArgumentError.new("Amount #{amount} must be between 0% and 100%")
  end

  color = color.dup
  color.alpha += (1 - color.alpha) * (amount.value / 100.0)
  color
end

#percentage(value) ⇒ Number

Converts a decimal number to a percentage. For example:

percentage(100px / 50px) => 200%

Parameters:

  • value (Number)

    The decimal number to convert to a percentage

Returns:

Raises:

  • (ArgumentError)

    If value isn't a unitless number



335
336
337
338
339
340
# File 'lib/sass/script/functions.rb', line 335

def percentage(value)
  unless value.is_a?(Sass::Script::Number) && value.unitless?
    raise ArgumentError.new("#{value.inspect} is not a unitless number")
  end
  Sass::Script::Number.new(value.value * 100, ['%'])
end

#red(color) ⇒ Number

Returns the red component of a color.

Parameters:

Returns:

Raises:

  • (ArgumentError)

    If color isn't a color



240
241
242
243
# File 'lib/sass/script/functions.rb', line 240

def red(color)
  assert_type color, :Color
  Sass::Script::Number.new(color.red)
end

#rgb(red, green, blue) ⇒ Object

Creates a Color object from red, green, and blue values.

Parameters:

  • red

    A number between 0 and 255 inclusive, or between 0% and 100% inclusive

  • green

    A number between 0 and 255 inclusive, or between 0% and 100% inclusive

  • blue

    A number between 0 and 255 inclusive, or between 0% and 100% inclusive



137
138
139
# File 'lib/sass/script/functions.rb', line 137

def rgb(red, green, blue)
  rgba(red, green, blue, Number.new(1))
end

#rgba(red, green, blue, alpha) ⇒ Object

Creates a Color object from red, green, and blue values, as well as an alpha channel indicating opacity.

Parameters:

  • red

    A number between 0 and 255 inclusive

  • green

    A number between 0 and 255 inclusive

  • blue

    A number between 0 and 255 inclusive

  • alpha

    A number between 0 and 1



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/sass/script/functions.rb', line 152

def rgba(red, green, blue, alpha)
  assert_type red, :Number
  assert_type green, :Number
  assert_type blue, :Number
  assert_type alpha, :Number

  rgb = [red, green, blue].map do |c|
    v = c.value
    if c.numerator_units == ["%"] && c.denominator_units.empty?
      next v * 255 / 100.0 if (0..100).include?(v)
      raise ArgumentError.new("Color value #{c} must be between 0% and 100% inclusive")
    else
      next v if (0..255).include?(v)
      raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive")
    end
  end

  unless (0..1).include?(alpha.value)
    raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1 inclusive")
  end

  Color.new(rgb + [alpha.value])
end

#round(value) ⇒ Number

Rounds a number to the nearest whole number. For example:

round(10.4px) => 10px
round(10.6px) => 11px

Parameters:

  • value (Number)

    The number

Returns:

  • (Number)

    The rounded number

Raises:



351
352
353
# File 'lib/sass/script/functions.rb', line 351

def round(value)
  numeric_transformation(value) {|n| n.round}
end

#transparentize(color, amount) ⇒ Object Also known as: fade_out

Makes a color more transparent. Takes a color and an amount between 0% and 100% and returns a color that's that much closer to transparent.

For example, 50% will make the color twice as transparent:

opacify(rgba(0, 0, 0, 0.5), 50%) => rgba(0, 0, 0, 0.25)
opacify(rgba(0, 0, 0, 0.8), 50%) => rgba(0, 0, 0, 0.4)
opacify(rgba(0, 0, 0, 0.2), 50%) => rgba(0, 0, 0, 0.1)

Specifically, transparentize(color, n%) will make the color n% closer to fully transparent.



314
315
316
317
318
319
320
321
322
323
324
# File 'lib/sass/script/functions.rb', line 314

def transparentize(color, amount)
  assert_type color, :Color
  assert_type amount, :Number
  unless (0..100).include?(amount.value)
    raise ArgumentError.new("Amount #{amount} must be between 0% and 100%")
  end

  color = color.dup
  color.alpha *= 1 - (amount.value / 100.0)
  color
end