<div class="container" id="app">
  <div class="fields">
    <label>#</label>
    <input type="text" v-model="baseColor">
    <label>#</label>
    <input type="text" v-model="targetColor">
    <button @click="generate()" :disabled="active == true ? false : true">Generate</button>
  </div>
  <div class="colors">
    <div class="color" :style="{ backgroundColor: '#' + computedBaseColor }"></div>
    <div class="color" :style="{ backgroundColor: '#' + computedTargetColor }"></div>
    <div class="color" :style="{ backgroundColor: '#' + computedBaseColor, filter: 'hue-rotate(' + hue + 'deg) saturate(' + saturation + '%) brightness(' + brightness + '%)'}"></div>
  </div>
  <div class="result" v-if="">filter: hue-rotate({{hue}}deg) saturate({{saturation}}%) brightness({{brightness}}%);</div>
</div>
html, body {
  height: 100%;
}
body {
  background: #333333;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
body * {
  font-family: 'Roboto', sans-serif;
  outline: none;
}
.box {
  width: 100px;
  height: 100px;
}
input[type="text"] {
  border-radius: 3px;
  background-color: #E5E8ED;
  border: 2px solid transparent;
  height: 39px;
  width: 200px;
  font-size: 18px;
  line-height: 24px;
  padding: 8px 12px;
  box-sizing: border-box;
  transition: border-color 0.3s ease;
}
input[type="text"]:focus {
  border-color: #44BF84;
}
label {
  font-size: 24px;
  color: #fff;
  margin-left: 12px;
  margin-right: 8px;
  line-height: 39px;
}
button {
  background-color: #44BF84;
  color: #fff;
  border-radius: 3px;
  border: none;
  height: 39px;
  line-height: 15px;
  box-sizing: border-box;
  padding: 12px 20px;
  text-transform: uppercase;
  font-weight: 700;
  margin-left: 12px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  &:hover {
    background-color: lighten(#44BF84, 10%);
  }
}
button[disabled] {
  background-color: #767676;
  color: #585858;
  cursor: not-allowed;
}
.fields {
  display: flex;
  justify-content: center;
  margin-left: -34px;
}
.colors {    
  display: flex;
  justify-content: space-between;
  width: 524px;
  margin: 54px auto;
}
.color {
  width: 120px;
  height: 120px;
  border-radius: 50%;
}
.result {
  text-align: center;
  font-size: 20px;
  line-height: 26px;
  color: #fff;
}
.container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100%;
}
View Compiled
function rgbToHsl(r, g, b){
  r /= 255, g /= 255, b /= 255;
  var max = Math.max(r, g, b), min = Math.min(r, g, b);
  var l = (max + min) / 2;
  var d = max - min;

  s = (d == 0) ? 0 : d / (1 - Math.abs(2*l-1));

  if(d == 0) { 
    h = 0;
  }
  else {
    switch(max){
      case r: h = 60 * (((g-b)/d)%6); break;
      case g: h = 60 * (((b-r)/d) + 2); break;
      case b: h = 60 * ((r-g)/d + 4); break;
    }
  }

  h = h;
  s = s * 100;
  l = l * 100;

  return [h, s, l];
}

function hexToRgb(hex) {
  hex = stripHash(hex);
  var r = parseInt(hex.substr(0, 2), 16);
  var g = parseInt(hex.substr(2, 2), 16);
  var b = parseInt(hex.substr(4, 2), 16);
  return [r, g, b];
}

function hexToHSL(hex) {
  var rgb = hexToRgb(hex); 
  return rgbToHsl(rgb[0], rgb[1], rgb[2]);
}

function stripHash(code) {
  return code.charAt(0)=='#' ? code.substring(1) : code;
}

var vue = new Vue({
  el: '#app',
  data: {
    baseColor: '87C540',
    targetColor: 'FFC248',
    hue: '',
    saturation: '',
    brightness: ''
  },
  computed: {
    active: function() {
      if(this.baseColor.match(/^\#?([0-9a-fA-F]{6})$/g) && this.targetColor.match(/^\#?([0-9a-fA-F]{6})$/g)) {
        return true;
      } 
      return false;
    },
    computedBaseColor: function() {
      return stripHash(this.baseColor);
    },
    computedTargetColor: function() {
      return stripHash(this.targetColor);
    }
  },
  methods: {
    generate: function() {
      var baseHSL   = hexToHSL(this.baseColor);
      var targetHSL = hexToHSL(this.targetColor);
      this.hue = Math.round((targetHSL[0] - baseHSL[0]) * 100) / 100;
      this.saturation = 100 + Math.round((targetHSL[1] - baseHSL[1]) * 100) / 100;
      this.brightness = 100 + Math.round((targetHSL[2] - baseHSL[2]) * 100) / 100;
    }
  }
});
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js