{"id":3192,"date":"2014-10-07T00:03:24","date_gmt":"2014-10-07T06:03:24","guid":{"rendered":"http:\/\/iohelix.net\/blog\/?p=3192"},"modified":"2020-01-22T07:45:30","modified_gmt":"2020-01-22T14:45:30","slug":"sass-color-function-comparison","status":"publish","type":"post","link":"http:\/\/iohelix.net\/blog\/2014\/10\/sass-color-function-comparison\/","title":{"rendered":"SASS Color function comparison"},"content":{"rendered":"<p>So I&#8217;ve been working with <acronym title=\"Syntactically Awesome Style Sheets\">SASS<\/acronym> a lot lately, and was looking into replacing all the instances of <span class=\"lang:sass decode:true crayon-inline\">scale-color($color, $lightness: 20%)<\/span> with <span class=\"lang:sass decode:true &nbsp;crayon-inline \">lighten($color, 20%)<\/span>, as it&#8217;s a more compact syntax and seems like it should do the same thing. But as I was doing that, I noticed that the colors that were being generated were not quite the same, and in some cases, wildly different. So I&#8217;m going to explain the differences between <span class=\"lang:sass decode:true &nbsp;crayon-inline \">lighten<\/span>&nbsp;and <span class=\"lang:sass decode:true &nbsp;crayon-inline \">darken<\/span>&nbsp;vs <span class=\"lang:sass decode:true &nbsp;crayon-inline \">scale-color<\/span>&nbsp;.<\/p>\n\n\n\n<p>To start off, every color has a lightness value, which is the L part of the HSL values for a color. With the lightness value for white being 100%, and black being 0%. For a middle gray <span style=\"background: gray; color: white;\">(#808080)<\/span>, that value is very nearly 50% (50.19608% to be precise). And for a darker color, like rebeccapurple <span style=\"background: #663399; color: white;\">(#663399)<\/span>, that value is 40%.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>When testing these functions to figure out why their outputs were different, I used them to generate&nbsp;new colors using the same settings, and then grabbed the lightness value of those new colors. So for white, I did the following:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">.white {\n &nbsp; &nbsp; &nbsp; &nbsp;base: white;\n &nbsp; &nbsp; &nbsp; &nbsp;-lb: lightness(white);\n &nbsp; &nbsp; &nbsp; &nbsp;darken20: darken(white, 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ld20: lightness(darken(white, 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;\/* -20% to replicate darkening *\/\n &nbsp; &nbsp; &nbsp; &nbsp;scale20: scale-color(white, $lightness: -20%); \n &nbsp; &nbsp; &nbsp; &nbsp;-ls20: lightness(scale-color(white, $lightness: -20%)); \n}<\/pre>\n\n\n\n<p>and for black:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">.black {\n &nbsp; &nbsp; &nbsp; &nbsp;base: black;\n &nbsp; &nbsp; &nbsp; &nbsp;-lb: lightness(black);\n &nbsp; &nbsp; &nbsp; &nbsp;lighten20: lighten(black, 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ll20: lightness(lighten(black, 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale20: scale-color(black, $lightness: 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls20: lightness(scale-color(black, $lightness: 20%));\n}<\/pre>\n\n\n\n<p>The output for those:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* line 2, ..\/scss\/test.scss *\/\n.white {\n &nbsp;base: white;\n &nbsp;-lb: 100%;\n &nbsp;darken20: #cccccc;\n &nbsp;-ld20: 80%;\n &nbsp;scale20: #cccccc;\n &nbsp;-ls20: 80%;\n}\n\n\/* line 11, ..\/scss\/test.scss *\/\n.black {\n &nbsp;base: black;\n &nbsp;-lb: 0%;\n &nbsp;lighten20: #333333;\n &nbsp;-ll20: 20%;\n &nbsp;scale20: #333333;\n &nbsp;-ls20: 20%;\n}<\/pre>\n\n\n\n<p>As you can see, when we darken white by 20%, we end up with a light gray that has a lightness value of 80%. This is as expected. The same goes for black. When we lighten it by 20%, we end up with a dark gray that has a lightness value of 20%. This outcome did nothing to explain why the outputs of those functions were different, because they weren&#8217;t. But I didn&#8217;t expect them to be. I figured that using white and black would not show any differences. I was simply using those colors to mark a baseline for further experiments.<\/p>\n\n\n\n<p>The colors that do show the differences are the gray and the rebeccapurple. For those, I created the following code:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">.gray {\n &nbsp; &nbsp; &nbsp; &nbsp;base: gray;\n &nbsp; &nbsp; &nbsp; &nbsp;-lb: lightness(gray);\n &nbsp; &nbsp; &nbsp; &nbsp;lighten20: lighten(gray, 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ll20: lightness(lighten(gray, 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale20: scale-color(gray, $lightness: 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls20: lightness(scale-color(gray, $lightness: 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;darken20: darken(gray, 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ld20: lightness(darken(gray, 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale20: scale-color(gray, $lightness: -20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls20: lightness(scale-color(gray, $lightness: -20%));\n &nbsp; &nbsp; &nbsp; &nbsp;lighten50: lighten(gray, 50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ll50: lightness(lighten(gray, 50%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale50: scale-color(gray, $lightness: 50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls50: lightness(scale-color(gray, $lightness: 50%));\n &nbsp; &nbsp; &nbsp; &nbsp;darken50: darken(gray, 50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ld50: lightness(darken(gray, 50%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale50: scale-color(gray, $lightness: -50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls50: lightness(scale-color(gray, $lightness: -50%));\n &nbsp; &nbsp; &nbsp; &nbsp;lighten80: lighten(gray, 80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ll80: lightness(lighten(gray, 80%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale80: scale-color(gray, $lightness: 80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls80: lightness(scale-color(gray, $lightness: 80%));\n &nbsp; &nbsp; &nbsp; &nbsp;darken80: darken(gray, 80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ld80: lightness(darken(gray, 80%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale80: scale-color(gray, $lightness: -80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls80: lightness(scale-color(gray, $lightness: -80%));\n}\n\n.rebeccapurple {\n &nbsp; &nbsp; &nbsp; &nbsp;base: rebeccapurple;\n &nbsp; &nbsp; &nbsp; &nbsp;-lb: lightness(rebeccapurple);\n &nbsp; &nbsp; &nbsp; &nbsp;lighten20: lighten(rebeccapurple, 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ll20: lightness(lighten(rebeccapurple, 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale20: scale-color(rebeccapurple, $lightness: 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls20: lightness(scale-color(rebeccapurple, $lightness: 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;darken20: darken(rebeccapurple, 20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ld20: lightness(darken(rebeccapurple, 20%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale20: scale-color(rebeccapurple, $lightness: -20%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls20: lightness(scale-color(rebeccapurple, $lightness: -20%));\n &nbsp; &nbsp; &nbsp; &nbsp;lighten50: lighten(rebeccapurple, 50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ll50: lightness(lighten(rebeccapurple, 50%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale50: scale-color(rebeccapurple, $lightness: 50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls50: lightness(scale-color(rebeccapurple, $lightness: 50%));\n &nbsp; &nbsp; &nbsp; &nbsp;darken50: darken(rebeccapurple, 50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ld50: lightness(darken(rebeccapurple, 50%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale50: scale-color(rebeccapurple, $lightness: -50%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls50: lightness(scale-color(rebeccapurple, $lightness: -50%));\n &nbsp; &nbsp; &nbsp; &nbsp;lighten80: lighten(rebeccapurple, 80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ll80: lightness(lighten(rebeccapurple, 80%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale80: scale-color(rebeccapurple, $lightness: 80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls80: lightness(scale-color(rebeccapurple, $lightness: 80%));\n &nbsp; &nbsp; &nbsp; &nbsp;darken80: darken(rebeccapurple, 80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ld80: lightness(darken(rebeccapurple, 80%));\n &nbsp; &nbsp; &nbsp; &nbsp;scale80: scale-color(rebeccapurple, $lightness: -80%);\n &nbsp; &nbsp; &nbsp; &nbsp;-ls80: lightness(scale-color(rebeccapurple, $lightness: -80%));\n}<\/pre>\n\n\n\n<p>With that output being:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* line 20, ..\/scss\/test.scss *\/\n.gray {\n &nbsp;base: gray;\n &nbsp;-lb: 50.19608%;\n &nbsp;lighten20: #b3b3b3;\n &nbsp;-ll20: 70.19608%;\n &nbsp;scale20: #999999;\n &nbsp;-ls20: 60.15686%;\n &nbsp;darken20: #4d4d4d;\n &nbsp;-ld20: 30.19608%;\n &nbsp;scale20: #666666;\n &nbsp;-ls20: 40.15686%;\n &nbsp;lighten50: white;\n &nbsp;-ll50: 100%;\n &nbsp;scale50: silver;\n &nbsp;-ls50: 75.09804%;\n &nbsp;darken50: black;\n &nbsp;-ld50: 0.19608%;\n &nbsp;scale50: #404040;\n &nbsp;-ls50: 25.09804%;\n &nbsp;lighten80: white;\n &nbsp;-ll80: 100%;\n &nbsp;scale80: #e6e6e6;\n &nbsp;-ls80: 90.03922%;\n &nbsp;darken80: black;\n &nbsp;-ld80: 0%;\n &nbsp;scale80: #1a1a1a;\n &nbsp;-ls80: 10.03922%;\n}\n\n\/* line 49, ..\/scss\/test.scss *\/\n.rebeccapurple {\n &nbsp;base: rebeccapurple;\n &nbsp;-lb: 40%;\n &nbsp;lighten20: #9966cc;\n &nbsp;-ll20: 60%;\n &nbsp;scale20: #8547c2;\n &nbsp;-ls20: 52%;\n &nbsp;darken20: #33194d;\n &nbsp;-ld20: 20%;\n &nbsp;scale20: #52297a;\n &nbsp;-ls20: 32%;\n &nbsp;lighten50: #e6d9f2;\n &nbsp;-ll50: 90%;\n &nbsp;scale50: #b28cd9;\n &nbsp;-ls50: 70%;\n &nbsp;darken50: black;\n &nbsp;-ld50: 0%;\n &nbsp;scale50: #33194d;\n &nbsp;-ls50: 20%;\n &nbsp;lighten80: white;\n &nbsp;-ll80: 100%;\n &nbsp;scale80: #e0d1f0;\n &nbsp;-ls80: 88%;\n &nbsp;darken80: black;\n &nbsp;-ld80: 0%;\n &nbsp;scale80: #140a1f;\n &nbsp;-ls80: 8%;\n}<\/pre>\n\n\n\n<p>This is where we start to see differences. If you&#8217;ll notice, the lightness percentage for gray was ~50%, and the output of <span class=\"lang:sass decode:true &nbsp;crayon-inline \">lighten<\/span> gave a color with a lightness value of ~70% (20% more). The output of <span class=\"lang:sass decode:true &nbsp;crayon-inline \">scale-color<\/span> gave a color with a lightness value of ~60% (only 10% more). The same can be said for <span class=\"lang:sass decode:true &nbsp;crayon-inline \">darken<\/span> as well as the other instances that use higher percentages.<\/p>\n\n\n\n<p>The difference between the functions comes down to how those percentages are applied. In the <span class=\"lang:sass decode:true &nbsp;crayon-inline \">lighten<\/span>&nbsp;and <span class=\"lang:sass decode:true &nbsp;crayon-inline \">darken<\/span> functions, the percentages are added\/subtracted directly to the current value. So when we have a color with a lightness value of 40% and we add 20%, we end up with 60%. In contrast, <span class=\"lang:sass decode:true &nbsp;crayon-inline \">scale-color<\/span> adds or subtracts the percentage of the difference of the lightness to the color, so when we start with the same 40% lightness value, and scale-color by 20%, it ends up at 52% (12% more), because 20% of the remainder (60%) is 12%.<\/p>\n\n\n\n<p>You&#8217;ll also notice that when we <span class=\"lang:sass decode:true &nbsp;crayon-inline \">darken<\/span>&nbsp;&nbsp;rebeccapurple by 50%, it goes to black. This is because it&#8217;s lightness is originally only 40%, and when we subtract 50% from it, we get -10%, which <acronym title=\"Syntactically Awesome Style Sheets\">SASS<\/acronym> clamps to 0% (black). But when we&nbsp;<span class=\"lang:sass decode:true &nbsp;crayon-inline \">scale-color<\/span>&nbsp;by -50%, we end up at a color with a lightness of 20% (50% of 40%).<\/p>\n\n\n\n<p>So that&#8217;s why the output of <span class=\"lang:sass decode:true &nbsp;crayon-inline \">lighten<\/span>, <span class=\"lang:sass decode:true &nbsp;crayon-inline \">darken<\/span>, and <span class=\"lang:sass decode:true &nbsp;crayon-inline \">scale-color<\/span> are different. And in my opinion, <span class=\"lang:sass decode:true &nbsp;crayon-inline \">scale-color<\/span> is the more useful of the three, as it behaves a little more intuitively, scaling the color instead of just raw addition or subtraction.<\/p>","protected":false},"excerpt":{"rendered":"<p>So I&#8217;ve been working with SASS a lot lately, and was looking into replacing all the instances of scale-color($color, $lightness: 20%) with lighten($color, 20%), as it&#8217;s a more compact syntax and seems like it should do the same thing. But as I was doing that, I noticed that the colors that were being generated were &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/iohelix.net\/blog\/2014\/10\/sass-color-function-comparison\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;SASS Color function comparison&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,12,19],"tags":[],"class_list":["post-3192","post","type-post","status-publish","format-standard","hentry","category-geek","category-programming","category-web-development"],"_links":{"self":[{"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/posts\/3192"}],"collection":[{"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/comments?post=3192"}],"version-history":[{"count":10,"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/posts\/3192\/revisions"}],"predecessor-version":[{"id":3235,"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/posts\/3192\/revisions\/3235"}],"wp:attachment":[{"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/media?parent=3192"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/categories?post=3192"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/iohelix.net\/blog\/wp-json\/wp\/v2\/tags?post=3192"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}