HTML
CSS
JS
Result
Skip Results Iframe
EDIT ON
Live
Live
Live
This Pen is owned by
web.dev
on
CodePen
.
See more by @web-dot-dev on CodePen
External CSS
https://codepen.io/web-dot-dev/pen/XWqWYgB.css
https://codepen.io/web-dot-dev/pen/ZExZWBQ.css
External JavaScript
https://codepen.io/web-dot-dev/pen/XWqWYgB.js
https://codepen.io/web-dot-dev/pen/ZExZWBQ.js
{"__browser":{"country":"US","device":"unknown_device","mobile":false,"name":"unknown browser","platform":"unknown_platform","version":"0"},"__constants":{},"__CPDATA":{"domain_iframe":"https://cdpn.io","environment":"production","host":"codepen.io","iframe_allow":"accelerometer; ambient-light-sensor; camera; display-capture; encrypted-media; geolocation; gyroscope; microphone; midi; payment; vr; web-share","iframe_sandbox":"allow-forms allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation allow-downloads allow-presentation"},"__graphql":{"data":{"data":null,"errors":[{"message":"Cannot return null for non-nullable field Query.sessionUser"}]},"url":"https://codepen.io/graphql","api":"cprails"},"__pay_stripe_public_key":"pk_live_2GndomDfiklqpSNQn8FrGuwZSMIMzha7DkLJqlYe7IR0ihKAlKdiHg68JJc5eVPt68rzAjzAAVXcUwjySHRCsgjQQ00gtRBUFNH","__pay_braintree_env":"production","__boomboom":{"serve_url":"https://cdpn.io/cpe/boomboom","store_url":"https://codepen.io/cpe/boomboom/store"},"__pageType":"embed","__item":"{\"editor_settings\":{\"auto_run\":true,\"autocomplete\":false,\"code_folding\":true,\"css_pre_processor\":\"none\",\"css_prefix\":\"neither\",\"css_starter\":\"neither\",\"emmet_active\":true,\"font_size\":14,\"font_type\":\"system\",\"format_on_save\":true,\"html_pre_processor\":\"none\",\"indent_with\":\"spaces\",\"js_pre_processor\":\"none\",\"key_bindings\":\"normal\",\"line_numbers\":true,\"line_wrapping\":true,\"match_brackets\":true,\"snippets\":{\"markupSnippets\":{},\"stylesheetSnippets\":{}},\"tab_size\":2,\"theme\":\"twilight\",\"id\":\"JjvoPrx\",\"auto_save\":true},\"hashid\":\"JjvoPrx\",\"itemType\":\"pen\",\"resources\":[{\"url\":\"https://codepen.io/web-dot-dev/pen/XWqWYgB.css\",\"order\":0,\"resource_type\":\"css\",\"par_content\":\"\"},{\"url\":\"https://codepen.io/web-dot-dev/pen/XWqWYgB.js\",\"order\":0,\"resource_type\":\"js\",\"par_content\":\"\"},{\"url\":\"https://codepen.io/web-dot-dev/pen/ZExZWBQ.css\",\"order\":1,\"resource_type\":\"css\",\"par_content\":\"\"},{\"url\":\"https://codepen.io/web-dot-dev/pen/ZExZWBQ.js\",\"order\":1,\"resource_type\":\"js\",\"par_content\":\"\"}],\"tags\":[],\"id\":62926209,\"user_id\":5928893,\"html\":\"<svg class=\\\"inactivity-ring\\\" viewBox=\\\"0 0 50 50\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <circle cx=\\\"25\\\" cy=\\\"25\\\" r=\\\"20\\\" stroke-width=\\\"10\\\" stroke-linejoin=\\\"round\\\" />\\n</svg>\\n<main>\\n <header>\\n <h1>screensaver.js</h1>\\n </header>\\n <article>\\n <p>\\n <strong>\\n In this demo, leave the page inactive for 4 seconds, and a screensaver will appear using a pop-up. On <code>show</code> it generates the animation behavior and leverages \\\"light dismiss\\\".\\n </strong>\\n </p>\\n <p>Lorem ipsum, dolor, sit amet consectetur adipisicing elit. Repellat illo eum hic possimus, libero voluptates, facere nihil deserunt similique error sunt vero minima enim cupiditate quis velit rem ab repellendus.</p>\\n <p>Neque hic veniam cum voluptates quae magnam quisquam saepe. Dolorum quasi amet officiis vero aliquid pariatur commodi repellendus. Quos iure nobis doloremque ipsum facere nostrum neque adipisci hic labore voluptates?</p>\\n <p>Mollitia beatae, repellat est laboriosam officiis? Earum veritatis incidunt explicabo id tempora perspiciatis non doloribus natus nisi asperiores quia error autem laudantium, amet doloremque, vitae quos. Soluta unde numquam id.</p>\\n <p>Recusandae facere esse quod dolorum maxime corrupti ex quam iure id quis eius cumque fugiat, consequatur autem, excepturi molestias libero velit illo a quo. Sed quae aut inventore quia, ipsa.</p>\\n <p>Eius id laboriosam, quas iure laborum corrupti optio corporis tempore odit laudantium similique, accusamus, vel! Perspiciatis sed saepe rem. Nihil explicabo ea at vitae rerum eum, corrupti ipsam suscipit, id!</p>\\n <p>Voluptate pariatur, cum praesentium, veniam tenetur distinctio totam voluptates ea beatae, dicta voluptatum illum sit! Earum harum odio natus perspiciatis. Magni eos temporibus harum quas laborum aspernatur, minus, sunt illum.</p>\\n <p>Ducimus nobis, libero illum commodi aliquid. Molestias beatae ducimus ratione quod, quis itaque ipsum, illum amet labore, nostrum quisquam enim. Sint aperiam qui nihil eaque id quam odio? Repudiandae, sint!</p>\\n <p>In rem tenetur accusamus accusantium id, officia quaerat atque, placeat architecto nihil unde, sit cupiditate minima tempore! Magni, atque labore. Dolor voluptatum eius incidunt, enim? Asperiores similique, ut amet atque?</p>\\n <p>Illum, quam fugiat, veniam officia totam nihil aut dolore quo! Officiis ipsa harum vero voluptatibus eaque repudiandae amet eligendi ducimus laboriosam ab maiores labore, odit, voluptas quos illo sint nulla.</p>\\n <p>Eius earum nihil officiis, inventore accusantium consequuntur dolor reprehenderit in esse quos eos iste nemo amet facere, mollitia, assumenda cum provident quam. Ipsam, vitae! Excepturi quos possimus enim, quia distinctio.</p>\\n <p>Lorem ipsum, dolor, sit amet consectetur adipisicing elit. Commodi eaque, ipsa voluptate quia deserunt mollitia pariatur harum, vero temporibus dolores, quibusdam rem provident sint? Architecto sequi, quasi sunt neque recusandae.</p>\\n </article>\\n</main>\\n<div id=\\\"screensaver\\\" popover>\\n <div class=\\\"dvd\\\">\\n <div class=\\\"dvd__scale\\\">\\n <div class=\\\"dvd__slide\\\">\\n <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewbox=\\\"8 44 178 104\\\">\\n <g fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\">\\n <path d=\\\"M108.605 58.081c1.766-2.129 11.285-13.399 11.285-13.399h35.936c18.197 0 30.922 9.53 28.012 21.776-2.906 12.247-20.248 21.778-38.359 21.778h-24.09l7.227-30.422H145.6l-4.949 20.833h3.812c10.139 0 19.738-3.697 21.756-12.189 1.854-7.798-4.873-12.188-15.791-12.188h-3.984l-16.529.014-39.02 44.041-15.324-43.274s-.112-.276-.254-.649c-.035-.089-.328-.397-.485-.338-.286.106-.24.603-.19.711.125.266.162.367.196.497 1.368 3.34 1.446 8.946.89 11.187-3.031 12.218-20.25 21.778-38.359 21.778h-24.09l7.228-30.422H37.49l-4.949 20.833h3.812c10.138 0 19.682-3.697 21.699-12.189 1.852-7.798-4.817-12.188-15.734-12.188h-3.985l-16.983-.008 2.277-9.58H46.13l29.846-.039v.039h12.289s3.469 10.161 4.545 13.236c5.149 14.707 4.297 15.702 4.297 15.702s-.619-.949 11.498-15.54zM8.504 110.273c0-6.496 37.163-11.762 83.001-11.762 45.841 0 83.001 5.266 83.001 11.762 0 6.498-37.16 11.764-83.001 11.764-45.838 0-83.001-5.266-83.001-11.764zm79.997 4.153c10.47 0 18.954-1.754 18.954-3.922 0-2.164-8.484-3.92-18.954-3.92-10.467 0-18.952 1.756-18.952 3.92 0 2.168 8.485 3.922 18.952 3.922zm79.655 5.232h-.765l-.336 2.377h-.371l.332-2.377h-.764l.047-.338h1.902l-.045.338zm2.815 2.377h-.358v-2.058h-.008l-1.091 2.058-.469-2.078h-.008l-.67 2.078h-.357l.894-2.715h.311l.422 1.84.976-1.84h.358v2.715zM36.536 142.711h.062l5.119-10.32h4.816l-8.93 15.722h-2.622l-8.777-15.722h4.816l5.516 10.32zm25.447 4.996h-4.481v-15.316h4.481v15.316zm13.01-15.316h6.399c6.645 0 11.095 3.311 11.095 7.678 0 4.307-4.573 7.639-11.125 7.639h-6.37v-15.317h.001zm4.479 12.714h.731c5.517 0 7.651-2.031 7.651-5.059 0-3.33-2.562-5.057-7.651-5.057h-.731v10.116zm29.442-10.115v3.371h7.131v2.604h-7.131v4.14h7.406v2.602h-11.886v-15.316h11.886v2.599h-7.406zm19.041 5.037c0-4.287 4.662-8.045 11.367-8.045 6.703 0 11.369 3.758 11.369 8.045 0 4.387-4.666 8.086-11.369 8.086-6.705 0-11.367-3.699-11.367-8.086zm4.633-.119c0 2.312 2.926 5.26 6.734 5.26s6.734-2.947 6.734-5.26c0-2.479-2.803-4.979-6.734-4.979-3.933.001-6.734 2.501-6.734 4.979z\\\"></path>\\n </g>\\n </svg>\\n </div>\\n </div>\\n </div>\\n</div>\",\"css\":\"@layer demo {\\n .dvd__scale {\\n position: fixed;\\n top: 0;\\n left: 0;\\n animation: dvd-scale calc(var(--duration) * 1s) calc(var(--delay) * -1s)\\n infinite linear alternate;\\n /*\\n\\t\\tFor debugging the corner\\n\\t\\tanimation-duration: 4s;\\n\\t\\tanimation-delay: 0s;\\n\\t*/\\n }\\n\\n .dvd__slide {\\n animation: dvd-slide calc(var(--duration) * 1s) calc(var(--delay) * -1s)\\n infinite linear alternate;\\n /*\\n\\t\\tFor debugging the corner\\n\\t\\tanimation-duration: 4s;\\n\\t\\tanimation-delay: 0s;\\n\\t*/\\n }\\n\\n #screensaver::backdrop {\\n background: hsl(0 0% 20% / 0.5);\\n backdrop-filter: blur(2px);\\n }\\n\\n .dvd svg {\\n fill: hsl(var(--hue, 0) 80% 50%);\\n stroke: none;\\n width: clamp(2rem, 20vmin, 10rem);\\n }\\n\\n @keyframes dvd-scale {\\n to {\\n transform: translateY(calc(100vh - 100%));\\n }\\n }\\n\\n @keyframes dvd-slide {\\n to {\\n transform: translateX(calc(100vw - 100%));\\n }\\n }\\n}\\n\\n@layer base {\\n *,\\n *:after,\\n *:before {\\n box-sizing: border-box;\\n }\\n\\n body {\\n display: block;\\n min-height: 100vh;\\n font-family: \\\"Google Sans\\\", sans-serif, system-ui;\\n overflow: auto;\\n }\\n\\n :where([popover]) {\\n margin: auto;\\n border-width: 0;\\n border-style: none;\\n background: transparent;\\n }\\n\\n h1 {\\n margin: 0;\\n color: var(--gray-0);\\n }\\n\\n header {\\n height: 35vmin;\\n min-height: 200px;\\n background: var(--gradient-16);\\n display: grid;\\n place-items: center;\\n color: var(--gray-0);\\n padding: var(--size-4);\\n grid-template-columns: 1fr;\\n }\\n\\n h1 {\\n background: var(--gradient-18);\\n background-clip: text;\\n -webkit-background-clip: text;\\n background-attachment: fixed;\\n color: transparent;\\n font-size: var(--font-size-fluid-3);\\n }\\n\\n main {\\n margin: 0 auto;\\n }\\n\\n article {\\n padding: var(--size-4);\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n }\\n\\n article > * + * {\\n margin-top: var(--size-4);\\n }\\n\\n /* Inactivity ring */\\n .inactivity-ring {\\n fill: none;\\n position: fixed;\\n top: var(--size-4);\\n right: var(--size-4);\\n color: var(--teal-6);\\n width: 40px;\\n aspect-ratio: 1;\\n stroke-dasharray: 130;\\n stroke-dashoffset: 130;\\n transform: rotate(-90deg);\\n z-index: 20;\\n }\\n\\n .inactivity-ring circle {\\n stroke: currentColor;\\n }\\n\\n .timing .inactivity-ring {\\n animation: load calc(var(--threshold) * 1ms) linear;\\n }\\n\\n @keyframes load {\\n to {\\n stroke-dashoffset: 0;\\n }\\n }\\n}\\n\",\"js\":\"const randomInRange = (min, max) =>\\n Math.floor(\\n Math.random() * (Math.floor(max) - Math.ceil(min) + 1) + Math.ceil(min)\\n );\\n\\nconst POPUP = document.querySelector(\\\"#screensaver\\\");\\nconst RING = document.querySelector(\\\"svg\\\");\\nconst SCALE = document.querySelector(\\\".dvd__scale\\\");\\nconst SLIDE = document.querySelector(\\\".dvd__slide\\\");\\nconst DVD = document.querySelector(\\\".dvd\\\");\\nconst MOVERS = [SLIDE, SCALE];\\nconst SCREENSAVER_THRESHOLD = 4000;\\nconst BOUNCE_THRESHOLD = 2; // ms between bounces for a cheer. Ideal is 0 for a corner.\\n\\nlet checker;\\nlet screensaverTimeout;\\nconst EVENT_TYPES = [\\n \\\"pointermove\\\",\\n \\\"keypress\\\",\\n \\\"keydown\\\",\\n \\\"keyup\\\",\\n \\\"scroll\\\",\\n \\\"click\\\"\\n];\\n\\nconst setSaverTimer = () => {\\n if (screensaverTimeout) {\\n clearTimeout(screensaverTimeout);\\n document.body.classList.remove(\\\"timing\\\");\\n }\\n\\n if (!POPUP.matches(\\\":open\\\")) {\\n screensaverTimeout = setTimeout(() => {\\n document.body.classList.remove(\\\"timing\\\");\\n POPUP.showPopover();\\n }, SCREENSAVER_THRESHOLD);\\n requestAnimationFrame(() => {\\n document.body.classList.add(\\\"timing\\\");\\n });\\n }\\n};\\n\\nconst BOUNCES = {\\n dvd__scale: 0,\\n dvd__slide: 0\\n};\\n\\nconst CHEER = new Audio(\\n \\\"https://assets.codepen.io/605876/grunt-party--optimised.mp3\\\"\\n);\\n\\nconst handleBounce = (e) => {\\n BOUNCES[e.target.className] = Date.now();\\n DVD.style.setProperty(\\\"--hue\\\", randomInRange(0, 359));\\n const diff = Math.abs(BOUNCES.dvd__scale - BOUNCES.dvd__slide);\\n if (diff <= BOUNCE_THRESHOLD) CHEER.play();\\n};\\n\\nPOPUP.addEventListener(\\\"beforetoggle\\\", ({ newState }) => {\\n if (newState === \\\"closed\\\") {\\n setSaverTimer();\\n } else {\\n DVD.style.setProperty(\\\"--hue\\\", randomInRange(0, 359));\\n MOVERS.forEach((el) => {\\n const duration = randomInRange(2, 6);\\n el.style = `\\n --duration: ${duration};\\n --delay: ${duration * Math.random()};\\n `;\\n });\\n }\\n});\\n\\nMOVERS.forEach((mover) =>\\n mover.addEventListener(\\\"animationiteration\\\", handleBounce)\\n);\\n\\nEVENT_TYPES.forEach((e) => document.body.addEventListener(e, setSaverTimer));\\n\\ndocument.body.classList.add(\\\"timing\\\");\\ndocument.documentElement.style.setProperty(\\n \\\"--threshold\\\",\\n SCREENSAVER_THRESHOLD\\n);\\nsetSaverTimer();\\n\",\"html_pre_processor\":\"none\",\"css_pre_processor\":\"none\",\"js_pre_processor\":\"none\",\"html_classes\":\"popup-support\",\"css_starter\":\"neither\",\"js_library\":null,\"created_at\":\"2022-09-03T20:26:27.418Z\",\"updated_at\":\"2023-01-19T11:28:40.010Z\",\"title\":\"24. Screensaver.js\",\"description\":\"\",\"slug_hash\":\"JjvoPrx\",\"head\":\"\",\"private\":false,\"has_animation\":true,\"team_id\":0,\"css_prefix\":\"neither\",\"template\":false,\"parent_id\":0,\"comments_count\":0,\"custom_screenshot_filename\":null,\"loves_count\":0,\"pick\":false,\"popularity_score\":0,\"views_count\":0,\"pick_visible_at\":null,\"cpid\":\"01830508-82da-72f1-b045-22a5fde55963\",\"is_new_editor_pen\":false,\"pen_hash\":null}","__processorsMap":{"autoprefixer":"autoprefixer-10","babel":"babel-7","coffeescript":"coffeescript-2","format-1":"format-1","flutter":"flutter-1","haml":"haml-4","less":"less-3","lint-1":"lint-1","livescript":"livescript-1","markdown":"markdown-11","postcss":"postcss-7","pug":"pug-2","sass":"sass-1","scss":"sass-1","sass-ruby-3":"sass-ruby-3","sass-ruby-compass-3":"sass-ruby-compass-3","slim":"slim-3","stylus":"stylus-0","typescript":"typescript-4","vue":"vue-2","vue3":"vue-3"},"__favicon_mask_icon":"https://cpwebassets.codepen.io/assets/favicon/logo-pin-b4b4269c16397ad2f0f7a01bcdf513a1994f4c94b8af2f191c09eb0d601762b1.svg","__favicon_shortcut_icon":"https://cpwebassets.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico","__path_to_iframe_console_runner":"https://cpwebassets.codepen.io/assets/editor/iframe/iframeConsoleRunner-6d8bf8b4b479137260842506acbb12717dace0823c023e08b96360e60b0840d9.js","__path_to_iframe_refresh_css":"https://cpwebassets.codepen.io/assets/editor/iframe/iframeRefreshCSS-44fe83e49b63affec96918c9af88c0d80b209a862cf87ac46bc933074b8c557d.js","__path_to_iframe_runtime_errors":"https://cpwebassets.codepen.io/assets/editor/iframe/iframeRuntimeErrors-4f205f2c14e769b448bcf477de2938c681660d5038bc464e3700256713ebe261.js","__path_to_processor_worker":"https://cpwebassets.codepen.io/assets/packs/router.js","__path_to_stop_execution_on_timeout":"https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-2c7831bb44f98c1391d6a4ffda0e1fd302503391ca806e7fcc7b9b87197aec26.js","__pen_normalize_css_url":"https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css","__pen_prefix_free_url":"https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js","__pen_reset_css_url":"https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css","__path_to_infinite_loop_detection":"https://cpwebassets.codepen.io/assets/packs/js/infiniteLoopDetection-f0d5935eb4c2121dfc41.js"}