We help IT Professionals succeed at work.

Sass Modular Scale Mixin / Function

asp_net2
asp_net2 asked
on
Hello Experts,

Can anyone help me with a SASS mixin and or a SASS function that takes the value from a modular scale such as (major-third, perfect-fourth, golden-section) values against my base-font-size of 16px and provide me the "em" value from that for all of my heading styles of h1,h2,h3,h4,h5,h6?

Everytime I change the modular scale value to see what I like better I have to compute them all into "ems" and then add them to my css file for all of my h1,h2,h3,h4,h5,h6 font-size values. I'm looking for a way to just plug in the modular scales value that I plan on using and use some type of equation with my base font size to have it compute all my individual h1,h2,h3,h4,h5,h6 headings for me.
Comment
Watch Question

Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:

Author

Commented:
Hi Kyle,

Yes, I have seen both of those already. I would like to be able to create my own rather than using someone else's so that I can learn from it rather than rely on something that i didn't create. I don't need what I'm trying to create to be very detailed. Basically something that I plug the ration, base-size and how many values I would want. That's it.
Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
Ratio, Base size, and:
how many values I would want

not sure what you mean by how many values.

here is one simple suggestion. Since the default browser font size is actually 16px, you can specify the base size as 1em.

If your intention is to learn, build on this, or read through the source of modular-scale. remember that ems are relative to the overall font size - that's what the body class is for. So if you specified your body font size to 50%, 1 em would be 8px

body{
	font-size: 100%; // 16 px = 1em
}
// stolen from modular-scale:
$phi              : 1.618034          ;
$golden           : $phi              ;
$double-octave    : 4                 ;
$major-twelfth    : 3                 ;
$major-eleventh   : 2.666666667       ;
$major-tenth      : 2.5               ;
$octave           : 2                 ;
$major-seventh    : 1.875             ;
$minor-seventh    : 1.777777778       ;
$major-sixth      : 1.666666667       ;
$minor-sixth      : 1.6               ;
$fifth            : 1.5               ;
$augmented-fourth : 1.41421           ;
$fourth           : 1.333333333       ;
$major-third      : 1.25              ;
$minor-third      : 1.2               ;
$major-second     : 1.125             ;
$minor-second     : 1.066666667       ;

$font-size-base   : 1em;  // ex: 14px = 14/16 em

@mixin scalar($scalar, $multiplier){
	font-size: $font-size-base * $scalar * $multiplier;
}

h1{
	@include scalar($golden, 2)
}

Open in new window

Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
oh, and I found this converter. very convenient seeing quick results.

http://sasstocss.appspot.com/

Author

Commented:
Kyle,

First of all thank you for helping me with this post!!!

>> not sure what you mean by how many values.
I'm sorry, what I meant was I would like a mixin/function that would output the h1-h6 headings for me after proving my font-size-base and ratio that I would like to use. I tried the mixin that you supplied above on http://sassmeister.com and it seems that the output values are off compared to what they are on http://www.modularscale.com

Mixin that you supplied Kyle with me adding the h2-h6 headings. Nothing else what modified.
body{
	font-size: 100%; // 16 px = 1em
}
// stolen from modular-scale:
$phi              : 1.618             ;
$golden           : $phi              ;
$double-octave    : 4                 ;
$major-twelfth    : 3                 ;
$major-eleventh   : 2.666666667       ;
$major-tenth      : 2.5               ;
$octave           : 2                 ;
$major-seventh    : 1.875             ;
$minor-seventh    : 1.777777778       ;
$major-sixth      : 1.666666667       ;
$minor-sixth      : 1.6               ;
$fifth            : 1.5               ;
$augmented-fourth : 1.41421           ;
$fourth           : 1.333333333       ;
$major-third      : 1.25              ;
$minor-third      : 1.2               ;
$major-second     : 1.125             ;
$minor-second     : 1.066666667       ;

$font-size-base   : 1rem;  // ex: 14px = 14/16 em

@mixin scalar($scalar, $multiplier){
	font-size: $font-size-base * $scalar * $multiplier;
}

h1{
	@include scalar($golden, 6)
}
h2{
	@include scalar($golden, 5)
}
h3{
	@include scalar($golden, 4)
}
h4{
	@include scalar($golden, 3)
}
h5{
	@include scalar($golden, 2)
}
h6{
	@include scalar($golden, 1)
}

Open in new window


Results:
body {
  font-size: 100%;
}

h1 {
  font-size: 9.708rem;
}

h2 {
  font-size: 8.09rem;
}

h3 {
  font-size: 6.472rem;
}

h4 {
  font-size: 4.854rem;
}

h5 {
  font-size: 3.236rem;
}

h6 {
  font-size: 1.618rem;
}

Open in new window


Now if you look at the h2-h6 values they are larger than what is on the http://www.modularscale.com website. Why is that?
Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
cause I'm an idiot :)

it's not correct to just multiply by the "multiplier". You need to multiply by the scalar "multiplier" number of times.

so in pseudo code, you would do:

font-size: $font-size-base * ( $scalar  to the power of $multiplier);

have a look at :
https://github.com/modularscale/modularscale-sass/blob/2.x/stylesheets/modular-scale/_pow.scss
Data Scientist
Most Valuable Expert 2014
Commented:
putting it all together :

body{
	font-size: 100%; // 16 px = 1em
}
// stolen from modular-scale:
$phi              : 1.618             ;
$golden           : $phi              ;
$double-octave    : 4                 ;
$major-twelfth    : 3                 ;
$major-eleventh   : 2.666666667       ;
$major-tenth      : 2.5               ;
$octave           : 2                 ;
$major-seventh    : 1.875             ;
$minor-seventh    : 1.777777778       ;
$major-sixth      : 1.666666667       ;
$minor-sixth      : 1.6               ;
$fifth            : 1.5               ;
$augmented-fourth : 1.41421           ;
$fourth           : 1.333333333       ;
$major-third      : 1.25              ;
$minor-third      : 1.2               ;
$major-second     : 1.125             ;
$minor-second     : 1.066666667       ;

$font-size-base   : 1rem;  // ex: 14px = 14/16 em
// If a native exponent function doesnt exist
// this one is needed.
@function pow($Base, $Exponent) {

  // Find and remove unit.
  // Avoids messyness with unit calculations
  $Unit: $Base * 0 + 1;
  $Base: $Base/$Unit;

  // This function doesnt support non-interger exponents.
  // Warn the user about why this is breaking.
	@if round($Exponent) != $Exponent {
		@warn "Unfortunately, you need Compass to use non-integer exponents";
	}

  // Set up the loop, priming the return with the base.
	$Return: $Base;

  // If the number is positive, multiply it.
  @if $Exponent > 0 {
    // Basic feedback loop as exponents
    // are recursivley multiplied numbers.
    @for $i from 1 to $Exponent {
      $Return: $Return * $Base;
    }
  }

  // If the number is 0 or negitive
  // divide instead of multiply.
  @else {
    // Libsass doesnt allow negitive values in loops
    @for $i from (-1 + 1) to (abs($Exponent) + 1) {
      $Return: $Return / $Base;
    }
  }

  // Return is now compounded redy to be returned.
  // Add the unit back onto the number.
	@return $Return * $Unit;
}
@mixin scalar($scalar, $multiplier){
	font-size: $font-size-base * pow($scalar, $multiplier);
}

h1{
	@include scalar($golden, 6)
}
h2{
	@include scalar($golden, 5)
}
h3{
	@include scalar($golden, 4)
}
h4{
	@include scalar($golden, 3)
}
h5{
	@include scalar($golden, 2)
}
h6{
	@include scalar($golden, 1)
}

Open in new window

Author

Commented:
Your not an idiot :) I feel like the idiot asking :) I actually got the same results as you did yesterday in my own mixin hence the reason I'm asking for help now ;)

Ok, so how would I implement that into what you supplied me in the original mixin that you did?
Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
I stole the power function from modular scale. see above post ID: 40638782. It appears to be working correctly now.

in real life you would move your function to a separate file to get rid of clutter, and to be able to import it where ever else you need

if you are using compass, there is a pow function built in.

Author

Commented:
Hi Kyle,

Yes, that seems a lot better :) Is there a way on top of what you did to round those values up to whole numbers or to round them up to the values that modular scale outputs to, rather than having the long decimal values?

Also, is there a way to just implement what you did in your mixin in pseudo code rather than use the "pow" function?

Thank you very much Kyle for your input, patience and hard work on trying to help me with this issue!!!!
Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
no prob

to round, you can do:

round up:
font-size: ceil($font-size-base * pow($scalar, $multiplier));

Open in new window


round down:
font-size: floor($font-size-base * pow($scalar, $multiplier));

Open in new window


round
font-size: round($font-size-base * pow($scalar, $multiplier));

Open in new window


the pseudo code just says "use a power function here". So the answer is no, not really. Unless you are using compass, there is no power function out of the box, so you have to write one. but like I said, you should move it out to a separate file so it's not "in the way" so to speak.

Also, have a look here for a SCSS implementation of toFixed() - this will give you a number with the specified number of decimal places - as well as an alternative pow function.

https://css-tricks.com/snippets/sass/fix-number-n-digits/

Author

Commented:
Kyle,

You are a God send!! Thank you very much!!! :)

I took your advice and looked at CSS-Tricks and I think I may use that one instead.

Only, one more question, I PROMISE :)

So, the next question is how do I get the values below 1em using the mixin that you provided with the ratio? Just like in Modularscale how they have values starting at 0.0xxxx?
Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
you mean to set the font size below 1em?

you would provide a negative exponent:

@include scalar($golden, -2)
Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
just fyi.. the only difference between the two pow functions is that the modscale one gives you a warning if you provide a non-integer exponent - but neither function actually allows for non-integer exponents. And it has lots of comments. but the rest is the same. (oh, it's got that weird $Unit thing that doesn't appear to actually do anything. wt..?)

cheers.

Author

Commented:
Ok, thank you for letting me know that. Thank you again so much Kyle for helping me out with this. You have been able to answer all the questions I have, thank you so much! for everything. I'm sure you will see me around here again for me questions in regards to CSS,HTML and SASS ;) Take care Kyle...
Kyle HamiltonData Scientist
Most Valuable Expert 2014

Commented:
:)
 c u next time

Author

Commented:
Thank you again very much Kyle!!!