Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Add decimal support to Modular Scale #717

Closed
drtimofey opened this issue Apr 15, 2015 · 6 comments
Closed

Add decimal support to Modular Scale #717

drtimofey opened this issue Apr 15, 2015 · 6 comments

Comments

@drtimofey
Copy link

Here's a messy demonstration showing one example how it can be done. Replace the existing modular_scale() function with:

@function modular-scale($increment, $value: $modular-scale-base, $ratio: $modular-scale-ratio) {
  @return $value * (math-pow($ratio, $increment));
}

@function math-pow($number, $exp) {
  @if (round($exp) != $exp) {
    @return math-exp($exp * math-ln($number));
  }

  // Traditional method for integers
  $value: 1;

  @if $exp > 0 {
    @for $i from 1 through $exp {
      $value: $value * $number;
    }
  }
  @else if $exp < 0 {
    @for $i from 1 through -$exp {
      $value: $value / $number;
    }
  }

  @return $value;
}

@function math-factorial($value) {
  @if $value == 0 {
    @return 1;
  }

  $result: 1;

  @for $index from 1 through $value {
    $result: $result * $index;
  }

  @return $result;
}

@function math-summation($iteratee, $input, $initial: 0, $limit: 100) {
  $sum: 0;

  @for $index from $initial to $limit {
    $sum: $sum + call($iteratee, $input, $index);
  }

  @return $sum;
}

@function math-exp-maclaurin($x, $n) {
  $result: math-pow($x, $n) / math-factorial($n);
  @return $result;
}
@function math-exp($value) {
  $result: math-summation(math-exp-maclaurin, $value, 0, 100);
  @return $result;
}

@function math-ln-maclaurin($x, $n) {
  $result: (math-pow(-1, $n + 1) / $n) * (math-pow($x - 1, $n));
  @return $result;
}
@function math-ln($value) {
  $ten-exp: 1;
  $ln-ten: 2.30258509;

  @while ($value > math-pow(10, $ten-exp)) {
    $ten-exp: $ten-exp + 1;
  }

  $value: $value / math-pow(10, $ten-exp);

  $result: math-summation(math-ln-maclaurin, $value, 1, 100);

  @return $result + $ten-exp * $ln-ten;
}

This will allow you to scale by decimal values, such as modular_scale(1.2).

This script is based on https://gist.github.com/davidkpiano/ad6e6771df050ff3727f
To see SASS progress on exponents: sass/sass#684

@tysongach
Copy link
Contributor

So this would make it possible to do things like: modular-scale(1.6). Currently, you can only

But doesn’t this defeat the purpose of the modular-scale? I think its biggest feature is that the possible values returned are limited and relate to one another.

If you increment up or down the scale in non-whole steps, the values returned can no longer be traced to a specific point in the scale and the relationship between values is lost.

@drtimofey
Copy link
Author

This discussion goes in depth on sass/sass#684

I think the whole concept of the responsive design is that it's scalable to any degree and not limited to specific break points.

There are cases when people will choose to keep it simple, they can still use whole numbers. In my case, the design team wanted developers to scale paragraph text from 16px to 14px. Since modular_scale(-1) scaled it to 11px, I had to use modular_scale(-.5). This feature does come handy with certain advanced senarios.

Not sure if I understood you correctly on the last part. I believe the values should still be traceable. If you set the child to modular-scale(-1.5), you can recover to the previous scale with modular-scale(1.5).

@tysongach
Copy link
Contributor

The issue you link to above is a discussion around adding math functions to Sass, not using decimals in a modular-scale function. I consider those two very different things. Having those math functions in Sass would indeed be very useful to construct the modular-scale function itself, but it wouldn’t deem a change in how it works now (i.e. passing whole numbers in and getting an altered value in return).

As for your example use case above: I don’t think this is proper use of the modular-scale. If you need an exact value (i.e. 14px), you should just define 14px or 0.875em (if 1em == 16px). When using the modular-scale, it’s less about what the returned value is and more about how the returned value relates via a scale to other values defined by the modular-scale. It’s all about proportions and seeking a harmonious relationship between components/sizes of your design.

It’s worth noting that you can change the base value and the ratio/scale that the modular-scale uses; both on a global and a per-use basis. More info on this can be found in our docs: http://bourbon.io/docs/#modular-scale

@drtimofey
Copy link
Author

Apologies, I didn't explain my example right :)

If I understand correctly, the purpose of modular-scale is to scale content between screen sizes and scale regions in relationship to the website (i.e. <footer> smaller than main content , etc...).

Say the default settings are:
h3 = 25px (modular-scale(2, 1em, $major_third))
p = 16px (modular-scale(0, 1em, $major_third))

The design team wants <aside> slightly smaller than the rest of main text... where $em-base is about 14px and everything else scales accordingly:
aside = modular-scale(-.5)
h3 = 22px (inherited from aside)
p = 14px (inherited from aside)

In this case, scaling a whole number will make text too small, and setting p to an exact value, won't scale the rest of the content.

@tysongach
Copy link
Contributor

The modular-scale can be used to scale regions or components of your design, but it can be in lots of other ways, too. There’s no one right way of using it, but rather, it’s used to produce values that are related to one another (they are picked from a defined scale). A very common use is to scale type sizes.

One major thing to note is that the modular-scale has no knowledge of screen sizes, nor is it a function that directly deals with producing values at specific screen sizes (yet). I think this might be where the mis-understanding is. While it can be used within a responsive design, it’s not a responsive design tool.

If I’m correctly understanding your example above, I don’t see why a decimal value would be necessary. Can it not be something like this:

.aside-content {
  font-size: modular-scale(-1);
}

.main-content {
  font-size: modular-scale(0);
}

Is the issue with the above simply that stepping down -1 on the scale is too large of a difference in size? If so, then I would suggest changing your ratio to something smaller, maybe $major-second instead of $major-third? You can change the ratio globally, or inline each time you call the function.

You can also use a double stranded scale, which would provide you with more values by jumping between two ratios, rather than one. All of this is in the docs.

The whole purpose of the modular-scale is to provide specific values that relate to each other via a defined ratio, e.g. the golden ratio: 1:1.618. It uses that ratio to build a series/scale of number values that you can pick from. If you introduce decimal values, say to step up the scale 0.5 times, you no longer are picking from a relational value, but rather creating a new value between two proper values.

@drtimofey
Copy link
Author

I'm unable to change the ratio globally, since it will impact larger texts, i.e. h1, h2, etc.. I will look into double stranded scale, maybe that's what I'm missing. Thank you for your detailed tips & reasoning, hopefully others can find this discussion just as helpful!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants