├── .gitignore ├── README.md ├── colors.js ├── index.html ├── prefixfree.min.js └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | *.zip 3 | list.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [CSS colors](http://leaverou.github.io/css-colors) 2 | 3 | ## Purpose 4 | CSS.coloratum is a nifty little tool that helps you: 5 | 6 | * Share colors with friends and colleagues (never have to go through describing a shade again, just give them the link!) 7 | * Check out what RGB & HSL values correspond to that color keyword you keep using 8 | * Covert HSL to RGB, because you're done with your prototype and now it has to work in IE8 too 9 | * ...and much more! 10 | 11 | ## Technical details (cause we're geeks after all!) 12 | CSS.coloratum is built with cutting edge open web technologies, so it only works with modern browsers. In its 3KB, it makes use of cool new technologies like: 13 | 14 | * HTML5: canvas, autofocus, output, oninput event, hashchange event 15 | * CSS3: gradients, media queries, box-sizing, background-clip, border-radius, shadows, RGBA 16 | * ES5: Array#map() 17 | * Selectors API 18 | 19 | ## Links 20 | 21 | * CSS Colors is one of my 2 entries to the 10K contest. If you like it, [vote for it](http://10k.aneventapart.com/Entry/Details/538)! 22 | * [My blog post about it](http://lea.verou.me/2011/09/css-coloratum-convert-and-share-css-colors/) 23 | * It's released under an MIT-like License, like most of my stuff. In short, do whatever the eff you want with it, as long as you give me credit in some decent way. 24 | -------------------------------------------------------------------------------- /colors.js: -------------------------------------------------------------------------------- 1 | function $(expr) { return document.querySelector(expr); } 2 | function $$(expr) { return document.querySelectorAll(expr); } 3 | 4 | var body = document.body, 5 | canvas = document.createElement('canvas'), 6 | ctx = canvas.getContext('2d'), 7 | input = $('#color'), 8 | form = $('form'), 9 | out = $$('output > input'); 10 | 11 | canvas.width = canvas.height = 16; 12 | body.appendChild(canvas); 13 | 14 | // Simple class for handling sRGB colors 15 | function Color(rgba) { 16 | if (rgba === 'transparent') { 17 | rgba = [0,0,0,0]; 18 | } 19 | else if (typeof rgba === 'string') { 20 | var rgbaString = rgba; 21 | rgba = rgbaString.match(/rgba?\(([\d.]+), ([\d.]+), ([\d.]+)(?:, ([\d.]+))?\)/); 22 | 23 | if (rgba) { 24 | rgba.shift(); 25 | } 26 | else { 27 | throw new Error('Invalid string: ' + rgbaString); 28 | } 29 | } 30 | 31 | if (rgba[3] === undefined) { 32 | rgba[3] = 1; 33 | } 34 | 35 | rgba = rgba.map(function (a) { return Math.round(a * 100)/100 }); 36 | 37 | this.rgba = rgba; 38 | } 39 | 40 | Color.prototype = { 41 | get rgb () { 42 | return this.rgba.slice(0,3); 43 | }, 44 | 45 | get alpha () { 46 | return this.rgba[3]; 47 | }, 48 | 49 | set alpha (alpha) { 50 | this.rgba[3] = alpha; 51 | }, 52 | 53 | get hex () { 54 | var hex = this.rgb.map(function(a) { 55 | return (a < 16? '0' : '') + a.toString(16); 56 | }).join('') 57 | 58 | if(this.alpha >= 1) { 59 | if(/(([\da-z])\2){3}/i.test(hex)) { 60 | hex = hex.charAt(0) + hex.charAt(2) + hex.charAt(4); 61 | } 62 | } 63 | else { 64 | var alpha255 = Math.round(this.alpha * 255); 65 | 66 | hex += (alpha255 < 16? '0' : '') + alpha255.toString(16); 67 | } 68 | 69 | return '#' + hex; 70 | }, 71 | 72 | get hsl () { 73 | var rgb = this.rgb.map(function(a) { return a / 2.55 }); 74 | 75 | var hsl = [], 76 | max = Math.max.apply(Math, rgb), 77 | min = Math.min.apply(Math, rgb); 78 | 79 | hsl[2] = Math.round((min + max)/2); 80 | 81 | var d = max - min; 82 | 83 | if(d !== 0) { 84 | hsl[1] = Math.round(d*100 / (100 - Math.abs(2*hsl[2] - 100))) + '%'; 85 | 86 | switch(max){ 87 | case rgb[0]: hsl[0] = (rgb[1] - rgb[2]) / d + (rgb[1] < rgb[2] ? 6 : 0); break; 88 | case rgb[1]: hsl[0] = (rgb[2] - rgb[0]) / d + 2; break; 89 | case rgb[2]: hsl[0] = (rgb[0] - rgb[1]) / d + 4; 90 | } 91 | 92 | hsl[0] = Math.round(hsl[0]*60); 93 | } 94 | else { 95 | hsl[0] = 0; 96 | hsl[1] = '0%'; 97 | } 98 | 99 | hsl[2] += '%'; 100 | 101 | return hsl; 102 | }, 103 | 104 | toString: function() { 105 | return 'rgb' + (this.alpha < 1? 'a' : '') + '(' + (this.rgba.slice(0, this.alpha >= 1? 3 : 4).join(', ') + ')').replace(/\b0\./, '.'); 106 | }, 107 | 108 | toHSLString: function() { 109 | var hsl = this.hsl; 110 | 111 | return 'hsl' + (this.alpha < 1? 'a' : '') + '(' + hsl.join(', ') + ((this.alpha < 1? ', ' + this.alpha : '') + ')').replace(/\b0\./, '.'); 112 | }, 113 | 114 | clone: function() { 115 | return new Color(this.rgba); 116 | } 117 | } 118 | 119 | form.onsubmit = function(e) { 120 | e && e.preventDefault(); 121 | 122 | var oldColor = getComputedStyle(document.body).backgroundColor; 123 | 124 | document.body.style.background = ''; 125 | document.body.style.background = input.value; 126 | 127 | var newColor = document.body.style.background; 128 | 129 | if (!newColor) { 130 | // Invalid color 131 | document.body.style.background = oldColor; 132 | input.className = 'invalid'; 133 | 134 | return; 135 | } 136 | 137 | newColor = getComputedStyle(document.body).backgroundColor; 138 | 139 | input.removeAttribute('class'); 140 | 141 | var color = new Color(newColor); 142 | 143 | out[1].value = color.hex; 144 | 145 | out[0].value = color + ''; 146 | 147 | out[2].value = color.toHSLString(); 148 | 149 | ctx.fillStyle = color + ''; 150 | ctx.clearRect(0, 0, 16, 16); 151 | ctx.fillRect(0, 0, 16, 16); 152 | 153 | $('link[rel="shortcut icon"]').setAttribute('href', canvas.toDataURL()); 154 | document.title = color + ' ✿ CSS.coloratum'; 155 | 156 | if(history.pushState) { 157 | history.pushState(null, null, '#' + encodeURIComponent(input.value)); 158 | } 159 | 160 | return false; 161 | }; 162 | 163 | input.onblur = function() { 164 | if(input.className) { 165 | return; 166 | } 167 | 168 | var hashchange = onhashchange; 169 | window.onhashchange = null; 170 | location.hash = '#' + encodeURIComponent(input.value); 171 | window.onhashchange = hashchange; 172 | } 173 | 174 | input.oninput = function() { form.onsubmit() }; 175 | 176 | (onhashchange = function() { 177 | var color = location.hash.slice(1) || 'slategray'; 178 | 179 | try { 180 | input.value = decodeURIComponent(color); 181 | } 182 | catch(e) { input.value = color }; 183 | 184 | form.onsubmit(); 185 | })(); 186 | 187 | for(var i=0; i 2 | 3 | 4 | 5 | 6 | CSS Colors: Convert and share CSS colors 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

CSS Colors

15 |
16 | 20 | 21 | 22 | 23 |
24 | 29 | 30 | 31 | 32 | Tweet 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /prefixfree.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * StyleFix 1.0.3 & PrefixFree 1.0.7 3 | * @author Lea Verou 4 | * MIT license 5 | */(function(){function t(e,t){return[].slice.call((t||document).querySelectorAll(e))}if(!window.addEventListener)return;var e=window.StyleFix={link:function(t){try{if(t.rel!=="stylesheet"||t.hasAttribute("data-noprefix"))return}catch(n){return}var r=t.href||t.getAttribute("data-href"),i=r.replace(/[^\/]+$/,""),s=t.parentNode,o=new XMLHttpRequest,u;o.onreadystatechange=function(){o.readyState===4&&u()};u=function(){var n=o.responseText;if(n&&t.parentNode&&(!o.status||o.status<400||o.status>600)){n=e.fix(n,!0,t);if(i){n=n.replace(/url\(\s*?((?:"|')?)(.+?)\1\s*?\)/gi,function(e,t,n){return/^([a-z]{3,10}:|\/|#)/i.test(n)?e:'url("'+i+n+'")'});var r=i.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1");n=n.replace(RegExp("\\b(behavior:\\s*?url\\('?\"?)"+r,"gi"),"$1")}var u=document.createElement("style");u.textContent=n;u.media=t.media;u.disabled=t.disabled;u.setAttribute("data-href",t.getAttribute("href"));s.insertBefore(u,t);s.removeChild(t);u.media=t.media}};try{o.open("GET",r);o.send(null)}catch(n){if(typeof XDomainRequest!="undefined"){o=new XDomainRequest;o.onerror=o.onprogress=function(){};o.onload=u;o.open("GET",r);o.send(null)}}t.setAttribute("data-inprogress","")},styleElement:function(t){if(t.hasAttribute("data-noprefix"))return;var n=t.disabled;t.textContent=e.fix(t.textContent,!0,t);t.disabled=n},styleAttribute:function(t){var n=t.getAttribute("style");n=e.fix(n,!1,t);t.setAttribute("style",n)},process:function(){t('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);t("style").forEach(StyleFix.styleElement);t("[style]").forEach(StyleFix.styleAttribute)},register:function(t,n){(e.fixers=e.fixers||[]).splice(n===undefined?e.fixers.length:n,0,t)},fix:function(t,n,r){for(var i=0;i-1&&(e=e.replace(/(\s|:|,)(repeating-)?linear-gradient\(\s*(-?\d*\.?\d*)deg/ig,function(e,t,n,r){return t+(n||"")+"linear-gradient("+(90-r)+"deg"}));e=t("functions","(\\s|:|,)","\\s*\\(","$1"+s+"$2(",e);e=t("keywords","(\\s|:)","(\\s|;|\\}|$)","$1"+s+"$2$3",e);e=t("properties","(^|\\{|\\s|;)","\\s*:","$1"+s+"$2:",e);if(n.properties.length){var o=RegExp("\\b("+n.properties.join("|")+")(?!:)","gi");e=t("valueProperties","\\b",":(.+?);",function(e){return e.replace(o,s+"$1")},e)}if(r){e=t("selectors","","\\b",n.prefixSelector,e);e=t("atrules","@","\\b","@"+s+"$1",e)}e=e.replace(RegExp("-"+s,"g"),"-");e=e.replace(/-\*-(?=[a-z]+)/gi,n.prefix);return e},property:function(e){return(n.properties.indexOf(e)?n.prefix:"")+e},value:function(e,r){e=t("functions","(^|\\s|,)","\\s*\\(","$1"+n.prefix+"$2(",e);e=t("keywords","(^|\\s)","(\\s|$)","$1"+n.prefix+"$2$3",e);return e},prefixSelector:function(e){return e.replace(/^:{1,2}/,function(e){return e+n.prefix})},prefixProperty:function(e,t){var r=n.prefix+e;return t?StyleFix.camelCase(r):r}};(function(){var e={},t=[],r={},i=getComputedStyle(document.documentElement,null),s=document.createElement("div").style,o=function(n){if(n.charAt(0)==="-"){t.push(n);var r=n.split("-"),i=r[1];e[i]=++e[i]||1;while(r.length>3){r.pop();var s=r.join("-");u(s)&&t.indexOf(s)===-1&&t.push(s)}}},u=function(e){return StyleFix.camelCase(e)in s};if(i.length>0)for(var a=0;a input { 90 | background: transparent; 91 | border: 0; 92 | color: inherit; 93 | font-size: 180%; 94 | text-shadow: inherit; 95 | border-radius: 10px; 96 | } 97 | 98 | canvas { 99 | display: none; 100 | } 101 | 102 | footer { 103 | margin-top: .3em; 104 | font-weight: bold; 105 | color: rgba(0,0,0,.8); 106 | } 107 | 108 | .twitter-share-button { 109 | position: absolute; 110 | top: 10px; 111 | left: 10px; 112 | } 113 | 114 | @media (max-width: 500px) { 115 | body { font-size: 90%; } 116 | } 117 | 118 | @media (max-width: 400px) { 119 | body { font-size: 80%; } 120 | } --------------------------------------------------------------------------------