<div class='outer-wrap round'>
  <ul class='quadrants fill'>
    <li class='q'>Q I</li>
    <li class='q'>Q II</li>
    <li class='q'>Q III</li>
    <li class='q'>Q IV</li>
  </ul>
  <div class='box centre-me'></div>
  <div class='axis angle-start-axis centre-me'></div>
  <div class='axis h-axis centre-me'></div>
  <div class='moving-line grad-line centre-me'></div>
  <div class='moving-line grad-start centre-me'></div>
  <div class='moving-line grad-end centre-me'></div>
  <ul class='angles fill round'></ul>
</div>
<code class='grad-code'></code>
<p>
  Demo by <a href="http://codepen.io/thebabydino">Ana Tudor</a>. Licensed under MIT.
</p>
html,
body {
  min-width: 240px;
  min-height: 240px;
  height: 100%;
  margin: 0;
}

html {
  font: .8em Verdana, sans-serif;
  text-align: center;
}

body {
  padding: 20px;
}

.centre-me {
  position: absolute;
  top: 50%;
  left: 50%;
}

.fill {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: 0;
}

.round {
  border-radius: 50%;
}

.outer-wrap {
  position: relative;
  margin: 4em auto 0;
}

.outer-wrap ul {
  list-style: none;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.q {
  position: absolute;
  font-weight: 700;
}

.q:first-child {
  top: -1em;
  right: -1em;
}

.q:nth-child(2) {
  right: -1em;
  bottom: -1em;
}

.q:nth-child(3) {
  bottom: -1em;
  left: -1em;
}

.q:nth-child(4) {
  top: -1em;
  left: -1em;
}

.angles {
  -webkit-transform: rotate(-90deg);
  -ms-transform: rotate(-90deg);
  transform: rotate(-90deg);
}

.angle {
  margin: -1px;
  border: solid 1px;
  cursor: pointer;
  -webkit-transition: box-shadow .3s;
  transition: box-shadow .3s;
}

.angle:after {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -7px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  content: '';
}

.angle:before {
  position: absolute;
  top: -10px;
  left: 11px;
  padding: 0 3px;
  border-radius: 4px;
  box-shadow: 0 0 2px;
  background: -webkit-linear-gradient(whitesmoke, gainsboro);
  background: linear-gradient(whitesmoke, gainsboro);
  color: black;
}

.sec:before {
  -webkit-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  transform: rotate(180deg);
}

.angle:hover,
.selected {
  box-shadow: 0 0 1px 3px crimson, 0 0 1px 5px white, 0 0 1px 7px crimson;
}

.angle:hover:before,
.selected:before {
  content: attr(data-angle) '°';
}

.major {
  margin: -2px;
  border: solid 2px;
  color: crimson;
}

.box {
  margin: -15% -30%;
  width: 60%;
  height: 30%;
  background: -webkit-linear-gradient(90deg, deeppink, yellow, springgreen);
  background: linear-gradient(0deg, deeppink, yellow, springgreen);
  -webkit-transition: background-image .75s linear;
  transition: background-image .75s linear;
}

.axis {
  top: -50px;
  bottom: -50px;
  width: 1px;
  background: dimgrey;
}

.angle-start-axis:before {
  display: block;
  min-width: 125px;
  text-align: left;
  text-indent: 2px;
  content: '← angle start axis';
}

.h-axis {
  -webkit-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  transform: rotate(90deg);
}

.grad-line {
  top: 12px;
  bottom: 12px;
  width: 1px;
  background: dodgerblue;
  -webkit-transition: -webkit-transform .75s linear;
  transition: -webkit-transform .75s linear;
  transition: transform .75s linear;
}

.grad-line:before {
  display: block;
  margin-top: 7px;
  min-width: 105px;
  text-align: left;
  text-indent: 2px;
  content: '← gradient line';
}

.rev:before {
  -webkit-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  transform: rotate(180deg);
  content: 'gradient line →';
}

.grad-start,
.grad-end {
  left: 20%;
  right: 20%;
  height: 1px;
  background: crimson;
  -webkit-transition: .75s linear;
  transition: .75s linear;
}

.grad-end {
  background: black;
}

.grad-code {
  display: inline-block;
  position: relative;
  z-index: 1;
  margin-top: 3em;
  padding: .5em;
  background: black;
  color: white;
  font: 1.25em monospace;
}

@media (min-width: 240px) {
  html {
    overflow-x: hidden;
  }
}
(function() {
  var fullCircle = 360,
      Demo = function() {
        // utility class
        var EUtil = function() {
          this.getSize = function(m /* integer */) {
            var w = document.body.clientWidth, h = document.body.clientHeight, s;
            s = Math.max(Math.min(Math.min(w,h) - m - 96, 640), 199);
            return (s%2 !== 0)?s:(s-1);
          }

          this.setStyle = function(elStyles) {
            /*
        elStyles is an array
        [
          [element_1, {property_1_1: value_1_1, property_1_2: value_1_2}], 
          [element_2, {property_2_1: value_2_1}]
        ]
        */
            var t, len = elStyles.length,
                prefixed = {'property': ['transform'], 'value': ['linear-gradient']}, 
                prefixList = ['-webkit-', '-moz', '-o-'], l = prefixList.length;
            for(var i = 0; i < len; i++) {
              for(var p in elStyles[i][1]) {
                if(prefixed['property'][0].indexOf(p) != -1) { /* check if the property needs to be prefixed */
                  for(var j = 0; j < l; j++)
                    elStyles[i][0].style[prefixList[j] + p] = elStyles[i][1][p];
                }
                if(elStyles[i][1][p].indexOf(prefixed['value'][0]) != -1) { /* check if the value needs to be prefixed */
                  t = 90 - parseInt(elStyles[i][1][p].split(prefixed['value'][0]+'(')[1].split('deg')[0], 10);
                  t = prefixed['value'][0] + '(' + t + 'deg' + elStyles[i][1][p].split('deg')[1];
                  for(var j = 0; j < l; j++)
                    elStyles[i][0].style[p] = prefixList[j] + t;
                }
                elStyles[i][0].style[p] = elStyles[i][1][p]; /* just set styles, no prefixes */
              }
            }
          };
        };

        // angle class
        var Angle = function(angleValue, u, r) {
          var value = angleValue, 
              selected = (angleValue === 0)?true:false, 
              el = document.createElement('li'); /* this is a dot on the circle */
          el.setAttribute('class', 'angle centre-me round');
          this.isSelected = function() 	{ return selected; };
          this.select = function() 		  { selected = true; el.classList.add('selected'); };
          this.unselect = function() 		{ selected = false; el.classList.remove('selected'); };
          this.getValue = function() 		{ return value; };
          this.getElement = function() 	{ return el; };
          this.isMajor = function()		  { return value%15 === 0; };
          this.isSec = function()			  { return value > 180; };
          if(this.isMajor()) el.classList.add('major');
          if(this.isSec()) el.classList.add('sec');
          if(this.isSelected()) el.classList.add('selected');
          if(el.dataset) el.dataset.angle = value;
          else el.setAttribute('data-angle', value);
          u.setStyle([[el, {'transform': 'rotate(' + value + 'deg) translate(' + r + 'px)'}]]);
        };

        var AngleCircle = function() {
          var angles = [], currentAngle, 
              getSensitivity = function(size) {
                if(size < 240) return 15; /* every 15° for smallest screen */
                if(size < 320) return 10; /* every 10° */
                if(size < 480) return 6;
                if(size < 560) return 5;
                return 3;
              }

          this.createCircle = function(parent, u) {
            var parentStyle = window.getComputedStyle(parent, null), 
                margin = parseInt(parentStyle.marginTop.split('px')[0], 10) + 36, 
                size = u.getSize(margin), r = size/2, s = getSensitivity(size), 
                listWrap = parent.querySelector('.angles');
            u.setStyle([[parent, {'width': size + 'px', 'height': size + 'px'}]]);
            listWrap.innerHTML = '';
            listWrap = parent.removeChild(listWrap);
            for(var i = 0; i < fullCircle/s; i++) {
              currentAngle = new Angle(i*s, u, r);
              angles.push(currentAngle);
              listWrap.appendChild(currentAngle.getElement());
            }
            parent.appendChild(listWrap);
          };

          this.getSelected = function() {
            var len = angles.length;
            for(var i = 0; i < len; i++)
              if(angles[i].isSelected()) return angles[i];
            console.log('error, no angle selected :(');
            return null;
          };

          this.getAngle = function(angleValue) {
            var len = angles.length;
            for(var i = 0; i < len; i++) 
              if(angles[i].getValue() == angleValue) return angles[i];
            console.log('error, no angle with such value :(');
            return null;
          };

          this.select = function(angleValue) {
            var len = angles.length, selectedAngle = this.getSelected();
            if(angleValue == selectedAngle.getValue()) {
              console.log('already selected :)');
              return -1;
            }
            this.getAngle(angleValue).select();
            selectedAngle.unselect();
          };
        };

        this.init = function() {
          var u = new EUtil(), wrap = document.querySelector('.outer-wrap'), 
              box = wrap.querySelector('.box'), 
              codeEl = document.querySelector('.grad-code'), 
              codetxt = 'linear-gradient(0deg, deeppink, yellow, lime)', 
              gradLine = document.querySelector('.grad-line'), 
              gradStart = document.querySelector('.grad-start'), 
              gradEnd = document.querySelector('.grad-end'), 
              angleCircle = new AngleCircle(), currentAngle = 0;

          angleCircle.createCircle(wrap, u);
          u.setStyle([[gradLine, {'transform': 'rotate(0)'}], 
                      [gradStart, {'transform': 'rotate(0)', 'left': '-10%', 'right': '50%', 'top': '65%'}], 
                      [gradEnd, {'transform': 'rotate(0)', 'left': '50%', 'right': '-10%', 'top': '35%'}], 
                      [box, {'backgroundImage': codetxt}]]);
          codeEl.innerHTML = codetxt;
          if(gradLine.classList.contains('rev')) gradLine.classList.remove('rev');

          wrap.addEventListener('click', function(e) {
            var t = e.target, a, dif;
            if(t.classList.contains('angle')) {
              if(t.dataset) a = parseInt(t.dataset.angle, 10);
              else a = parseInt(t.getAttribute('data-angle'), 10);
              if(angleCircle.select(a) == -1) return;
              dif = a - currentAngle%360;
              currentAngle += (Math.abs(dif) > 180) ? (Math.abs(dif) - 360)*Math.abs(dif)/dif : dif;
              codetxt = 'linear-gradient(' + currentAngle + 'deg, deeppink, yellow, lime)';
              u.setStyle([[gradLine, {'transform': 'rotate(' + currentAngle + 'deg)'}], 
                          [gradStart, {'transform': 'rotate(' + currentAngle + 'deg)'}], 
                          [gradEnd, {'transform': 'rotate(' + currentAngle + 'deg)'}], 
                          [box, {'backgroundImage': codetxt}]]);
              codetxt = 'linear-gradient(' + ((currentAngle%360>=0)?(currentAngle%360):(360+currentAngle%360)) + 'deg, deeppink, yellow, lime)';
              codeEl.innerHTML = codetxt;
              if(a > 90 && a < 270) gradLine.classList.add('rev');
              else gradLine.classList.remove('rev');
              if(a >= 0 && a < 90)
                u.setStyle([[gradStart, {'left': '-10%', 'right': '50%', 'top': '65%'}], 
                            [gradEnd, {'left': '50%', 'right': '-10%', 'top': '35%'}]]);
              if(a >= 90 && a < 180)
                u.setStyle([[gradStart, {'left': '-10%', 'right': '50%', 'top': '35%'}], 
                            [gradEnd, {'left': '50%', 'right': '-10%', 'top': '65%'}]]);
              if(a >= 180 && a < 270)
                u.setStyle([[gradStart, {'left': '50%', 'right': '-10%', 'top': '35%'}], 
                            [gradEnd, {'left': '-10%', 'right': '50%', 'top': '65%'}]]);
              if(a >= 270 && a < 360)
                u.setStyle([[gradStart, {'left': '50%', 'right': '-10%', 'top': '65%'}], 
                            [gradEnd, {'left': '-10%', 'right': '50%', 'top': '35%'}]]);

            }
          }, false);
        };
      }

  var d = new Demo();
  d.init();
  window.addEventListener('resize', function(e) { d.init(); }, false);
}());