diff --git a/buttons/multi-button-pill/README.md b/buttons/multi-button-pill/README.md new file mode 100644 index 0000000..2c9ba3d --- /dev/null +++ b/buttons/multi-button-pill/README.md @@ -0,0 +1 @@ +# Multi-Button Pill diff --git a/buttons/multi-button-pill/index.html b/buttons/multi-button-pill/index.html new file mode 100644 index 0000000..74f2e82 --- /dev/null +++ b/buttons/multi-button-pill/index.html @@ -0,0 +1,29 @@ + + + + + Multi-Button Pill Challenge + + + + + +
+ + + +
+ + + + + diff --git a/buttons/multi-button-pill/script.js b/buttons/multi-button-pill/script.js new file mode 100644 index 0000000..69e521f --- /dev/null +++ b/buttons/multi-button-pill/script.js @@ -0,0 +1,17 @@ +window.onload = () => { + const buttons = document.querySelectorAll(".multi-button button"); + buttons.forEach((button, index) => { + button.addEventListener("mouseover", () => { + if (index > 0) { + const prevTooltip = buttons[index - 1].querySelector("div"); + prevTooltip.classList.remove("animate-right"); + prevTooltip.classList.add("animate-left"); + } + if (index < buttons.length - 1) { + const nextTooltip = buttons[index + 1].querySelector("div"); + nextTooltip.classList.remove("animate-left"); + nextTooltip.classList.add("animate-right"); + } + }); + }); +}; \ No newline at end of file diff --git a/buttons/multi-button-pill/style.css b/buttons/multi-button-pill/style.css new file mode 100644 index 0000000..04a8a47 --- /dev/null +++ b/buttons/multi-button-pill/style.css @@ -0,0 +1,100 @@ +@import url("https://fonts.googleapis.com/css?family=Raleway:400,500,700&display=swap"); +body { + height: 100vh; + margin: 0; + display: grid; + place-items: center; + background: rgba(205, 207, 219, 0.2); +} + +.multi-button { + padding: 8px 10px; + border-radius: 50px; + background: #fff; + border: 0.5px solid rgba(146, 152, 176, 0.4); + box-shadow: 0 0 10px rgba(146, 152, 176, 0.2), 4px 4px 10px rgba(146, 152, 176, 0.2); + cursor: default; +} +.multi-button button { + border: 0 solid transparent; + background: transparent; + padding: 10px 30px; + margin: 0 -2px; + color: #273043; + font-size: 17px; + border-radius: 12px; + cursor: pointer; + position: relative; + top: 0; + left: 0; + outline: none; + transition: background 0.2s ease-in-out; +} +.multi-button button:first-child { + border-top-left-radius: 40px; + border-bottom-left-radius: 40px; +} +.multi-button button:last-child { + border-top-right-radius: 40px; + border-bottom-right-radius: 40px; +} +.multi-button button div { + position: absolute; + top: -43px; + left: calc(50% - 40px); + width: 80px; + font-size: 13px; + color: #fff; + background: rgba(20, 25, 36, 0.7); + border-radius: 16px; + line-height: 30px; + font-family: 'Raleway', Arial, sans-serif; + text-align: center; + font-weight: 500; + letter-spacing: 1px; + box-shadow: 0 0 5px rgba(39, 48, 68, 0.3), 1px 1px 5px rgba(39, 48, 68, 0.2); + display: none; + cursor: pointer; +} +.multi-button button:hover { + background: #f0f1f4; +} +.multi-button button:hover div { + display: block; + animation: tooltip-animation-normal 0.3s ease-out forwards; +} +.multi-button button:hover div.animate-right { + animation: tooltip-animation-right 0.3s ease-out forwards; +} +.multi-button button:hover div.animate-left { + animation: tooltip-animation-left 0.3s ease-out forwards; +} +.multi-button button:active { + outline: none; + background: #d6d8e1; +} + +@keyframes tooltip-animation-right { + 0% { + transform: translateX(-75px); + } + 100% { + transform: translateX(0); + } +} +@keyframes tooltip-animation-left { + 0% { + transform: translateX(75px); + } + 100% { + transform: translateX(0); + } +} +@keyframes tooltip-animation-normal { + 0% { + transform: translateY(-20px); + } + 100% { + transform: translateY(0); + } +} \ No newline at end of file diff --git a/buttons/toggles/README.md b/buttons/toggles/README.md new file mode 100644 index 0000000..74fbf03 --- /dev/null +++ b/buttons/toggles/README.md @@ -0,0 +1,2 @@ +# 2020 Toggles + \ No newline at end of file diff --git a/buttons/toggles/index.html b/buttons/toggles/index.html new file mode 100644 index 0000000..580e196 --- /dev/null +++ b/buttons/toggles/index.html @@ -0,0 +1,67 @@ + + + + + 2020 Toggles + + + + + + + + + + + + diff --git a/buttons/toggles/style.css b/buttons/toggles/style.css new file mode 100644 index 0000000..d584b1d --- /dev/null +++ b/buttons/toggles/style.css @@ -0,0 +1,180 @@ +@supports (-webkit-appearance: none) or (-moz-appearance: none) { + input[type='checkbox'], + input[type='radio'] { + --active: #275EFE; + --active-inner: #fff; + --focus: 2px rgba(39, 94, 254, .3); + --border: #BBC1E1; + --border-hover: #275EFE; + --background: #fff; + --disabled: #F6F8FF; + --disabled-inner: #E1E6F9; + -webkit-appearance: none; + -moz-appearance: none; + height: 21px; + outline: none; + display: inline-block; + vertical-align: top; + position: relative; + margin: 0; + cursor: pointer; + border: 1px solid var(--bc, var(--border)); + background: var(--b, var(--background)); + transition: background .3s, border-color .3s, box-shadow .2s; + } + input[type='checkbox']:after, + input[type='radio']:after { + content: ''; + display: block; + left: 0; + top: 0; + position: absolute; + transition: opacity var(--d-o, 0.2s), -webkit-transform var(--d-t, 0.3s) var(--d-t-e, ease); + transition: transform var(--d-t, 0.3s) var(--d-t-e, ease), opacity var(--d-o, 0.2s); + transition: transform var(--d-t, 0.3s) var(--d-t-e, ease), opacity var(--d-o, 0.2s), -webkit-transform var(--d-t, 0.3s) var(--d-t-e, ease); + } + input[type='checkbox']:checked, + input[type='radio']:checked { + --b: var(--active); + --bc: var(--active); + --d-o: .3s; + --d-t: .6s; + --d-t-e: cubic-bezier(.2, .85, .32, 1.2); + } + input[type='checkbox']:disabled, + input[type='radio']:disabled { + --b: var(--disabled); + cursor: not-allowed; + opacity: .9; + } + input[type='checkbox']:disabled:checked, + input[type='radio']:disabled:checked { + --b: var(--disabled-inner); + --bc: var(--border); + } + input[type='checkbox']:disabled + label, + input[type='radio']:disabled + label { + cursor: not-allowed; + } + input[type='checkbox']:hover:not(:checked):not(:disabled), + input[type='radio']:hover:not(:checked):not(:disabled) { + --bc: var(--border-hover); + } + input[type='checkbox']:focus, + input[type='radio']:focus { + box-shadow: 0 0 0 var(--focus); + } + input[type='checkbox']:not(.switch), + input[type='radio']:not(.switch) { + width: 21px; + } + input[type='checkbox']:not(.switch):after, + input[type='radio']:not(.switch):after { + opacity: var(--o, 0); + } + input[type='checkbox']:not(.switch):checked, + input[type='radio']:not(.switch):checked { + --o: 1; + } + input[type='checkbox'] + label, + input[type='radio'] + label { + font-size: 14px; + line-height: 21px; + display: inline-block; + vertical-align: top; + cursor: pointer; + margin-left: 4px; + } + + input[type='checkbox']:not(.switch) { + border-radius: 7px; + } + input[type='checkbox']:not(.switch):after { + width: 5px; + height: 9px; + border: 2px solid var(--active-inner); + border-top: 0; + border-left: 0; + left: 7px; + top: 4px; + -webkit-transform: rotate(var(--r, 20deg)); + transform: rotate(var(--r, 20deg)); + } + input[type='checkbox']:not(.switch):checked { + --r: 43deg; + } + input[type='checkbox'].switch { + width: 38px; + border-radius: 11px; + } + input[type='checkbox'].switch:after { + left: 2px; + top: 2px; + border-radius: 50%; + width: 15px; + height: 15px; + background: var(--ab, var(--border)); + -webkit-transform: translateX(var(--x, 0)); + transform: translateX(var(--x, 0)); + } + input[type='checkbox'].switch:checked { + --ab: var(--active-inner); + --x: 17px; + } + input[type='checkbox'].switch:disabled:not(:checked):after { + opacity: .6; + } + + input[type='radio'] { + border-radius: 50%; + } + input[type='radio']:after { + width: 19px; + height: 19px; + border-radius: 50%; + background: var(--active-inner); + opacity: 0; + -webkit-transform: scale(var(--s, 0.7)); + transform: scale(var(--s, 0.7)); + } + input[type='radio']:checked { + --s: .5; + } +} +ul { + margin: 12px; + padding: 0; + list-style: none; + width: 100%; + max-width: 320px; +} +ul li { + margin: 16px 0; + position: relative; +} + +html { + box-sizing: border-box; +} + +* { + box-sizing: inherit; +} +*:before, *:after { + box-sizing: inherit; +} + +body { + min-height: 100vh; + font-family: 'Inter', Arial, sans-serif; + color: #8A91B4; + display: flex; + justify-content: center; + align-items: center; + background: #F6F8FF; +} +@media (max-width: 800px) { + body { + flex-direction: column; + } +} \ No newline at end of file diff --git a/cards/expanding-flex-cards/README.md b/cards/expanding-flex-cards/README.md new file mode 100644 index 0000000..ade0850 --- /dev/null +++ b/cards/expanding-flex-cards/README.md @@ -0,0 +1 @@ +# Expanding flex cards diff --git a/cards/expanding-flex-cards/index.html b/cards/expanding-flex-cards/index.html new file mode 100644 index 0000000..ec473de --- /dev/null +++ b/cards/expanding-flex-cards/index.html @@ -0,0 +1,81 @@ + + + + + Expanding flex cards + + + + + + + + +
+
+
+
+
+ +
+
+
Blonkisoaz
+
Omuke trughte a otufta
+
+
+
+
+
+
+
+ +
+
+
Oretemauw
+
Omuke trughte a otufta
+
+
+
+
+
+
+
+ +
+
+
Iteresuselle
+
Omuke trughte a otufta
+
+
+
+
+
+
+
+ +
+
+
Idiefe
+
Omuke trughte a otufta
+
+
+
+
+
+
+
+ +
+
+
Inatethi
+
Omuke trughte a otufta
+
+
+
+
+ + + + + + diff --git a/cards/expanding-flex-cards/script.js b/cards/expanding-flex-cards/script.js new file mode 100644 index 0000000..4f8eaf9 --- /dev/null +++ b/cards/expanding-flex-cards/script.js @@ -0,0 +1,5 @@ +$(".option").click(function(){ + $(".option").removeClass("active"); + $(this).addClass("active"); + +}); \ No newline at end of file diff --git a/cards/expanding-flex-cards/style.css b/cards/expanding-flex-cards/style.css new file mode 100644 index 0000000..3c4b978 --- /dev/null +++ b/cards/expanding-flex-cards/style.css @@ -0,0 +1,171 @@ +body { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + overflow: hidden; + height: 100vh; + font-family: 'Roboto', sans-serif; +} +body .credit { + position: absolute; + bottom: 20px; + left: 20px; + color: #000; +} +body .options { + display: flex; + flex-direction: row; + align-items: stretch; + overflow: hidden; + min-width: 600px; + max-width: 900px; + width: calc(100% - 100px); + height: 400px; +} +@media screen and (max-width: 718px) { + body .options { + min-width: 520px; + } + body .options .option:nth-child(5) { + display: none; + } +} +@media screen and (max-width: 638px) { + body .options { + min-width: 440px; + } + body .options .option:nth-child(4) { + display: none; + } +} +@media screen and (max-width: 558px) { + body .options { + min-width: 360px; + } + body .options .option:nth-child(3) { + display: none; + } +} +@media screen and (max-width: 478px) { + body .options { + min-width: 280px; + } + body .options .option:nth-child(2) { + display: none; + } +} +body .options .option { + position: relative; + overflow: hidden; + min-width: 60px; + margin: 10px; + background: var(--optionBackground, var(--defaultBackground, #E6E9ED)); + background-size: auto 120%; + background-position: center; + cursor: pointer; + transition: 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95); +} +body .options .option:nth-child(1) { + --defaultBackground:#ED5565; +} +body .options .option:nth-child(2) { + --defaultBackground:#FC6E51; +} +body .options .option:nth-child(3) { + --defaultBackground:#FFCE54; +} +body .options .option:nth-child(4) { + --defaultBackground:#2ECC71; +} +body .options .option:nth-child(5) { + --defaultBackground:#5D9CEC; +} +body .options .option:nth-child(6) { + --defaultBackground:#AC92EC; +} +body .options .option.active { + flex-grow: 10000; + -webkit-transform: scale(1); + transform: scale(1); + max-width: 600px; + margin: 0px; + border-radius: 40px; + background-size: auto 100%; + /*&:active { + transform:scale(0.9); + }*/ +} +body .options .option.active .shadow { + box-shadow: inset 0 -120px 120px -120px black, inset 0 -120px 120px -100px black; +} +body .options .option.active .label { + bottom: 20px; + left: 20px; +} +body .options .option.active .label .info > div { + left: 0px; + opacity: 1; +} +body .options .option:not(.active) { + flex-grow: 1; + border-radius: 30px; +} +body .options .option:not(.active) .shadow { + bottom: -40px; + box-shadow: inset 0 -120px 0px -120px black, inset 0 -120px 0px -100px black; +} +body .options .option:not(.active) .label { + bottom: 10px; + left: 10px; +} +body .options .option:not(.active) .label .info > div { + left: 20px; + opacity: 0; +} +body .options .option .shadow { + position: absolute; + bottom: 0px; + left: 0px; + right: 0px; + height: 120px; + transition: 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95); +} +body .options .option .label { + display: flex; + position: absolute; + right: 0px; + height: 40px; + transition: 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95); +} +body .options .option .label .icon { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + min-width: 40px; + max-width: 40px; + height: 40px; + border-radius: 100%; + background-color: white; + color: var(--defaultBackground); +} +body .options .option .label .info { + display: flex; + flex-direction: column; + justify-content: center; + margin-left: 10px; + color: white; + white-space: pre; +} +body .options .option .label .info > div { + position: relative; + transition: 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95), opacity 0.5s ease-out; +} +body .options .option .label .info .main { + font-weight: bold; + font-size: 1.2rem; +} +body .options .option .label .info .sub { + transition-delay: .1s; +} \ No newline at end of file diff --git a/cards/horizontal-cards-with-fade-animation/README.md b/cards/horizontal-cards-with-fade-animation/README.md new file mode 100644 index 0000000..90e1e9b --- /dev/null +++ b/cards/horizontal-cards-with-fade-animation/README.md @@ -0,0 +1,3 @@ +# Horizontal Cards with Fade Animation + +Adding fade animation to material design horizontal cards. \ No newline at end of file diff --git a/cards/horizontal-cards-with-fade-animation/index.html b/cards/horizontal-cards-with-fade-animation/index.html new file mode 100644 index 0000000..58cdb31 --- /dev/null +++ b/cards/horizontal-cards-with-fade-animation/index.html @@ -0,0 +1,80 @@ + + + + + Horizontal Cards with Fade Animation + + + + + + + +
+
+ +
+
+ +
+
+
+ San Francisco +

A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine. +

+
+ +
+
+
+ + +
+ +
+ +
+
+ New York +

A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine. +

+
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ London +

A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine. +

+
+ +
+
+
+
+ + + + + + + diff --git a/cards/horizontal-cards-with-fade-animation/script.js b/cards/horizontal-cards-with-fade-animation/script.js new file mode 100644 index 0000000..f84466d --- /dev/null +++ b/cards/horizontal-cards-with-fade-animation/script.js @@ -0,0 +1,10 @@ +$(window).scroll(function() { + $('.fadedfx').each(function(){ + var imagePos = $(this).offset().top; + + var topOfWindow = $(window).scrollTop(); + if (imagePos < topOfWindow+500) { + $(this).addClass("fadeIn"); + } + }); + }); \ No newline at end of file diff --git a/cards/horizontal-cards-with-fade-animation/style.css b/cards/horizontal-cards-with-fade-animation/style.css new file mode 100644 index 0000000..836afeb --- /dev/null +++ b/cards/horizontal-cards-with-fade-animation/style.css @@ -0,0 +1,32 @@ +.fadedfx { + background-color: #fe5652; + visibility: hidden; +} + +.fadeIn { + animation-name: fadeIn; + -webkit-animation-name: fadeIn; + animation-duration: 1.5s; + -webkit-animation-duration: 1.5s; + animation-timing-function: ease-in-out; + -webkit-animation-timing-function: ease-in-out; + visibility: visible !important; +} + +@keyframes fadeIn { + 0% { + opacity: 0.0; + } + 100% { + opacity: 1; + } +} + +@-webkit-keyframes fadeIn { + 0% { + opacity: 0.0; + } + 100% { + opacity: 1; + } +} \ No newline at end of file diff --git a/cards/react-0-2-0article-cards/README.md b/cards/react-0-2-0article-cards/README.md new file mode 100644 index 0000000..4fa7ed3 --- /dev/null +++ b/cards/react-0-2-0article-cards/README.md @@ -0,0 +1 @@ +# React 0.2.0 - Article Cards diff --git a/cards/react-0-2-0article-cards/index.html b/cards/react-0-2-0article-cards/index.html new file mode 100644 index 0000000..91c3e6e --- /dev/null +++ b/cards/react-0-2-0article-cards/index.html @@ -0,0 +1,18 @@ + + + + + React 0.2.0 - Article Cards + + + + + + +
+ + + + + + diff --git a/cards/react-0-2-0article-cards/script.js b/cards/react-0-2-0article-cards/script.js new file mode 100644 index 0000000..5ee3093 --- /dev/null +++ b/cards/react-0-2-0article-cards/script.js @@ -0,0 +1,83 @@ +/* + App + +*/ +var App = React.createClass({ displayName: "App", + getInitialState: function () { + return { + articles: { + 'article': { + "color": "FEC006", + "title": "Snow in Turkey Brings Travel Woes", + "thumbnail": "", + "category": "News", + "excerpt": "Heavy snowstorm in Turkey creates havoc as hundreds of villages left without power, and hundreds of roads closed", + "date": new Date() }, + + 'article-1': { + "color": "2196F3", + "title": "Landslide Leaving Thousands Homeless", + "thumbnail": "", + "category": "News", + "excerpt": "An aburt landslide in the Silcon Valley has left thousands homeless and on the streets.", + "date": new Date() }, + + 'article-2': { + "color": "FE5621", + "title": "Hail the size of baseballs in New York", + "thumbnail": "", + "category": "News", + "excerpt": "A rare and unexpected event occurred today as hail the size of snowball hits New York citizens.", + "date": new Date() }, + + 'article-3': { + "color": "673AB7", + "title": "Earthquake destorying San Fransisco", + "thumbnail": "", + "category": "News", + "excerpt": "A massive earthquake just hit San Fransisco leaving behind a giant crater.", + "date": new Date() } } }; + + + + }, + renderArticle: function (key) { + return ( + React.createElement("div", { className: "column" }, + React.createElement(Article, { key: key, index: key, details: this.state.articles[key] }))); + + + }, + render: function () { + return ( + React.createElement("div", { className: "app" }, + React.createElement("div", { className: "container" }, + Object.keys(this.state.articles).map(this.renderArticle)))); + + + + } }); + + +/* + Article +
+ */ +var Article = React.createClass({ displayName: "Article", + render: function () { + var details = this.props.details, + styles = { + backgroundColor: '#' + details.color }; + + + return ( + React.createElement("article", { className: "article" }, + React.createElement("h3", { className: "article__category", style: styles }, details.category), + React.createElement("h2", { className: "article__title" }, details.title), + React.createElement("p", { className: "article__excerpt" }, details.excerpt))); + + + } }); + + +ReactDOM.render(React.createElement(App, null), document.querySelector('#app')); \ No newline at end of file diff --git a/cards/react-0-2-0article-cards/style.css b/cards/react-0-2-0article-cards/style.css new file mode 100644 index 0000000..255627a --- /dev/null +++ b/cards/react-0-2-0article-cards/style.css @@ -0,0 +1,79 @@ +/* Base */ +body { + background: #F3F3F3; + padding: 20px; + font-family: "Open Sans", sans-serif; +} + +/* Container */ +.container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: 90%; + max-width: 960px; + margin: 0 auto; +} + +/* Column */ +.column { + flex-basis: 33.3333333333%; + width: 33.3333333333%; + padding: 0 10px; + box-sizing: border-box; +} +@media (max-width: 900px) { + .column { + flex-basis: 50%; + width: 50%; + } +} +@media (max-width: 600px) { + .column { + flex-basis: 100%; + width: 100%; + } +} + +/* Article (Component) */ +.article { + background: #FFF; + margin: 0 0 20px; + padding: 20px; + border-radius: 2px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: 0.3s ease; +} +.article:hover { + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 4px 8px rgba(0, 0, 0, 0.2); +} +.article:active { + box-shadow: none; + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: scale(0.98); + transform: scale(0.98); +} +.article__category { + display: inline-block; + padding: 8px 10px; + margin: 0 0 10px; + color: #FFF; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.075rem; + text-transform: uppercase; +} +.article__excerpt { + color: #666; + line-height: 1.5rem; + font-size: 0.875rem; +} +.article__title { + margin: 0 0 10px; + color: #444; + font-size: 1.25rem; + font-weight: 600; + line-height: 1.75rem; +} \ No newline at end of file diff --git a/css-effects/pixel-repulsion/README.md b/css-effects/pixel-repulsion/README.md new file mode 100644 index 0000000..d767fc7 --- /dev/null +++ b/css-effects/pixel-repulsion/README.md @@ -0,0 +1,4 @@ +# Pixel Repulsion + _A Pen created at CodePen.io. Original URL: [https://codepen.io/mendieta/pen/PowaQEm](https://codepen.io/mendieta/pen/PowaQEm). + + Image pixel manipulation and repulsion with raw HTML5 canvas made with students at Harbour.Space for module Programming Interactivity of the Interaction Design Master. \ No newline at end of file diff --git a/css-effects/pixel-repulsion/index.html b/css-effects/pixel-repulsion/index.html new file mode 100644 index 0000000..1d39548 --- /dev/null +++ b/css-effects/pixel-repulsion/index.html @@ -0,0 +1,20 @@ + + + + + Pixel Repulsion + + + + + + + + + + + + + + + diff --git a/css-effects/pixel-repulsion/script.js b/css-effects/pixel-repulsion/script.js new file mode 100644 index 0000000..f125977 --- /dev/null +++ b/css-effects/pixel-repulsion/script.js @@ -0,0 +1,152 @@ +const canvas = document.querySelector("canvas"); +const context = canvas.getContext("2d"); +const img = document.querySelector("img"); + +let built = false; +let pixels = []; +const config = { + strength: 2000, + easeFactor: 0.1, + glow: true, + stats: false, + pxSize: 15 +}; +const mousePosition = { x: 0, y: 0 }; + +function resize() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + buildPixelData(); +} + +function draw() { + context.clearRect(0, 0, canvas.width, canvas.height); + stats.begin(); + if (!built) { + this.buildPixelData(); + } + + for (let i = 0; i < pixels.length; i++) { + const pixel = pixels[i]; + const deltaX = pixel.x - mousePosition.x; + const deltaY = pixel.y - mousePosition.y; + const angle = Math.atan2(deltaY, deltaX); + let distance = + config.strength / Math.sqrt(deltaX * deltaX + deltaY * deltaY); + + if (config.glow) { + pixel.r += distance; + pixel.g += distance; + pixel.b += distance; + pixel.r += (pixel.or - pixel.r) * config.easeFactor; + pixel.g += (pixel.og - pixel.g) * config.easeFactor; + pixel.b += (pixel.ob - pixel.b) * config.easeFactor; + context.fillStyle = `rgb(${pixel.r}, ${pixel.g}, ${pixel.b})`; + } else { + context.fillStyle = `rgb(${pixel.or}, ${pixel.og}, ${pixel.ob})`; + } + + pixel.x += Math.cos(angle) * distance; + pixel.y += Math.sin(angle) * distance; + pixel.x += (pixel.ox - pixel.x) * config.easeFactor; + pixel.y += (pixel.oy - pixel.y) * config.easeFactor; + + context.beginPath(); + context.arc(pixel.x, pixel.y, pixel.size / 2, 0, Math.PI * 2); + context.fill(); + } + stats.end(); + window.requestAnimationFrame(draw); +} + +function getPixels() { + const data = context.getImageData(0, 0, img.width, img.height); + const pxs = []; + for (let x = 0; x < data.width; x += config.pxSize) { + for (let y = 0; y < data.height; y += config.pxSize) { + let index = x * 4 + y * 4 * img.width; + let alpha = data.data[index + 3]; + if (alpha > 0) { + pxs.push({ + x: canvas.width / 2 - img.width / 2 + x, + y: canvas.height / 2 - img.height / 2 + y, + ox: canvas.width / 2 - img.width / 2 + x, + oy: canvas.height / 2 - img.height / 2 + y, + size: config.pxSize, + oSize: config.pxSize, + r: data.data[index], + g: data.data[index + 1], + b: data.data[index + 2], + or: data.data[index], + og: data.data[index + 1], + ob: data.data[index + 2], + rgb: + "rgb(" + + data.data[index] + + "," + + data.data[index + 1] + + "," + + data.data[index + 2] + + ")" + }); + } + } + } + return pxs; +} + +function buildPixelData() { + if(img.width === 0 || img.height === 0){ + return; + } + context.clearRect(0, 0, canvas.width, canvas.height); + context.drawImage(img, 0, 0); + pixels = []; + pixels = getPixels(); + context.clearRect(0, 0, canvas.width, canvas.height); + if (pixels.length > 0) { + built = true; + } +} + +function buildGUI() { + const gui = new dat.GUI({ closed: true }); + gui.closed = true; + gui.add(config, "strength", 0, 7000); + gui.add(config, "easeFactor", 0.05, 0.2); + gui.add(config, "glow"); + const sizeController = gui.add(config, "pxSize", 8, 80, 1); + const statsController = gui.add(config, "stats"); + sizeController.onFinishChange(() => { + buildPixelData(); + }); + statsController.onChange(value => { + if (value) { + document.body.appendChild(stats.dom); + } else { + stats.dom.parentNode.removeChild(stats.dom); + } + }); +} + +function onMouseMove(event) { + mousePosition.x = event.clientX; + mousePosition.y = event.clientY; +} + +function touchMoveHandler(event) { + mousePosition.x = event.touches[0].clientX; + mousePosition.y = event.touches[0].clientY; +} + +const stats = new Stats(); +stats.showPanel(0); + +window.addEventListener("DOMContentLoaded", event => { + buildGUI(); + resize(); + window.addEventListener("mousemove", onMouseMove); + window.addEventListener("touchmove", touchMoveHandler); + window.addEventListener("resize", resize); + window.requestAnimationFrame(draw); +}); \ No newline at end of file diff --git a/css-effects/pixel-repulsion/style.css b/css-effects/pixel-repulsion/style.css new file mode 100644 index 0000000..3aef2af --- /dev/null +++ b/css-effects/pixel-repulsion/style.css @@ -0,0 +1,27 @@ +canvas, +body { + width: 100%; + height: 100%; + margin: 0; + background-color: black; + overflow: hidden; +} + +img { + visibility: hidden; + display: none; +} + +footer { + color: white; + position: fixed; + bottom: 0; + left: 0; + padding: 15px; + font-family: "Helvetica", "Roboto", "Sans"; +} + +footer a { + color: white; + font-family: "Helvetica", "Roboto", "Sans"; +} \ No newline at end of file diff --git a/css-effects/power-switch-css/README.md b/css-effects/power-switch-css/README.md new file mode 100644 index 0000000..94e716b --- /dev/null +++ b/css-effects/power-switch-css/README.md @@ -0,0 +1,3 @@ +# Power switch animation - Only CSS + + Simple power switch animation \ No newline at end of file diff --git a/css-effects/power-switch-css/index.html b/css-effects/power-switch-css/index.html new file mode 100644 index 0000000..cd30699 --- /dev/null +++ b/css-effects/power-switch-css/index.html @@ -0,0 +1,37 @@ + + + + + Power switch animation - Only CSS + + + + + + +
+ +
+ + + + + + + + +
+
+ + + + + + + + + + + + + diff --git a/css-effects/power-switch-css/style.css b/css-effects/power-switch-css/style.css new file mode 100644 index 0000000..a40f773 --- /dev/null +++ b/css-effects/power-switch-css/style.css @@ -0,0 +1,234 @@ +.power-switch { + --color-invert: #ffffff; + --width: 150px; + --height: 150px; + position: relative; + display: flex; + justify-content: center; + align-items: center; + width: var(--width); + height: var(--height); +} +.power-switch .button { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + position: relative; +} +.power-switch .button:after { + content: ""; + width: 100%; + height: 100%; + position: absolute; + background: radial-gradient(circle closest-side, var(--color-invert), transparent); + -webkit-filter: blur(20px); + filter: blur(20px); + opacity: 0; + transition: opacity 1s ease, -webkit-transform 1s ease; + transition: opacity 1s ease, transform 1s ease; + transition: opacity 1s ease, transform 1s ease, -webkit-transform 1s ease; + -webkit-transform: perspective(1px) translateZ(0); + transform: perspective(1px) translateZ(0); + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} +.power-switch .button .power-on, +.power-switch .button .power-off { + height: 100%; + width: 100%; + position: absolute; + z-index: 1; + fill: none; + stroke: var(--color-invert); + stroke-width: 8px; + stroke-linecap: round; + stroke-linejoin: round; +} +.power-switch .button .power-on .line, +.power-switch .button .power-off .line { + opacity: .2; +} +.power-switch .button .power-on .circle, +.power-switch .button .power-off .circle { + opacity: .2; + -webkit-transform: rotate(-58deg); + transform: rotate(-58deg); + -webkit-transform-origin: center 80px; + transform-origin: center 80px; + stroke-dasharray: 220; + stroke-dashoffset: 40; +} +.power-switch .button .power-on { + -webkit-filter: drop-shadow(0px 0px 6px rgba(255, 255, 255, 0.8)); + filter: drop-shadow(0px 0px 6px rgba(255, 255, 255, 0.8)); +} +.power-switch .button .power-on .line { + opacity: 0; + transition: opacity .3s ease 1s; +} +.power-switch .button .power-on .circle { + opacity: 1; + stroke-dashoffset: 220; + transition: stroke-dashoffset 1s ease 0s, -webkit-transform 0s ease; + transition: transform 0s ease, stroke-dashoffset 1s ease 0s; + transition: transform 0s ease, stroke-dashoffset 1s ease 0s, -webkit-transform 0s ease; +} +.power-switch input { + position: absolute; + height: 100%; + width: 100%; + z-index: 2; + cursor: pointer; + opacity: 0; +} +.power-switch input:checked + .button:after { + opacity: 0.15; + -webkit-transform: scale(2) perspective(1px) translateZ(0); + transform: scale(2) perspective(1px) translateZ(0); + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transition: opacity .5s ease, -webkit-transform .5s ease; + transition: opacity .5s ease, transform .5s ease; + transition: opacity .5s ease, transform .5s ease, -webkit-transform .5s ease; +} +.power-switch input:checked + .button .power-on, +.power-switch input:checked + .button .power-off { + -webkit-animation: click-animation .3s ease forwards; + animation: click-animation .3s ease forwards; + -webkit-transform: scale(1); + transform: scale(1); +} +.power-switch input:checked + .button .power-on .line, +.power-switch input:checked + .button .power-off .line { + -webkit-animation: line-animation .8s ease-in forwards; + animation: line-animation .8s ease-in forwards; +} +.power-switch input:checked + .button .power-on .circle, +.power-switch input:checked + .button .power-off .circle { + -webkit-transform: rotate(302deg); + transform: rotate(302deg); +} +.power-switch input:checked + .button .power-on .line { + opacity: 1; + transition: opacity .05s ease-in .55s; +} +.power-switch input:checked + .button .power-on .circle { + -webkit-transform: rotate(302deg); + transform: rotate(302deg); + stroke-dashoffset: 40; + transition: stroke-dashoffset .4s ease .2s, -webkit-transform .4s ease .2s; + transition: transform .4s ease .2s, stroke-dashoffset .4s ease .2s; + transition: transform .4s ease .2s, stroke-dashoffset .4s ease .2s, -webkit-transform .4s ease .2s; +} + +@-webkit-keyframes line-animation { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + 10% { + -webkit-transform: translateY(10px); + transform: translateY(10px); + } + 40% { + -webkit-transform: translateY(-25px); + transform: translateY(-25px); + } + 60% { + -webkit-transform: translateY(-25px); + transform: translateY(-25px); + } + 85% { + -webkit-transform: translateY(10px); + transform: translateY(10px); + } + 100% { + -webkit-transform: translateY(0px); + transform: translateY(0px); + } +} + +@keyframes line-animation { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + 10% { + -webkit-transform: translateY(10px); + transform: translateY(10px); + } + 40% { + -webkit-transform: translateY(-25px); + transform: translateY(-25px); + } + 60% { + -webkit-transform: translateY(-25px); + transform: translateY(-25px); + } + 85% { + -webkit-transform: translateY(10px); + transform: translateY(10px); + } + 100% { + -webkit-transform: translateY(0px); + transform: translateY(0px); + } +} +@-webkit-keyframes click-animation { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + 50% { + -webkit-transform: scale(0.9); + transform: scale(0.9); + } + 100% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +@keyframes click-animation { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + 50% { + -webkit-transform: scale(0.9); + transform: scale(0.9); + } + 100% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +body { + background: #1B1A23; + height: 100vh; + font: 400 16px 'Poppins', sans-serif; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +body .socials { + position: fixed; + display: block; + left: 20px; + bottom: 20px; +} +body .socials > a { + display: block; + width: 30px; + opacity: .2; + -webkit-transform: scale(var(--scale, 0.8)); + transform: scale(var(--scale, 0.8)); + transition: -webkit-transform 0.3s cubic-bezier(0.38, -0.12, 0.24, 1.91); + transition: transform 0.3s cubic-bezier(0.38, -0.12, 0.24, 1.91); + transition: transform 0.3s cubic-bezier(0.38, -0.12, 0.24, 1.91), -webkit-transform 0.3s cubic-bezier(0.38, -0.12, 0.24, 1.91); +} +body .socials > a:hover { + --scale: 1; +} \ No newline at end of file diff --git a/css-effects/rotating-text/README.md b/css-effects/rotating-text/README.md new file mode 100644 index 0000000..543d127 --- /dev/null +++ b/css-effects/rotating-text/README.md @@ -0,0 +1,3 @@ +# Rotating Text + + \ No newline at end of file diff --git a/css-effects/rotating-text/index.html b/css-effects/rotating-text/index.html new file mode 100644 index 0000000..542b973 --- /dev/null +++ b/css-effects/rotating-text/index.html @@ -0,0 +1,25 @@ + + + + + Rotating Text + + + + + +
+

CSS Animation is

+

+ awesome. + beautiful. + creative. + fabulous. + interesting. +

+
+ + + + + diff --git a/css-effects/rotating-text/script.js b/css-effects/rotating-text/script.js new file mode 100644 index 0000000..623e078 --- /dev/null +++ b/css-effects/rotating-text/script.js @@ -0,0 +1,37 @@ +"use strict"; +let words = document.querySelectorAll(".word"); +words.forEach(word => { + let letters = word.textContent.split(""); + word.textContent = ""; + letters.forEach(letter => { + let span = document.createElement("span"); + span.textContent = letter; + span.className = "letter"; + word.append(span); + }); +}); +let currentWordIndex = 0; +let maxWordIndex = words.length - 1; +words[currentWordIndex].style.opacity = "1"; +let rotateText = () => { + let currentWord = words[currentWordIndex]; + let nextWord = currentWordIndex === maxWordIndex ? words[0] : words[currentWordIndex + 1]; + // rotate out letters of current word + Array.from(currentWord.children).forEach((letter, i) => { + setTimeout(() => { + letter.className = "letter out"; + }, i * 80); + }); + // reveal and rotate in letters of next word + nextWord.style.opacity = "1"; + Array.from(nextWord.children).forEach((letter, i) => { + letter.className = "letter behind"; + setTimeout(() => { + letter.className = "letter in"; + }, 340 + i * 80); + }); + currentWordIndex = + currentWordIndex === maxWordIndex ? 0 : currentWordIndex + 1; +}; +rotateText(); +setInterval(rotateText, 4000); \ No newline at end of file diff --git a/css-effects/rotating-text/style.css b/css-effects/rotating-text/style.css new file mode 100644 index 0000000..2a93c07 --- /dev/null +++ b/css-effects/rotating-text/style.css @@ -0,0 +1,59 @@ +@import url(https://fonts.googleapis.com/css?family=Lato:600); +body { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background: #222; +} + +.rotating-text { + font-family: Lato, sans-serif; + font-weight: 600; + font-size: 36px; + color: white; + transform: translateX(-80px); +} +.rotating-text p { + display: inline-flex; + margin: 0; + vertical-align: top; +} +.rotating-text p .word { + position: absolute; + display: flex; + opacity: 0; +} +.rotating-text p .word .letter { + transform-origin: center center 25px; +} +.rotating-text p .word .letter.out { + transform: rotateX(90deg); + transition: 0.32s cubic-bezier(0.6, 0, 0.7, 0.2); +} +.rotating-text p .word .letter.in { + transition: 0.38s ease; +} +.rotating-text p .word .letter.behind { + transform: rotateX(-90deg); +} + +.alizarin { + color: #e74c3c; +} + +.wisteria { + color: #8e44ad; +} + +.peter-river { + color: #3498db; +} + +.emerald { + color: #2ecc71; +} + +.sun-flower { + color: #f1c40f; +} \ No newline at end of file diff --git a/forms/contact-form-blackboard/README.md b/forms/contact-form-blackboard/README.md new file mode 100644 index 0000000..830b96a --- /dev/null +++ b/forms/contact-form-blackboard/README.md @@ -0,0 +1 @@ +# Blackboard Contact Form diff --git a/forms/contact-form-blackboard/index.html b/forms/contact-form-blackboard/index.html new file mode 100644 index 0000000..ec5ee9f --- /dev/null +++ b/forms/contact-form-blackboard/index.html @@ -0,0 +1,46 @@ + + + + + Blackboard Contact Form + + + + + + + +
+
+
+

+ + +

+

+ + +

+

+ + +

+

+ + +

+

+ + +

+

+ +

+
+
+
+ + + + + diff --git a/forms/contact-form-blackboard/style.css b/forms/contact-form-blackboard/style.css new file mode 100644 index 0000000..187854b --- /dev/null +++ b/forms/contact-form-blackboard/style.css @@ -0,0 +1,108 @@ +body { + height: 100%; + background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/50598/concrete-wall-background.jpg) center center fixed; + background-size: cover; +} + +.shade { + overflow: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background-image: linear-gradient( 150deg, rgba(0, 0, 0, 0.65), transparent); +} + +.blackboard { + position: relative; + width: 640px; + margin: 7% auto; + border: tan solid 12px; + border-top: #bda27e solid 12px; + border-left: #b19876 solid 12px; + border-bottom: #c9ad86 solid 12px; + box-shadow: 0px 0px 6px 5px rgba(58, 18, 13, 0), 0px 0px 0px 2px #c2a782, 0px 0px 0px 4px #a58e6f, 3px 4px 8px 5px rgba(0, 0, 0, 0.5); + background-image: radial-gradient( circle at left 30%, rgba(34, 34, 34, 0.3), rgba(34, 34, 34, 0.3) 80px, rgba(34, 34, 34, 0.5) 100px, rgba(51, 51, 51, 0.5) 160px, rgba(51, 51, 51, 0.5)), linear-gradient( 215deg, transparent, transparent 100px, #222 260px, #222 320px, transparent), radial-gradient( circle at right, #111, rgba(51, 51, 51, 1)); + background-color: #333; +} + +.blackboard:before { + box-sizing: border-box; + display: block; + position: absolute; + width: 100%; + height: 100%; + background-image: linear-gradient( 175deg, transparent, transparent 40px, rgba(120, 120, 120, 0.1) 100px, rgba(120, 120, 120, 0.1) 110px, transparent 220px, transparent), linear-gradient( 200deg, transparent 80%, rgba(50, 50, 50, 0.3)), radial-gradient( ellipse at right bottom, transparent, transparent 200px, rgba(80, 80, 80, 0.1) 260px, rgba(80, 80, 80, 0.1) 320px, transparent 400px, transparent); + border: #2c2c2c solid 2px; + content: "Contact Us"; + font-family: 'Permanent Marker', cursive; + font-size: 2.2em; + color: rgba(238, 238, 238, 0.7); + text-align: center; + padding-top: 20px; +} + +.form { + padding: 70px 20px 20px; +} + +p { + position: relative; + margin-bottom: 1em; +} + +label { + vertical-align: middle; + font-family: 'Permanent Marker', cursive; + font-size: 1.6em; + color: rgba(238, 238, 238, 0.7); +} + +p:nth-of-type(5) > label { + vertical-align: top; +} + +input, +textarea { + vertical-align: middle; + padding-left: 10px; + background: none; + border: none; + font-family: 'Permanent Marker', cursive; + font-size: 1.6em; + color: rgba(238, 238, 238, 0.8); + line-height: .6em; + outline: none; +} + +textarea { + height: 120px; + font-size: 1.4em; + line-height: 1em; + resize: none; +} + +input[type="submit"] { + cursor: pointer; + color: rgba(238, 238, 238, 0.7); + line-height: 1em; + padding: 0; +} + +input[type="submit"]:focus { + background: rgba(238, 238, 238, 0.2); + color: rgba(238, 238, 238, 0.2); +} + +::-moz-selection { + background: rgba(238, 238, 238, 0.2); + color: rgba(238, 238, 238, 0.2); + text-shadow: none; +} + +::selection { + background: rgba(238, 238, 238, 0.4); + color: rgba(238, 238, 238, 0.3); + text-shadow: none; +} \ No newline at end of file diff --git a/template-basic-login-form/index.html b/forms/login-form-basic/index.html similarity index 100% rename from template-basic-login-form/index.html rename to forms/login-form-basic/index.html diff --git a/template-basic-login-form/style.css b/forms/login-form-basic/style.css similarity index 100% rename from template-basic-login-form/style.css rename to forms/login-form-basic/style.css diff --git a/forms/login-form-modern/README.md b/forms/login-form-modern/README.md new file mode 100644 index 0000000..931bb33 --- /dev/null +++ b/forms/login-form-modern/README.md @@ -0,0 +1 @@ +# Login Form diff --git a/forms/login-form-modern/index.html b/forms/login-form-modern/index.html new file mode 100644 index 0000000..61d15d0 --- /dev/null +++ b/forms/login-form-modern/index.html @@ -0,0 +1,36 @@ + + + + + Login Form + + + + + + + +Forgot password? + + + diff --git a/forms/login-form-modern/style.css b/forms/login-form-modern/style.css new file mode 100644 index 0000000..bb31688 --- /dev/null +++ b/forms/login-form-modern/style.css @@ -0,0 +1,126 @@ +* { + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +html, body { + height: 100%; +} + +body { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + position: relative; + background: linear-gradient(135deg, rgba(36, 46, 77, 0.9), rgba(137, 126, 121, 0.9)); + font-family: 'Roboto', helvetica, arial, sans-serif; + font-size: 1.5em; +} +body:before { + content: ''; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOMzt/XWRWAz5GuSBIkwG1H3FabJ2OsUOUhGC6tK4EMtJO0ttC6IBD3kM0ve0tJwMdSfjZo+EEISaeTr9P3wYrGjXqyC1krcKdhMpxEnt5JetoulscpyzhXN5FRpuPHvbeQaKxFAEB6EN+cYN6xD7RYGpXpNndMmZgM5Dcs3YSNFDHUo2LGfZuukSWyUYirJAdYbF3MfqEKmjM+I2EfhA94iG3L7uKrR+GdWD73ydlIB+6hgref1QTlmgmbM3/LeX5GI1Ux1RWpgxpLuZ2+I+IjzZ8wqE4nilvQdkUdfhzI5QDWy+kw5Wgg2pGpeEVeCCA7b85BO3F9DzxB3cdqvBzWcmzbyMiqhzuYqtHRVG2y4x+KOlnyqla8AoWWpuBoYRxzXrfKuILl6SfiWCbjxoZJUaCBj1CjH7GIaDbc9kqBY3W/Rgjda1iqQcOJu2WW+76pZC9QG7M00dffe9hNnseupFL53r8F7YHSwJWUKP2q+k7RdsxyOB11n0xtOvnW4irMMFNV4H0uqwS5ExsmP9AxbDTc9JwgneAT5vTiUSm1E7BSflSt3bfa1tv8Di3R8n3Af7MNWzs49hmauE2wP+ttrq+AsWpFG2awvsuOqbipWHgtuvuaAE+A1Z/7gC9hesnr+7wqCwG8c5yAg3AL1fm8T9AZtp/bbJGwl1pNrE7RuOX7PeMRUERVaPpEs+yqeoSmuOlokqw49pgomjLeh7icHNlG19yjs6XXOMedYm5xH2YxpV2tc0Ro2jJfxC50ApuxGob7lMsxfTbeUv07TyYxpeLucEH1gNd4IKH2LAg5TdVhlCafZvpskfncCfx8pOhJzd76bJWeYFnFciwcYfubRc12Ip/ppIhA1/mSZ/RxjFDrJC5xifFjJpY2Xl5zXdguFqYyTR1zSp1Y9p+tktDYYSNflcxI0iyO4TPBdlRcpeqjK/piF5bklq77VSEaA+z8qmJTFzIWiitbnzR794USKBUaT0NTEsVjZqLaFVqJoPN9ODG70IPbfBHKK+/q/AWR0tJzYHRULOa4MP+W/HfGadZUbfw177G7j/OGbIs8TahLyynl4X4RinF793Oz+BU0saXtUHrVBFT/DnA3ctNPoGbs4hRIjTok8i+algT1lTHi4SxFvONKNrgQFAq2/gFnWMXgwffgYMJpiKYkmW3tTg3ZQ9Jq+f8XN+A5eeUKHWvJWJ2sgJ1Sop+wwhqFVijqWaJhwtD8MNlSBeWNNWTa5Z5kPZw5+LbVT99wqTdx29lMUH4OIG/D86ruKEauBjvH5xy6um/Sfj7ei6UUVk4AIl3MyD4MSSTOFgSwsH/QJWaQ5as7ZcmgBZkzjjU1UrQ74ci1gWBCSGHtuV1H2mhSnO3Wp/3fEV5a+4wz//6qy8JxjZsmxxy5+4w9CDNJY09T072iKG0EnOS0arEYgXqYnXcYHwjTtUNAcMelOd4xpkoqiTYICWFq0JSiPfPDQdnt+4/wuqcXY47QILbgAAAABJRU5ErkJggg==); + opacity: .3; +} + +.login-form { + width: 100%; + padding: 2em; + position: relative; + background: rgba(0, 0, 0, 0.15); +} +.login-form:before { + content: ''; + position: absolute; + top: -2px; + left: 0; + height: 2px; + width: 100%; + background: linear-gradient(to right, #35c3c1, #00d6b7); +} +@media screen and (min-width: 600px) { + .login-form { + width: 50vw; + max-width: 15em; + } +} + +.flex-row { + display: flex; + margin-bottom: 1em; +} + +.lf--label { + width: 2em; + display: flex; + align-items: center; + justify-content: center; + background: #f5f6f8; + cursor: pointer; +} + +.lf--input { + flex: 1; + padding: 1em; + border: 0; + color: #8f8f8f; + font-size: 1rem; +} +.lf--input:focus { + outline: none; + transition: -webkit-transform .15s ease; + transition: transform .15s ease; + transition: transform .15s ease, -webkit-transform .15s ease; + -webkit-transform: scale(1.1); + transform: scale(1.1); +} + +.lf--submit { + display: block; + padding: 1em; + width: 100%; + background: linear-gradient(to right, #35c3c1, #00d6b7); + border: 0; + color: #fff; + cursor: pointer; + font-size: .75em; + font-weight: 600; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); +} +.lf--submit:focus { + outline: none; + transition: -webkit-transform .15s ease; + transition: transform .15s ease; + transition: transform .15s ease, -webkit-transform .15s ease; + -webkit-transform: scale(1.1); + transform: scale(1.1); +} + +.lf--forgot { + margin-top: 1em; + color: #00d6b7; + font-size: .65em; + text-align: center; + position: relative; +} + +::-webkit-input-placeholder { + color: #8f8f8f; +} + +:-ms-input-placeholder { + color: #8f8f8f; +} + +::-ms-input-placeholder { + color: #8f8f8f; +} + +::placeholder { + color: #8f8f8f; +} \ No newline at end of file diff --git a/forms/login-form-redhat/README.md b/forms/login-form-redhat/README.md new file mode 100644 index 0000000..9b9604d --- /dev/null +++ b/forms/login-form-redhat/README.md @@ -0,0 +1,4 @@ +# Less annoying form + _A Pen created at CodePen.io. Original URL: [https://codepen.io/andyfitz/pen/eYmKNEx](https://codepen.io/andyfitz/pen/eYmKNEx). + + \ No newline at end of file diff --git a/forms/login-form-redhat/index.html b/forms/login-form-redhat/index.html new file mode 100644 index 0000000..d96ffc4 --- /dev/null +++ b/forms/login-form-redhat/index.html @@ -0,0 +1,121 @@ + + + + + + Red Hat Sign-In + + + + + + + + + + + + + +
+ + + + + + + + Red Hat ID + + + + + PIN + Token + + + + + + +NOTE: You must close your browser or clear your cookies to completely log out. + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/forms/login-form-redhat/style.css b/forms/login-form-redhat/style.css new file mode 100644 index 0000000..d1cd6c6 --- /dev/null +++ b/forms/login-form-redhat/style.css @@ -0,0 +1,504 @@ +:root { + font-size: 1.25rem; + user-select: none; +} + +:root { + font-family: "Red Hat Text", sans-serif; + --brand: #e00; + --bg: #fff; + --fg: #000811; + --mid: #999; + outline: none; +} + +*, :before, :after { + box-sizing: border-box; + outline: 0; +} + +body { + background-color: var(--bg); + background-color: #fafafa; + color: var(--fg); + overscroll-behavior: none; + /* display: flex;*/ + flex-direction: column; + overflow: hidden; + width: 100vw; + height: 100vh; + text-align: center; + display: flex; +} + +@media (prefers-color-scheme: dark) { + :root { + --bg: #050505; + --fg: #ddd; + --mid: #555; + } + + body { + background-color: #050505; + } + + #band { + fill: transparent; + } + + form:before { + opacity: 0.2 !important; + } +} +body::before, +body::after { + content: ""; + /* flex: 1; */ +} + +form { + position: relative; + display: block; + border-radius: 0.4rem; + box-shadow: 0 0.5rem 0.75rem -0.75rem rgba(0, 0, 0, 0.5); + width: 20rem; + margin: 0 auto; + min-height: 4rem; +} + +form:before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--mid); + opacity: 0.085; + z-index: 0; + border-radius: 0.4rem; +} + +/* BEGIN GHETTO RESET */ +*, +*:before, +*:after { + box-sizing: border-box; + padding: 0; + appearance: none; + font-size: 1rem; + font-weight: 300; + font-family: "Red Hat Text", sans-serif; + border: 0; + box-shadow: 0; + pointer-events: none; + text-rendering: optimizelegibility; +} + +input { + appearance: none; + pointer-events: all; + color: currentcolor; + cursor: pointer; + box-shadow: none; + outline: 0 !important; +} + +small { + color: var(--mid); + z-index: 1; +} + +:valid + label, +:focus + label { + z-index: 4; + transform-origin: 2.5rem 0; + animation: rise 0.45s ease-out forwards; + transform: scale(0.75) translate(0, -1rem); +} + +@keyframes rise { + 0% { + transform: scale(1) translate(0, -0.5rem); + color: currentcolor; + opacity: 0; + } + 100% { + transform: scale(0.75) translate(0, -1rem); + } +} +:valid + label { + color: var(--mid); +} + +:focus + label { + color: var(--brand); +} + +:focus { + outline: 0; +} + +::selection { + color: #fff; + background: rgba(238, 0, 0, 0.99); +} + +::-moz-focus-inner { + border: 0; + outline: 0; +} + +label { + font-weight: 400; + color: var(--mid); +} + +input, +label, +svg, +small { + width: 10rem; + height: 4rem; + line-height: 4.5rem; + position: absolute; + padding: 0; + display: block; + margin: 0 auto; + text-indent: 0; + text-align: left; +} + +/* END GHETTO RESET */ +[type="submit"] { + background-color: var(--brand); + color: #fff; + border-radius: 0 0 0.4rem 0.4rem; + text-align: center; + background-image: linear-gradient(#f00, #c00); + line-height: 4rem; + width: 100%; + position: relative; + display: block; + transition: all 0.24s ease; + overflow: hidden; + position: absolute; + bottom: -4rem; +} + +[type="submit"]:after { + content: ""; + display: block; + position: absolute; + height: 4rem; + top: 0; + left: 50%; + margin-left: -4rem; + transform: skew(-45deg) translate(-200%, 0); + background-color: #f00; + width: 8rem; + transition: all .5s ease; +} + +[type="submit"]:focus:after { + transform: skew(-45deg) translate(200%, 0); + opacity: 0; +} + +/*hide submit button until fields have input*/ +:not(:valid) ~ [type="submit"] { + opacity: 0; + transform: translate(0, 0.3rem); + z-index: 0; +} + +:valid ~ :valid ~ [type="submit"] { + height: 4rem; + margin-top: 4rem; + opacity: 1; + transform: translate(0, -0.1rem); + box-shadow: 0 0.5rem 0.5rem -0.5rem rgba(0, 0, 0, 0.3); + transition: all 0.5s cubic-bezier(0.3, 0.2, 0.2, 1); +} + +[type="submit"]:focus { + box-shadow: 0 0.5rem 0.5rem -0.5rem rgba(0, 0, 0, 0.3) !important; +} + +.note { + position: fixed; + bottom: 1em; + left: 0; + color: var(--mid); + width: 100%; + font-size: 0.5em; + z-index: -1; +} + +small { + opacity: 0; + font-weight: 200; +} + +:focus:not(:valid) + label + small { + opacity: 0.5; + transition: opacity 1s ease 1s; +} + +label, +small { + text-indent: 2.75rem; +} + +[type="text"], +[type="password"] { + text-indent: 2.75rem; + text-align: left; + background-color: transparent; + line-height: 4rem; + padding-top: 0.5rem; + top: 0; + /* +background-image: linear-gradient(145deg, transparent, rgba(0,0,0,0.035) );*/ +} + +[type="text"] { + border-radius: 0 0 0; +} + +[type="text"]:focus, +[type="password"]:focus { + /* box-shadow: 0 -.15rem var(--brand);*/ + transition: box-shadow 0.4s ease; + background-image: none; + background-color: var(--bg); + box-shadow: 0 0.5rem 0.5rem -0.4rem rgba(0, 0, 0, 0.4); +} + +[type="password"], +[type="password"] + label, +[type="password"] + label + small { + right: 0; +} + +[type="password"] + label + small + svg { + left: 10.75rem; +} + +/* +Portrait mode for phones and sidebars +*/ +@media screen and (max-width: 440px) { + :root { + font-size: 1rem; + } + + form { + min-height: 8rem; + width: 10rem; + } + + [type="submit"] { + margin-top: 4rem; + position: relative; + height: 3rem; + line-height: 3rem; + } + + :valid ~ :valid ~ [type="submit"] { + height: 3rem; + line-height: 3rem; + } + + [type="text"]:focus, + [type="password"]:focus { + box-shadow: 0 0.1em 0 var(--brand); + z-index: 3; + } + + [type="password"], + [type="password"] + label, + [type="password"] + label + small, + [type="password"] + label + small + svg { + top: 4rem; + } + + [viewbox="0 0 10 10"] { + left: 0.25rem; + } + + [type="password"] + label + small + svg { + left: 0.25rem; + top: 5.5rem; + } +} +@media (min-width: 300px) and (orientation: landscape) { + .hbox { + display: block !important; + width: 100%; + height: 4rem; + top: 0; + fill: none; + stroke-width: 1; + stroke: var(--mid); + stroke-dasharray: 0 468; + stroke-dashoffset: -96; + transition: all 0.5s ease; + } + + [type="text"]:focus ~ .hbox, + [type="password"]:focus ~ .hbox { + stroke-dasharray: 138 334; + stroke-dashoffset: 42; + stroke: var(--brand); + } + + [type="submit"]:focus ~ .hbox { + stroke-dashoffset: -300; + } + + [type="password"]:focus ~ .hbox { + stroke-dashoffset: -96; + } + + /*field outline*/ +} +small + svg { + stroke: var(--mid); + color: var(--mid); +} + +input:focus + label + small + svg, +input:focus + label + small + svg use { + stroke: var(--brand); + color: var(--brand); +} + +.fedora { + fill: currentcolor !important; +} + +/* icons*/ +#burst { + stroke: var(--mid); +} + +#fed, +#user, +#lock, +#pad, +#burst, +[viewbox="0 0 10 10"] use { + fill: transparent; + stroke-width: 1px; +} + +#fed { + fill: currentcolor !important; +} + +input + label + small + svg { + text-align: left; + z-index: 3; + height: 1.25rem; + width: 1.25rem; + left: 0.5rem; + top: 1.5rem; +} + +.fedora { + transform: translate(0, -1.5px); + opacity: 0; +} + +.lock { + transform: translate(0, 0px); +} + +[type="password"]:valid ~ svg .lock { + transition: transform 0.5s ease; + transform: translate(0, 1.25px); +} + +input[type="text"]:valid ~ svg .fedora { + transform: translate(0, -0.7px); + transition: opacity 0.2s ease, transform 0.35s ease; + opacity: 1; +} + +svg use { + fill: none; +} + +#fed { + fill: auto !important; +} + +.logo { + width: 100%; + position: relative; + margin: 1rem auto; + width: 100%; +} + +#brim { + fill: var(--brand); +} + +#type { + fill: currentcolor; +} + +.flash { + stroke-dasharray: 1 5; + stroke-dashoffset: -4; + stroke-linecap: round; + opacity: 0; +} + +:focus + label + small + svg .flash { + stroke-dashoffset: 1; + transition: all 0.6s ease-out; + opacity: 1; + stroke-linecap: round; +} + +[type="text"] { + user-select: all; +} + +.logo { + height: 2.5rem; +} + +/*helper objects */ +.hbox { + display: none; +} + +@media (max-height: 300px) and (orientation: landscape) { + body { + overflow-y: auto; + } + + .hbox { + display: none; + } + + form .note, + form .logo { + display: none; + } +} +input:-webkit-autofill, +input:-webkit-autofill:hover, +input:-webkit-autofill:focus { + transition: background-color 50000s ease-in-out 50000s; + font-family: "Red Hat Text", sans-serif !important; + box-shadow: inset 0 0 0 10rem var(--bg); + z-index: 3; +} + +input:-webkit-autofill:hover + label + small { + display: none !important; +} \ No newline at end of file diff --git a/loading-icons/loading-animation/README.md b/loading-icons/loading-animation/README.md new file mode 100644 index 0000000..720d41a --- /dev/null +++ b/loading-icons/loading-animation/README.md @@ -0,0 +1,3 @@ +# Loading animation + +simple loading animation with SVG and CSS \ No newline at end of file diff --git a/loading-icons/loading-animation/index.html b/loading-icons/loading-animation/index.html new file mode 100644 index 0000000..468a0e8 --- /dev/null +++ b/loading-icons/loading-animation/index.html @@ -0,0 +1,33 @@ + + + + + Loading animation + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/loading-icons/loading-animation/script.js b/loading-icons/loading-animation/script.js new file mode 100644 index 0000000..a19e8e3 --- /dev/null +++ b/loading-icons/loading-animation/script.js @@ -0,0 +1,4 @@ +const bdy = document.querySelector('body'); +addEventListener('click', e => { + bdy.classList.toggle('invert'); +}); \ No newline at end of file diff --git a/loading-icons/loading-animation/style.css b/loading-icons/loading-animation/style.css new file mode 100644 index 0000000..d5336f7 --- /dev/null +++ b/loading-icons/loading-animation/style.css @@ -0,0 +1,49 @@ +body { + background: var( --background-col ); + padding: 0; + margin:0; + min-height:100vh; + display: flex; + justify-content:center; + align-items:center; + --foreground-col: #fff; + --background-col: #000; +} +body.invert { + --foreground-col: #000; + --background-col: #fff; +} +button { + position: absolute; + top: 10px; + right:10px; + border-radius: 50%; + width: 40px; + height: 40px; +} +svg { + width: 50vw; + +} +#outline { + fill:none; + stroke: var( --foreground-col ); + stroke-width: .1px; +} +#load { + fill: var( --foreground-col ); + stroke-width: 0px; + animation: loading 6s linear infinite; +} +#mask { + fill: var( --background-col ); + stroke-width: 0px; +} +@keyframes loading { + from { + y: 11.5px; + } + to { + y: -6px; + } +} \ No newline at end of file diff --git a/modal-bootstrap-close-current-open-new/README.md b/modal/bootstrap-close-current-open-new/README.md similarity index 100% rename from modal-bootstrap-close-current-open-new/README.md rename to modal/bootstrap-close-current-open-new/README.md diff --git a/modal-bootstrap-close-current-open-new/index.html b/modal/bootstrap-close-current-open-new/index.html similarity index 100% rename from modal-bootstrap-close-current-open-new/index.html rename to modal/bootstrap-close-current-open-new/index.html diff --git a/modal-bootstrap-close-current-open-new/style.css b/modal/bootstrap-close-current-open-new/style.css similarity index 100% rename from modal-bootstrap-close-current-open-new/style.css rename to modal/bootstrap-close-current-open-new/style.css diff --git a/modal-dialogs-angularjs-bootstrap-3/README.md b/modal/dialogs-angularjs-bootstrap-3/README.md similarity index 100% rename from modal-dialogs-angularjs-bootstrap-3/README.md rename to modal/dialogs-angularjs-bootstrap-3/README.md diff --git a/modal-dialogs-angularjs-bootstrap-3/index.html b/modal/dialogs-angularjs-bootstrap-3/index.html similarity index 100% rename from modal-dialogs-angularjs-bootstrap-3/index.html rename to modal/dialogs-angularjs-bootstrap-3/index.html diff --git a/modal-dialogs-angularjs-bootstrap-3/script.js b/modal/dialogs-angularjs-bootstrap-3/script.js similarity index 100% rename from modal-dialogs-angularjs-bootstrap-3/script.js rename to modal/dialogs-angularjs-bootstrap-3/script.js diff --git a/modal-dialogs-angularjs-bootstrap-3/style.css b/modal/dialogs-angularjs-bootstrap-3/style.css similarity index 100% rename from modal-dialogs-angularjs-bootstrap-3/style.css rename to modal/dialogs-angularjs-bootstrap-3/style.css diff --git a/modal-pure-css/README.md b/modal/pure-css-modal/README.md similarity index 100% rename from modal-pure-css/README.md rename to modal/pure-css-modal/README.md diff --git a/modal-pure-css/image.jpg b/modal/pure-css-modal/image.jpg similarity index 100% rename from modal-pure-css/image.jpg rename to modal/pure-css-modal/image.jpg diff --git a/modal-pure-css/index.html b/modal/pure-css-modal/index.html similarity index 100% rename from modal-pure-css/index.html rename to modal/pure-css-modal/index.html diff --git a/modal-pure-css/style.css b/modal/pure-css-modal/style.css similarity index 100% rename from modal-pure-css/style.css rename to modal/pure-css-modal/style.css diff --git a/modal-responsive-design/README.md b/modal/responsive-modal-design/README.md similarity index 100% rename from modal-responsive-design/README.md rename to modal/responsive-modal-design/README.md diff --git a/modal-responsive-design/index.html b/modal/responsive-modal-design/index.html similarity index 100% rename from modal-responsive-design/index.html rename to modal/responsive-modal-design/index.html diff --git a/modal-responsive-design/script.js b/modal/responsive-modal-design/script.js similarity index 100% rename from modal-responsive-design/script.js rename to modal/responsive-modal-design/script.js diff --git a/modal-responsive-design/style.css b/modal/responsive-modal-design/style.css similarity index 100% rename from modal-responsive-design/style.css rename to modal/responsive-modal-design/style.css diff --git a/techniques/neumorphism-study-change-color-with-dot/README.md b/techniques/neumorphism-study-change-color-with-dot/README.md new file mode 100644 index 0000000..31d7dc7 --- /dev/null +++ b/techniques/neumorphism-study-change-color-with-dot/README.md @@ -0,0 +1,2 @@ +# Neumorphism study (change color with dot, best in Chrome) + \ No newline at end of file diff --git a/techniques/neumorphism-study-change-color-with-dot/index.html b/techniques/neumorphism-study-change-color-with-dot/index.html new file mode 100644 index 0000000..88e60fc --- /dev/null +++ b/techniques/neumorphism-study-change-color-with-dot/index.html @@ -0,0 +1,20 @@ + + + + + Neumorphism study (change color with dot, best in Chrome) + + + + + + + + + + + + + + + diff --git a/techniques/neumorphism-study-change-color-with-dot/script.js b/techniques/neumorphism-study-change-color-with-dot/script.js new file mode 100644 index 0000000..a24ee7b --- /dev/null +++ b/techniques/neumorphism-study-change-color-with-dot/script.js @@ -0,0 +1,6 @@ +const color = document.getElementById('color'); + +function changeColor() { + console.log(color.value); + document.body.style.setProperty('--color', color.value); +} \ No newline at end of file diff --git a/techniques/neumorphism-study-change-color-with-dot/style.css b/techniques/neumorphism-study-change-color-with-dot/style.css new file mode 100644 index 0000000..26e0ea1 --- /dev/null +++ b/techniques/neumorphism-study-change-color-with-dot/style.css @@ -0,0 +1,69 @@ +body { + --color: hsl(210deg,10%,30%); + background: var(--color); +} + +.neumorphic { + border-radius: 1rem; + background: var(--color); + -webkit-animation: 1s -.3s 1 paused opacify; + animation: 1s -.3s 1 paused opacify; + -webkit-backdrop-filter: blur(1.5rem); + backdrop-filter: blur(1.5rem); + border: 1px solid rgba(255, 255, 255, 0.2); + box-shadow: -0.25rem -0.25rem 0.5rem rgba(255, 255, 255, 0.07), 0.25rem 0.25rem 0.5rem rgba(0, 0, 0, 0.12), -0.75rem -0.75rem 1.75rem rgba(255, 255, 255, 0.07), 0.75rem 0.75rem 1.75rem rgba(0, 0, 0, 0.12), inset 8rem 8rem 8rem rgba(0, 0, 0, 0.05), inset -8rem -8rem 8rem rgba(255, 255, 255, 0.05); +} + +@-webkit-keyframes opacify { + to { + background: transparent; + } +} + +@keyframes opacify { + to { + background: transparent; + } +} +card { + position: absolute; + top: 50vh; + left: 50vw; + width: 400px; + height: 300px; + max-width: 80vw; + max-height: 80vh; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + box-sizing: border-box; + padding: .5rem; +} + +img { + position: absolute; + top: 2rem; + bottom: 2rem; + right: 2rem; + -o-object-fit: cover; + object-fit: cover; + width: calc(50vw - 2rem); + height: calc(100vh - 4rem); + box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.3); + border-radius: .2rem; +} + +input.neumorphic { + width: 1rem; + height: 1rem; + border: 0; + padding: 0; + border-radius: 50%; + display: block; + border: 1px solid rgba(255, 255, 255, 0.5); + cursor: pointer; + overflow: hidden; +} + +input[type="color"]::-webkit-color-swatch { + opacity: 0; +} \ No newline at end of file diff --git a/techniques/vanilla-js-smooth-scroll/README.md b/techniques/vanilla-js-smooth-scroll/README.md new file mode 100644 index 0000000..2faf45e --- /dev/null +++ b/techniques/vanilla-js-smooth-scroll/README.md @@ -0,0 +1,21 @@ +# Vanilla JS Smooth Scroll + + Pure JavaScript smooth to anchor scrolling +

+Easy to implement and with some great features to enhance flexibility. The script will find all the links on your site that are hash based and linking to the current file, all other links are ignored. +

+

+Clicking on a hash based link will force your website to scroll smoothly down to the area defined with either the same id or name attribute as the current hash. +

+

+Feel free to use the script with the latest version from Github +

+Changelog: + \ No newline at end of file diff --git a/techniques/vanilla-js-smooth-scroll/index.html b/techniques/vanilla-js-smooth-scroll/index.html new file mode 100644 index 0000000..5eda05f --- /dev/null +++ b/techniques/vanilla-js-smooth-scroll/index.html @@ -0,0 +1,116 @@ + + + + + Vanilla JS Smooth Scroll + + + + + + + +
+
+ Vanilla JS Smooth Scroll +
+
+
+
+ Easy to use! +
+
+
+
+ Usage: +
+    
+  let links = document.getElementsByTagName('a');
+
+  [].forEach.call(links, (el) => {
+    el.scrollToSmooth({
+      speed: 500,
+      easing: 'easeInOutQuint',
+      callback: function () { console.log('we reached it!'); },
+      fixedHeader: null
+    });
+  });
+    
+    
+
+
+
+
+

Options:

+
+
speed
+
+ Type: Number
+ Default: 400 +

+ Scroll time in milliseconds +

+
+
easing
+
+ Type: string
+ Default: linear +

+ Easing function used for scrolling.
+ Available Easings: +

    +
  • linear
  • +
  • easeInQuad
  • +
  • easeOutQuad
  • +
  • easeInOutQuad
  • +
  • easeInCubic
  • +
  • easeOutCubic
  • +
  • easeInOutCubic
  • +
  • easeInQuart
  • +
  • easeOutQuart
  • +
  • easeInOutQuart
  • +
  • easeInQuint
  • +
  • easeOutQuint
  • +
  • easeInOutQuint
  • +
  • easeInElastic
  • +
  • easeOutElastic
  • +
  • easeInOutElastic
  • +
+

+
+
callback
+
+ Type: function
+ Default: null +

+ Callback to be executed when scrolling is finished +

+
+
fixedHeader
+
+ Type: string
+ Default: null +

+ The header element
+ Example: '#fixed-header' +

+
+
+
+
+
+
+ Here we go! +
+
+ + + + + diff --git a/techniques/vanilla-js-smooth-scroll/script.js b/techniques/vanilla-js-smooth-scroll/script.js new file mode 100644 index 0000000..cebd286 --- /dev/null +++ b/techniques/vanilla-js-smooth-scroll/script.js @@ -0,0 +1,176 @@ +/** + * Vanilla JS Smooth Scroll + * Author: Bastian Fießinger + * Version: 1.0.1 + */ + +'use strict'; + +HTMLAnchorElement.prototype.scrollToSmooth = function (settings) { + + if (typeof (settings) == 'undefined') { + settings = {}; + } + + // Setup Default Settings Object + let defaults = { + speed: 400, + easing: 'linear', + callback: null, + fixedHeader: null + }; + + /** + * Merge two or more objects together. + * @param {Object} objects The objects to merge together + * @returns {Object} Merged values of defaults and settings + */ + let extend = function () { + var merged = {}; + Array.prototype.forEach.call(arguments, (obj) => { + for (var key in obj) { + if (!obj.hasOwnProperty(key)) return; + merged[key] = obj[key]; + } + }); + return merged; + }; + + // Available Easing Functions + const easings = { + linear(t) { return t; }, + easeInQuad(t) { return t * t; }, + easeOutQuad(t) { return t * (2 - t); }, + easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; }, + easeInCubic(t) { return t * t * t; }, + easeOutCubic(t) { return (--t) * t * t + 1; }, + easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; }, + easeInQuart(t) { return t * t * t * t; }, + easeOutQuart(t) { return 1 - (--t) * t * t * t; }, + easeInOutQuart(t) { return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t; }, + easeInQuint(t) { return t * t * t * t * t; }, + easeOutQuint(t) { return 1 + (--t) * t * t * t * t; }, + easeInOutQuint(t) { return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t; }, + easeInElastic: function (t) { return (.04 - .04 / t) * Math.sin(25 * t) + 1 }, + easeOutElastic: function (t) { return .04 * t / (--t) * Math.sin(25 * t) }, + easeInOutElastic: function (t) { return (t -= .5) < 0 ? (.02 + .01 / t) * Math.sin(50 * t) : (.02 - .01 / t) * Math.sin(50 * t) + 1 } + }; + + // Build the Settings Object from Defaults and user defined settings + settings = extend(defaults, settings || {}); + + const reqAnimFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + const cancelAnimFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame; + + // Get All Links with hashes based on the current URI + const findHashLinks = () => { + + // Make sure to only apply to hash links + if (this.href.indexOf(this.baseURI.replace(/\/+$/, '')) != -1 && this.href.indexOf('#') != -1 && this.hash != '') { + this.addEventListener('click', clickHandler); + } + + } + + const clickHandler = (e) => { + + // Prevent Default Behaviour of how the browser would treat the click event + e.preventDefault(); + + // Evaluate the current Target Element + const currentTargetIdSliced = this.hash.slice(1); + let currentTarget = document.getElementById(currentTargetIdSliced); + + // If no ID for the current target is present try to find an element with it's name attribute. + currentTarget = currentTarget ? currentTarget : document.querySelector('[name="' + currentTargetIdSliced + '"]'); + if (!currentTarget) return; + + const windowStartPos = window.pageYOffset; + const startTime = 'now' in window.performance ? performance.now() : new Date().getTime(); + + const docHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight); + const winHeight = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight; + const targetOffset = currentTarget.offsetTop; + let distToScroll = Math.round(docHeight - targetOffset < winHeight ? docHeight - winHeight : targetOffset); + + if (settings.fixedHeader !== null) { + + const fixedHeader = document.querySelector(settings.fixedHeader); + if (fixedHeader.tagName) { + distToScroll -= Math.round(fixedHeader.getBoundingClientRect().height); + } + + } + + // Distance can't be negative + distToScroll = (distToScroll < 0) ? 0 : distToScroll; + + scrollToTarget(0, distToScroll, windowStartPos, startTime); + + } + + // Animate the ScrollTop + const scrollToTarget = (timestamp, distToScroll, startPos, startTime) => { + + const now = 'now' in window.performance ? performance.now() : new Date().getTime(); + const time = Math.min(1, ((now - startTime) / settings.speed)); + const timeFunction = easings[settings.easing](time); + let curScrollPosition = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop; + + window.scroll(0, Math.ceil((timeFunction * (distToScroll - startPos)) + startPos)); + + if (Math.ceil(curScrollPosition) === distToScroll) { + if (settings.callback) { + settings.callback(); + } + + // Stop when the element is reached + return; + } + + let scrollAnimationFrame = reqAnimFrame((timestamp) => { + scrollToTarget(timestamp, distToScroll, startPos, startTime); + }); + + // Cancel Animation on User Scroll Interaction + let cancelAnimationOnEvents = ['mousewheel', 'wheel', 'touchstart']; + cancelAnimationOnEvents.forEach((ev) => { + window.addEventListener(ev, () => { + cancelAnimationFrame( scrollAnimationFrame ); + }); + }); + + } + + const BindEvents = () => { + + window.addEventListener('load', findHashLinks); + + } + + this.init = () => { + // Bind Events + BindEvents.call(this); + }; + + this.init(); + +} + +document.addEventListener('DOMContentLoaded', function () { + + let links = document.getElementsByTagName('a'); + + [].forEach.call(links, (el) => { + el.scrollToSmooth({ + speed: 500, + easing: 'easeInOutQuint', + callback: function () { console.log('we reached it!'); }, + fixedHeader: null + }); + }); + + // Init Highlight JS + hljs.initHighlightingOnLoad(); + +}); \ No newline at end of file diff --git a/techniques/vanilla-js-smooth-scroll/style.css b/techniques/vanilla-js-smooth-scroll/style.css new file mode 100644 index 0000000..6b0e053 --- /dev/null +++ b/techniques/vanilla-js-smooth-scroll/style.css @@ -0,0 +1,114 @@ +@import url("https://fonts.googleapis.com/css?family=Montserrat:400,900&display=swap"); +* { + box-sizing: border-box; +} + +body { + font-family: 'Montserrat', sans-serif; +} + +nav { + position: fixed; + right: 20px; + top: 50%; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} +nav a { + font-size: 0px; + line-height: 0px; + display: block; + width: 20px; + height: 20px; + background: transparent; + border: 4px solid #FFF; + border-radius: 50%; + margin: 10px 0; + -webkit-filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5)); + filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5)); +} + +section { + width: 100%; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + color: #FFF; + padding: 5rem; +} +section#section-1 { + background-color: #e67e22; +} +section#section-2 { + background-color: #2980b9; +} +section#section-3 { + background-color: #8e44ad; +} +section#section-4 { + color: #000; +} +section#section-5 { + background-color: #c0392b; +} +section > div { + width: 80%; +} + +strong { + font-size: 80px; + text-align: center; + display: block; +} + +.hljs, code { + font-family: 'Space Mono', monospace; +} + +.hljs { + font-size: 14px; + padding: 0 26px; + border-radius: 4px; + flex: 1; + overflow: auto; + line-height: 1.6; +} + +pre { + margin: 1rem 0; + display: flex; +} + +.options dt { + margin-bottom: 10px; +} +.options dd { + line-height: 24px; + margin-left: 0; + border-bottom: 1px solid #000; + margin-bottom: 20px; +} +.options dd:last-child { + margin-bottom: 0; + border-bottom: 0; +} +.options code { + font-weight: bold; + background: #f7f7f7; + font-size: 90%; + font-weight: normal; + padding: 1px 5px; + border-radius: 2px; + color: #000; +} + +@media (max-width: 840px) { + strong { + font-size: 40px; + } + + section { + padding: 2rem; + } +} \ No newline at end of file diff --git a/template-onepage-section-navigation/README.md b/template-onepage-section-navigation/README.md new file mode 100644 index 0000000..b168d82 --- /dev/null +++ b/template-onepage-section-navigation/README.md @@ -0,0 +1,2 @@ +# Section Navigation Menu +An experiment with a navigation menu for page sections. The active anchor link updates based on the current page section as the user scrolls. When the menu overflows, it will automatically scroll an active link into view if it spills outside the viewport. \ No newline at end of file diff --git a/template-onepage-section-navigation/index.html b/template-onepage-section-navigation/index.html new file mode 100644 index 0000000..c4399ca --- /dev/null +++ b/template-onepage-section-navigation/index.html @@ -0,0 +1,84 @@ + + + + + Section Navigation Menu + + + + + + +
+

Horizontal Section Navigation

+
+ + + +
+
+

About

+

As you scroll through each section, the horizontal navigation will update its active state to the correlating anchor link. The menu overflows horizontally and allows the user to scroll left and right. If an anchor link is outside of the viewport, the menu will automatically scroll the active item into view.

+

And now... placeholder text: Lorem ipsum dolor sit amet consectetur, adipisicing elit. Consequatur corporis, placeat eaque iure ex possimus ab exercitationem atque sed culpa eos vel, ipsa porro corrupti omnis tempore, fuga quos explicabo.

+

Velit eos maxime veritatis sunt provident accusantium vitae, aperiam consectetur, laboriosam consequatur beatae quam recusandae, corporis iste laudantium illo praesentium amet ratione aliquid modi. Officia similique incidunt magni doloremque aperiam!

+

Cupiditate odio exercitationem dolorem explicabo numquam natus, cum a omnis incidunt ipsam quibusdam eligendi odit consectetur? Laboriosam magni labore, nobis, facilis aliquid delectus ad molestiae quo iusto a, consectetur molestias?

+

Minus ratione quae, quibusdam ab atque obcaecati. Necessitatibus perferendis quibusdam, placeat ipsa expedita recusandae culpa labore? Aut quaerat animi culpa minima illo, odio tempore corporis, quidem nisi eius iure fugit! Id, earum reprehenderit. Placeat voluptate aut, provident aspernatur consequuntur praesentium ullam, magni deserunt repellendus dicta eos odio modi aliquid quasi tempora saepe adipisci itaque? Unde distinctio aut perferendis delectus quam?

+

Lorem ipsum dolor

+
    +
  • Lorem ipsum dolor, sit amet consectetur adipisicing elit. Debitis, quasi temporibus laborum quidem praesentium et vero incidunt itaque. Hic, aliquid odio non atque exercitationem ipsa? A repudiandae dolores blanditiis voluptatem.
  • +
  • Dolore dolorem velit impedit libero non. Deserunt optio rerum earum quas recusandae. Praesentium, voluptates ipsa temporibus. Nisi, qui autem. Aliquid?
  • +
  • Ea facilis corporis enim tempora tenetur consectetur quam asperiores, porro reprehenderit expedita! Esse laboriosam suscipit illo. Quasi numquam tempora aperiam corrupti alias? Amet provident esse tenetur eveniet voluptatum modi iure.
  • +
  • Provident labore iusto, voluptatibus incidunt cumque cum quisquam, asperiores accusamus velit repellat mollitia facilis. Sit, voluptas tempore. Placeat quas, corporis enim ratione accusamus repellendus quos repellat quo voluptatum, eos rerum.
  • +
+
+
+

Documentation

+
    +
  • Lorem ipsum dolor sit, amet consectetur adipisicing elit. Aut delectus, fuga tempore, recusandae vel ut aliquam reprehenderit dolorum odio ratione unde accusantium dolore, modi mollitia sapiente ipsa autem quibusdam. Qui?
  • +
  • Iste facilis perspiciatis veritatis minima totam modi autem quaerat natus ullam at, qui similique asperiores laboriosam, voluptas quos blanditiis tempora illum et. Ea commodi facere tempora, officiis minus in odio.
  • +
  • Ratione molestias, temporibus perferendis aspernatur voluptatem optio, necessitatibus distinctio cum doloremque, deserunt cumque deleniti a quos beatae magni in ab. Ipsa libero ullam minima repellat sit molestiae, maxime accusamus dicta?
  • +
  • Ipsa dolor eveniet explicabo.
  • +
  • Molestiae nobis quasi unde rerum cum laboriosam voluptatum id dolores autem fugiat aliquam, vitae error iure. Totam nesciunt earum dolorum facilis doloremque fuga asperiores fugiat, dicta nostrum, debitis harum veritatis.
  • +
+
+
+

Showcase

+

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ea voluptatem perferendis quaerat neque voluptatibus vel unde, nostrum saepe voluptate voluptates iure veniam. Soluta possimus deserunt earum, itaque porro quam praesentium.

+

Vel itaque quae nostrum, blanditiis doloribus mollitia delectus unde rerum ab dignissimos voluptatum repellendus odit sint necessitatibus totam possimus cum voluptatem ipsa ex corrupti sit veritatis libero expedita laboriosam? Quas?

+

Illum repellendus modi at, nostrum harum iste. Natus animi corporis corrupti suscipit dicta magni distinctio a exercitationem ut. Saepe cum sequi asperiores? Quos, nemo corporis animi porro odit iure? Itaque?

+

Nesciunt in quibusdam, esse tempore sequi earum illum exercitationem praesentium reprehenderit aliquam asperiores sint impedit dolor? Sapiente, asperiores atque ipsam voluptatem molestiae repudiandae. In, optio! Quidem rem rerum perferendis pariatur.

+

Ipsam asperiores voluptas porro commodi? Consequuntur magni ipsum facere officiis fugit nesciunt itaque officia accusamus, cum tempore sed velit vero praesentium quod, hic blanditiis ducimus quis. Aperiam, sed! Deleniti, dolorum.

+
+
+

Latest News

+

Lorem ipsum dolor sit amet consectetur, adipisicing elit.

+

Atque iste repellendus accusantium vitae nam eaque dolorem consequuntur laborum impedit ex nesciunt quod, aliquid pariatur nihil dolor deserunt animi ad earum voluptatibus ullam fugit id? Ex, nihil dolorum. Corporis? Maxime nemo amet iste itaque obcaecati dolor non ea, quae hic ducimus saepe, fugiat vitae voluptatem veniam reprehenderit minima sint! Atque dolor, mollitia doloremque id reiciendis debitis vel aspernatur facilis?

+

Itaque blanditiis soluta magni obcaecati maxime iure similique esse quibusdam fuga inventore. Sapiente pariatur quas delectus rerum, repellendus fugit possimus eligendi vel sit ipsum saepe nihil, accusamus obcaecati vitae atque!

+

Quibusdam accusamus, architecto obcaecati amet quasi fuga soluta quaerat tenetur. Omnis harum eos cum sed officiis rerum dignissimos nemo. Laboriosam illum vero pariatur ea consequuntur, autem cupiditate rerum eaque iste!

+
+
+

Contact Us

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Velit provident necessitatibus laudantium, illo blanditiis inventore minima ipsam distinctio incidunt odio, itaque officiis vel facere unde. Ratione ex doloribus minus eius.

+

Quibusdam accusamus, architecto obcaecati amet quasi fuga soluta quaerat tenetur. Omnis harum eos cum sed officiis rerum dignissimos nemo. Laboriosam illum vero pariatur ea consequuntur, autem cupiditate rerum eaque iste!

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Velit provident necessitatibus laudantium, illo blanditiis inventore minima ipsam distinctio incidunt odio, itaque officiis vel facere unde. Ratione ex doloribus minus eius.

+

Quibusdam accusamus, architecto obcaecati amet quasi fuga soluta quaerat tenetur. Omnis harum eos cum sed officiis rerum dignissimos nemo. Laboriosam illum vero pariatur ea consequuntur, autem cupiditate rerum eaque iste!

+
+
+
+

Footer section

+
+ + + + + + diff --git a/template-onepage-section-navigation/script.js b/template-onepage-section-navigation/script.js new file mode 100644 index 0000000..efedf92 --- /dev/null +++ b/template-onepage-section-navigation/script.js @@ -0,0 +1,79 @@ +const sectionsContainer = document.querySelector('.page-sections'); +const sections = document.querySelectorAll('.page-section'); +const nav = document.querySelector('.nav-sections'); +const menu = nav.querySelector('.menu'); +const links = nav.querySelectorAll('.menu-item-link'); +const activeLine = nav.querySelector('.active-line'); +const sectionOffset = nav.offsetHeight + 24; +const activeClass = 'active'; +let activeIndex = 0; +let isScrolling = true; +let userScroll = true; + +const setActiveClass = () => { + links[activeIndex].classList.add(activeClass); +}; + +const removeActiveClass = () => { + links[activeIndex].classList.remove(activeClass); +}; + +const moveActiveLine = () => { + const link = links[activeIndex]; + const linkX = link.getBoundingClientRect().x; + const menuX = menu.getBoundingClientRect().x; + + activeLine.style.transform = `translateX(${menu.scrollLeft - menuX + linkX}px)`; + activeLine.style.width = `${link.offsetWidth}px`; +}; + +const setMenuLeftPosition = position => { + menu.scrollTo({ + left: position, + behavior: 'smooth' }); + +}; + +const checkMenuOverflow = () => { + const activeLink = links[activeIndex].getBoundingClientRect(); + const offset = 30; + + if (Math.floor(activeLink.right) > window.innerWidth) { + setMenuLeftPosition(menu.scrollLeft + activeLink.right - window.innerWidth + offset); + } else if (activeLink.left < 0) { + setMenuLeftPosition(menu.scrollLeft + activeLink.left - offset); + } +}; + +const handleActiveLinkUpdate = current => { + removeActiveClass(); + activeIndex = current; + checkMenuOverflow(); + setActiveClass(); + moveActiveLine(); +}; + +const init = () => { + moveActiveLine(links[0]); + document.documentElement.style.setProperty('--section-offset', sectionOffset); +}; + +links.forEach((link, index) => link.addEventListener('click', () => { + userScroll = false; + handleActiveLinkUpdate(index); +})); + +window.addEventListener("scroll", () => { + const currentIndex = sectionsContainer.getBoundingClientRect().top < 0 ? + sections.length - 1 - [...sections].reverse().findIndex(section => window.scrollY >= section.offsetTop - sectionOffset * 2) : + 0; + + if (userScroll && activeIndex !== currentIndex) { + handleActiveLinkUpdate(currentIndex); + } else { + window.clearTimeout(isScrolling); + isScrolling = setTimeout(() => userScroll = true, 100); + } +}); + +init(); \ No newline at end of file diff --git a/template-onepage-section-navigation/style.css b/template-onepage-section-navigation/style.css new file mode 100644 index 0000000..5b3180f --- /dev/null +++ b/template-onepage-section-navigation/style.css @@ -0,0 +1,141 @@ +:root { + --space: 1rem; + --border: 4px; + --page-width: 80ch; + --font-family: 'Helvetica', sans-serif; + --color-link: black; + --color-active: royalblue; + --ease: cubic-bezier(0.23, 1, 0.32, 1); + --duration: 350ms; + --section-offset: 0; +} + +* { + box-sizing: border-box; +} + +html { + --scroll-behavior: smooth; + scroll-behavior: var(--scroll-behavior); +} +@media (prefers-reduced-motion: reduce) { + html { + --scroll-behavior: auto; + } +} + +body { + font-family: var(--font-family); + line-height: 1.5; +} + +h1, h2, h3 { + font-weight: bold; + line-height: 1.25; +} + +h1 { + font-size: 2.75rem; +} + +h2 { + font-size: 2.25rem; +} + +h3 { + font-size: 1.5rem; +} + +ul:not(.menu) { + list-style-type: disc; + margin-left: var(--space); +} +ul:not(.menu) > li + li { + margin-top: var(--space); +} + +.nav-sections { + position: -webkit-sticky; + position: sticky; + top: 0; + width: 100%; + background-color: white; + box-shadow: inset lightgray 0 -1px 0, rgba(0, 0, 0, 0.15) 0 3px 10px 0; + z-index: 100; +} +.nav-sections .menu { + position: relative; + display: flex; + flex-wrap: nowrap; + overflow: scroll; + -ms-scroll-chaining: none; + overscroll-behavior: none; + scrollbar-width: none; + -ms-overflow-style: none; + margin: 0 auto; + max-width: var(--page-width); + -webkit-transform: translateZ(0); + transform: translateZ(0); + transition: -webkit-transform var(--ease) var(--duration); + transition: transform var(--ease) var(--duration); + transition: transform var(--ease) var(--duration), -webkit-transform var(--ease) var(--duration); +} +.nav-sections .menu::-webkit-scrollbar { + display: none; +} +.nav-sections .menu-item-link { + display: block; + padding: calc(var(--space) * 1.5) var(--space); + text-decoration: none; + white-space: nowrap; + color: var(--color-link); + transition: color var(--ease) var(--duration); +} +.nav-sections .menu-item-link.active { + color: var(--color-active); +} + +.active-line { + position: absolute; + bottom: 0; + left: 0; + height: 4px; + background-color: var(--color-active); + transition: width var(--ease) var(--duration), -webkit-transform var(--ease) var(--duration); + transition: width var(--ease) var(--duration), transform var(--ease) var(--duration); + transition: width var(--ease) var(--duration), transform var(--ease) var(--duration), -webkit-transform var(--ease) var(--duration); +} + +.placeholder-section { + display: flex; + align-items: center; + justify-content: center; + text-align: center; + height: 50vh; + background-color: lightgray; +} + +.page-sections { + margin: 0 auto; + max-width: var(--page-width); +} + +.page-section { + margin: calc(var(--space) * 2) 0; + padding: calc(var(--space) * 2) var(--space); +} +.page-section > * + * { + margin-top: calc(var(--space) * 1.5); +} + +.section-title { + outline: none; +} +.section-title:before { + content: ""; + display: block; + visibility: hidden; + pointer-events: none; + margin-top: calc(var(--section-offset) * -1px); + height: calc(var(--section-offset) * 1px); +} \ No newline at end of file