0

How can I pass the return value form a custom Sass function to a Susy function? Or is there any better approach?


This works fine:

.foo{ 
    max-width: get_breakpoint('large');
}

But that won't:

.foo{
    @include layout(get_breakpoint('large') 12);
}

Susy just falls back to the default container width instead of using the one from my get_breakpoint() function.

The built uses Compass, I have the following function in my config.rb:

module Sass::Script::Functions
    #
    # get breakpoint values from prefs file (json)
    #
    def get_breakpoint(bp)
        if PROJ_PREFS['breakpoint'].include?(bp.value)
            retVal = PROJ_PREFS['breakpoint'][bp.value][0].to_s+'px'
        else
            retVal = bp.to_s
        end
        Sass::Script::String.new(retVal)
    end
end

Software versions: sass (3.4.21), compass (1.0.3), susy (2.2.12).

Many thanks.

Maciek Rek
  • 1,525
  • 2
  • 14
  • 18
  • In fact, just realised that after posting, SUSY won't get any input from even a standard Sass function such as: `@include layout(unquote('1040px') 12);` Is it normal behaviour? – Maciek Rek Apr 27 '16 at 12:38
  • Susy does get that information — `layout()` just doesn't have any output. The `layout` mixin only changes the global `$susy` variable. The `container()` mixin is the only one that does anything with container-width information. – Miriam Suzanne Apr 27 '16 at 18:17
  • Thanks for the tip, however `@include container(unquote('1040px'));` doesn't seem to work either... strange – Maciek Rek Apr 28 '16 at 08:42
  • Just found a problem in my code – due to my little knowledge of Sass I wrongly assumed that units such as 1044px are strings while they are **numbers**. Now just need to find the way to convert them accordingly. – Maciek Rek Apr 28 '16 at 13:51

1 Answers1

1

It turns out that it shouldn't be a problem to use a custom function as a Susy mixin argument as long as it passes the right value. I was passing a string instead of Sass number.


Just in case someone stumble across similar problem, below there is an example of working solution retrieving breakpoint values from Json into Sass (Assuming you've got json gem installed).

Note that this solution isn't perfect from the performance point of view as it recreates the $BREAKPOINT map each time the _base.scss partial is imported. (It also omits my custom breakpoint mixin as not relevant here and which uses the breakpoint function as well)

My breakpoint definitions are stored as 'unitless' numbers in json

{
    "breakpoint" : {
        "mini"          : [  481    ,   "phablet portrait phone landscape"],
        "xsmall"        : [  736    ,   "phablet landscape (iPhone6plus) tablet portrait"],
...

Ruby code (in Compass config.rb)

require 'json'

file = File.read(File.dirname(__FILE__)+'/preferences.json')
PROJ_PREFS = JSON.parse(file)

module Sass::Script::Functions
  def get_breakpoints()
    retMap = Hash.new
    PROJ_PREFS['breakpoint'].each do |bp_name, bp_value|
       retMap[Sass::Script::Value::String.new(bp_name.to_s)] = Sass::Script::Value::Number.new(bp_value[0],'px')
    end
    Sass::Script::Value::Map.new(retMap)
  end
end

Sass code (e.g. _base.scss)

// create Sass map with custom function

$BREAKPOINT:get_breakpoints();


// allow Sass numbers (such as 12em, 355px) or breakpoint names (such as small, large) to be passed through
// it was just easier for me to code it in Sass (since I don't know Ruby at all) 

@function breakpoint($key) {
    @if not map-has-key($BREAKPOINT, $key) { @return $key; }
    @return map-get($BREAKPOINT, $key);
}

Usage example (involving Susy)

.foo{
    @include container(breakpoint(large));
}
Maciek Rek
  • 1,525
  • 2
  • 14
  • 18