├── .editorconfig ├── .gitignore ├── README.md ├── _config.yml ├── homepage-assets ├── favicon.png ├── homepage.js ├── jquery-3.4.1.min.js ├── logo.svg ├── mobile.css ├── preview.gif └── style.css ├── index.html ├── loaders ├── awesome-spin │ └── awesome-spin.css ├── blasting-circle │ └── blasting-circle.css ├── blasting-ripple │ └── blasting-ripple.css ├── block-spin │ └── block-spin.css ├── bouncing-circle │ └── bouncing-circle.css ├── box-rotation │ └── box-rotation.css ├── cascading-bars │ └── cascading-bars.css ├── clock │ └── clock.css ├── color-pulse-ball │ └── color-pulse-ball.css ├── double-circle │ └── double-circle.css ├── hour-glass │ └── hour-glass.css ├── quantum-spinner │ └── quantum-spinner.css ├── recursive-circle │ └── recursive-circle.css ├── rotating-plane │ └── rotating-plane.css ├── simple-circle │ └── simple-circle.css └── vars.css └── react ├── .babelrc ├── .gitignore ├── build └── index.js ├── package.json ├── readme.MD ├── src └── index.js ├── webpack.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | charset = utf-8 7 | trim_trailing_whitespace = false 8 | insert_final_newline = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache/ 2 | .DS_Store 3 | node_modules/ 4 | dist/ 5 | .idea/ 6 | .vscode/ 7 | package-lock.json 8 | yarn.lock -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### CSS Only loaders 2 | 3 | loaders made with pure CSS and zero bulk. Will be converted to a react component once matured 4 | 5 | [![star this repo](http://githubbadges.com/star.svg?user=theanam&repo=css-only-loaders&style=default)](https://github.com/theanam/css-only-loaders) 6 | [![fork this repo](http://githubbadges.com/fork.svg?user=theanam&repo=css-only-loaders&style=default)](https://github.com/theanam/css-only-loaders/fork) 7 | 8 | ![CSS Only Loaders](https://raw.githubusercontent.com/theanam/css-only-loaders/master/homepage-assets/preview.gif) 9 | 10 | #### React component 11 | 12 | [![NPM](https://nodei.co/npm/cssonly-loaders-react.png)](https://nodei.co/npm/cssonly-loaders-react/) 13 | 14 | **Readme still incomplete** 15 | 16 | > This is a work in progress. if you have a cool loader idea, please contribute 17 | 18 | #### Contribution guide: 19 | 20 | * Please use [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) in the `looaders/vars.css` file. Make sure the custom measurements in your loader is related to the values in the vars file. Use [calc](https://developer.mozilla.org/en-US/docs/Web/CSS/calc) if necessary. 21 | 22 | * Please make sure the folder name in the `loaders` folder, the css file name and the class name is the same. This is **Important** for the automatic defination loading to work. 23 | 24 | * If you want your loader to be added to the react component as well, add the referenece to the CSS file to the `react/src/index.js` file. As the files are placed two folder above use a format like this: `import "../../loaders/simple-circle/simple-circle.css";`. Should be enough to include it to the react component once a new version is released on npm. 25 | 26 | 27 | #### Seeking help for: 28 | 29 | * Vue component 30 | * Angular Component 31 | * New loader Ideas 32 | 33 | The Loader icon on the logo is taken from [Icofont](icofont.com) 34 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | exclude: ["react"] -------------------------------------------------------------------------------- /homepage-assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theanam/css-only-loaders/330d2297cbde36103513e1e4090b014087e7f20e/homepage-assets/favicon.png -------------------------------------------------------------------------------- /homepage-assets/homepage.js: -------------------------------------------------------------------------------- 1 | var baseURL = "https://raw.githubusercontent.com/theanam/css-only-loaders/master/loaders"; 2 | var size = 70; 3 | var color = "#27ae60"; 4 | var line = 3; 5 | var dur = 2; 6 | function getBaseCSS(){ 7 | return ` 8 | /* 9 | The loaders use CSS custom properties (variables) to control the attributes of the loaders 10 | */ 11 | :root{ 12 | --loader-width: ${size}px; 13 | --loader-height: ${size}px; 14 | --loader-color-primary: ${color}; 15 | --loader-color-secondary: #eee; 16 | --line-width: ${line}px; 17 | --animation-duration: ${dur}s; 18 | --loader-initial-scale: 0.1; 19 | } 20 | .loader,.loader:before,.loader:after{ 21 | box-sizing: border-box; 22 | flex-grow: 0; 23 | flex-shrink: 0; 24 | } 25 | /* 26 | In order to get optimal results, please only change the 27 | variables above and don't change anything in the actual loader code 28 | */ 29 | 30 | `; 31 | } 32 | function getDefination(cssClass,callback){ 33 | $(".loadingindicator").css("display","flex"); 34 | $.get(`${baseURL}/${cssClass}/${cssClass}.css`) 35 | .then(data=>{ 36 | callback(data); 37 | $(".loadingindicator").css("display","none"); 38 | }) 39 | .catch(e=>{ 40 | console.log("CSS defination fetch error"); 41 | $(".loadingindicator").css("display","none"); 42 | }); 43 | } 44 | 45 | function prepareSourceCode(data,defName){ 46 | $(".sourceholder").css("display","flex"); 47 | $(".html-code").text(`
`); 48 | $(".actual-code").text(getBaseCSS() + "\n\n" + data); 49 | $(".current-loader-name").val(defName); 50 | } 51 | 52 | $(".loader").on("click",function(e){ 53 | var classes = $(this).attr("class"); 54 | var defName = classes.split(" ")[1]; 55 | if(!defName) return console.log("Defination class missing"); 56 | getDefination(defName,function(data){ 57 | prepareSourceCode(data,defName); 58 | }); 59 | }); 60 | 61 | $(".source").on("click",function(e){ 62 | e.stopPropagation(); 63 | }); 64 | 65 | $(".sourceholder").on("click",function(){ 66 | $(this).css("display","none"); 67 | }); 68 | $(".size").on("mousemove change",function(){ 69 | let _size = $(this).val() || size; 70 | size = _size; 71 | $(".lsize").html(size); 72 | document.querySelector(":root").style.setProperty("--loader-width",`${_size}px`); 73 | document.querySelector(":root").style.setProperty("--loader-height",`${_size}px`); 74 | }); 75 | $(".line").on("mousemove change",function(){ 76 | let _line = $(this).val() || line; 77 | line = _line; 78 | $(".lline").html(line); 79 | document.querySelector(":root").style.setProperty("--line-width",`${_line}px`); 80 | }); 81 | $(".dur").on("mousemove change",function(){ 82 | let _dur = $(this).val() || dur; 83 | dur = _dur; 84 | $(".ldur").html(dur); 85 | document.querySelector(":root").style.setProperty("--animation-duration",`${_dur}s`); 86 | }); 87 | $(".color").on("change",function(){ 88 | let _color = $(this).val() || color; 89 | color = _color; 90 | $(".lcolor").html(color); 91 | document.querySelector(":root").style.setProperty("--loader-color-primary",_color); 92 | }); 93 | $(".copy").on("click",function(){ 94 | let target = $(this).data('target'); 95 | let targetEl = $(`.${target}`); 96 | targetEl.select(); 97 | document.execCommand("copy"); 98 | }); 99 | 100 | $(function(){ 101 | $(".lcolor").html(color); 102 | $(".ldur").html(dur); 103 | $(".lline").html(line); 104 | $(".lsize").html(size); 105 | $.each($(".loader"),function(idx,item){ 106 | let _cls = $(item).attr("class").split(" ")[1]; 107 | $(item).attr("title",_cls); 108 | }) 109 | }); -------------------------------------------------------------------------------- /homepage-assets/jquery-3.4.1.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /homepage-assets/mobile.css: -------------------------------------------------------------------------------- 1 | @media screen and (max-width:450px){ 2 | :root{ 3 | --side-margin: 20px; 4 | } 5 | .header{ 6 | padding: var(--side-margin, 60px); 7 | } 8 | .controls{ 9 | position: relative; 10 | } 11 | .logo{ 12 | height: 30px; 13 | } 14 | .source{ 15 | padding: 5px; 16 | height: 80vh; 17 | width: 90vw; 18 | } 19 | } -------------------------------------------------------------------------------- /homepage-assets/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theanam/css-only-loaders/330d2297cbde36103513e1e4090b014087e7f20e/homepage-assets/preview.gif -------------------------------------------------------------------------------- /homepage-assets/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | } 5 | :root{ 6 | --side-margin: 60px; 7 | --primary-blue: #2980b9; 8 | } 9 | body{ 10 | font-family: sans-serif; 11 | } 12 | .header{ 13 | box-sizing: border-box; 14 | padding: 40px var(--side-margin, 60px); 15 | } 16 | .logo{ 17 | height: 50px; 18 | } 19 | .badges{ 20 | margin-top: 1em; 21 | } 22 | .instruction{ 23 | padding: 0.2em 0.5em; 24 | display: inline-block; 25 | background: #222; 26 | color: #fff; 27 | border-radius: 0.2em; 28 | margin-top: 1em; 29 | } 30 | .usage-instructions{ 31 | margin-top: 1em; 32 | font-size: 0.9em; 33 | color: #333; 34 | } 35 | .container{ 36 | padding:10px; 37 | } 38 | .footer{ 39 | padding: 40px var(--side-margin, 60px); 40 | } 41 | .loader{ 42 | display: inline-block; 43 | margin: var(--side-margin,60px); 44 | cursor: pointer; 45 | background: #fff; 46 | } 47 | .loaders{ 48 | display: flex; 49 | flex-wrap: wrap; 50 | justify-content: space-between; 51 | } 52 | .sourceholder{ 53 | width:100%; 54 | height:100%; 55 | left:0px; 56 | top:0px; 57 | position: fixed; 58 | background: rgba(0,0,0,0.5); 59 | display: none; 60 | z-index: 10000; 61 | align-items: center; 62 | justify-content: center; 63 | } 64 | .source{ 65 | width:80vw; 66 | height:80vh; 67 | background-color: var(--primary-blue,#2980b9); 68 | padding:20px; 69 | z-index: 30000; 70 | border-radius:4px; 71 | display: flex; 72 | flex-direction: column; 73 | overflow:hidden; 74 | z-index:10000; 75 | } 76 | .source div{ 77 | color: white; 78 | padding: 5px; 79 | } 80 | textarea.html-code{ 81 | height: 1.1em; 82 | } 83 | .copy{ 84 | display: inline-block; 85 | padding: 0.1em 0.2em; 86 | border: 1px solid white; 87 | border-radius: 0.2em; 88 | background: #fff; 89 | color: var(--primary-blue, #2980b9); 90 | margin-left: 0.5em; 91 | cursor: pointer; 92 | } 93 | .copy.rmargin{ 94 | margin-left:0; 95 | margin-right: 0.5em; 96 | } 97 | textarea.html-code,textarea.actual-code{ 98 | font-family: monospace; 99 | background: #222; 100 | display: block; 101 | overflow: scroll; 102 | color: #fff; 103 | padding: 10px; 104 | border-radius: 3px; 105 | font-size: 12px; 106 | margin: 0; 107 | border: none; 108 | pointer-events: none; 109 | } 110 | textarea.actual-code{ 111 | flex: 1; 112 | } 113 | .mainnameholder{ 114 | display: flex; 115 | align-items: center; 116 | } 117 | .current-loader-name{ 118 | display: block; 119 | color: #fff; 120 | font-family: monospace; 121 | font-size: 2em; 122 | /* margin-bottom: 0.6em; */ 123 | background-color: transparent; 124 | border: 0; 125 | pointer-events: none; 126 | } 127 | .controls{ 128 | position: fixed; 129 | right: 0px; 130 | padding: 10px; 131 | top: 0px; 132 | background: #fff; 133 | z-index: 4000; 134 | } 135 | .control{ 136 | display: flex; 137 | height: 1.3em; 138 | padding: 0.3em; 139 | align-items: center; 140 | } 141 | .control:nth-child(2n){ 142 | background-color: #eee; 143 | } 144 | .control span{ 145 | flex: 1; 146 | } 147 | .internalloader{ 148 | --animation-duration: 1s; 149 | background: transparent !important; 150 | pointer-events: none; 151 | } 152 | .loadingindicator{ 153 | display: none; 154 | position: fixed; 155 | top:0px; 156 | left:0px; 157 | background: rgba(0,0,0,0.5); 158 | width: 100%; 159 | height: 100%; 160 | z-index: 30000; 161 | align-items: center; 162 | justify-content: center; 163 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | CSS Only Loaders 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 |
33 | 34 | Star 35 | 36 | Fork 37 | 38 |
39 |
40 | Click on any loader to view CSS code 41 |
42 |
43 |
44 |
45 |
Size (70px):
46 |
Line (3 px):
47 |
Duration (2s):
48 |
Color (#27ae60):
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 78 | 79 |
80 |
81 |
82 | Copy 83 | 84 |
85 |
HTML Code Copy
86 | 87 |
CSS Code Copy
88 | 89 |
90 |
91 |
92 |
93 |
94 |
95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /loaders/awesome-spin/awesome-spin.css: -------------------------------------------------------------------------------- 1 | .loader.awesome-spin { 2 | border-radius: 50%; 3 | color: var(--loader-color-primary, #33f); 4 | border-top: var(--line-width, 10px) solid; 5 | border-bottom: var(--line-width, 10px) solid; 6 | width: var(--loader-width, 100px); 7 | height: var(--loader-height, 100px); 8 | animation: awesome-spin var(--animation-duration, 2s) linear infinite; 9 | } 10 | 11 | @keyframes awesome-spin { 12 | 0% { transform: rotate(0deg); } 13 | 100% { transform: rotate(360deg); } 14 | } -------------------------------------------------------------------------------- /loaders/blasting-circle/blasting-circle.css: -------------------------------------------------------------------------------- 1 | /* 2 | Blasting Circle Styles 3 | */ 4 | @keyframes blast { 5 | 0% { 6 | opacity: var(--loader-initial-scale, 0.1); 7 | transform: scale(var(--loader-initial-scale, 0.1)); 8 | } 9 | 100% { 10 | transform: scale(1); 11 | opacity: 1; 12 | } 13 | } 14 | 15 | .loader.blasting-circle { 16 | width: var(--loader-width, 100px); 17 | height: var(--loader-height, 100px); 18 | border-radius: 50%; 19 | background-color: var(--loader-color-primary, #00f); 20 | animation: blast var(--animation-duration, 1s) infinite ease-out; 21 | } -------------------------------------------------------------------------------- /loaders/blasting-ripple/blasting-ripple.css: -------------------------------------------------------------------------------- 1 | /* 2 | Blasting Ripple Styles 3 | */ 4 | @keyframes blast-ripple { 5 | 0% { 6 | top: calc(var(--loader-height, 100px) / 2 - var(--line-width, 4px)); 7 | left: calc(var(--loader-width, 100px) / 2 - var(--line-width, 4px)); 8 | width: 0; 9 | height: 0; 10 | opacity: 1; 11 | } 12 | 100% { 13 | top: -1px; 14 | left: -1px; 15 | width: calc(var(--loader-width, 100px) - var(--line-width, 4px)); 16 | height: calc(var(--loader-height, 100px) - var(--line-width, 4px)); 17 | opacity: 0; 18 | } 19 | } 20 | 21 | .loader.blasting-ripple { 22 | position: relative; 23 | width: var(--loader-width, 100px); 24 | height: var(--loader-height, 100px); 25 | } 26 | 27 | .loader.blasting-ripple::after { 28 | opacity: 0; 29 | content: ""; 30 | position: absolute; 31 | border: var(--line-width, 4px) solid var(--loader-color-primary, #00f); 32 | opacity: 1; 33 | border-radius: 50%; 34 | animation: blast-ripple var(--animation-duration, 1s) cubic-bezier(0, 0.2, 0.8, 1) infinite; 35 | } 36 | .loader.blasting-ripple::before { 37 | opacity: 0; 38 | top: calc(var(--loader-height, 100px) / 2 - var(--line-width, 4px)); 39 | left: calc(var(--loader-width, 100px) / 2 - var(--line-width, 4px)); 40 | content: ""; 41 | position: absolute; 42 | border: var(--line-width, 4px) solid var(--loader-color-primary, #00f); 43 | opacity: 1; 44 | border-radius: 50%; 45 | animation: blast-ripple var(--animation-duration, 1s) cubic-bezier(0, 0.2, 0.8, 1) infinite; 46 | animation-delay: calc(var(--animation-duration,1s) / 2); 47 | } -------------------------------------------------------------------------------- /loaders/block-spin/block-spin.css: -------------------------------------------------------------------------------- 1 | @keyframes block-spin { 2 | 0% { 3 | -webkit-transform: rotate(0deg); 4 | transform: rotate(0deg); 5 | } 6 | 100% { 7 | -webkit-transform: rotate(360deg); 8 | transform: rotate(360deg); 9 | } 10 | } 11 | 12 | .loader.block-spin { 13 | height: var(--loader-height, 100px); 14 | width: var(--loader-width, 100px); 15 | position: relative; 16 | border-radius: 60px; 17 | border: var(--line-width, 4px) solid; 18 | color: var(--loader-color-primary, #33f); 19 | border-left-color: transparent; 20 | border-top-color: transparent; 21 | animation: block-spin var(--animation-duration, .8s) linear infinite; 22 | 23 | } 24 | 25 | .loader.loader.block-spin:after { 26 | position: absolute; 27 | content: ""; 28 | width: 30px; 29 | height: 30px; 30 | top: var(--loader-offset, 50%); 31 | left: var(--loader-offset, 50%); 32 | border-radius: 60px; 33 | border: var(--line-width, 4px) solid; 34 | color: var(--loader-color-primary, #33f); 35 | margin-top: -15px; 36 | margin-left: -15px; 37 | } 38 | -------------------------------------------------------------------------------- /loaders/bouncing-circle/bouncing-circle.css: -------------------------------------------------------------------------------- 1 | @keyframes bounce { 2 | 0% { 3 | transform: translate3d(0, 0, 0); 4 | } 5 | 50% { 6 | transform: translate3d(0, var(--bounce-height, 20px), 0); 7 | } 8 | 100% { 9 | transform: translate3d(0, 0, 0); 10 | } 11 | } 12 | @keyframes shadow{ 13 | 0% { 14 | transform: translate3d(0, 0, 0); 15 | box-shadow: 0px 0px 4px 2px var(--loader-color-secondary, #666); 16 | } 17 | 50% { 18 | transform: translate3d(0, -var(--bounce-height, 20px), 0); 19 | box-shadow: 0px 0px 4px 10px var(--loader-color-secondary, #666); 20 | } 21 | 100% { 22 | transform: translate3d(0, 0, 0); 23 | box-shadow: 0px 0px 4px 2px var(--loader-color-secondary, #666); 24 | } 25 | } 26 | .loader.bouncing-circle { 27 | --bounce-height: calc(var(--loader-height, 100px) / 5); 28 | position: relative; 29 | perspective: calc(var(--loader-width, 100px) * 3); 30 | border-radius: 50%; 31 | width: var(--loader-width, 100px); 32 | height: var(--loader-height, 100px); 33 | background-color: var(--loader-color-primary, #00f); 34 | background: radial-gradient(circle at calc(var(--loader-width, 100px) / 3) calc(var(--loader-width, 100px) / 3), var(--loader-color-primary, #00f), #000); 35 | animation: bounce var(--animation-duration, 1s) infinite ease-in-out; 36 | } 37 | .loader.bouncing-circle::after{ 38 | content: ""; 39 | display: block; 40 | width: 6px; 41 | height: 3px; 42 | position: absolute; 43 | border-radius: 50%; 44 | top: calc(var(--loader-height, 100px) + 10px); 45 | left: calc((var(--loader-width,100px) / 2) - 3px); 46 | background-color: var(--loader-color-secondary, #666); 47 | animation: shadow var(--animation-duration, 1s) infinite ease-in-out; 48 | } -------------------------------------------------------------------------------- /loaders/box-rotation/box-rotation.css: -------------------------------------------------------------------------------- 1 | @keyframes rect-rotate { 2 | 0% { 3 | transform: rotate(0); 4 | } 5 | 50%, 100% { 6 | transform: rotate(360deg); 7 | } 8 | } 9 | 10 | @keyframes fill-rect { 11 | 0%, 50% { 12 | height: 0px; 13 | } 14 | 100% { 15 | 16 | height: inherit; 17 | } 18 | } 19 | 20 | .loader.box-rotation { 21 | transform-origin: center center; 22 | color: var(--loader-color-primary, #33f); 23 | width: var(--loader-width, 100px); 24 | height: var(--loader-height, 100px); 25 | position: relative; 26 | border: var(--line-width, 4px) solid; 27 | display: inline-block; 28 | animation: rect-rotate var(--animation-duration, 1s) linear infinite; 29 | } 30 | 31 | .loader.box-rotation::after { 32 | content: ""; 33 | height: 0px; 34 | width: 100%; 35 | height:100%; 36 | display: block; 37 | background: var(--loader-color-primary, #33f); 38 | opacity: 0.5; 39 | animation: fill-rect var(--animation-duration, 1s) linear infinite; 40 | } 41 | -------------------------------------------------------------------------------- /loaders/cascading-bars/cascading-bars.css: -------------------------------------------------------------------------------- 1 | @keyframes grow-and-shrink { 2 | 3 | 0%, 4 | 80%, 5 | 100% { 6 | /* transform: translateY(0); */ 7 | transform: scaleY(1); 8 | } 9 | 10 | 40% { 11 | /* transform: translateY(calc(var(--loader-height) * 0.125)); */ 12 | transform: scaleY(1.2); 13 | } 14 | } 15 | 16 | .loader.cascading-bars, 17 | .loader.cascading-bars::before, 18 | .loader.cascading-bars::after { 19 | display: block; 20 | position: relative; 21 | content: ""; 22 | width: calc(var(--loader-width)/4); 23 | height: var(--loader-height); 24 | background: var(--loader-color-primary); 25 | } 26 | 27 | .loader.cascading-bars { 28 | top: 0; 29 | animation: grow-and-shrink calc(var(--animation-duration)/3) ease-in-out infinite; 30 | animation-delay: calc(var(--animation-duration) * 0.083); 31 | } 32 | 33 | .loader.cascading-bars::before { 34 | position: absolute; 35 | top: 0; 36 | left: calc(-0.35 * var(--loader-width)); 37 | animation: grow-and-shrink calc(var(--animation-duration)/3) ease-in-out infinite; 38 | } 39 | 40 | .loader.cascading-bars::after { 41 | position: absolute; 42 | top: 0; 43 | left: calc(0.35 * var(--loader-width)); 44 | animation: grow-and-shrink calc(var(--animation-duration)/3) ease-in-out calc(var(--animation-duration)/6) infinite; 45 | animation-delay: calc(var(--animation-duration) * 0.167); 46 | } -------------------------------------------------------------------------------- /loaders/clock/clock.css: -------------------------------------------------------------------------------- 1 | .loader.clock { 2 | position: relative; 3 | width: var(--loader-width, 100px); 4 | height: var(--loader-height, 100px); 5 | border-radius: 50%; 6 | border: var(--line-width, 4px) solid var(--loader-color-primary, #33f); 7 | } 8 | 9 | .loader.clock::before{ 10 | content: ''; 11 | position: absolute; 12 | top: 8px; 13 | left: calc(50% - 2px); 14 | background: var(--loader-color-primary, #33f); 15 | width: var(--line-width, 4px); 16 | height: calc( 50% - 8px ); 17 | border-radius: calc(var(--line-width, 4px) + 1); 18 | transform-origin: 50% 100%; 19 | animation: circle-loader var(--animation-duration,1s) infinite linear ; 20 | } -------------------------------------------------------------------------------- /loaders/color-pulse-ball/color-pulse-ball.css: -------------------------------------------------------------------------------- 1 | @keyframes colorpulse { 2 | 0% { 3 | filter: hue-rotate(0deg); 4 | } 5 | 100% { 6 | filter: hue-rotate(359.9deg); 7 | } 8 | } 9 | 10 | @keyframes pulse { 11 | 0%, 1% { 12 | opacity: 1; 13 | transform: scale(0.1); 14 | } 15 | 100% { 16 | opacity: 0; 17 | transform: scale(1); 18 | } 19 | } 20 | 21 | .loader.color-pulse-ball { 22 | width: var(--loader-width, 100px); 23 | height: var(--loader-height, 100px); 24 | border-radius: 50%; 25 | background-color: var(--loader-color-primary, #00f); 26 | animation: colorpulse calc(3 * var(--animation-duration,1s)) infinite ease-in-out, 27 | pulse var(--animation-duration,1s) infinite ease; 28 | } 29 | -------------------------------------------------------------------------------- /loaders/double-circle/double-circle.css: -------------------------------------------------------------------------------- 1 | .loader.double-circle { 2 | position: relative; 3 | width: var(--loader-width, 100px); 4 | height: var(--loader-height, 100px); 5 | } 6 | 7 | .double-circle::before, 8 | .double-circle::after{ 9 | content: ''; 10 | display: block; 11 | position: absolute; 12 | border-radius: 50%; 13 | border: var(--line-width, 4px) solid transparent; 14 | border-bottom-color: var(--loader-color-primary, #33f); 15 | animation: circle-loader var(--animation-duration, 1s) infinite linear ; 16 | } 17 | 18 | .double-circle::before{ 19 | width: 100%; 20 | height: 100%; 21 | top: 0; 22 | left: 0; 23 | } 24 | 25 | .double-circle::after{ 26 | width: calc(100% - 12px); 27 | height: calc(100% - 12px); 28 | top: 6px; 29 | left: 6px; 30 | animation-direction: reverse; 31 | } -------------------------------------------------------------------------------- /loaders/hour-glass/hour-glass.css: -------------------------------------------------------------------------------- 1 | @keyframes slide { 2 | 0% { 3 | transform: translateY(0%); 4 | } 5 | 6 | 25% { 7 | transform: translateY(100%); 8 | } 9 | 10 | 50% { 11 | transform: translateY(100%); 12 | } 13 | 14 | 75% { 15 | transform: translateY(0%); 16 | } 17 | 18 | 100% { 19 | transform: translateY(0%); 20 | } 21 | } 22 | 23 | @keyframes spin { 24 | 0% { 25 | transform: rotate(0deg); 26 | } 27 | 28 | 25% { 29 | transform: rotate(0deg); 30 | } 31 | 32 | 50% { 33 | transform: rotate(180deg); 34 | } 35 | 36 | 75% { 37 | transform: rotate(180deg); 38 | } 39 | 40 | 100% { 41 | transform: rotate(360deg); 42 | } 43 | } 44 | 45 | .loader.hour-glass { 46 | position: relative; 47 | width: var(--loader-width, 100px); 48 | height: var(--loader-height, 100px); 49 | background-color: var(--loader-color-primary, #00f); 50 | -webkit-clip-path: polygon(0% 0%, 100% 0%, 50% 50%, 100% 100%, 0% 100%, 50% 50%); 51 | clip-path: polygon(0% 0%, 100% 0%, 50% 50%, 100% 100%, 0% 100%, 50% 50%); 52 | overflow: hidden; 53 | animation: spin var(--animation-duration, 4s) infinite ease-in-out; 54 | } 55 | 56 | .hour-glass:before { 57 | content: ""; 58 | position: absolute; 59 | top: 0px; 60 | left: 0px; 61 | width: var(--loader-width, 100px); 62 | height: 50%; 63 | background-color: var(--loader-color-secondary, #eee); 64 | animation: slide var(--animation-duration, 4s) infinite ease-in-out; 65 | } 66 | -------------------------------------------------------------------------------- /loaders/quantum-spinner/quantum-spinner.css: -------------------------------------------------------------------------------- 1 | 2 | @keyframes momentum { 3 | 0% { 4 | transform: rotate(0deg); 5 | } 6 | 100% { 7 | transform: rotate(-360deg); 8 | } 9 | } 10 | 11 | .loader.quantum-spinner { 12 | --primary-circle-offset: calc(((var(--loader-width,100px) * 0.2) / 2) - var(--line-width,4px)); 13 | --secondary-circle-offset: calc(((var(--loader-width,100px) * 0.4) / 2) - var(--line-width,4px)); /*- (var(--line-width,4px) * 2)*/ 14 | position: relative; 15 | width: var(--loader-width, 100px); 16 | height: var(--loader-height, 100px); 17 | transform-origin: center center; 18 | border-radius: 50%; 19 | border: var(--line-width, 4px) solid rgba(0,0,0,0); 20 | border-top-color: var(--loader-color-primary, #33f); 21 | animation: momentum var(--animation-duration, 1s) linear infinite; 22 | } 23 | 24 | .quantum-spinner:before { 25 | content: ""; 26 | position: absolute; 27 | transform-origin: center center; 28 | top: var(--primary-circle-offset,10px); 29 | left: var(--primary-circle-offset,10px); 30 | width: calc(var(--loader-width,100px) * 0.8); 31 | height: calc(var(--loader-height,100px) * 0.8); 32 | border-radius: 50%; 33 | border: var(--line-width,4px) solid rgba(0,0,0,0); 34 | border-top-color: var(--loader-color-primary, #33f); 35 | opacity: 0.7; 36 | filter: hue-rotate(3eg); 37 | animation: momentum calc(var(--animation-duration, 1s) * 2) linear infinite; 38 | } 39 | 40 | .quantum-spinner:after { 41 | content: ""; 42 | position: absolute; 43 | top: var(--secondary-circle-offset,20px); 44 | left: var(--secondary-circle-offset,20px); 45 | width: calc(var(--loader-width,100px) * 0.6); 46 | height: calc(var(--loader-height,100px) * 0.6); 47 | border-radius: 50%; 48 | transform-origin: center center; 49 | border: var(--line-width,4px) solid rgba(0,0,0,0); 50 | border-top-color: var(--loader-color-primary, #33f); 51 | opacity: 0.3; 52 | filter: hue-rotate(6eg); 53 | animation: momentum var(--animation-duration, 1s) linear infinite; 54 | } -------------------------------------------------------------------------------- /loaders/recursive-circle/recursive-circle.css: -------------------------------------------------------------------------------- 1 | @keyframes recursive-circle { 2 | 0% { 3 | transform: rotate(0); 4 | } 5 | 100% { 6 | transform: rotate(360deg); 7 | } 8 | } 9 | 10 | .loader.recursive-circle { 11 | --loader-offset: calc((var(--loader-width,100px) / 4) - (var(--line-width,4px) / 2)); 12 | height: var(--loader-height, 100px); 13 | width: var(--loader-width, 100px); 14 | color: var(--loader-color-primary, #33f); 15 | display: inline-block; 16 | position: relative; 17 | border: var(--line-width, 4px) solid; 18 | border-radius: 50%; 19 | border-top-color: transparent; 20 | transform-origin: center center; 21 | animation: recursive-circle var(--animation-duration, 1s) linear infinite; 22 | } 23 | .loader.recursive-circle::after { 24 | content: ""; 25 | height: 50%; 26 | width: 50%; 27 | display: block; 28 | box-sizing: border-box; 29 | position: absolute; 30 | top: var(--loader-offset,21px); 31 | left: var(--loader-offset,21px); 32 | border: var(--line-width, 4px) solid; 33 | transform-origin: center center; 34 | border-radius: 50%; 35 | border-top-color: transparent; 36 | animation: recursive-circle calc(var(--animation-duration, 1s) / 2) linear infinite reverse; 37 | } 38 | -------------------------------------------------------------------------------- /loaders/rotating-plane/rotating-plane.css: -------------------------------------------------------------------------------- 1 | @keyframes rotateplane { 2 | 0% { 3 | transform: perspective(var(--perspective-value)) rotateX(0deg) rotateY(0deg); 4 | } 5 | 50% { 6 | transform: perspective(var(--perspective-value)) rotateX(-180.1deg) rotateY(0deg); 7 | } 8 | 100% { 9 | transform: perspective(var(--perspective-value)) rotateX(-180deg) rotateY(-179.9deg); 10 | } 11 | } 12 | 13 | .loader.rotating-plane { 14 | --perspective-value: calc(3 * var(--loader-width, 100px)); 15 | width: var(--loader-width, 100px); 16 | height: var(--loader-height, 100px); 17 | background: var(--loader-color-primary, #00f); 18 | animation: rotateplane var(--animation-duration, 1s) infinite ease-in-out; 19 | } -------------------------------------------------------------------------------- /loaders/simple-circle/simple-circle.css: -------------------------------------------------------------------------------- 1 | @keyframes circle-loader { 2 | 0% { 3 | transform: rotate(0deg); 4 | } 5 | 100% { 6 | transform: rotate(360deg); 7 | } 8 | } 9 | 10 | .loader.simple-circle { 11 | transform-origin: center center; 12 | border: var(--line-width, 4px) solid var(--loader-color-secondary, #fff); 13 | border-right-color: var(--loader-color-primary, #00f); 14 | width: var(--loader-width, 100px); 15 | height: var(--loader-height, 100px); 16 | border-radius: 50%; 17 | animation: circle-loader var(--animation-duration, 1s) infinite ease-out; 18 | } -------------------------------------------------------------------------------- /loaders/vars.css: -------------------------------------------------------------------------------- 1 | /* 2 | The loaders use CSS custom properties (variables) to control the attributes of the loaders 3 | */ 4 | :root{ 5 | --loader-width: 70px; 6 | --loader-height: 70px; 7 | --loader-color-primary: #27ae60; 8 | --loader-color-secondary: #eee; 9 | --line-width: 3px; 10 | --animation-duration: 2s; 11 | --loader-initial-scale: 0.1; 12 | } 13 | .loader,.loader:before,.loader:after{ 14 | box-sizing: border-box; 15 | flex-grow: 0; 16 | flex-shrink: 0; 17 | } 18 | /* 19 | In order to get optimal results, please only change the variables above and don't change anything in the actual loader code 20 | */ -------------------------------------------------------------------------------- /react/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env" 4 | ], 5 | "plugins": [ 6 | "transform-object-rest-spread", 7 | "transform-react-jsx" 8 | ] 9 | } -------------------------------------------------------------------------------- /react/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /react/build/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | /******/ 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | /******/ 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) { 11 | /******/ return installedModules[moduleId].exports; 12 | /******/ } 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ i: moduleId, 16 | /******/ l: false, 17 | /******/ exports: {} 18 | /******/ }; 19 | /******/ 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | /******/ 23 | /******/ // Flag the module as loaded 24 | /******/ module.l = true; 25 | /******/ 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | /******/ 30 | /******/ 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | /******/ 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | /******/ 37 | /******/ // identity function for calling harmony imports with the correct context 38 | /******/ __webpack_require__.i = function(value) { return value; }; 39 | /******/ 40 | /******/ // define getter function for harmony exports 41 | /******/ __webpack_require__.d = function(exports, name, getter) { 42 | /******/ if(!__webpack_require__.o(exports, name)) { 43 | /******/ Object.defineProperty(exports, name, { 44 | /******/ configurable: false, 45 | /******/ enumerable: true, 46 | /******/ get: getter 47 | /******/ }); 48 | /******/ } 49 | /******/ }; 50 | /******/ 51 | /******/ // getDefaultExport function for compatibility with non-harmony modules 52 | /******/ __webpack_require__.n = function(module) { 53 | /******/ var getter = module && module.__esModule ? 54 | /******/ function getDefault() { return module['default']; } : 55 | /******/ function getModuleExports() { return module; }; 56 | /******/ __webpack_require__.d(getter, 'a', getter); 57 | /******/ return getter; 58 | /******/ }; 59 | /******/ 60 | /******/ // Object.prototype.hasOwnProperty.call 61 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 62 | /******/ 63 | /******/ // __webpack_public_path__ 64 | /******/ __webpack_require__.p = ""; 65 | /******/ 66 | /******/ // Load entry module and return exports 67 | /******/ return __webpack_require__(__webpack_require__.s = 17); 68 | /******/ }) 69 | /************************************************************************/ 70 | /******/ ([ 71 | /* 0 */ 72 | /***/ (function(module, exports) { 73 | 74 | /* 75 | MIT License http://www.opensource.org/licenses/mit-license.php 76 | Author Tobias Koppers @sokra 77 | */ 78 | // css base code, injected by the css-loader 79 | module.exports = function(useSourceMap) { 80 | var list = []; 81 | 82 | // return the list of modules as css string 83 | list.toString = function toString() { 84 | return this.map(function (item) { 85 | var content = cssWithMappingToString(item, useSourceMap); 86 | if(item[2]) { 87 | return "@media " + item[2] + "{" + content + "}"; 88 | } else { 89 | return content; 90 | } 91 | }).join(""); 92 | }; 93 | 94 | // import a list of modules into the list 95 | list.i = function(modules, mediaQuery) { 96 | if(typeof modules === "string") 97 | modules = [[null, modules, ""]]; 98 | var alreadyImportedModules = {}; 99 | for(var i = 0; i < this.length; i++) { 100 | var id = this[i][0]; 101 | if(typeof id === "number") 102 | alreadyImportedModules[id] = true; 103 | } 104 | for(i = 0; i < modules.length; i++) { 105 | var item = modules[i]; 106 | // skip already imported module 107 | // this implementation is not 100% perfect for weird media query combinations 108 | // when a module is imported multiple times with different media queries. 109 | // I hope this will never occur (Hey this way we have smaller bundles) 110 | if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { 111 | if(mediaQuery && !item[2]) { 112 | item[2] = mediaQuery; 113 | } else if(mediaQuery) { 114 | item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; 115 | } 116 | list.push(item); 117 | } 118 | } 119 | }; 120 | return list; 121 | }; 122 | 123 | function cssWithMappingToString(item, useSourceMap) { 124 | var content = item[1] || ''; 125 | var cssMapping = item[3]; 126 | if (!cssMapping) { 127 | return content; 128 | } 129 | 130 | if (useSourceMap && typeof btoa === 'function') { 131 | var sourceMapping = toComment(cssMapping); 132 | var sourceURLs = cssMapping.sources.map(function (source) { 133 | return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' 134 | }); 135 | 136 | return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); 137 | } 138 | 139 | return [content].join('\n'); 140 | } 141 | 142 | // Adapted from convert-source-map (MIT) 143 | function toComment(sourceMap) { 144 | // eslint-disable-next-line no-undef 145 | var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); 146 | var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; 147 | 148 | return '/*# ' + data + ' */'; 149 | } 150 | 151 | 152 | /***/ }), 153 | /* 1 */ 154 | /***/ (function(module, exports, __webpack_require__) { 155 | 156 | /* 157 | MIT License http://www.opensource.org/licenses/mit-license.php 158 | Author Tobias Koppers @sokra 159 | */ 160 | 161 | var stylesInDom = {}; 162 | 163 | var memoize = function (fn) { 164 | var memo; 165 | 166 | return function () { 167 | if (typeof memo === "undefined") memo = fn.apply(this, arguments); 168 | return memo; 169 | }; 170 | }; 171 | 172 | var isOldIE = memoize(function () { 173 | // Test for IE <= 9 as proposed by Browserhacks 174 | // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805 175 | // Tests for existence of standard globals is to allow style-loader 176 | // to operate correctly into non-standard environments 177 | // @see https://github.com/webpack-contrib/style-loader/issues/177 178 | return window && document && document.all && !window.atob; 179 | }); 180 | 181 | var getTarget = function (target, parent) { 182 | if (parent){ 183 | return parent.querySelector(target); 184 | } 185 | return document.querySelector(target); 186 | }; 187 | 188 | var getElement = (function (fn) { 189 | var memo = {}; 190 | 191 | return function(target, parent) { 192 | // If passing function in options, then use it for resolve "head" element. 193 | // Useful for Shadow Root style i.e 194 | // { 195 | // insertInto: function () { return document.querySelector("#foo").shadowRoot } 196 | // } 197 | if (typeof target === 'function') { 198 | return target(); 199 | } 200 | if (typeof memo[target] === "undefined") { 201 | var styleTarget = getTarget.call(this, target, parent); 202 | // Special case to return head of iframe instead of iframe itself 203 | if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { 204 | try { 205 | // This will throw an exception if access to iframe is blocked 206 | // due to cross-origin restrictions 207 | styleTarget = styleTarget.contentDocument.head; 208 | } catch(e) { 209 | styleTarget = null; 210 | } 211 | } 212 | memo[target] = styleTarget; 213 | } 214 | return memo[target] 215 | }; 216 | })(); 217 | 218 | var singleton = null; 219 | var singletonCounter = 0; 220 | var stylesInsertedAtTop = []; 221 | 222 | var fixUrls = __webpack_require__(32); 223 | 224 | module.exports = function(list, options) { 225 | if (typeof DEBUG !== "undefined" && DEBUG) { 226 | if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment"); 227 | } 228 | 229 | options = options || {}; 230 | 231 | options.attrs = typeof options.attrs === "object" ? options.attrs : {}; 232 | 233 | // Force single-tag solution on IE6-9, which has a hard limit on the # of ); 40 | } 41 | function Loader(props){ 42 | let {type = "simple-circle", visible = true} = props; 43 | if(!visible) return null; 44 | return ( 45 | 46 | 47 |
48 |
49 | ); 50 | } 51 | 52 | function FullLoader(props){ 53 | const {backgroundColor = `rgba(0,0,0,0.4)`, visible = true } ={props}; 54 | if(!visible) return null; 55 | return (
56 | 57 |
); 58 | } 59 | 60 | const fullLoaderStyle = { 61 | width: '100%', 62 | height: '100%', 63 | flex: 1, 64 | display: 'flex', 65 | alignItems: 'center', 66 | justifyContent: 'center', 67 | position: 'absolute', 68 | left: 0, 69 | top: 0, 70 | zIndex: 40000 71 | } 72 | 73 | export { 74 | Loader as default, 75 | FullLoader 76 | } -------------------------------------------------------------------------------- /react/webpack.config.js: -------------------------------------------------------------------------------- 1 | 2 | var path = require('path'); 3 | module.exports = { 4 | entry: './src/index.js', 5 | output: { 6 | path: path.resolve(__dirname, 'build'), 7 | filename: 'index.js', 8 | libraryTarget: 'commonjs2' 9 | }, 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.js$/, 14 | include: path.resolve(__dirname, 'src'), 15 | exclude: /(node_modules|bower_components|build)/, 16 | use: { 17 | loader: 'babel-loader', 18 | options: { 19 | presets: ['env'] 20 | } 21 | } 22 | }, 23 | { 24 | test: /\.css$/, 25 | include: path.resolve(__dirname,'../loaders'), 26 | exclude: /(node_modules|bower_components|build)/, 27 | use:['style-loader','css-loader'] 28 | } 29 | ] 30 | }, 31 | externals: { 32 | 'react': 'commonjs react' 33 | } 34 | }; --------------------------------------------------------------------------------