├── .prettierignore
├── img
├── color.jpg
├── color-sprite.jpg
└── color-sprite-lg.jpg
├── .gitignore
├── .travis.yml
├── bower.json
├── package.json
├── css
├── gray.min.css
├── gray.css
├── main.css
└── normalize.css
├── LICENSE
├── README.md
├── js
├── jquery.gray.min.js
└── jquery.gray.js
└── index.html
/.prettierignore:
--------------------------------------------------------------------------------
1 | css/
2 | js/
3 |
--------------------------------------------------------------------------------
/img/color.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlhorky/gray/HEAD/img/color.jpg
--------------------------------------------------------------------------------
/img/color-sprite.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlhorky/gray/HEAD/img/color-sprite.jpg
--------------------------------------------------------------------------------
/img/color-sprite-lg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlhorky/gray/HEAD/img/color-sprite-lg.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .DS_Store?
3 | ._*
4 | .Spotlight-V100
5 | .Trashes
6 | ehthumbs.db
7 | Thumbs.db
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | deploy:
3 | provider: npm
4 | email: karl.horky@gmail.com
5 | api_key:
6 | secure: Kf9l3hRuNlWd/7LUOmzu7Tky8r5eGNWl4Tlh6xE2qViOov5WVLQyrb+22MSYfuPBcOb7F++rUMeCpz8Ef6rz8rTrKFMYgNXNSVTe35Zi7BnE6jf0GvPi8gkQLgNwxywEB4jRvRV8O+lanuVROHsiK3O2taktE5YG7+nP0pbT9Cw=
7 | on:
8 | tags: true
9 | repo: karlhorky/gray
10 | branch: gh-pages
11 | notifications:
12 | email: false
13 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gray",
3 | "version": "1.7.0",
4 | "homepage": "https://github.com/karlhorky/gray",
5 | "authors": [
6 | "Karl Horky"
7 | ],
8 | "description": "Make an image gray in all browsers.",
9 | "main": ["css/gray.css", "js/jquery.gray.min.js"],
10 | "keywords": [
11 | "gray",
12 | "grey",
13 | "grayscale",
14 | "images",
15 | "image",
16 | "img"
17 | ],
18 | "license": "MIT",
19 | "ignore": [
20 | "**/.*",
21 | "node_modules",
22 | "bower_components",
23 | "test",
24 | "tests"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-gray",
3 | "version": "1.7.0",
4 | "description": "Make an image grayscale in all browsers.",
5 | "main": "js/jquery.gray.js",
6 | "scripts": {
7 | "test": "echo \"No test specified\""
8 | },
9 | "repository": "karlhorky/gray",
10 | "keywords": [
11 | "gray",
12 | "grey",
13 | "grayscale",
14 | "images",
15 | "image",
16 | "jquery",
17 | "jquery-plugin",
18 | "ecosystem:jquery"
19 | ],
20 | "author": "Karl Horky",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/karlhorky/gray/issues"
24 | },
25 | "homepage": "https://github.com/karlhorky/gray#readme"
26 | }
27 |
--------------------------------------------------------------------------------
/css/gray.min.css:
--------------------------------------------------------------------------------
1 | /*! Gray v1.7.0 (https://github.com/karlhorky/gray) | MIT */
2 | .grayscale{filter:url("data:image/svg+xml;utf8,#grayscale");-webkit-filter:grayscale(1);filter:grayscale(1);filter:gray}.grayscale.grayscale-fade{transition:filter .5s}@media screen and (-webkit-min-device-pixel-ratio:0){.grayscale.grayscale-fade{-webkit-transition:-webkit-filter .5s;transition:-webkit-filter .5s}}.grayscale.grayscale-fade:hover,.grayscale.grayscale-off{-webkit-filter:grayscale(0);filter:grayscale(0)}.grayscale.grayscale-replaced{-webkit-filter:none;filter:none}.grayscale.grayscale-replaced>svg{-webkit-transition:opacity .5s ease;transition:opacity .5s ease;opacity:1}.grayscale.grayscale-replaced.grayscale-fade:hover>svg,.grayscale.grayscale-replaced.grayscale-off>svg{opacity:0}
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Karl Horky
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/css/gray.css:
--------------------------------------------------------------------------------
1 | /*! Gray v1.7.0 (https://github.com/karlhorky/gray) | MIT */
2 | .grayscale {
3 | /* Firefox 10-34 */
4 | filter: url("data:image/svg+xml;utf8,#grayscale");
5 |
6 | /*
7 | Chrome 19+,
8 | Safari 6+,
9 | Safari 6+ iOS,
10 | Opera 15+
11 | */
12 | -webkit-filter: grayscale(1);
13 |
14 | /* Firefox 35+ */
15 | filter: grayscale(1);
16 |
17 | /* IE 6-9 */
18 | filter: gray;
19 | }
20 |
21 | .grayscale.grayscale-fade {
22 | transition: filter .5s;
23 | }
24 |
25 | /* Webkit hack until filter is unprefixed */
26 | @media screen and (-webkit-min-device-pixel-ratio: 0) {
27 | .grayscale.grayscale-fade {
28 | -webkit-transition: -webkit-filter .5s;
29 | transition: -webkit-filter .5s;
30 | }
31 | }
32 |
33 | .grayscale.grayscale-off,
34 | .grayscale.grayscale-fade:hover {
35 | -webkit-filter: grayscale(0);
36 | filter: grayscale(0);
37 | }
38 |
39 | /* Background element */
40 | .grayscale.grayscale-replaced {
41 | -webkit-filter: none;
42 | filter: none;
43 | }
44 |
45 | .grayscale.grayscale-replaced > svg {
46 | -webkit-transition: opacity .5s ease;
47 | transition: opacity .5s ease;
48 | opacity: 1;
49 | }
50 |
51 | .grayscale.grayscale-replaced.grayscale-off > svg,
52 | .grayscale.grayscale-replaced.grayscale-fade:hover > svg {
53 | opacity: 0;
54 | }
55 |
--------------------------------------------------------------------------------
/css/main.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box
3 | }
4 |
5 | body {
6 | font-family: 'Open Sans', sans-serif;
7 | text-align: center;
8 | padding: 40px 0;
9 | }
10 |
11 | h1 {
12 | color: #bbb;
13 | }
14 |
15 | h1 small {
16 | font-size: 60%;
17 | display: block;
18 | }
19 |
20 | h2 {
21 | display: none;
22 | }
23 |
24 | h3 {
25 | font-size: 14px;
26 | text-align: left;
27 | background: #aaa;
28 | margin: 20px 0 25px;
29 | padding: 8px 10px;
30 | border-radius: 4px;
31 | }
32 |
33 | h3,
34 | h3 a {
35 | color: #fff;
36 | text-decoration: none;
37 | }
38 |
39 | h3 a:hover:before {
40 | content: '#';
41 | font-size: 20px;
42 | color: #aaa;
43 | position: absolute;
44 | margin-left: -30px;
45 | margin-top: -4px;
46 | }
47 |
48 | .container {
49 | width: 80%;
50 | max-width: 500px;
51 | margin: 0 auto;
52 | }
53 |
54 | .row:before,
55 | .row:after {
56 | content: " ";
57 | display: table;
58 | }
59 |
60 | .row:after {
61 | clear: both;
62 | }
63 |
64 | .row {
65 | *zoom: 1;
66 | }
67 |
68 | h3 + .col-half,
69 | h3 + .col-half + .col-half {
70 | position: relative;
71 | height: 120px;
72 | top: 25px;
73 | }
74 |
75 | h3 + .col-half {
76 | padding-bottom: 80px;
77 | }
78 |
79 | pre {
80 | margin-top: 20px;
81 | display: inline-block;
82 | background-color: #f3f3f3;
83 | color: #888;
84 | border: 1px solid #ddd;
85 | font-size: 12px;
86 | line-height: 20px;
87 | overflow: auto;
88 | padding: 6px 10px;
89 | border-radius: 3px;
90 | text-align: left;
91 | max-width: 90%;
92 | }
93 |
94 | code {
95 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
96 | }
97 |
98 | *[data-label]:before {
99 | content: attr(data-label);
100 | font-size: 15px;
101 | color: #999;
102 | display: block;
103 | position: absolute;
104 | text-align: center;
105 | top: -25px;
106 | width: 100%;
107 | }
108 |
109 | .github-iframe {
110 | margin-bottom: -9px;
111 | }
112 |
113 | .tweet,
114 | .tweet > div > div {
115 | display: inline-block
116 | }
117 |
118 | .tweet {
119 | text-decoration: none;
120 | color: #fff;
121 | margin-left: 1em;
122 | }
123 |
124 | .tweet > div {
125 | border-radius: 5px;
126 | transition: 25ms ease-out;
127 | padding: 4px 8px;
128 | background-color: #55acee;
129 | border-color: #55acee;
130 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
131 | }
132 |
133 | .tweet > div:hover,
134 | .tweet > div:active {
135 | background-color: #2795e9;
136 | border-color: #2795e9;
137 | }
138 |
139 | .tweet > div > div {
140 | fill: #fff;
141 | stroke: none;
142 | }
143 |
144 | .tweet svg {
145 | margin-top: -4px;
146 | width: 1em;
147 | height: 1em;
148 | vertical-align: middle;
149 | }
150 |
151 | @media (min-width: 481px) {
152 | body {
153 | padding-top: 0;
154 | }
155 |
156 | h1 small {
157 | display: inline;
158 | }
159 |
160 | h2 {
161 | display: block;
162 | }
163 |
164 | h3 + .col-half,
165 | h3 + .col-half + .col-half {
166 | height: 77px;
167 | top: 0;
168 | }
169 |
170 | h3 + .col-half {
171 | padding-bottom: 0;
172 | }
173 |
174 | .container {
175 | max-width: 740px;
176 | }
177 |
178 | *[data-label]:before {
179 | content: none;
180 | }
181 |
182 | .col-half {
183 | float: left;
184 | width: 50%;
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gray
2 |
3 | CSS Styles and jQuery plugin to display images in grayscale.
4 |
5 | #### [Demo](https://karlhorky.github.io/gray/)
6 |
7 | Support:
8 |
9 | - IE 6-11 (10 and 11 use the JavaScript polyfill)
10 | - Edge 12+ (12 uses the JavaScript polyfill)
11 | - Firefox 10+, Firefox on Android
12 | - Chrome 19+, Chrome for Android 25+
13 | - Android Browser 4.4+
14 | - Safari 6+, Safari iOS 6+
15 | - Opera 15+, Opera Mobile 16+
16 | - BlackBerry Browser 10+
17 |
18 | ## Installation
19 |
20 | You can install with [npm](https://www.npmjs.com/):
21 |
22 | ```shell
23 | npm install --save jquery-gray
24 | ```
25 |
26 | Or [Bower](http://bower.io):
27 |
28 | ```shell
29 | bower install --save gray
30 | ```
31 |
32 | Or use the CDN links:
33 |
34 | ```
35 | https://npmcdn.com/jquery-gray@1.7.0/css/gray.min.css
36 | https://npmcdn.com/jquery-gray@1.7.0/js/jquery.gray.min.js
37 | ```
38 |
39 | Or you can just [download](https://github.com/karlhorky/gray/archive/gh-pages.zip) it.
40 |
41 | ## How to Use
42 |
43 | 1. Add the CSS from [gray.css](https://github.com/karlhorky/gray/blob/gh-pages/css/gray.css).
44 |
45 | If you want to use your own CSS selector instead of `.grayscale`, edit or copy the CSS.
46 |
47 | 2. Add the plugin after jQuery at the bottom of the body.
48 |
49 | ```html
50 |
51 | ```
52 |
53 | The plugin automatically initializes for all elements with a class of `grayscale`.
54 |
55 | The plugin can also be called manually with:
56 |
57 | ```javascript
58 | $('.my-grayscale-class').gray();
59 | ```
60 |
61 | The effect can be toggled with the `grayscale-off` class:
62 |
63 | ```javascript
64 | $('.grayscale').toggleClass('grayscale-off');
65 | ```
66 |
67 | 3. Add your image with a class of `grayscale`.
68 |
69 | ```html
70 |
71 | ```
72 |
73 | Images with CSS background-image, background-size and (numeric) background-position are also supported:
74 |
75 | ```html
76 |
95 | ```
96 |
97 | 5. If you are using Modernizr already, make sure that the [required feature detects](https://github.com/karlhorky/gray#modernizr) are included in your build.
98 |
99 | 6. Revel in your absolute and utter awesomeness.
100 |
101 | ## Caveats
102 |
103 | ### Non-numeric background-size and background-position
104 |
105 | Non-numeric background-size (`cover`, `contain`, ...) and background-position (`center`, ...) are not currently supported.
106 |
107 | ### Percentage-based background-position
108 |
109 | Percentage-based background-position (ex. `50% 50%`, ...) is not currently supported.
110 |
111 | ### Non-visible elements will not be correctly initialized
112 |
113 | Calling the plugin on hidden images (or other images that cannot have their size calculated) will fail in polyfill browsers. Workarounds can be found in the discussions at [#57](https://github.com/karlhorky/gray/issues/57#issuecomment-193702953) and [#40](https://github.com/karlhorky/gray/issues/40#issuecomment-136187306).
114 |
115 | ### Child elements removed in browsers without support for CSS filters
116 |
117 | Target elements with child elements will have those child elements removed in browsers without support for CSS filters. [#61](https://github.com/karlhorky/gray/issues/61)
118 |
119 | ### Event listeners removed in browsers without support for CSS filters
120 |
121 | Target elements with event listeners removed in browsers without support for CSS filters. [#65](https://github.com/karlhorky/gray/issues/65)
122 |
123 | ### Colored borders
124 |
125 | Colored borders will be also converted to grayscale in non-polyfill browsers. To also convert to grayscale in polyfill browsers, the class `grayscale-replaced` can be used:
126 |
127 | ```css
128 | .grayscale-replaced {
129 | border-color: #494949 !important;
130 | }
131 | ```
132 |
133 | ## How it Works
134 |
135 | In [browsers that support css filters](http://caniuse.com/#feat=css-filters), the styles in `gray.css` will use CSS filters to turn the image gray.
136 |
137 | ### Modernizr
138 |
139 | The `jquery.gray` plugin uses the [`Modernizr._prefixes`, `css-filters`, `Inline SVG` and `svg-filters` feature detects](https://modernizr.com/download/?cssfilters-inlinesvg-svgfilters-prefixes-setclasses) from Modernizr to determine browser support. If a browser supports inline SVG and SVG filters but not CSS filters, the plugin replaces the elements with SVG elements with filters.
140 |
141 | ## Changelog
142 |
143 | - v1.7.0: Upgrade Modernizr [#80](https://github.com/karlhorky/gray/issues/80)
144 | - v1.6.0: Throw error when modernizr feature detects not in build [#71](https://github.com/karlhorky/gray/issues/71) [#72](https://github.com/karlhorky/gray/issues/72)
145 | - v1.5.0: Add SVG <title> to polyfill for accessibility ([demo](https://karlhorky.github.io/gray/#img-alt))
146 | - v1.4.5: Fix sizing of img tags with padding
147 | - v1.4.4: Fix bug with missing padding properties with background images
148 | - v1.4.3: Fix bug with padding on img tag
149 | - v1.4.2: Add Firefox 35+ support, normalize cross-browser rendering
150 | - v1.4.1: Fix bug with `display: none` on parents
151 | - v1.4.0: Add support for programmatic toggling of grayscale
152 | - v1.3.6: Fix image size with resized img tag and grayscale-fade in polyfill
153 | - v1.3.5: Declare variables to fix error in strict mode
154 | - v1.3.4: Don't override existing modernizr
155 | - v1.3.3: Update minified js to match source
156 | - v1.3.2: Remove grayscale on hover in ie6-9 (fade option), use same svg filter in polyfill as in css
157 | - v1.3.1: Bugfix for empty gray class name
158 | - v1.3.0: Rename fade class to grayscale-fade to resolve conflict with bootstrap
159 | - v1.2.0: IE shim: Copy styles from element to replacement element
160 | - v1.1.1: Improve documentation and demo
161 | - v1.1.0: Support for background images with basic background-size and background-position
162 | - v1.0.0: First basic version with support for <img> tags
163 |
164 | ## License
165 |
166 | MIT © Karl Horky
167 |
--------------------------------------------------------------------------------
/js/jquery.gray.min.js:
--------------------------------------------------------------------------------
1 | /*! Gray v1.7.0 https://github.com/karlhorky/gray) | MIT */
2 | /*! Modernizr 2.8.3 (Custom Build) | MIT & BSD */
3 | if(function(e,t,i){if(!e.Modernizr){var r=[],n=[],s={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var i=this;setTimeout((function(){t(i[e])}),0)},addTest:function(e,t,i){n.push({name:e,fn:t,options:i})},addAsyncTest:function(e){n.push({name:null,fn:e})}},o=s._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):["",""];s._prefixes=o;var a=function(){};a.prototype=s,(a=new a).addTest("svgfilters",(function(){var t=!1;try{t="SVGFEColorMatrixElement"in e&&2==SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE}catch(e){}return t}));var l="CSS"in e&&"supports"in e.CSS,d="supportsCSS"in e;a.addTest("supports",l||d);var u=t.documentElement,f="svg"===u.nodeName.toLowerCase();a.addTest("inlinesvg",(function(){var e=w("div");return e.innerHTML="","http://www.w3.org/2000/svg"==("undefined"!=typeof SVGRect&&e.firstChild&&e.firstChild.namespaceURI)}));var h="Moz O ms Webkit",g=s._config.usePrefixes?h.split(" "):[];s._cssomPrefixes=g;var p=s._config.usePrefixes?h.toLowerCase().split(" "):[];s._domPrefixes=p;var c={elem:w("modernizr")};a._q.push((function(){delete c.elem}));var m={style:c.elem.style};a._q.unshift((function(){delete m.style})),s.testAllProps=k,s.testAllProps=M,a.addTest("cssfilters",(function(){if(a.supports)return M("filter","blur(2px)");var e=w("a");return e.style.cssText=o.join("filter:blur(2px); "),!!e.style.length&&(t.documentMode===i||t.documentMode>9)})),function(){var e,t,i,s,o,l;for(var d in n)if(n.hasOwnProperty(d)){if(e=[],(t=n[d]).name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(i=0;iMake an image gray in all browsers.
21 | 22 | 30 | 31 | 37 |<img src="img/color.jpg" class="grayscale">
85 | <img src="img/color.jpg" class="grayscale grayscale-fade">
104 | <img src="img/color.jpg" class="grayscale" alt="Decorative lights">
123 | <img src="img/color.jpg" class="grayscale" style="
163 | position : absolute;
164 | top : 0;
165 | left : 50%;
166 | margin : 0 0 0 -90px;
167 | padding : 5px;
168 | border : 1px solid #ddd;
169 | ">
170 | <div style="
204 | background-image: url(img/color.jpg);
205 | display : inline-block;
206 | width : 180px;
207 | height : 72px;
208 | " class="grayscale"></div>
209 | <div style="
245 | background-image : url(img/color-sprite.jpg);
246 | background-position: -180px 0;
247 | display : inline-block;
248 | width : 180px;
249 | height : 72px;
250 | " class="grayscale"></div>
251 | <div style="
291 | background-image : url(img/color-sprite-lg.jpg);
292 | background-size : auto 72px;
293 | background-position: -180px 0;
294 | display : inline-block;
295 | width : 180px;
296 | height : 72px;
297 | " class="grayscale"></div>
298 | $('.grayscale').toggleClass('grayscale-off');
314 |
324 |
325 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
--------------------------------------------------------------------------------
/js/jquery.gray.js:
--------------------------------------------------------------------------------
1 | /*! Gray v1.7.0 https://github.com/karlhorky/gray) | MIT */
2 | /*! modernizr 3.6.0 (Custom Build) | MIT *
3 | * https://modernizr.com/download/?-cssfilters-inlinesvg-svgfilters-prefixes-setclasses !*/
4 | !function(e,n,t){if(e.Modernizr)return;function r(e,n){return typeof e===n}function s(){var e,n,t,s,o,i,l;for(var a in S)if(S.hasOwnProperty(a)){if(e=[],n=S[a],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;t