### Obs.js Adaptive Installation Script Source: https://github.com/csswizardry/obs.js/blob/main/README.md Place this inline script in the
of your document before any other scripts or stylesheets. It must be an inline, classic ``` -------------------------------- ### Analytics Installation for Obs.js Source: https://github.com/csswizardry/obs.js/blob/main/README.md Install Obs.js to collect analytics signals by disabling adaptive mode. This script should be placed before the main obs.js script. ```html ``` -------------------------------- ### Initialize LUX object and performance variables Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html Initializes the LUX object and its associated arrays for marks and measures. It determines the starting point for performance measurements, using `window.performance.timing.navigationStart` if available, otherwise falling back to the current time. ```javascript var a=("undefined"!==typeof(LUX)&&"undefined"!==typeof(LUX.gaMarks)?LUX.gaMarks:[]);var d=("undefined"!==typeof(LUX)&&"undefined"!==typeof(LUX.gaMeasures)?LUX.gaMeasures:[]);var j="LUX_start";var k=window.performance;var l=("undefined"!==typeof(LUX)&&LUX.ns?LUX.ns:(Date.now?Date.now():+(new Date())));if(k&&k.timing&&k.timing.navigationStart){l=k.timing.navigationStart} ``` -------------------------------- ### Get current high-resolution time Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html Provides a function to get the current high-resolution time using `window.performance.now()` if available. If not, it falls back to calculating the difference between the current time and the initial start time `l`. ```javascript function f(){if(k&&k.now){return k.now()}var o=Date.now?Date.now():+(new Date());return o-l} ``` -------------------------------- ### Obs.js Data Object Source: https://github.com/csswizardry/obs.js/blob/main/README.md An example of the `window.obs` object structure, detailing configuration, data saver status, network round-trip time (RTT) and downlink buckets, connection capabilities, conservation preferences, delivery mode, and battery status. ```js { "config": { "adaptive": true, "observeChanges": false }, "dataSaver": false, "rttBucket": 50, "rttCategory": "low", "downlinkBucket": 10, "connectionCapability": "strong", "conservationPreference": "neutral", "deliveryMode": "rich", "canShowRichMedia": true, "shouldAvoidRichMedia": false, "batteryCritical": false, "batteryLow": false, "batteryCharging": true } ``` -------------------------------- ### HTML with Obs.js Classes Source: https://github.com/csswizardry/obs.js/blob/main/README.md Example of an HTML element with CSS classes added by Obs.js, indicating low latency, high bandwidth, charging battery, strong connection capability, neutral conservation preference, and rich delivery mode. ```html ``` -------------------------------- ### Measure time between two points Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html Measures the duration between two performance points (start and end) using `performance.measure` or `performance.webkitMeasure`. It supports specifying start and end marks by name or using navigation timing attributes. Fallback recording in array `d` is included. ```javascript function m(p,t,n){if("undefined"===typeof(t)&&h(j)){t=j}if(k){if(k.measure){if(t){if(n){return k.measure(p,t,n)}else{return k.measure(p,t)}}else{return k.measure(p)}}else{if(k.webkitMeasure){return k.webkitMeasure(p,t,n)}}}var r=0,o=f();if(t){var s=h(t);if(s){r=s.startTime}else{if(k&&k.timing&&k.timing[t]){r=k.timing[t]-k.timing.navigationStart}else{return}}}if(n){var q=h(n);if(q){o=q.startTime}else{if(k&&k.timing&&k.timing[n]){o=k.timing[n]-k.timing.navigationStart}else{return}}}d.push({name:p,entryType:"measure",startTime:r,dura ``` -------------------------------- ### Classify CSS Classes for Performance Indicators Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html Maps CSS class names starting with 'has-' to specific visual styles ('c-pill u-bad', 'c-pill u-warn', 'c-pill u-good') based on performance-related keywords like battery, latency, bandwidth, RAM, CPU, and connection capability. Returns a neutral 'c-pill' if no specific category matches. ```javascript const classify = (name) => { if ( /battery-critical/.test(name) || /latency-high/.test(name) || /bandwidth-low/.test(name) || /ram-very-low/.test(name) || /ram-low/.test(name) || /cpu-low/.test(name) || /connection-capability-weak/.test(name) || /device-capability-weak/.test(name) || /delivery-mode-lite/.test(name) ) return 'c-pill u-bad'; if ( /battery-low/.test(name) || /data-saver/.test(name) || /device-capability-moderate/.test(name) || /ram-medium/.test(name) || /cpu-medium/.test(name) || /bandwidth-medium/.test(name) || /latency-medium/.test(name) || /conservation-preference-conserve/.test(name) || /connection-capability-moderate/.test(name) || /delivery-mode-cautious/.test(name) ) return 'c-pill u-warn'; if ( /connection-capability-strong/.test(name) || /device-capability-strong/.test(name) || /delivery-mode-rich/.test(name) || /bandwidth-high/.test(name) || /ram-high/.test(name) || /cpu-high/.test(name) || /latency-low/.test(name) ) return 'c-pill u-good'; return 'c-pill'; }; ``` -------------------------------- ### Obs.js Performance Measurement Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html This snippet measures the execution time of the Obs.js script itself using the Performance API. It marks the start and end points and logs the duration to the console. ```javascript performance.mark('obs\_end'); const obs\_time = performance.measure('obs\_time', 'obs\_start', 'obs\_end'); console.log('Obs.js time: ' + obs\_time.duration) ``` -------------------------------- ### Obs.js Initialization and Core Logic Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html This snippet initializes Obs.js, sets up configuration, and contains the core logic for detecting and applying performance-related context. It includes adaptive logic, network and battery status checks, and device capability analysis. It's designed to run inline in the `` of an HTML document. ```javascript window.obs = { config: { observeChanges: true } }; performance.mark('obs\_start'); /*! Obs.js | (c) Harry Roberts, csswizardry.com | MIT */ ;(()=>{const e=document.currentScript,i=window.obs&&window.obs.config||{},n=!1!==i.adaptive;if(n&&(!e||e.src||e.type&&"module"===e.type.toLowerCase())&&!1===/^(localhost|127\.0\.0\.1|::1)$/.test(location.hostname))return void console.warn("\n[Obs.js] Skipping: must be an inline, classic ``` -------------------------------- ### Serve Lite Version to Slow Browsers Source: https://github.com/csswizardry/obs.js/blob/main/README.md Use this snippet to serve the lite version of media to browsers that support Obs.js but are detected as slow. Otherwise, serve the rich version to fast supportive browsers and Safari. ```javascript if (window.obs?.shouldAvoidRichMedia === true) { // Serve lite version to slow supportive browsers. } else { // Serve rich version to fast supportive browsers and Safari. } ``` -------------------------------- ### Serve Rich Version to Fast Browsers Source: https://github.com/csswizardry/obs.js/blob/main/README.md Use this snippet to serve the rich version of media to browsers that support Obs.js and are detected as fast. Otherwise, serve the lite version to slow supportive browsers and Safari. ```javascript if (window.obs?.canShowRichMedia === true) { // Serve rich version to fast supportive browsers. } else { // Serve lite version to slow supportive browsers and Safari. } ``` -------------------------------- ### CSS to Serve Low-Resolution Images Source: https://github.com/csswizardry/obs.js/blob/main/README.md This CSS demonstrates how to conditionally serve low-resolution images by applying a different background image when the delivery mode is set to 'lite' by Obs.js. ```css body { background-image: url('hi-res.jpg'); } /** * Show low-resolution images if the user can’t take rich media right now. */ .has-delivery-mode-lite body { background-image: url('lo-res.jpg'); } ``` -------------------------------- ### Listen for Changes in Obs.js Source: https://github.com/csswizardry/obs.js/blob/main/README.md Configure Obs.js to observe changes in connection and battery status for long-lived pages or SPAs. The default is false. ```html ``` -------------------------------- ### Obs.js Device and RAM Detection Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html This snippet focuses on detecting device memory (RAM) and CPU core count. It categorizes these into buckets (e.g., 'low', 'medium', 'high') and applies corresponding CSS classes to the `` element. It also determines an overall 'device capability' based on RAM and CPU. ```javascript h=()=>{if(!l){if(l=!0,w(),a&&o&&"function"==typeof o.addEventListener&&o.addEventListener("change",w),"getBattery"in navigator&&navigator.getBattery().then(e=>{u(e),a&&"function"==typeof e.addEventListener&&(e.addEventListener("levelchange",()=>u(e)),e.addEventListener("chargingchange",()=>u(e)))}).catch(()=>{}),"deviceMemory"in navigator){const i=Number(navigator.deviceMemory),n=Number.isFinite(i)?i:null;window.obs.ramBucket=n;const t=(e=n,Number.isFinite(e)?e<=1?"very-low":e<=2?"low":e<=4?"medium":"high":null);t&&(window.obs.ramCategory=t,r(["very-low","low","medium","high"].map(e=>`has-ram-${e}`)),c(`has-ram-${t}`))}}var e;if("hardwareConcurrency"in navigator){const e=Number(navigator.hardwareConcurrency),i=Number.isFinite(e)?e:null;window.obs.cpuBucket=i;const n=(e=>Number.isFinite(e)?e<=2?"low":e<=5?"medium":"high":null)(i);n&&(window.obs.cpuCategory=n,r(["low","medium","high"].map(e=>`has-cpu-${e}`)),c(`has-cpu-${n}`))}(()=>{const e=window.obs||{},i=e.ramCategory,n=e.cpuCategory;let t="moderate";"high"!==i&&"medium"!==i||"high"!==n?("very-low"===i||"low"===i||"low"===n)&&(t="weak"):t="strong";e.deviceCapability=t,r(["strong","moderate","weak"].map(e=>`has-device-capability-${e}`)),c(`has-device-capability-${t}`)})()}}() ``` -------------------------------- ### Render Observed Data Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html Renders the current state of the `window.obs` object as a JSON string. It attempts to create a deep copy before stringifying to ensure a clean snapshot. If stringification fails, it falls back to displaying the raw `window.obs` value. ```javascript function renderObs() { try { const snapshot = window.obs ? JSON.parse(JSON.stringify(window.obs)) : {}; obsEl.textContent = JSON.stringify(snapshot, null, 2); } catch { obsEl.textContent = String(window.obs); } } ``` -------------------------------- ### Obs.js Basic Layout Styling Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html This snippet applies basic margin and padding rules for common HTML elements like headings, paragraphs, and code blocks. It also includes a media query for adjusting left margin on ordered lists for larger screens. ```css h1, h2, p, details, pre, ul, .c-snippet, .c-hero, .c-video > video, .c-video >img { margin-bottom: 1.5rem; } ol { margin-left: 1.5rem; } @media (min-width: 45em) { ol { margin-left: 0; } } ``` -------------------------------- ### Conditionally Inject Video or Image Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html Injects a video element if the connection is good, otherwise injects a static image. Handles autoplay, looping, and muted properties, with specific adjustments for 'cautious' delivery modes or low battery. ```javascript (() => { const videoWrapper = document.getElementById('jsVideo'); if (window.obs?.shouldAvoidRichMedia === true) { const img = new Image(); img.src = './assets/poster.png'; img.alt = ''; img.width = '1500'; img.height = '966'; img.classList.add('c-hero'); videoWrapper.appendChild(img); } else { const video = document.createElement('video'); video.src = './assets/video.min.mp4'; video.poster = './assets/poster.png'; video.autoplay = true; video.loop = true; video.muted = true; video.controls = true; video.preload = 'auto'; if (window.obs?.deliveryMode === 'cautious') { video.preload = 'metadata'; } if (window.obs?.batteryLow === true) { video.autoplay = false; } videoWrapper.appendChild(video); } })(); ``` -------------------------------- ### Obs.js CSS Variables and Reset Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html This snippet defines CSS variables for colors and includes a basic CSS reset. It sets up the fundamental styling for the page, ensuring consistent appearance across different browsers. ```css :root { --fg: #333; --bg: #f9f9f9; --brand: #009aa2; --csswizardry: #f43059; --ok: #0a0; --warn: #a60; --bad: #a00; } * { box-sizing: border-box; margin: 0; padding: 0; } ``` -------------------------------- ### Render Performance Classes Source: https://github.com/csswizardry/obs.js/blob/main/demo/index.html Filters and displays all 'has-*' CSS classes present on the document element, applying a 'classify' function to style them based on performance indicators. If no 'has-*' classes are found, it displays a message indicating that APIs may be unavailable. ```javascript function renderClasses() { const list = (document.documentElement.className || '') .split(/\s+/) .filter(Boolean) .filter(interesting) .sort((a,b)=>a.localeCompare(b)); if (!list.length) { classesEl.innerHTML = 'has-\* classes present (APIs may be unavailable).