css Audio - Active file-generic CSS - Active Generic - Active HTML - Active JS - Active SVG - Active Text - Active file-generic Video - Active header Love html icon-new-collection icon-person icon-team numbered-list123 pop-out spinner split-screen star tv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              input type="range" name="slider" min="-50" max="50" id="slider"
            
          
!
            
              @import compass

html, body, input
  height: 100%
  width: 100%
  
body
  background: #000
            
          
!
            
              // Intended behavior (outlined by a friend): 
// Slider that lets us go from pink (left) to green (right) through black (middle). We decided on rgb(200,0,100) for the left, moving towards rgb(90,0,45) at the center... but at the center he needed it to *actually* display black. Similarily, he needed the right side to act like it started at rgb(0, 90, 45) at the center and move to rgb(0, 200, 100) on the far right.

// ...still with me? If that description lost you, just play around with the demo before moving on and you'll get it.

// This came up at a weekly hack night, so I decided to make it hacky. Here's the breakdown.
// Build time:
//   15m: mathy things, double-checking returns from && and ||
//   10m: cancel operations and calculations to make it slim, general tidying, type it out
//   1h: explain to my friend (new to js) what the hell is going on here...
//   40m: comment the code like crazy

///////////////////// CODE /////////////////////
// Block comment at bottom contains bare code //
////////////////////////////////////////////////

// Caching this so that we don't have to get it every time the slider changes
//var bs = document.body.style;

// Whenever the slider is changed, run an anonymous function to update the body's bg color 
//document.getElementById('slider').addEventListener('change', function () {
  
  // Why is the slider value (see HTML) bounded between -50 and 50? Well, remember that we wanted our "MAX" red and green color values to be 200, and the "MIN"s to be 100.  That means that for each, the range is 200 - 100 = 100. We bounded the slider to 50 because it is half of the range (100)... we'll get in to why we halved it soon. 
  
  // Grab the slider's value
//  val = parseInt(this.value);
  
  // Store the absolute value so that we only need to calculate it once
//  aval = Math.abs(val);
  
  // Now for some math trickery. Imagine a value 'x'. If 'x' is positive, the absolute value of x, minus x, will equal 0. That is to say, |x| - x = 0 when x is +ve. Similarly, |x| - x = 2x when x is -ve.
  // This allows us to store the distance from the center into r IF the slider's value is left of the center mark. Otherwise, a 0 is stored into r.
//  r = aval - val;
  
  // Exact same principle for green, just flipped so that a positive value leads to 2x. You can figure this one out :)
//  g = aval + val;
  // Notice that above, we store either 0 or 2x. 2x represents *twice* the value selected on the slider. Re-read line 23. We halved the range of 100 to 50 because we knew that this value would end up being doubled in a few steps, resulting in the correct amount!
  
  // This next line is where the magic truly happens. Right now we have an r value which is the slider value if we're on the red half, or 0 if we're on the green half. We have a similar g value. We're going to start by taking a look at the function, and then work our way from the inside out.
//  (r += r && 100) || (g += g && 100);
  
  // Starting with 'r && 100':
  // 0 evaluates to false in Javascript, and an && requires both the left- and right-hand sides to be true. Logical expressions are evaluated from left to right, so if r == 0, Javascript already knows that, regardless of the right side, the expression will evaluate to false. Because of this, it skips the right side and returns the left side (0).
  // On the other hand, if r !== 0, it evaluates to true. Javascript must then check the right side of the expression, since it affects the statement's truthiness. Since the right side is evaluated, its value (100) will be returned.
  
  // Let's zoom out to r += r && 100:
  // We know that r && 90 returns 0 if r == 0 and 100 otherwise. Essentially, we're saying:
  // if(r !== 0) 
  //   r += 100
  // This means that if it's 0, it will stay 0. BUT, if it has a value, the +100 will increase the (undesired) 0 to 100 range to the (desired) 100 to 200 range discussed.
  
  // Let's look at our magic line again:
  // (r += r && 100) || (g += g && 100);
  
  // We know what the left side of the || does; the right side does the same thing.
  // The || has an opposite effect to the &&. || needs only one side to be true to return true; since we evaluate from left to right, if the left side returns anything other than 0 (in other words, if r has a value), we skip over the right side. We can do this because we already know that if red has a value, green must be 0. The || is included so that we avoid the unnecessary calculation of g = 0 + 0 when red has a value. 
  
  // Finally, we set the body's background-color to use r and g
//  bs.backgroundColor = 'rgb(' + r + ',' + g + ',' + (r+g)/2 + ')';  
//}, false);

// And we made it!!! Please comment if anything requires clarification, if you have suggestions on how my code can be improved (or made even grosser), or if you just want to chat. 

// Until next time,
// rileyjshaw.com



/* Bare code: */ //////////////////////////////////

var bs = document.body.style;
document.getElementById('slider').addEventListener('change', function () {
  val = parseInt(this.value);
  aval = Math.abs(val);
  (r = aval - val) ? r += 90 : 0;
  (g = aval + val) ? g += 90 : 0;
  bs.backgroundColor = 'rgb(' + r + ',' + g + ',' + (r+g)/2 + ')';
}, false);

///////////////////////////////////////////////
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console