├── .editorconfig ├── .gitignore ├── CNAME ├── accordion ├── first-example │ ├── index.html │ └── styles.css ├── index.html ├── second-example │ ├── index.html │ └── styles.css └── styles.css ├── dark-mode-toggle ├── index.html ├── main.js └── styles.css ├── first-letter-selector ├── facebook-devil.png ├── floating-castle.png ├── index.html └── styles.css ├── material-design-tab ├── index.html ├── main.js └── styles.css └── text-glitch-animation ├── index.html ├── main.js └── styles.css /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_size = 2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | examples.yetanother.blog -------------------------------------------------------------------------------- /accordion/first-example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Accordion element with plain HTML and CSS – first example 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | What's this? 13 | It's an accordion. 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /accordion/first-example/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Sans-Serif; 3 | margin-top: 1rem; 4 | } 5 | 6 | details { 7 | max-width: 46rem; 8 | margin: 0 auto; 9 | } -------------------------------------------------------------------------------- /accordion/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Accordion element with plain HTML and CSS – final example 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | What's an accordion? 14 |
15 |
16 |
17 |

18 | An accordion is a list of headers that hide or reveal additional 19 | content when selected/opened. You may see them often on FAQ pages, 20 | where it makes it easy for users to scan the list of questions without 21 | getting distracted by answers and a lot of text, and giving them 22 | control by clicking on the questions that pertain to them. 23 |

24 |
25 |
26 |
27 | 28 | When should I use an accordion? 29 |
30 |
31 |
32 |

33 | There are 3 general principles that should be considered when using 34 | accordions: reducing cognitive load, increasing readability, and 35 | clarity. Accordions are most appropriate when users will only need a 36 | few specific pieces of content within a page or if you have only a 37 | small space to display a lot of content. 38 |

39 |
40 |
41 |
42 | 43 | Why accordions are not always a good solution? 44 |
45 |
46 |
47 |

48 | While they can make a web page easier to read, accordions should be 49 | used in moderation elements to describe situations or deliver 50 | information clearly. If users need to see most or all of the 51 | information on a page, it is better to use well-formatted text 52 | instead. 53 |

54 |
55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /accordion/second-example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Accordion element with plain HTML and CSS – second example 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | What's this? 13 | It's an accordion. 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /accordion/second-example/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Sans-Serif; 3 | margin-top: 1rem; 4 | } 5 | 6 | details { 7 | max-width: 46rem; 8 | margin: 0 auto; 9 | } -------------------------------------------------------------------------------- /accordion/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --gray-300: rgb(200, 200, 200); 3 | --grey-700: rgb(88, 88, 88); 4 | --gray-900: rgb(26, 26, 26); 5 | } 6 | 7 | :focus { 8 | outline: 0; 9 | } 10 | 11 | :focus:not([tabindex='-1']) { 12 | outline: 4px solid var(--grey-700); 13 | outline-offset: 3px; 14 | } 15 | 16 | body { 17 | font-family: Sans-Serif; 18 | margin-top: 4rem; 19 | } 20 | 21 | details { 22 | max-width: 46rem; 23 | margin: 0 auto; 24 | } 25 | 26 | details + details { 27 | margin-top: 1rem; 28 | } 29 | 30 | details { 31 | border-bottom: 2px solid var(--gray-300); 32 | } 33 | 34 | .chevron-icon { 35 | height: 48px; 36 | width: 48px; 37 | background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE1LjUgMTEuMjk5OEw5Ljg5OTk1IDUuNTk5OEM5LjQ5OTk1IDUuMTk5OCA4Ljg5OTk1IDUuMTk5OCA4LjQ5OTk1IDUuNTk5OEM4LjA5OTk1IDUuOTk5OCA4LjA5OTk1IDYuNTk5OCA4LjQ5OTk1IDYuOTk5OEwxMy40IDExLjg5OThMOC40OTk5NSAxNi43OTk4QzguMjk5OTUgMTYuOTk5OCA4LjE5OTk1IDE3LjE5OTggOC4xOTk5NSAxNy40OTk4QzguMTk5OTUgMTguMDk5OCA4LjU5OTk1IDE4LjQ5OTggOS4xOTk5NSAxOC40OTk4QzkuNDk5OTUgMTguNDk5OCA5LjY5OTk1IDE4LjM5OTggOS44OTk5NSAxOC4xOTk4TDE1LjYgMTIuNDk5OEMxNS45IDEyLjI5OTggMTUuOSAxMS42OTk4IDE1LjUgMTEuMjk5OFoiIGZpbGw9ImJsYWNrIi8+Cjwvc3ZnPgo="); 38 | background-position: center; 39 | background-repeat: no-repeat; 40 | transition: transform 150ms ease-in; 41 | } 42 | 43 | /* Access the active state with the open attribute */ 44 | details[open] .chevron-icon { 45 | transform: rotate(90deg); 46 | } 47 | 48 | .content-wrapper { 49 | padding: 1rem; 50 | } 51 | 52 | p { 53 | width: 65ch; 54 | max-width: 100%;; 55 | line-height: 1.5; 56 | } 57 | 58 | /* Get rid of the marker pseudo-element from all browser for good */ 59 | details > summary { 60 | display: flex; 61 | align-items: center; 62 | justify-content: space-between; 63 | font-size: 1.125rem; 64 | color: var(--grey-900); 65 | padding: 0.5rem 0 0.5rem 1rem; 66 | cursor: pointer; 67 | list-style: none; 68 | } 69 | 70 | details > summary::-webkit-details-marker { 71 | display: none; 72 | } -------------------------------------------------------------------------------- /dark-mode-toggle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dark Mode Toggle with CSS and JS 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /dark-mode-toggle/main.js: -------------------------------------------------------------------------------- 1 | const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)'); 2 | const toggle = document.querySelector('.toggle'); 3 | const html = document.querySelector('html'); 4 | 5 | html.dataset.dark = localStorage.dark || prefersDarkMode.matches; 6 | 7 | toggle.addEventListener('click', () => { 8 | localStorage.dark = !(html.dataset.dark == 'true'); 9 | html.dataset.dark = localStorage.dark; 10 | }); -------------------------------------------------------------------------------- /dark-mode-toggle/styles.css: -------------------------------------------------------------------------------- 1 | html { 2 | --background-color: #fcfcfc; 3 | --primary-color: #fb00ff; 4 | } 5 | 6 | html[data-dark="true"] { 7 | --background-color: #0f0f0f; 8 | } 9 | 10 | body { 11 | width: 100vw; 12 | height: 100vh; 13 | display: flex; 14 | justify-content: center; 15 | align-items: center; 16 | margin: 0; 17 | background-color: var(--background-color); 18 | } 19 | 20 | .toggle { 21 | font-family: "Source Code Pro", monospace; 22 | font-size: 20px; 23 | line-height: 1.3; 24 | color: var(--primary-color); 25 | border: 2px solid var(--primary-color); 26 | background: none; 27 | padding: 16px 30px; 28 | cursor: pointer; 29 | border-radius: 30px; 30 | transition: 200ms transform ease-in-out; 31 | } 32 | 33 | .toggle:hover { 34 | transform: scale(0.95); 35 | } 36 | -------------------------------------------------------------------------------- /first-letter-selector/facebook-devil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanother-blog/examples/5a9c3b486e988c12912e282d45a672c9cd926364/first-letter-selector/facebook-devil.png -------------------------------------------------------------------------------- /first-letter-selector/floating-castle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanother-blog/examples/5a9c3b486e988c12912e282d45a672c9cd926364/first-letter-selector/floating-castle.png -------------------------------------------------------------------------------- /first-letter-selector/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | First Letter Selector - Fairy Tale 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | floating castle with google logos on the towers 17 |

Once upon a time...

18 |

19 | That year, a computer programmer in Switzerland named Tim Berners-Lee 20 | introduced the World Wide Web: an internet that was not simply a way to 21 | send files from one place to another but was itself a “web” of 22 | information that anyone on the Internet could retrieve. Berners-Lee 23 | created the Internet that we know today. 24 |

25 |

26 | Since then, the internet has changed in many ways. In 1992, a group of 27 | students and researchers at the University of Illinois developed a 28 | sophisticated browser that they called Mosaic. (It later became 29 | Netscape.) Mosaic offered a user-friendly way to search the Web: It 30 | allowed users to see words and pictures on the same page for the first 31 | time and to navigate using scrollbars and clickable links. 32 |

33 |

34 | That same year, Congress decided that the Web could be used for 35 | commercial purposes. As a result, companies of all kinds hurried to set 36 | up websites of their own, and e-commerce entrepreneurs began to use the 37 | internet to sell goods directly to customers. More recently, social 38 | networking sites like Facebook have become a popular way for people of 39 | all ages to stay connected. 40 |

41 |

The End

42 |

(of the world wide web)

43 | facebook devil which says be evil 48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /first-letter-selector/styles.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Quintessential&family=UnifrakturMaguntia&family=Merriweather:wght@300&display=swap"); 2 | 3 | :root { 4 | --accent-color: #cf4242; 5 | --background-color: #f4f0e5; 6 | --base-font-size: 20px; 7 | --headline-font: "UnifrakturMaguntia", cursive; 8 | --copy-font: "Merriweather", serif; 9 | } 10 | 11 | body { 12 | display: flex; 13 | align-items: center; 14 | justify-content: center; 15 | margin: 0; 16 | padding: 0; 17 | background-color: var(--background-color); 18 | } 19 | 20 | .wrapper { 21 | display: grid; 22 | grid-template-columns: repeat(12, minmax(10px, 1fr)); 23 | column-gap: 10px; 24 | padding-top: 20px; 25 | } 26 | 27 | .floating-castle { 28 | grid-column: 1 / -1; 29 | width: 100%; 30 | } 31 | 32 | .facebook-devil { 33 | grid-column: 6 / 12; 34 | width: 100%; 35 | } 36 | 37 | .headline, 38 | .subline { 39 | font-size: 32px; 40 | font-family: var(--headline-font); 41 | margin-bottom: 0; 42 | padding: 0; 43 | grid-column: 2 / 12; 44 | line-height: 1; 45 | letter-spacing: 0.03em; 46 | } 47 | 48 | .subline { 49 | grid-column: 2 / 12; 50 | } 51 | 52 | .headline::first-letter { 53 | font-size: 80px; 54 | margin-right: 4px; 55 | color: var(--accent-color); 56 | vertical-align: middle; 57 | } 58 | 59 | .paragraph { 60 | font-size: var(--base-font-size); 61 | font-family: var(--copy-font); 62 | line-height: 1.6; 63 | font-weight: 500; 64 | margin-bottom: 40px; 65 | grid-column: 2 / 12; 66 | } 67 | 68 | /* desktop */ 69 | @media (min-width: 992px) { 70 | .wrapper { 71 | grid-template-columns: repeat(12, 60px); 72 | } 73 | 74 | .floating-castle { 75 | grid-column: 1 / 12; 76 | } 77 | 78 | .headline, 79 | .subline { 80 | font-size: 72px; 81 | line-height: 0.4; 82 | } 83 | 84 | .headline { 85 | grid-column: 1 / 12; 86 | } 87 | 88 | .headline::first-letter { 89 | font-size: 220px; 90 | margin-right: 18px; 91 | padding: 0 10px; 92 | } 93 | 94 | p:first-of-type { 95 | grid-column: 4 / 12; 96 | } 97 | 98 | .facebook-devil { 99 | grid-column: 8 / 12; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /material-design-tab/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Material Design Tab - vanilla JS 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /material-design-tab/main.js: -------------------------------------------------------------------------------- 1 | const ACTIVE_CLASS = 'active' 2 | const tabItems = document.querySelectorAll('.js-tab-button'); 3 | const indicator = document.querySelector('.js-tab-indicator'); 4 | const tabsMenu = document.querySelector('.js-tabs-menu'); 5 | 6 | const indicatorPosition = tabItems[0].getBoundingClientRect().left - tabsMenu.getBoundingClientRect().left; 7 | indicator.style.width = `${tabItems[0].clientWidth}px`; 8 | 9 | tabItems.forEach(tab => { 10 | tab.setAttribute('aria-selected', 'false'); 11 | tab.addEventListener('click', (e) => { 12 | handleTabSelection(e); 13 | 14 | const current = document.querySelector(`.focus`); 15 | if(current) { 16 | current.className = current.className.replace(` focus`, ''); 17 | } 18 | }) 19 | tab.addEventListener('mousedown', handleRippleEffect); 20 | tab.addEventListener('keydown', handleArrowKeysFocus); 21 | }); 22 | 23 | function handleTabSelection(e) { 24 | toggleActiveClass(e); 25 | moveTabIndicator(e); 26 | handleA11y(e); 27 | } 28 | 29 | function toggleActiveClass(e) { 30 | const current = document.querySelector(`.${ACTIVE_CLASS}`); 31 | if(current) { 32 | current.className = current.className.replace(` ${ACTIVE_CLASS}`, ''); 33 | } 34 | 35 | e.target.className += ` ${ACTIVE_CLASS}`; 36 | } 37 | 38 | function toggleFocusClass(e) { 39 | const current = document.querySelector(`.focus`); 40 | if(current) { 41 | current.className = current.className.replace(` focus`, ''); 42 | } 43 | 44 | e.currentTarget.className += ` focus`; 45 | } 46 | 47 | function moveTabIndicator(e) { 48 | const indicatorPosition = e.target.getBoundingClientRect().left - tabsMenu.getBoundingClientRect().left; 49 | indicator.style.width = `${e.target.clientWidth}px`; 50 | indicator.style.left = `${indicatorPosition}px`; 51 | } 52 | 53 | function handleRippleEffect(e) { 54 | const posX = e.target.offsetLeft; 55 | const posY = e.target.offsetTop; 56 | const span = document.createElement('span'); 57 | const x = e.pageX - e.target.getBoundingClientRect().left; 58 | const y = e.pageY - e.target.getBoundingClientRect().top; 59 | 60 | span.classList.add('tab-button__ripple'); 61 | e.target.appendChild(span); 62 | span.style.left = `${x}px`; 63 | span.style.top = `${y}px`; 64 | 65 | setTimeout(() => { 66 | span.remove(); 67 | }, 1000); 68 | } 69 | 70 | function handleA11y(e) { 71 | tabItems.forEach(tab => { 72 | const addActiveFocus = () => { 73 | e.target.setAttribute('aria-selected', 'true') 74 | e.target.setAttribute('tabindex', '0'); 75 | }; 76 | 77 | const removeActiveFocus = () => { 78 | tab.setAttribute('aria-selected', 'false'); 79 | tab.setAttribute('tabindex', '-1'); 80 | }; 81 | tab === e.target ? addActiveFocus() : removeActiveFocus(); 82 | }); 83 | } 84 | 85 | function handleArrowKeysFocus(e) { 86 | const totalTabItems = tabItems.length - 1; 87 | const leftArrowKey = e.which === 37; 88 | const rightArrowKey = e.which === 39; 89 | 90 | let index = Array.prototype.indexOf.call(tabItems, e.currentTarget); 91 | let newIndex; 92 | 93 | const decrementIndex = () => { 94 | newIndex = index - 1; 95 | 96 | if (newIndex < 0) { 97 | newIndex = totalTabItems; 98 | } 99 | } 100 | 101 | const incrementIndex = () => { 102 | newIndex = index + 1; 103 | 104 | if (newIndex > totalTabItems) { 105 | newIndex = 0; 106 | } 107 | } 108 | 109 | if (leftArrowKey) { 110 | decrementIndex(); 111 | toggleFocusClass(e); 112 | } 113 | 114 | if (rightArrowKey) { 115 | incrementIndex(); 116 | toggleFocusClass(e); 117 | } 118 | 119 | const current = document.querySelector(`.focus`); 120 | if(current) { 121 | current.className = current.className.replace(` focus`, ''); 122 | } 123 | 124 | if (tabItems[newIndex]) { 125 | tabItems[newIndex].className += ` focus`; 126 | tabItems[newIndex].focus(); 127 | } 128 | } 129 | 130 | // Initially activate the first tab 131 | tabItems[0].setAttribute('tabindex', '0'); 132 | tabItems[0].setAttribute('aria-selected', 'true'); -------------------------------------------------------------------------------- /material-design-tab/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --primary-color: #90caf9; 3 | --accent-color: #f48fb1; 4 | 5 | --grey-700-color: #423f3f; 6 | --grey-900-color: #333333; 7 | 8 | --base-spacing: 8px; 9 | --font-m: 14px; 10 | 11 | --shadow-small: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%); 12 | } 13 | 14 | body { 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | height: 100vh; 19 | margin: 0; 20 | padding: 0; 21 | background-color: var(--grey-900-color); 22 | } 23 | 24 | .tabs-box { 25 | display: flex; 26 | justify-content: center; 27 | max-width: 640px; 28 | height: 48px; 29 | width: 100%; 30 | background-color: var(--primary-color); 31 | box-shadow: var(--shadow-small); 32 | border-top-left-radius: 3px; 33 | border-top-right-radius: 3px; 34 | } 35 | 36 | .tabs-menu { 37 | display: flex; 38 | justify-content: center; 39 | position: relative; 40 | } 41 | 42 | .tab-button { 43 | display: flex; 44 | justify-content: center; 45 | align-items: center; 46 | border: none; 47 | position: relative; 48 | overflow: hidden; 49 | font-weight: 500; 50 | font-size: var(--font-m); 51 | color: var(--grey-700-color); 52 | text-transform: uppercase; 53 | letter-spacing: 0.02857em; 54 | white-space: normal; 55 | letter-spacing: 0.02857em; 56 | background-color: transparent; 57 | padding: var(--base-spacing) calc(var(--base-spacing) * 2); 58 | cursor: pointer; 59 | transition: color 250ms ease-in; 60 | } 61 | 62 | .tab-button .active { 63 | color: var(--grey-700); 64 | } 65 | 66 | .tab-button__content { 67 | display: block; 68 | pointer-events: none; 69 | } 70 | 71 | .tab-button:hover, 72 | .tab-button:focus { 73 | outline: none; 74 | color: var(--grey-700) 75 | } 76 | 77 | .tab-indicator { 78 | background-color: var(--accent-color); 79 | height: 3px; 80 | position: absolute; 81 | left: 0; 82 | bottom: 0; 83 | transition: left 250ms ease-in-out, width 650ms ease-in-out; 84 | } 85 | 86 | .tab-button__ripple { 87 | position: absolute; 88 | background-color: black; 89 | transform: translate(-50%, -50%); 90 | border-radius: 50%; 91 | animation: ripple 1000ms linear infinite; 92 | pointer-events: none; 93 | } 94 | 95 | .focus::after { 96 | content: ''; 97 | position: absolute; 98 | background-color: black; 99 | opacity: .2; 100 | border-radius: 50%; 101 | width: 80%; 102 | height: auto; 103 | padding-top: 80%; 104 | background: black; 105 | transition: transform 300ms ease-in-out; 106 | transform: scale(0); 107 | animation: focusRipple 300ms linear infinite, focusPulse 1700ms linear 300ms infinite; 108 | } 109 | 110 | @keyframes ripple { 111 | 0% { 112 | width: 0; 113 | height: 0; 114 | opacity: .4; 115 | } 116 | 117 | 100% { 118 | width: 500px; 119 | height: 500px; 120 | opacity: 0; 121 | } 122 | } 123 | 124 | @keyframes focusRipple { 125 | 0% { 126 | transform: scale(0); 127 | } 128 | 129 | 100% { 130 | transform: scale(1); 131 | } 132 | } 133 | 134 | @keyframes focusPulse { 135 | 0%, 100% { 136 | transform: scale(1); 137 | } 138 | 50% { 139 | transform: scale(1.1); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /text-glitch-animation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Text glitch animation 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

12 | Hey friend 13 | 14 | 22 | 25 | 26 | 27 |

28 | 29 | 30 | -------------------------------------------------------------------------------- /text-glitch-animation/main.js: -------------------------------------------------------------------------------- 1 | // 404 -------------------------------------------------------------------------------- /text-glitch-animation/styles.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Miriam+Libre:wght@700&display=swap"); 2 | 3 | :root { 4 | --grey-900: #101010; 5 | font-size: calc(1rem + 0.5vw); 6 | } 7 | 8 | *, 9 | ::after, 10 | ::before { 11 | font-family: inherit; 12 | font-size: inherit; 13 | color: inherit; 14 | margin: 0; 15 | padding: 0; 16 | box-sizing: border-box; 17 | } 18 | 19 | body { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | height: 100vh; 24 | background-color: var(--grey-900); 25 | font-family: "Miriam Libre", sans-serif; 26 | color: white; 27 | line-height: 1.5; 28 | } 29 | 30 | h2 { 31 | position: relative; 32 | font-size: 3rem; 33 | } 34 | 35 | .glitch__text::before { 36 | content: attr(data-text); 37 | position: absolute; 38 | width: 100%; 39 | left: -2px; 40 | text-shadow: 2px 0 blue; 41 | top: 0; 42 | color: white; 43 | background: var(--grey-900); 44 | overflow: hidden; 45 | clip: rect(0, 900px, 0, 0); 46 | animation: blue-glitch 3s infinite linear alternate-reverse; 47 | animation-delay: 4s; 48 | } 49 | 50 | .glitch__text::after { 51 | content: attr(data-text); 52 | position: absolute; 53 | left: 1px; 54 | width: 100%; 55 | text-shadow: -1px 0 red; 56 | top: 0; 57 | color: white; 58 | background: var(--grey-900); 59 | overflow: hidden; 60 | clip: rect(0, 900px, 0, 0); 61 | animation: red-glitch 4s infinite linear alternate-reverse; 62 | } 63 | 64 | .glitch__svg { 65 | position: absolute; 66 | width: calc(100% + 1.5rem); 67 | height: 100%; 68 | top: 0.1rem; 69 | left: -0.9rem; 70 | z-index: -1; 71 | animation: svg-glitch 2s infinite linear alternate-reverse; 72 | } 73 | 74 | svg { 75 | width: 100%; 76 | height: 100%; 77 | } 78 | 79 | @media (min-width: 960px) { 80 | h2 { 81 | font-size: 6rem; 82 | } 83 | 84 | .glitch__svg { 85 | width: calc(100% + 3rem); 86 | left: -1.7rem; 87 | } 88 | } 89 | 90 | /* interesting part */ 91 | @media screen and (prefers-reduced-motion: reduce) { 92 | .glitch__svg { 93 | animation: none; 94 | } 95 | 96 | .glitch__text { 97 | visibility: hidden; 98 | } 99 | 100 | .glitch__text::after, 101 | .glitch__text::before { 102 | animation: none; 103 | content: ""; 104 | } 105 | } 106 | 107 | @keyframes blue-glitch { 108 | 0% { 109 | clip: rect(194px, 1000px, 178px, 0); 110 | } 111 | 5% { 112 | clip: rect(482px, 1000px, 183px, 0); 113 | } 114 | 10% { 115 | clip: rect(279px, 1000px, 76px, 0); 116 | } 117 | 15% { 118 | clip: rect(451px, 1000px, 413px, 0); 119 | } 120 | 20% { 121 | clip: rect(356px, 1000px, 81px, 0); 122 | } 123 | 25% { 124 | clip: rect(467px, 1000px, 330px, 0); 125 | } 126 | 30% { 127 | clip: rect(406px, 1000px, 322px, 0); 128 | } 129 | 35% { 130 | clip: rect(98px, 1000px, 85px, 0); 131 | } 132 | 40% { 133 | clip: rect(13px, 1000px, 46px, 0); 134 | } 135 | 45% { 136 | clip: rect(184px, 1000px, 311px, 0); 137 | } 138 | 50% { 139 | clip: rect(30px, 1000px, 212px, 0); 140 | } 141 | 55% { 142 | clip: rect(440px, 1000px, 236px, 0); 143 | } 144 | 60% { 145 | clip: rect(271px, 1000px, 132px, 0); 146 | } 147 | 65% { 148 | clip: rect(484px, 1000px, 60px, 0); 149 | } 150 | 70% { 151 | clip: rect(34px, 1000px, 405px, 0); 152 | } 153 | 75% { 154 | clip: rect(361px, 1000px, 403px, 0); 155 | } 156 | 80% { 157 | clip: rect(216px, 1000px, 275px, 0); 158 | } 159 | 85% { 160 | clip: rect(379px, 1000px, 463px, 0); 161 | } 162 | 90% { 163 | clip: rect(491px, 1000px, 438px, 0); 164 | } 165 | 95% { 166 | clip: rect(140px, 1000px, 168px, 0); 167 | } 168 | 100% { 169 | clip: rect(131px, 1000px, 256px, 0); 170 | } 171 | } 172 | 173 | @keyframes red-glitch { 174 | 0% { 175 | clip: rect(97px, 1000px, 47px, 0); 176 | } 177 | 5% { 178 | clip: rect(37px, 1000px, 98px, 0); 179 | } 180 | 10% { 181 | clip: rect(40px, 1000px, 16px, 0); 182 | } 183 | 15% { 184 | clip: rect(29px, 1000px, 32px, 0); 185 | } 186 | 20% { 187 | clip: rect(10px, 1000px, 61px, 0); 188 | } 189 | 25% { 190 | clip: rect(60px, 1000px, 23px, 0); 191 | } 192 | 30% { 193 | clip: rect(29px, 1000px, 22px, 0); 194 | } 195 | 35% { 196 | clip: rect(18px, 1000px, 79px, 0); 197 | } 198 | 40% { 199 | clip: rect(60px, 1000px, 98px, 0); 200 | } 201 | 45% { 202 | clip: rect(46px, 1000px, 55px, 0); 203 | } 204 | 50% { 205 | clip: rect(3px, 1000px, 85px, 0); 206 | } 207 | 55% { 208 | clip: rect(55px, 1000px, 92px, 0); 209 | } 210 | 60% { 211 | clip: rect(12px, 1000px, 18px, 0); 212 | } 213 | 65% { 214 | clip: rect(54px, 1000px, 96px, 0); 215 | } 216 | 70% { 217 | clip: rect(95px, 1000px, 68px, 0); 218 | } 219 | 75% { 220 | clip: rect(96px, 1000px, 96px, 0); 221 | } 222 | 80% { 223 | clip: rect(44px, 1000px, 83px, 0); 224 | } 225 | 85% { 226 | clip: rect(87px, 1000px, 57px, 0); 227 | } 228 | 90% { 229 | clip: rect(31px, 1000px, 29px, 0); 230 | } 231 | 95% { 232 | clip: rect(27px, 1000px, 46px, 0); 233 | } 234 | 100% { 235 | clip: rect(28px, 1000px, 24px, 0); 236 | } 237 | } 238 | 239 | @keyframes svg-glitch { 240 | 0% { 241 | clip: rect(214px, 3222px, 72px, 100px); 242 | } 243 | 10% { 244 | clip: rect(207px, 3222px, 176px, 100px); 245 | } 246 | 20% { 247 | clip: rect(42px, 3222px, 118px, 100px); 248 | } 249 | 30% { 250 | clip: rect(376px, 3222px, 162px, 100px); 251 | } 252 | 40% { 253 | clip: rect(51px, 3222px, 94px, 100px); 254 | } 255 | 50% { 256 | clip: rect(244px, 3222px, 191px, 100px); 257 | } 258 | 60% { 259 | clip: rect(248px, 3222px, 94px, 100px); 260 | } 261 | 70% { 262 | clip: rect(211px, 3222px, 176px, 100px); 263 | } 264 | 80% { 265 | clip: rect(110px, 3222px, 198px, 100px); 266 | } 267 | 90% { 268 | clip: rect(340px, 3222px, 173px, 100px); 269 | } 270 | 100% { 271 | clip: rect(16px, 3222px, 45px, 100px); 272 | } 273 | } 274 | --------------------------------------------------------------------------------