octocatstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

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

Want a Run Button?

If active, the preview will update automatically when you change code.

            
              <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>
            
          
!
            
              html, body { min-width: 240px; min-height: 240px; height: 100%; }
html {
  overflow: hidden;
  background: gainsboro;
  font: .8em Verdana, sans-serif; text-align: center; }
body { overflow: auto; margin: 0 0 -1em; }
.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 1em;
}
.outer-wrap ul { list-style: none; }
.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 { transform: rotate(-90deg); }
.angle {
	margin: -1px;
	border: solid 1px;
	cursor: pointer;
	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: linear-gradient(whitesmoke, gainsboro);
	color: black;
}
.sec:before { 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: linear-gradient(0deg, deeppink, yellow, springgreen);
  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 { transform: rotate(90deg); }
.grad-line {
	top: 12px; bottom: 12px;
	width: 1px;
	background: dodgerblue;
	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 { transform: rotate(180deg); content: 'gradient line →'; }
.grad-start, .grad-end {
	left: 20%; right: 20%;
	height: 1px;
	background: crimson;
	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; }
}
            
          
!
            
              /*
 * JUST CLICK THE DOTS TO PICK A NEW ANGLE
 * 
 * Used as a helper demo for 
 * http://hugogiraudel.com/blog/css-gradients
 * 
 * See Details Tab.
 */


(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);
}());
            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console