diff --git a/docs/3df57813b7ec2de885ea6075ff46ed46.js b/docs/3df57813b7ec2de885ea6075ff46ed46.js index f8a7ac643..5e0182276 100644 --- a/docs/3df57813b7ec2de885ea6075ff46ed46.js +++ b/docs/3df57813b7ec2de885ea6075ff46ed46.js @@ -1,19 +1,19 @@ -require=function(r,e,n){function t(n,o){function i(r){return t(i.resolve(r))}function f(e){return r[n][1][e]||e}if(!e[n]){if(!r[n]){var c="function"==typeof require&&require;if(!o&&c)return c(n,!0);if(u)return u(n,!0);var l=new Error("Cannot find module '"+n+"'");throw l.code="MODULE_NOT_FOUND",l}i.resolve=f;var s=e[n]=new t.Module(n);r[n][0].call(s.exports,i,s,s.exports)}return e[n].exports}function o(r){this.id=r,this.bundle=t,this.exports={}}var u="function"==typeof require&&require;t.isParcelRequire=!0,t.Module=o,t.modules=r,t.cache=e,t.parent=u;for(var i=0;ie.length)return;if(!(w instanceof o)){p.lastIndex=0;var x=1;if(!(C=p.exec(w))&&f&&v!=t.length-1){if(p.lastIndex=k,!(C=p.exec(e)))break;for(var F=C.index+(h?C[1].length:0),S=C.index+C[0].length,A=v,j=k,P=t.length;A=(j+=t[A].length)&&(++v,k=j);if(t[v]instanceof o||t[A-1].greedy)continue;x=A-v,w=e.slice(k,j),C.index-=k}if(C){h&&(m=C[1].length);S=(F=C.index+m)+(C=C[0].slice(m)).length;var C,N=w.slice(0,F),O=w.slice(S),E=[v,x];N&&(++v,k+=N.length,E.push(N));var $=new o(u,d?n.tokenize(C,d):C,y,C,f);if(E.push($),O&&E.push(O),Array.prototype.splice.apply(t,E),1!=x&&n.matchGrammar(e,t,a,v,k,!0,u),s)break}else if(s)break}}}}},tokenize:function(e,t,a){var r=[e],i=t.rest;if(i){for(var s in i)t[s]=i[s];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(t)}}},r=n.Token=function(e,t,a,n,r){this.type=e,this.content=t,this.alias=a,this.length=0|(n||"").length,this.greedy=!!r};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(a){return r.stringify(a,t,e)}).join("");var i={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var s="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,s)}n.hooks.run("wrap",i);var l=Object.keys(i.attributes).map(function(e){return e+'="'+(i.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(l?" "+l:"")+">"+i.content+""},!t.document)return t.addEventListener?(n.disableWorkerMessageHandler||t.addEventListener("message",function(e){var a=JSON.parse(e.data),r=a.language,i=a.code,s=a.immediateClose;t.postMessage(n.highlight(i,n.languages[r],r)),s&&t.close()},!1),t.Prism):t.Prism;var i=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return i&&(n.filename=i.src,n.manual||i.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),t.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=a),void 0!==e&&(e.Prism=a),a.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),a.languages.xml=a.languages.markup,a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,a.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/\B!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},a.languages.css.atrule.inside.rest=a.util.clone(a.languages.css),a.languages.markup&&(a.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:a.languages.css,alias:"language-css",greedy:!0}}),a.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:a.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:a.languages.css}},alias:"language-css"}},a.languages.markup.tag)),a.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},a.languages.javascript=a.languages.extend("clike",{keyword:/\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+(?:[Ee][+-]?\d+)?|NaN|Infinity)\b/,function:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),a.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[[^\]\r\n]+]|\\.|[^/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"}}),a.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}}}),a.languages.markup&&a.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:a.languages.javascript,alias:"language-javascript",greedy:!0}}),a.languages.js=a.languages.javascript,"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(){var e={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"};Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(t){for(var n,r=t.getAttribute("data-src"),i=t,s=/\blang(?:uage)?-(?!\*)(\w+)\b/i;i&&!s.test(i.className);)i=i.parentNode;if(i&&(n=(t.className.match(s)||[,""])[1]),!n){var l=(r.match(/\.(\w+)$/)||[,""])[1];n=e[l]||l}var o=document.createElement("code");o.className="language-"+n,t.textContent="",o.textContent="Loading…",t.appendChild(o);var u=new XMLHttpRequest;u.open("GET",r,!0),u.onreadystatechange=function(){4==u.readyState&&(u.status<400&&u.responseText?(o.textContent=u.responseText,a.highlightElement(o)):u.status>=400?o.textContent="✖ Error "+u.status+" while fetching file: "+u.statusText:o.textContent="✖ Error: File does not exist or is empty")},u.send(null)})},document.addEventListener("DOMContentLoaded",self.Prism.fileHighlight)); -},{}],15:[function(require,module,exports) { +},{}],11:[function(require,module,exports) { var e=Element.prototype;e.matches||(e.matches=e.matchesSelector||e.msMatchesSelector||e.webkitMatchesSelector||e.mozMatchesSelector),e.closest||(e.closest=function(e){var t=this;if(!document.documentElement.contains(t))return null;do{if(t.matches(e))return t;t=t.parentElement||t.parentNode}while(null!==t&&1===t.nodeType);return null}); -},{}],22:[function(require,module,exports) { +},{}],14:[function(require,module,exports) { var global = (1,eval)("this"); var o=(0,eval)("this"),n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o};!function(o,t){"object"===("undefined"==typeof exports?"undefined":n(exports))&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):o.Jump=t()}(this,function(){"use strict";var o,t,e=function(o,n,t,e){return(o/=e/2)<1?t/2*o*o+n:-t/2*(--o*(o-2)-1)+n},i="function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?function(o){return void 0===o?"undefined":n(o)}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":void 0===o?"undefined":n(o)},r=function(){var o=void 0,n=void 0,t=void 0,r=void 0,u=void 0,d=void 0,f=void 0,c=void 0,a=void 0,s=void 0,l=void 0,y=void 0;function m(o){return o.getBoundingClientRect().top+n}function v(t){a||(a=t),l=u(s=t-a,n,f,c),window.scrollTo(0,l),s1&&void 0!==arguments[1]?arguments[1]:{};switch(c=s.duration||1e3,r=s.offset||0,y=s.callback,u=s.easing||e,d=s.a11y||!1,n=window.scrollY||window.pageYOffset,void 0===a?"undefined":i(a)){case"number":o=void 0,d=!1,t=n+a;break;case"object":t=m(o=a);break;case"string":o=document.querySelector(a),t=m(o)}switch(f=t-n+r,i(s.duration)){case"number":c=s.duration;break;case"function":c=s.duration(f)}window.requestAnimationFrame(v)}}();return o=void 0,t=function(){return o=!1},function(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!o){var i=window.scrollY||window.pageYOffset;return".header"!==n&&(location.hash=n),scroll(0,i),o=!0,setTimeout(t,e.duration||0),r(n,e)}}}); -},{}],23:[function(require,module,exports) { +},{}],15:[function(require,module,exports) { "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=exports.select=function(e){return document.querySelector(e)},t=exports.selectAll=function(e){return[].slice.call(document.querySelectorAll(e))},o=exports.scrollY=function(){return window.scrollY||window.pageYOffset},r=exports.easeOutQuint=function(e,t,o,r){return o*((e=e/r-1)*Math.pow(e,4)+1)+t};/iPhone|iPad|iPod/.test(navigator.platform)&&!window.MSStream&&(document.body.style.cursor="pointer"),function(){var e=navigator.userAgent,t=/Mac/.test(navigator.platform)&&(e.match(/OS X 10[._](\d{1,2})/)||[])[1]>=11,o=(e.match(/Chrome\/(\d+)\./)||[])[1]<64||(e.match(/Firefox\/(\d+)\./)||[])[1]<58,r=[].slice.call(document.querySelectorAll("*"));t&&o?(document.documentElement.style.letterSpacing="-0.3px",r.forEach(function(e){parseFloat(getComputedStyle(e).fontSize)>=20&&(e.style.letterSpacing="0.3px")})):t&&!o&&r.forEach(function(e){var t=getComputedStyle(e),o=t.fontSize;"italic"===t.fontStyle&&(e.style.letterSpacing=parseFloat(o)>=20?"0.3px":"-0.3px")})}(); -},{}],16:[function(require,module,exports) { +},{}],12:[function(require,module,exports) { "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../deps/jump"),t=i(e),s=require("../deps/utils");function i(e){return e&&e.__esModule?e:{default:e}}var r=(0,s.select)(".hamburger"),n=(0,s.select)(".sidebar__links"),a="is-active",u=function(){[r,n].forEach(function(e){return e.classList.toggle(a)}),r.setAttribute("aria-expanded",r.classList.contains(a)?"true":"false")};r.addEventListener("click",u),n.addEventListener("click",function(e){setTimeout(u,40),e.target.classList.contains("sidebar__link")&&(e.preventDefault(),(0,t.default)(e.target.getAttribute("href"),{duration:750,offset:window.innerWidth<=768?-64:-32,easing:s.easeOutQuint}))}),document.addEventListener("click",function(e){e.target.closest(".sidebar__links")||e.target.closest(".hamburger")||!n.classList.contains(a)||u()}),exports.default={toggle:u}; -},{"../deps/jump":22,"../deps/utils":23}],17:[function(require,module,exports) { +},{"../deps/jump":14,"../deps/utils":15}],13:[function(require,module,exports) { "use strict";var e=require("../deps/jump"),t=s(e),i=require("../deps/utils");function s(e){return e&&e.__esModule?e:{default:e}}var u=(0,i.select)(".back-to-top-button");window.addEventListener("scroll",function(){u.classList[(0,i.scrollY)()>500?"add":"remove"]("is-visible")}),u.onclick=function(){(0,t.default)(".header",{duration:750,easing:i.easeOutQuint})}; -},{"../deps/jump":22,"../deps/utils":23}],8:[function(require,module,exports) { +},{"../deps/jump":14,"../deps/utils":15}],7:[function(require,module,exports) { "use strict";require("normalize.css"),require("prismjs"),require("../css/deps/prism.css"),require("../css/index.scss"),require("./deps/polyfills");var e=require("./components/Menu"),s=u(e),r=require("./components/BackToTopButton"),i=u(r);function u(e){return e&&e.__esModule?e:{default:e}} -},{"normalize.css":26,"prismjs":27,"../css/deps/prism.css":26,"../css/index.scss":26,"./deps/polyfills":15,"./components/Menu":16,"./components/BackToTopButton":17}]},{},[8]) \ No newline at end of file +},{"normalize.css":16,"prismjs":17,"../css/deps/prism.css":16,"../css/index.scss":16,"./deps/polyfills":11,"./components/Menu":12,"./components/BackToTopButton":13}]},{},[7]) \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index a8edd786a..f98344022 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,7 +6,7 @@ *::after { box-sizing: inherit; } -

Demo

Demo

Explanation

  1. box-sizing: border-box makes the addition of padding or borders not affect an element's width or height.
  2. box-sizing: inherit makes an element respect its parent's box-sizing rule.

Browser support

98.2%

✅ No caveats.

Clearfix

Ensures that an element self-clears its children.

Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.

HTML

<div class="clearfix">
+

Demo

Demo

Explanation

  1. box-sizing: border-box makes the addition of padding or borders not affect an element's width or height.
  2. box-sizing: inherit makes an element respect its parent's box-sizing rule.

Browser support

98.2%

✅ No caveats.

Clearfix

Ensures that an element self-clears its children.

Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.

HTML

<div class="clearfix">
   <div class="floated">float a</div>
   <div class="floated">float b</div>
   <div class="floated">float c</div>
diff --git a/index.html b/index.html
index 1e31c0158..f9265c8b8 100644
--- a/index.html
+++ b/index.html
@@ -14,32 +14,44 @@
     
     
@@ -55,8 +67,20 @@
+
-

Box-sizing reset

+

Box-sizing resetlayout

Resets the box-model so that widths and heights are not affected by their borders or padding.

CSS

html {
   box-sizing: border-box;
@@ -67,7 +91,7 @@
   box-sizing: inherit;
 }
 
-

Demo

+

Demo

Demo
@@ -82,12 +106,12 @@ border: 5px solid; } -

Explanation

+

Explanation

  1. box-sizing: border-box makes the addition of padding or borders not affect an element's width or height.
  2. box-sizing: inherit makes an element respect its parent's box-sizing rule.
-

Browser support

+

Browser support

98.2% @@ -99,11 +123,13 @@ https://caniuse.com/#feat=css3-boxsizing + +
-

Clearfix

+

Clearfixlayout

Ensures that an element self-clears its children.

-
Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.
+
Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.

HTML

<div class="clearfix">
   <div class="floated">float a</div>
   <div class="floated">float b</div>
@@ -111,7 +137,7 @@
 </div>
 

CSS

.clearfix::after {
-  content: "";
+  content: '';
   display: block;
   clear: both;
 }
@@ -119,7 +145,7 @@
   float: left;
 }
 
-

Demo

+

Demo

float a
@@ -137,22 +163,24 @@ float: left; } -

Explanation

+

Explanation

  1. .clearfix::after defines a pseudo-element.
  2. content: '' allows the pseudo-element to affect layout.
  3. clear: both indicates that the left, right or both sides of the element cannot be adjacent to earlier floated elements within the same block formatting context.
-

Browser support

+

Browser support

99+%

✅ No caveats.

+ +
-

Constant width to height ratio

+

Constant width to height ratiolayout

Given an element of variable width, it will ensure its height remains proportionate in a responsive fashion (i.e., its width to height ratio remains constant).

HTML

<div class="constant-width-to-height-ratio"></div>
 
@@ -162,7 +190,7 @@ padding-top: 50%; }
-

Demo

+

Demo

Resize your browser window to see the proportion of the element remain the same.

@@ -174,19 +202,21 @@ padding-top: 50%; } -

Explanation

+

Explanation

padding-top and padding-bottom can be used as an alternative to height such that the percentage value causes an element's height to become a percentage of its parent's width, i.e. 50% means the height will be 50% of the parent element's width, which means it acts the same as width. This allows its proportion to remain constant.

-

Browser support

+

Browser support

99+%

⚠️ padding-top pushes any content within the element to the bottom.

+ +
-

Custom scrollbar

+

Custom scrollbarvisual

Customizes the scrollbar style for the document and elements with scrollable overflow, on WebKit platforms.

HTML

<div class="custom-scrollbar">
   <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure id exercitationem nulla qui repellat laborum vitae, molestias tempora velit natus. Quas, assumenda nisi. Quisquam enim qui iure, consequatur velit sit?</p>
@@ -197,18 +227,18 @@
   width: 8px;
 }
 ::-webkit-scrollbar-track {
-  box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
+  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
   border-radius: 10px;
 }
 ::-webkit-scrollbar-thumb {
   border-radius: 10px;
-  box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
+  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5);
 }
 /* Scrollable element */
 .some-element::webkit-scrollbar {
 }
 
-

Demo

+

Demo

@@ -236,7 +266,7 @@ box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); } -

Explanation

+

Explanation

  1. ::-webkit-scrollbar targets the whole scrollbar element.
  2. ::-webkit-scrollbar-track targets only the scrollbar track.
  3. @@ -245,7 +275,7 @@

    There are many other pseudo-elements that you can use to style scrollbars. For more info, visit the WebKit Blog

    -

    Browser support

    +

    Browser support

    87.3% @@ -257,9 +287,11 @@ https://caniuse.com/#feat=css-scrollbar + +
    -

    Custom text selection

    +

    Custom text selectionvisual

    Changes the styling of text selection.

    HTML

    <p class="custom-text-selection">Select some of this text.</p>
     
    @@ -272,7 +304,7 @@ color: white; }
    -

    Demo

    +

    Demo

    Select some of this text.

    @@ -286,9 +318,9 @@ color: white; } -

    Explanation

    +

    Explanation

    ::selection defines a pseudo selector on an element to style text within it when selected. Note that if you don't combine any other selector your style will be applied at document root level, to any selectable element.

    -

    Browser support

    +

    Browser support

    84.6% @@ -301,9 +333,11 @@ in any specification.

    https://caniuse.com/#feat=css-selection + +
    -

    Disable selection

    +

    Disable selectioninteractivity

    Makes the content unselectable.

    HTML

    <p>You can select me.</p>
     <p class="unselectable">You can't select me!</p>
    @@ -312,7 +346,7 @@ in any specification.

    user-select: none; }
    -

    Demo

    +

    Demo

    You can select me.

    You can't select me!

    @@ -322,9 +356,9 @@ in any specification.

    user-select: none; } -

    Explanation

    +

    Explanation

    user-select: none specifies that the text cannot be selected.

    -

    Browser support

    +

    Browser support

    86.3% @@ -336,15 +370,21 @@ in any specification.

    https://caniuse.com/#feat=user-select-none + +
    -

    Donut spinner

    +

    Donut spinneranimation

    Creates a donut spinner that can be used to indicate the loading of content.

    HTML

    <div class="donut"></div>
     

    CSS

    @keyframes donut-spin {
    -  0% { transform: rotate(0deg); }
    -  100% { transform: rotate(360deg); }
    +  0% {
    +    transform: rotate(0deg);
    +  }
    +  100% {
    +    transform: rotate(360deg);
    +  }
     }
     .donut {
       display: inline-block;
    @@ -356,7 +396,7 @@ in any specification.

    animation: donut-spin 1.2s linear infinite; }
    -

    Demo

    +

    Demo

    @@ -379,9 +419,9 @@ in any specification.

    animation: snippet-demo__donut-spin 1.2s linear infinite; } -

    Explanation

    +

    Explanation

    Use a semi-transparent border for the whole element, except one side that will serve as the loading indicator for the donut. Use animation to rotate the element.

    -

    Browser support

    +

    Browser support

    94.8% @@ -396,9 +436,11 @@ in any specification.

    https://caniuse.com/#feat=transforms2d + +
    -

    Easing variables

    +

    Easing variablesanimation

    Variables that can be reused for transition-timing-function properties, more powerful than the built-in ease, ease-in, ease-out and ease-in-out.

    HTML

    <div class="easing-variables"></div>
     
    @@ -432,7 +474,7 @@ in any specification.

    transform: rotate(45deg); } -

    Demo

    +

    Demo

    Hover
    @@ -473,10 +515,10 @@ in any specification.

    transform: rotate(45deg); } -

    Explanation

    +

    Explanation

    The variables are defined globally within the :root CSS pseudo-class which matches the root element of a tree representing the document. In HTML, :root represents the <html> element and is identical to the selector html, except that its specificity is higher.

    -

    Browser support

    +

    Browser support

    87.2% @@ -488,9 +530,11 @@ in any specification.

    https://caniuse.com/#feat=css-variables + +
    -

    Etched text

    +

    Etched textvisual

    Creates an effect where text appears to be "etched" or engraved into the background.

    HTML

    <p class="etched-text">I appear etched into the background.</p>
     
    @@ -501,7 +545,7 @@ in any specification.

    color: #b8bec5; } -

    Demo

    +

    Demo

    I appear etched into the background.

    @@ -513,11 +557,11 @@ in any specification.

    text-shadow: 0 2px 0 white; } -

    Explanation

    +

    Explanation

    text-shadow: 0 2px white creates a white shadow offset 0px horizontally and 2px vertically from the origin position.

    The background must be darker than the shadow for the effect to work.

    The text color should be slightly faded to make it look like it's engraved/carved out of the background.

    -

    Browser support

    +

    Browser support

    97.9% @@ -529,9 +573,11 @@ in any specification.

    https://caniuse.com/#feat=css-textshadow + +
    -

    Evenly distributed children

    +

    Evenly distributed childrenlayout

    Evenly distributes child elements within a parent element.

    HTML

    <div class="evenly-distributed-children">
       <p>Item1</p>
    @@ -544,7 +590,7 @@ in any specification.

    justify-content: space-between; }
    -

    Demo

    +

    Demo

    Item1

    @@ -559,13 +605,13 @@ in any specification.

    justify-content: space-between; } -

    Explanation

    +

    Explanation

    1. display: flex enables flexbox.
    2. justify-content: space-between evenly distributes child elements horizontally. The first item is positioned at the left edge, while the last item is positioned at the right edge.

    Alternatively, use justify-content: space-around to distribute the children with space around them, rather than between them.

    -

    Browser support

    +

    Browser support

    97.8% @@ -577,9 +623,11 @@ in any specification.

    https://caniuse.com/#feat=flexbox + +
    -

    Gradient text

    +

    Gradient textvisual

    Gives text a gradient color.

    HTML

    <p class="gradient-text">Gradient text</p>
     
    @@ -589,7 +637,7 @@ in any specification.

    -webkit-background-clip: text; } -

    Demo

    +

    Demo

    Gradient text @@ -605,13 +653,13 @@ in any specification.

    margin: 0; } -

    Explanation

    +

    Explanation

    1. background: -webkit-linear-gradient(...) gives the text element a gradient background.
    2. webkit-text-fill-color: transparent fills the text with a transparent color.
    3. webkit-background-clip: text clips the background with the text, filling the text with the gradient background as the color.
    -

    Browser support

    +

    Browser support

    90.7% @@ -623,9 +671,11 @@ in any specification.

    https://caniuse.com/#feat=text-stroke + +
    -

    Hairline border

    +

    Hairline bordervisual

    Gives an element a border equal to 1 native device pixel in width, which can look very sharp and crisp.

    HTML

    <div class="hairline-border">text</div>
     
    @@ -648,7 +698,7 @@ in any specification.

    } } -

    Demo

    +

    Demo

    Text with a hairline border around it.

    @@ -672,12 +722,12 @@ in any specification.

    } } -

    Explanation

    +

    Explanation

    1. box-shadow, when only using spread, adds a pseudo-border which can use subpixels*.
    2. Use @media (min-resolution: ...) to check the device pixel ratio (1dppx equals 96 DPI), setting the spread of the box-shadow equal to 1 / dppx.
    -

    Browser Support

    +

    Browser Support

    95.0% @@ -694,9 +744,11 @@ in any specification.


    *Chrome does not support subpixel values on border. Safari does not support subpixel values on box-shadow. Firefox supports subpixel values on both.

    + +
    -

    Horizontal and vertical centering

    +

    Horizontal and vertical centeringlayout

    Horizontally and vertically centers a child element within a parent element.

    HTML

    <div class="horizontal-and-vertical-centering">
       <div class="child"></div>
    @@ -708,7 +760,7 @@ in any specification.

    align-items: center; }
    -

    Demo

    +

    Demo

    Centered content.

    @@ -722,13 +774,13 @@ in any specification.

    height: 200px; } -

    Explanation

    +

    Explanation

    1. display: flex enables flexbox.
    2. justify-content: center centers the child horizontally.
    3. align-items: center centers the child vertically.
    -

    Browser support

    +

    Browser support

    97.8% @@ -740,9 +792,11 @@ in any specification.

    https://caniuse.com/#feat=flexbox + +
    -

    Hover underline animation

    +

    Hover underline animationanimation

    Creates an animated underline effect when the text is hovered over.

    Credit: @@ -773,7 +827,7 @@ in any specification.

    transform-origin: bottom left; } -

    Demo

    +

    Demo

    Hover this text to see the effect!

    @@ -800,7 +854,7 @@ in any specification.

    transform-origin: bottom left; } -

    Explanation

    +

    Explanation

    1. display: inline-block makes the block p an inline-block to prevent the underline from spanning the entire parent width rather than just the content (text).
    2. position: relative on the element establishes a Cartesian positioning context for pseudo-elements.
    3. @@ -814,7 +868,7 @@ in any specification.

    4. :hover::after then uses scaleX(1) to transition the width to 100%, then changes the transform-origin to bottom left so that the anchor point is reversed, allowing it transition out in the other direction when hovered off.
    -

    Browser support

    +

    Browser support

    94.9% @@ -829,9 +883,11 @@ in any specification.

    https://caniuse.com/#feat=css-transitions + +
    -

    Mouse cursor gradient tracking

    +

    Mouse cursor gradient trackingvisualinteractivity

    A hover effect where the gradient follows the mouse cursor.

    Credit: @@ -866,21 +922,21 @@ in any specification.

    height: var(--size); background: radial-gradient(circle closest-side, pink, transparent); transform: translate(-50%, -50%); - transition: width .2s ease, height .2s ease; + transition: width 0.2s ease, height 0.2s ease; } .mouse-cursor-gradient-tracking:hover::before { --size: 200px; }

    JavaScript

    var btn = document.querySelector('.mouse-cursor-gradient-tracking')
    -btn.onmousemove = function (e) {
    +btn.onmousemove = function(e) {
       var x = e.pageX - btn.offsetLeft
       var y = e.pageY - btn.offsetTop
       btn.style.setProperty('--x', x + 'px')
       btn.style.setProperty('--y', y + 'px')
     }
     
    -

    Demo

    +

    Demo

    ` + ) + ) +) +const content = document.querySelector('.content-wrapper') +content.before(components.backToTopButton) +content.before(components.sidebar) +content.append(components.header) +content.append(components.main) +components.main.querySelector('.container').prepend(components.tags) + // doctype declaration gets stripped, add it back in const html = ` ${pretty(document.documentElement.outerHTML, { ocd: true })} diff --git a/snippets/box-sizing-reset.md b/snippets/box-sizing-reset.md index 1bdd33e2f..eb5a2e3fb 100644 --- a/snippets/box-sizing-reset.md +++ b/snippets/box-sizing-reset.md @@ -44,3 +44,5 @@ html { ✅ No caveats. * https://caniuse.com/#feat=css3-boxsizing + + diff --git a/snippets/clearfix.md b/snippets/clearfix.md index e1fe64e6a..657679a99 100644 --- a/snippets/clearfix.md +++ b/snippets/clearfix.md @@ -18,7 +18,7 @@ Ensures that an element self-clears its children. ```css .clearfix::after { - content: ""; + content: ''; display: block; clear: both; } @@ -60,3 +60,5 @@ Ensures that an element self-clears its children. #### Browser support ✅ No caveats. + + diff --git a/snippets/constant-width-to-height-ratio.md b/snippets/constant-width-to-height-ratio.md index ff7ef0122..61ee886c8 100644 --- a/snippets/constant-width-to-height-ratio.md +++ b/snippets/constant-width-to-height-ratio.md @@ -43,3 +43,5 @@ causes an element's height to become a percentage of its parent's width, i.e. `5 #### Browser support ⚠️ `padding-top` pushes any content within the element to the bottom. + + diff --git a/snippets/custom-scrollbar.md b/snippets/custom-scrollbar.md index b63cc00ae..e6542dbbf 100644 --- a/snippets/custom-scrollbar.md +++ b/snippets/custom-scrollbar.md @@ -19,13 +19,13 @@ Customizes the scrollbar style for the document and elements with scrollable ove } ::-webkit-scrollbar-track { - box-shadow: inset 0 0 6px rgba(0,0,0,0.3); + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); border-radius: 10px; } ::-webkit-scrollbar-thumb { border-radius: 10px; - box-shadow: inset 0 0 6px rgba(0,0,0,0.5); + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); } /* Scrollable element */ @@ -80,3 +80,5 @@ There are many other pseudo-elements that you can use to style scrollbars. For m ⚠️ Scrollbar styling doesn't appear to be on any standards track. * https://caniuse.com/#feat=css-scrollbar + + diff --git a/snippets/custom-text-selection.md b/snippets/custom-text-selection.md index ff5136934..927c0937a 100644 --- a/snippets/custom-text-selection.md +++ b/snippets/custom-text-selection.md @@ -48,3 +48,5 @@ Changes the styling of text selection. in any specification. * https://caniuse.com/#feat=css-selection + + diff --git a/snippets/disable-selection.md b/snippets/disable-selection.md index 3250911b7..0ad8481e1 100644 --- a/snippets/disable-selection.md +++ b/snippets/disable-selection.md @@ -39,3 +39,5 @@ Makes the content unselectable. ⚠️ Requires prefixes for full support. * https://caniuse.com/#feat=user-select-none + + diff --git a/snippets/donut-spinner.md b/snippets/donut-spinner.md index 2c921414e..215972229 100644 --- a/snippets/donut-spinner.md +++ b/snippets/donut-spinner.md @@ -12,8 +12,12 @@ Creates a donut spinner that can be used to indicate the loading of content. ```css @keyframes donut-spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } .donut { display: inline-block; @@ -59,3 +63,5 @@ serve as the loading indicator for the donut. Use `animation` to rotate the elem * https://caniuse.com/#feat=css-animation * https://caniuse.com/#feat=transforms2d + + diff --git a/snippets/easing-variables.md b/snippets/easing-variables.md index de2ba1600..711642b27 100644 --- a/snippets/easing-variables.md +++ b/snippets/easing-variables.md @@ -104,3 +104,5 @@ The variables are defined globally within the `:root` CSS pseudo-class which mat ✅ No caveats. * https://caniuse.com/#feat=css-variables + + diff --git a/snippets/etched-text.md b/snippets/etched-text.md index 81f81911e..0f03b8f65 100644 --- a/snippets/etched-text.md +++ b/snippets/etched-text.md @@ -49,3 +49,5 @@ of the background. ✅ No caveats. * https://caniuse.com/#feat=css-textshadow + + diff --git a/snippets/evenly-distributed-children.md b/snippets/evenly-distributed-children.md index 35d9a1370..52583be88 100644 --- a/snippets/evenly-distributed-children.md +++ b/snippets/evenly-distributed-children.md @@ -51,3 +51,5 @@ Alternatively, use `justify-content: space-around` to distribute the children wi ⚠️ Needs prefixes for full support. * https://caniuse.com/#feat=flexbox + + diff --git a/snippets/gradient-text.md b/snippets/gradient-text.md index c778ccfb8..1c57c4f15 100644 --- a/snippets/gradient-text.md +++ b/snippets/gradient-text.md @@ -49,3 +49,5 @@ Gives text a gradient color. ⚠️ Uses non-standard properties. * https://caniuse.com/#feat=text-stroke + + diff --git a/snippets/hairline-border.md b/snippets/hairline-border.md index c27caf34a..e473077f1 100644 --- a/snippets/hairline-border.md +++ b/snippets/hairline-border.md @@ -81,3 +81,5 @@ very sharp and crisp.
    \*Chrome does not support subpixel values on `border`. Safari does not support subpixel values on `box-shadow`. Firefox supports subpixel values on both. + + diff --git a/snippets/horizontal-and-vertical-centering.md b/snippets/horizontal-and-vertical-centering.md index 6843798f4..0bb259d7a 100644 --- a/snippets/horizontal-and-vertical-centering.md +++ b/snippets/horizontal-and-vertical-centering.md @@ -48,3 +48,5 @@ Horizontally and vertically centers a child element within a parent element. ⚠️ Needs prefixes for full support. * https://caniuse.com/#feat=flexbox + + diff --git a/snippets/hover-underline-animation.md b/snippets/hover-underline-animation.md index 51f8d3064..d84e1429c 100644 --- a/snippets/hover-underline-animation.md +++ b/snippets/hover-underline-animation.md @@ -69,7 +69,7 @@ Creates an animated underline effect when the text is hovered over. #### Explanation 1. `display: inline-block` makes the block `p` an `inline-block` to prevent the underline from -spanning the entire parent width rather than just the content (text). + spanning the entire parent width rather than just the content (text). 2. `position: relative` on the element establishes a Cartesian positioning context for pseudo-elements. 3. `::after` defines a pseudo-element. 4. `position: absolute` takes the pseudo element out of the flow of the document and positions it in relation to the parent. @@ -77,11 +77,11 @@ spanning the entire parent width rather than just the content (text). 6. `transform: scaleX(0)` initially scales the pseudo element to 0 so it has no width and is not visible. 7. `bottom: 0` and `left: 0` position it to the bottom left of the block. 8. `transition: transform 0.25s ease-out` means changes to `transform` will be transitioned over 0.25 seconds -with an `ease-out` timing function. + with an `ease-out` timing function. 9. `transform-origin: bottom right` means the transform anchor point is positioned at the bottom right of the block. 10. `:hover::after` then uses `scaleX(1)` to transition the width to 100%, then changes the `transform-origin` -to `bottom left` so that the anchor point is reversed, allowing it transition out in the other direction when -hovered off. + to `bottom left` so that the anchor point is reversed, allowing it transition out in the other direction when + hovered off. #### Browser support @@ -89,3 +89,5 @@ hovered off. * https://caniuse.com/#feat=transforms2d * https://caniuse.com/#feat=css-transitions + + diff --git a/snippets/mouse-cursor-gradient-tracking.md b/snippets/mouse-cursor-gradient-tracking.md index 771563d03..3af06d91c 100644 --- a/snippets/mouse-cursor-gradient-tracking.md +++ b/snippets/mouse-cursor-gradient-tracking.md @@ -41,7 +41,7 @@ A hover effect where the gradient follows the mouse cursor. height: var(--size); background: radial-gradient(circle closest-side, pink, transparent); transform: translate(-50%, -50%); - transition: width .2s ease, height .2s ease; + transition: width 0.2s ease, height 0.2s ease; } .mouse-cursor-gradient-tracking:hover::before { @@ -53,7 +53,7 @@ A hover effect where the gradient follows the mouse cursor. ```js var btn = document.querySelector('.mouse-cursor-gradient-tracking') -btn.onmousemove = function (e) { +btn.onmousemove = function(e) { var x = e.pageX - btn.offsetLeft var y = e.pageY - btn.offsetTop btn.style.setProperty('--x', x + 'px') @@ -131,7 +131,10 @@ var y = e.pageY - btn.offsetTop - btn.offsetParent.offsetTop ``` #### Browser support +
    Requires JavaScript
    ⚠️ Requires JavaScript. * https://caniuse.com/#feat=css-variables + + diff --git a/snippets/overflow-scroll-gradient.md b/snippets/overflow-scroll-gradient.md index e4603cb4b..c0ffde89f 100644 --- a/snippets/overflow-scroll-gradient.md +++ b/snippets/overflow-scroll-gradient.md @@ -24,7 +24,10 @@ Adds a fading gradient to an overflowing element to better indicate there is mor bottom: 0; width: 300px; height: 25px; - background: linear-gradient(rgba(255, 255, 255, 0.001), white); /* transparent keyword is broken in Safari */ + background: linear-gradient( + rgba(255, 255, 255, 0.001), + white + ); /* transparent keyword is broken in Safari */ pointer-events: none; } .overflow-scroll-gradient__scroller { @@ -81,10 +84,10 @@ document.querySelector('.snippet-demo__overflow-scroll-gradient__scroller').inne 1. `position: relative` on the parent establishes a Cartesian positioning context for pseudo-elements. 2. `::after` defines a pseudo element. 3. `background-image: linear-gradient(...)` adds a linear gradient that fades from transparent to white -(top to bottom). + (top to bottom). 4. `position: absolute` takes the pseudo element out of the flow of the document and positions it in relation to the parent. 5. `width: 300px` matches the size of the scrolling element (which is a child of the parent that has - the pseudo element). + the pseudo element). 6. `height: 25px` is the height of the fading gradient pseudo-element, which should be kept relatively small. 7. `bottom: 0` positions the pseudo-element at the bottom of the parent. 8. `pointer-events: none` specifies that the pseudo-element cannot be a target of mouse events, allowing text behind it to still be selectable/interactive. @@ -94,3 +97,5 @@ document.querySelector('.snippet-demo__overflow-scroll-gradient__scroller').inne ✅ No caveats. * https://caniuse.com/#feat=css-gradients + + diff --git a/snippets/popout-menu.md b/snippets/popout-menu.md index 191cd92e2..859a33475 100644 --- a/snippets/popout-menu.md +++ b/snippets/popout-menu.md @@ -75,3 +75,5 @@ Reveals an interactive popout menu on hover. #### Browser support ✅ No caveats. + + diff --git a/snippets/pretty-text-underline.md b/snippets/pretty-text-underline.md index aa768666c..ba2e137c4 100644 --- a/snippets/pretty-text-underline.md +++ b/snippets/pretty-text-underline.md @@ -16,10 +16,7 @@ Natively implemented as `text-decoration-skip-ink: auto` but it has less control font-family: Arial, sans-serif; display: inline; font-size: 18px; - text-shadow: 1px 1px 0 #f5f6f9, - -1px 1px 0 #f5f6f9, - -1px -1px 0 #f5f6f9, - 1px -1px 0 #f5f6f9; + text-shadow: 1px 1px 0 #f5f6f9, -1px 1px 0 #f5f6f9, -1px -1px 0 #f5f6f9, 1px -1px 0 #f5f6f9; background-image: linear-gradient(90deg, currentColor 100%, transparent 100%); background-position: 0 0.98em; background-repeat: repeat-x; @@ -70,13 +67,13 @@ Natively implemented as `text-decoration-skip-ink: auto` but it has less control #### Explanation 1. `text-shadow: ...` has 4 values with offsets that cover a 4x4 px area to ensure the underline - has a "thick" shadow that covers the line where descenders clip it. Use a color - that matches the background. For a larger font, use a larger `px` size. + has a "thick" shadow that covers the line where descenders clip it. Use a color + that matches the background. For a larger font, use a larger `px` size. 2. `background-image: linear-gradient(...)` creates a 90deg gradient with the current - text color (`currentColor`). + text color (`currentColor`). 3. The `background-*` properties size the gradient as 1x1px at the bottom and repeats it along the x-axis. 4. The `::selection` pseudo selector ensures the text shadow does not interfere with text - selection. + selection. #### Browser support @@ -84,3 +81,5 @@ Natively implemented as `text-decoration-skip-ink: auto` but it has less control * https://caniuse.com/#feat=css-textshadow * https://caniuse.com/#feat=css-gradients + + diff --git a/snippets/shape-separator.md b/snippets/shape-separator.md index a0a5479e4..ed268abb5 100644 --- a/snippets/shape-separator.md +++ b/snippets/shape-separator.md @@ -64,3 +64,5 @@ Uses an SVG shape to separate two different blocks to create more a interesting ✅ No caveats. * https://caniuse.com/#feat=svg + + diff --git a/snippets/system-font-stack.md b/snippets/system-font-stack.md index 5b725be11..bc92b01f9 100644 --- a/snippets/system-font-stack.md +++ b/snippets/system-font-stack.md @@ -12,7 +12,8 @@ Uses the native font of the operating system to get close to a native app feel. ```css .system-font-stack { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, + Cantarell, 'Helvetica Neue', Helvetica, Arial, sans-serif; } ``` @@ -46,3 +47,5 @@ falls back to the next if it cannot find the font (on the system or defined in C #### Browser support ✅ No caveats. + + diff --git a/snippets/triangle.md b/snippets/triangle.md index b39bcf41e..5eb503bcc 100644 --- a/snippets/triangle.md +++ b/snippets/triangle.md @@ -89,3 +89,5 @@ Experiment with the `px` values to change the proportion of the triangle. #### Browser support ✅ No caveats. + + diff --git a/snippets/truncate-text.md b/snippets/truncate-text.md index 4f8024518..4781105a7 100644 --- a/snippets/truncate-text.md +++ b/snippets/truncate-text.md @@ -51,3 +51,5 @@ If the text is longer than one line, it will be truncated and end with an ellips ⚠️ Only works for single line elements. * https://caniuse.com/#feat=text-overflow + + diff --git a/src/css/components/sidebar.scss b/src/css/components/sidebar.scss index 78bd98709..536e92abb 100644 --- a/src/css/components/sidebar.scss +++ b/src/css/components/sidebar.scss @@ -35,6 +35,7 @@ max-height: 378px; margin-top: 44px; box-shadow: 0 0.25rem 0.5rem -0.1rem rgba(0, 32, 128, 0.2); + padding-bottom: 1rem; &.is-active { transform: rotateX(0); @@ -59,6 +60,16 @@ border-color: pink; } } + + &__section { + padding: 0 0.75rem; + } + + &__section-heading { + text-transform: capitalize; + color: #e3f5ff; + margin-bottom: 0.5rem; + } } @media (min-width: 992px) { diff --git a/src/css/components/snippet.scss b/src/css/components/snippet.scss index d02e323ad..787521772 100644 --- a/src/css/components/snippet.scss +++ b/src/css/components/snippet.scss @@ -14,6 +14,10 @@ margin-bottom: 1.25rem; margin-top: 0; line-height: 1.3; + + span:not(.snippet__tag) { + margin-right: 0.75rem; + } } code:not([class*='lang']) { @@ -42,16 +46,20 @@ h4 { display: inline-block; margin: 1rem 0 0.5rem; + font-size: 1.1rem; line-height: 2; - padding: 0 0.5rem; - border-radius: 3px; - font-size: 0.9rem; - text-transform: uppercase; - background: #333; - border: 1px solid #c6d6ea; - border-bottom-color: darken(#c6d6ea, 5); - background: white; - box-shadow: 0 0.25rem 0.5rem -0.1rem rgba(0, 32, 64, 0.15); + + &[data-type] { + background: #333; + padding: 0 0.5rem; + border-radius: 3px; + font-size: 0.9rem; + text-transform: uppercase; + border: 1px solid #c6d6ea; + border-bottom-color: darken(#c6d6ea, 5); + background: white; + box-shadow: 0 0.25rem 0.5rem -0.1rem rgba(0, 32, 64, 0.15); + } &[data-type='HTML'] { color: white; @@ -107,6 +115,9 @@ top: 1rem; right: 0; } + + &__tag { + } } .snippet-demo { diff --git a/src/css/components/tags.scss b/src/css/components/tags.scss new file mode 100644 index 000000000..96e266674 --- /dev/null +++ b/src/css/components/tags.scss @@ -0,0 +1,83 @@ +.tags { + position: relative; + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + margin-bottom: 1rem; + + &__tag { + display: inline-block; + position: relative; + top: -1px; + font-weight: bold; + font-size: 0.75rem; + text-transform: uppercase; + color: #8385aa; + white-space: nowrap; + border: 1px solid lighten(#8385aa, 15); + border-radius: 2px; + vertical-align: middle; + line-height: 2; + padding: 0 0.5rem; + margin-right: 0.5rem; + transition: all 0.1s ease-out; + outline: 0; + + &.is-large { + font-size: 0.95rem; + border-radius: 0.2rem; + + .feather { + top: -2px; + width: 18px; + height: 18px; + } + } + + .feather { + vertical-align: middle; + margin-right: 0.25rem; + position: relative; + top: -1px; + width: 14px; + height: 14px; + } + } + + button.tags__tag { + user-select: none; + cursor: pointer; + margin-bottom: 1rem; + margin-right: 1rem; + + &:hover { + background: #8385aa; + border-color: #8385aa; + color: white; + } + + &:focus { + box-shadow: 0 0 0 0.25rem transparentize(#8385aa, 0.5); + } + + &:active { + box-shadow: inset 0 0.1rem 0.1rem 0.1rem rgba(0, 0, 0, 0.2); + background: darken(#8385aa, 10); + border-color: darken(#8385aa, 10); + } + + &.is-active { + background: #7983ff; + border-color: #7983ff; + color: white; + + &:focus { + box-shadow: 0 0 0 0.25rem transparentize(#7983ff, 0.5); + } + } + } +} + +@media (min-width: 579px) { +} diff --git a/src/css/index.scss b/src/css/index.scss index a17bae5dc..d1b69ce68 100644 --- a/src/css/index.scss +++ b/src/css/index.scss @@ -4,3 +4,4 @@ @import './components/header.scss'; @import './components/snippet.scss'; @import './components/back-to-top-button.scss'; +@import './components/tags.scss'; diff --git a/src/html/components/back-to-top-button.html b/src/html/components/back-to-top-button.html new file mode 100644 index 000000000..b7e710382 --- /dev/null +++ b/src/html/components/back-to-top-button.html @@ -0,0 +1 @@ + diff --git a/src/html/components/footer.html b/src/html/components/footer.html new file mode 100644 index 000000000..5f6968b80 --- /dev/null +++ b/src/html/components/footer.html @@ -0,0 +1 @@ +
    diff --git a/src/html/components/header.html b/src/html/components/header.html new file mode 100644 index 000000000..6752c47cc --- /dev/null +++ b/src/html/components/header.html @@ -0,0 +1,10 @@ +
    +
    + +

    30 Seconds of CSS

    +

    + A curated collection of useful CSS snippets you can understand in 30 seconds or less. +

    + Star +
    +
    diff --git a/src/html/components/main.html b/src/html/components/main.html new file mode 100644 index 000000000..ed318e4b9 --- /dev/null +++ b/src/html/components/main.html @@ -0,0 +1,4 @@ +
    +
    +
    +
    diff --git a/src/html/components/sidebar.html b/src/html/components/sidebar.html new file mode 100644 index 000000000..b9fceb908 --- /dev/null +++ b/src/html/components/sidebar.html @@ -0,0 +1,9 @@ + diff --git a/src/html/components/tags.html b/src/html/components/tags.html new file mode 100644 index 000000000..97a84ba3e --- /dev/null +++ b/src/html/components/tags.html @@ -0,0 +1 @@ + diff --git a/src/html/index.html b/src/html/index.html new file mode 100644 index 000000000..10b35a213 --- /dev/null +++ b/src/html/index.html @@ -0,0 +1,15 @@ + + + + + + 30 Seconds of CSS + + + + + + +
    + + diff --git a/src/js/components/Menu.js b/src/js/components/Sidebar.js similarity index 52% rename from src/js/components/Menu.js rename to src/js/components/Sidebar.js index 9634c65aa..efc8747e5 100644 --- a/src/js/components/Menu.js +++ b/src/js/components/Sidebar.js @@ -1,27 +1,23 @@ -import jump from '../deps/jump' import { select, selectAll, easeOutQuint } from '../deps/utils' const menu = select('.hamburger') const links = select('.sidebar__links') +const sections = selectAll('.sidebar__section') const ACTIVE_CLASS = 'is-active' const toggle = () => { - const els = [menu, links] - els.forEach(el => el.classList.toggle(ACTIVE_CLASS)) - menu.setAttribute('aria-expanded', menu.classList.contains(ACTIVE_CLASS) ? 'true' : 'false') + if (window.innerWidth <= 991) { + const els = [menu, links] + els.forEach(el => el.classList.toggle(ACTIVE_CLASS)) + menu.setAttribute('aria-expanded', menu.classList.contains(ACTIVE_CLASS) ? 'true' : 'false') + } } menu.addEventListener('click', toggle) links.addEventListener('click', e => { - setTimeout(toggle, 40) if (e.target.classList.contains('sidebar__link')) { - e.preventDefault() - jump(e.target.getAttribute('href'), { - duration: 750, - offset: window.innerWidth <= 768 ? -64 : -32, - easing: easeOutQuint - }) + setTimeout(toggle, 100) } }) @@ -35,4 +31,13 @@ document.addEventListener('click', e => { } }) +EventHub.on('Tag.click', data => { + sections.forEach(section => { + section.style.display = 'block' + if (section.dataset.type !== data.type && data.type !== 'all') { + section.style.display = 'none' + } + }) +}) + export default { toggle } diff --git a/src/js/components/Snippet.js b/src/js/components/Snippet.js new file mode 100644 index 000000000..06457a16a --- /dev/null +++ b/src/js/components/Snippet.js @@ -0,0 +1,13 @@ +import { selectAll } from '../deps/utils' + +const snippets = selectAll('.snippet') +EventHub.on('Tag.click', data => { + snippets.forEach(snippet => { + snippet.style.display = 'block' + if (data.type === 'all') return + const tags = selectAll('.tags__tag', snippet) + if (!selectAll('.tags__tag', snippet).some(el => el.dataset.type === data.type)) { + snippet.style.display = 'none' + } + }) +}) diff --git a/src/js/components/Tag.js b/src/js/components/Tag.js new file mode 100644 index 000000000..734b2b320 --- /dev/null +++ b/src/js/components/Tag.js @@ -0,0 +1,14 @@ +import { select, selectAll, on } from '../deps/utils' + +const tagButtons = selectAll('button.tags__tag') + +const onClick = function() { + tagButtons.forEach(button => button.classList.remove('is-active')) + this.classList.add('is-active') + + EventHub.emit('Tag.click', { + type: this.dataset.type + }) +} + +tagButtons.forEach(button => on(button, 'click', onClick)) diff --git a/src/js/deps/jump.js b/src/js/deps/jump.js deleted file mode 100644 index fc77c8439..000000000 --- a/src/js/deps/jump.js +++ /dev/null @@ -1,196 +0,0 @@ -;(function(global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' - ? (module.exports = factory()) - : typeof define === 'function' && define.amd ? define(factory) : (global.Jump = factory()) -})(this, function() { - 'use strict' - - // Robert Penner's easeInOutQuad - - // find the rest of his easing functions here: http://robertpenner.com/easing/ - // find them exported for ES6 consumption here: https://github.com/jaxgeller/ez.js - - var easeInOutQuad = function easeInOutQuad(t, b, c, d) { - t /= d / 2 - if (t < 1) return c / 2 * t * t + b - t-- - return -c / 2 * (t * (t - 2) - 1) + b - } - - var _typeof = - typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' - ? function(obj) { - return typeof obj - } - : function(obj) { - return obj && - typeof Symbol === 'function' && - obj.constructor === Symbol && - obj !== Symbol.prototype - ? 'symbol' - : typeof obj - } - - var jumper = function jumper() { - // private variable cache - // no variables are created during a jump, preventing memory leaks - - var element = void 0 // element to scroll to (node) - - var start = void 0 // where scroll starts (px) - var stop = void 0 // where scroll stops (px) - - var offset = void 0 // adjustment from the stop position (px) - var easing = void 0 // easing function (function) - var a11y = void 0 // accessibility support flag (boolean) - - var distance = void 0 // distance of scroll (px) - var duration = void 0 // scroll duration (ms) - - var timeStart = void 0 // time scroll started (ms) - var timeElapsed = void 0 // time spent scrolling thus far (ms) - - var next = void 0 // next scroll position (px) - - var callback = void 0 // to call when done scrolling (function) - - // scroll position helper - - function location() { - return window.scrollY || window.pageYOffset - } - - // element offset helper - - function top(element) { - return element.getBoundingClientRect().top + start - } - - // rAF loop helper - - function loop(timeCurrent) { - // store time scroll started, if not started already - if (!timeStart) { - timeStart = timeCurrent - } - - // determine time spent scrolling so far - timeElapsed = timeCurrent - timeStart - - // calculate next scroll position - next = easing(timeElapsed, start, distance, duration) - - // scroll to it - window.scrollTo(0, next) - - // check progress - timeElapsed < duration - ? window.requestAnimationFrame(loop) // continue scroll loop - : done() // scrolling is done - } - - // scroll finished helper - - function done() { - // account for rAF time rounding inaccuracies - window.scrollTo(0, start + distance) - - // if scrolling to an element, and accessibility is enabled - if (element && a11y) { - // add tabindex indicating programmatic focus - element.setAttribute('tabindex', '-1') - - // focus the element - element.focus() - } - - // if it exists, fire the callback - if (typeof callback === 'function') { - callback() - } - - // reset time for next jump - timeStart = false - } - - // API - - function jump(target) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {} - - // resolve options, or use defaults - duration = options.duration || 1000 - offset = options.offset || 0 - callback = options.callback // "undefined" is a suitable default, and won't be called - easing = options.easing || easeInOutQuad - a11y = options.a11y || false - - // cache starting position - start = location() - - // resolve target - switch (typeof target === 'undefined' ? 'undefined' : _typeof(target)) { - // scroll from current position - case 'number': - element = undefined // no element to scroll to - a11y = false // make sure accessibility is off - stop = start + target - break - - // scroll to element (node) - // bounding rect is relative to the viewport - case 'object': - element = target - stop = top(element) - break - - // scroll to element (selector) - // bounding rect is relative to the viewport - case 'string': - element = document.querySelector(target) - stop = top(element) - break - } - - // resolve scroll distance, accounting for offset - distance = stop - start + offset - - // resolve duration - switch (_typeof(options.duration)) { - // number in ms - case 'number': - duration = options.duration - break - - // function passed the distance of the scroll - case 'function': - duration = options.duration(distance) - break - } - - // start the loop - window.requestAnimationFrame(loop) - } - - // expose only the jump method - return jump - } - - // export singleton - - var singleton = jumper() - - return (() => { - let scrolling - const end = () => (scrolling = false) - return (to, options = {}) => { - if (scrolling) return - const scrollY = window.scrollY || window.pageYOffset - if (to !== '.header') location.hash = to - scroll(0, scrollY) - scrolling = true - setTimeout(end, options.duration || 0) - return singleton(to, options) - } - })() -}) diff --git a/src/js/deps/utils.js b/src/js/deps/utils.js index bc16eef8e..ba5673286 100644 --- a/src/js/deps/utils.js +++ b/src/js/deps/utils.js @@ -1,8 +1,34 @@ -export const select = s => document.querySelector(s) -export const selectAll = s => [].slice.call(document.querySelectorAll(s)) +export const select = (s, parent = document) => parent.querySelector(s) + +export const selectAll = (s, parent = document) => [].slice.call(parent.querySelectorAll(s)) + export const scrollY = () => window.scrollY || window.pageYOffset + export const easeOutQuint = (t, b, c, d) => c * ((t = t / d - 1) * t ** 4 + 1) + b +export const on = (el, evt, fn, opts = {}) => { + const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e) + el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false) + if (opts.target) return delegatorFn +} + +export const createEventHub = () => ({ + hub: Object.create(null), + emit(event, data) { + ;(this.hub[event] || []).forEach(handler => handler(data)) + }, + on(event, handler) { + if (!this.hub[event]) this.hub[event] = [] + this.hub[event].push(handler) + }, + off(event, handler) { + const i = (this.hub[event] || []).findIndex(h => h === handler) + if (i > -1) this.hub[event].splice(i, 1) + } +}) + +window.EventHub = createEventHub() + /* * Make iOS behave normally. */ diff --git a/src/js/index.js b/src/js/index.js index dc97aae66..339f7935e 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -1,6 +1,8 @@ // Deps import 'normalize.css' import 'prismjs' +import feather from 'feather-icons' +feather.replace() // CSS import '../css/deps/prism.css' @@ -10,5 +12,7 @@ import '../css/index.scss' import './deps/polyfills' // Components -import Menu from './components/Menu' +import Sidebar from './components/Sidebar' import BackToTopButton from './components/BackToTopButton' +import Tag from './components/Tag' +import Snippet from './components/Snippet' diff --git a/utils/utils.js b/utils/utils.js index 916e04530..1ce71e567 100644 --- a/utils/utils.js +++ b/utils/utils.js @@ -1,8 +1,20 @@ +const fs = require('fs') +const { JSDOM } = require('jsdom') + exports.toKebabCase = str => str && str .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.toLowerCase()) - .join('-'); + .join('-') -exports.emptyHTML = (...els) => els.forEach(el => (el.innerHTML = '')) +exports.dom = path => { + const doc = new JSDOM(fs.readFileSync(path, 'utf8')).window.document + return path.includes('component') ? doc.body.firstElementChild : doc +} + +exports.createElement = str => { + const el = new JSDOM().window.document.createElement('div') + el.innerHTML = str + return el.firstElementChild +}