📌 What is screen?
The screen object provides information about the user’s physical screen (monitor),
not the browser window.
👉 It is part of the BOM and accessed via window.screen.
window.screen === screen // true🧩 Common screen Properties
1️⃣ screen.width & screen.height
console.log(screen.width);
console.log(screen.height);Explanation:
Returns the total screen resolution (including taskbars, docks).
2️⃣ screen.availWidth & screen.availHeight
console.log(screen.availWidth);
console.log(screen.availHeight);Explanation:
Returns the usable screen size, excluding OS UI (taskbar, menu bar).
3️⃣ screen.colorDepth
console.log(screen.colorDepth);Explanation:
Number of bits per pixel used to display colors.
4️⃣ screen.pixelDepth
console.log(screen.pixelDepth);Explanation:
Color depth per pixel (usually same as colorDepth).
<div class="infographic-screenkinds">
<style>
.infographic-screenkinds {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--good-soft: #e1f2ea;
--mono-font: 'IBM Plex Mono', monospace;
--display-font: 'Fraunces', Georgia, serif;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
overflow-x: hidden;
}
.infographic-screenkinds[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--good-soft: #16281f;
}
.infographic-screenkinds * { box-sizing: border-box; }
.infographic-screenkinds h1 { font-family: var(--display-font); font-weight: 600; margin: 0; }
.infographic-screenkinds p { margin: 0; }
.infographic-screenkinds button { font-family: inherit; }
.sk-icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.15em; stroke: currentColor; flex-shrink: 0; }
.sk-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.sk-hero { text-align: center; margin-bottom: 1.1rem; }
.sk-hero h1 { font-size: clamp(1.3rem, 4.5vw, 1.8rem); }
.sk-hero p { color: var(--ink-soft); margin-top: 0.4rem; font-size: 0.86rem; }
/* --- device toggle --- */
.sk-device-row { display: flex; gap: 0.5rem; justify-content: center; margin-bottom: 1.1rem; }
.sk-device-btn { display: flex; align-items: center; gap: 0.4rem; border: 1px solid var(--line); background: var(--paper);
color: var(--ink-soft); padding: 0.5rem 1rem; font-size: 0.8rem; font-weight: 600; border-radius: 6px; cursor: pointer; }
.sk-device-btn.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
/* --- device illustration --- */
.sk-stage { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; margin-top: 1.4rem; margin-bottom: 1rem; }
.sk-screen-wrap { height: 236px; display: flex; align-items: center; justify-content: center; }
.sk-screen { position: relative; border: 2px solid var(--accent); border-radius: 6px; background: var(--paper);
transition: width 0.4s ease, height 0.4s ease, border-radius 0.4s ease; width: 220px; height: 128px; overflow: hidden; }
.sk-chrome { position: absolute; background: var(--paper-alt); display: none; }
.sk-chrome-taskbar { left: 0; right: 0; bottom: 0; height: 16px; border-top: 1px solid var(--line); }
.sk-chrome-taskbar::after { content: ""; position: absolute; left: 10px; top: 4px; width: 22px; height: 8px; border-radius: 2px; background: var(--ink-soft); opacity: 0.4; }
.sk-chrome-notch { top: 0; left: 50%; transform: translateX(-50%); width: 42%; height: 9px; border-radius: 0 0 7px 7px; }
.sk-chrome-home { left: 50%; bottom: 5px; transform: translateX(-50%); width: 32%; height: 4px; border-radius: 2px; background: var(--ink-soft); opacity: 0.4; }
.sk-screen.is-desktop .sk-chrome-taskbar { display: block; }
.sk-screen.is-mobile .sk-chrome-notch,
.sk-screen.is-mobile .sk-chrome-home { display: block; }
.sk-overlay { position: absolute; left: 0; right: 0; background: var(--accent); opacity: 0; transition: opacity 0.25s ease, top 0.3s ease, bottom 0.3s ease; }
.sk-overlay.is-avail { background: var(--good); }
.sk-overlay.is-shown { opacity: 0.3; }
.sk-current { text-align: center; font-family: var(--mono-font); font-size: 0.72rem; color: var(--ink-soft); min-height: 1.2em; }
.sk-current strong { color: var(--accent); }
/* --- properties list --- */
.sk-proptable { max-width: 520px; margin: 0 auto 1rem; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.sk-proprow { display: flex; align-items: center; gap: 0.6rem; padding: 0.6rem 0.9rem; border-top: 1px solid var(--line); cursor: pointer; transition: background 0.15s ease; }
.sk-proprow:first-child { border-top: none; }
.sk-proprow:hover { background: var(--accent-soft); }
.sk-proprow.is-active { background: var(--accent-soft); }
.sk-prop-name { font-family: var(--mono-font); font-size: 0.76rem; font-weight: 700; color: var(--accent); min-width: 190px; }
.sk-prop-desc { font-size: 0.76rem; color: var(--ink-soft); flex: 1; }
.sk-detail { max-width: 560px; margin: 0 auto; text-align: center; background: var(--paper-alt); border-left: 3px solid var(--accent); border-radius: 4px; padding: 0.8rem 1rem; }
.sk-detail-code { font-family: var(--mono-font); font-size: 0.78rem; color: var(--ink); margin-bottom: 0.35rem; white-space: pre-line; }
.sk-detail-desc { font-size: 0.78rem; color: var(--ink-soft); margin-bottom: 0.55rem; }
.sk-detail-out { font-family: var(--mono-font); font-size: 0.8rem; color: var(--good); font-weight: 700; white-space: pre-line; }
.sk-note { text-align: center; font-size: 0.8rem; color: var(--ink-soft); padding-top: 1.3rem; max-width: 560px; margin: 0 auto; }
.sk-note strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-screenkinds *, .infographic-screenkinds *::before, .infographic-screenkinds *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="sk-wrap">
<div class="sk-device-row">
<button class="sk-device-btn is-active" data-device="desktop" type="button">
<svg class="sk-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/></svg>
Desktop monitor
</button>
<button class="sk-device-btn" data-device="mobile" type="button">
<svg class="sk-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="2" width="12" height="20" rx="2"/><path d="M11 18h2"/></svg>
Mobile phone
</button>
</div>
<div class="sk-stage">
<div class="sk-screen-wrap">
<div class="sk-screen is-desktop" id="skScreen">
<div class="sk-overlay" id="skOverlay"></div>
<div class="sk-chrome sk-chrome-taskbar"></div>
<div class="sk-chrome sk-chrome-notch"></div>
<div class="sk-chrome sk-chrome-home"></div>
</div>
</div>
<div class="sk-current" id="skCurrent">now: <strong>Desktop monitor</strong></div>
</div>
<div class="sk-proptable" id="skTable">
<div class="sk-proprow is-active" data-prop="widthheight">
<span class="sk-prop-name">screen.width / height</span>
<span class="sk-prop-desc">total resolution, OS chrome included</span>
</div>
<div class="sk-proprow" data-prop="availwidthheight">
<span class="sk-prop-name">screen.availWidth / availHeight</span>
<span class="sk-prop-desc">usable area, OS chrome excluded</span>
</div>
<div class="sk-proprow" data-prop="colorDepth">
<span class="sk-prop-name">screen.colorDepth</span>
<span class="sk-prop-desc">bits per pixel for color</span>
</div>
<div class="sk-proprow" data-prop="pixelDepth">
<span class="sk-prop-name">screen.pixelDepth</span>
<span class="sk-prop-desc">usually identical to colorDepth</span>
</div>
</div>
<div class="sk-detail" id="skDetail">
<div class="sk-detail-code" id="skDetailCode">console.log(screen.width);
console.log(screen.height);</div>
<div class="sk-detail-desc" id="skDetailDesc">Total screen resolution, including reserved OS space.</div>
<div class="sk-detail-out" id="skDetailOut">1920 × 1080</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-screenkinds')
|| document.querySelector('.infographic-screenkinds');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const deviceBtns = wrapper.querySelectorAll('.sk-device-btn');
const rows = wrapper.querySelectorAll('.sk-proprow');
const screenEl = wrapper.querySelector('#skScreen');
const overlay = wrapper.querySelector('#skOverlay');
const current = wrapper.querySelector('#skCurrent');
const detailCode = wrapper.querySelector('#skDetailCode');
const detailDesc = wrapper.querySelector('#skDetailDesc');
const detailOut = wrapper.querySelector('#skDetailOut');
const note = wrapper.querySelector('#skNote');
const DEVICES = {
desktop: {
label: 'Desktop monitor',
width: 220, height: 128, radius: 6,
chromeFrac: 16 / 128,
values: {
widthheight: { w: 1920, h: 1080 },
availwidthheight: { w: 1920, h: 1040 },
colorDepth: 24,
pixelDepth: 24
}
},
mobile: {
label: 'Mobile phone',
width: 118, height: 220, radius: 14,
chromeFrac: 0,
values: {
widthheight: { w: 390, h: 844 },
availwidthheight: { w: 390, h: 844 },
colorDepth: 24,
pixelDepth: 24
}
}
};
const PROP_INFO = {
widthheight: {
code: 'console.log(screen.width);\nconsole.log(screen.height);',
desc: 'Total screen resolution, including reserved OS space.',
out: (d) => d.values.widthheight.w + ' \u00d7 ' + d.values.widthheight.h,
overlay: 'full'
},
availwidthheight: {
code: 'console.log(screen.availWidth);\nconsole.log(screen.availHeight);',
desc: 'Usable screen size, excluding OS chrome (taskbar, notch, dock).',
out: (d) => d.values.availwidthheight.w + ' \u00d7 ' + d.values.availwidthheight.h,
overlay: 'avail'
},
colorDepth: {
code: 'console.log(screen.colorDepth);',
desc: 'Bits per pixel used to display color on this screen.',
out: (d) => String(d.values.colorDepth),
overlay: 'none'
},
pixelDepth: {
code: 'console.log(screen.pixelDepth);',
desc: 'Color depth per pixel \u2014 almost always equal to colorDepth.',
out: (d) => String(d.values.pixelDepth),
overlay: 'none'
}
};
let deviceKey = 'desktop';
let propKey = 'widthheight';
function render() {
const device = DEVICES[deviceKey];
const info = PROP_INFO[propKey];
screenEl.style.width = device.width + 'px';
screenEl.style.height = device.height + 'px';
screenEl.style.borderRadius = device.radius + 'px';
screenEl.classList.toggle('is-desktop', deviceKey === 'desktop');
screenEl.classList.toggle('is-mobile', deviceKey === 'mobile');
current.innerHTML = 'now: <strong>' + device.label + '</strong>';
if (info.overlay === 'none') {
overlay.classList.remove('is-shown');
} else {
overlay.classList.add('is-shown');
overlay.classList.toggle('is-avail', info.overlay === 'avail');
const chromePx = device.height * device.chromeFrac;
if (info.overlay === 'avail' && deviceKey === 'desktop') {
overlay.style.top = '0';
overlay.style.bottom = chromePx + 'px';
} else {
overlay.style.top = '0';
overlay.style.bottom = '0';
}
}
detailCode.textContent = info.code;
detailDesc.textContent = info.desc;
detailOut.textContent = info.out(device);
rows.forEach(r => r.classList.toggle('is-active', r.dataset.prop === propKey));
deviceBtns.forEach(b => b.classList.toggle('is-active', b.dataset.device === deviceKey));
}
deviceBtns.forEach(btn => {
btn.addEventListener('click', () => {
deviceKey = btn.dataset.device;
render();
});
});
rows.forEach(row => {
row.addEventListener('click', () => {
propKey = row.dataset.prop;
render();
});
});
render();
})();
</script>📐 Screen Orientation
5️⃣ screen.orientation
<div class="infographic-screenorient">
<style>
.infographic-screenorient {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--good-soft: #e1f2ea;
--mono-font: 'IBM Plex Mono', monospace;
--display-font: 'Fraunces', Georgia, serif;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
overflow-x: hidden;
}
.infographic-screenorient[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--good-soft: #16281f;
}
.infographic-screenorient * { box-sizing: border-box; }
.infographic-screenorient h1 { font-family: var(--display-font); font-weight: 600; margin: 0; }
.infographic-screenorient p { margin: 0; }
.infographic-screenorient button { font-family: inherit; }
.so-icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.15em; stroke: currentColor; flex-shrink: 0; }
.so-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.so-hero { text-align: center; margin-bottom: 1.1rem; }
.so-hero h1 { font-size: clamp(1.3rem, 4.5vw, 1.75rem); }
.so-hero p { color: var(--ink-soft); margin-top: 0.4rem; font-size: 0.86rem; }
.so-code { background: #1e1e1e; color: #d4d4d4; border-radius: 5px; padding: 0.6rem 0.8rem; font-family: var(--mono-font); font-size: 0.72rem; margin: 0 auto 1.1rem; max-width: 340px; text-align: left; }
.tok-fn { color: #dcdcaa; }
.tok-punc { color: #d4d4d4; }
.tok-var { color: #9cdcfe; }
.tok-prop { color: #9cdcfe; }
.so-shape-wrap { text-align: center; margin-bottom: 0.5rem; }
.so-shape { display: inline-block; border: 2px solid var(--accent); border-radius: 5px; background: var(--accent-soft); transition: width 0.35s ease, height 0.35s ease, transform 0.35s ease; width: 96px; height: 62px; position: relative; }
.so-shape::after { content: ""; position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); width: 14px; height: 3px; border-radius: 2px; background: var(--accent); opacity: 0.5; }
.so-shape.is-secondary { transform: rotate(180deg); }
.so-shape-caption { text-align: center; font-family: var(--mono-font); font-size: 0.68rem; color: var(--ink-soft); margin-bottom: 1rem; min-height: 1.2em; }
.so-shape-caption strong { color: var(--ink); }
.so-values { max-width: 380px; margin: 0 auto; display: flex; flex-direction: column; gap: 0.35rem; }
.so-value-row { font-family: var(--mono-font); font-size: 0.74rem; padding: 0.4rem 0.7rem; border: 1px solid var(--line); border-radius: 5px; color: var(--ink-soft); cursor: pointer; transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease; }
.so-value-row:hover { border-color: var(--accent); color: var(--accent); }
.so-value-row.is-previewed { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 700; }
.so-values-hint { text-align: center; font-family: var(--mono-font); font-size: 0.64rem; color: var(--ink-soft); margin-bottom: 0.5rem; }
.so-note { text-align: center; font-size: 0.8rem; color: var(--ink-soft); padding-top: 1.3rem; max-width: 520px; margin: 0 auto; }
.so-note strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-screenorient *, .infographic-screenorient *::before, .infographic-screenorient *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="so-wrap">
<div class="so-code"><span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-var">screen</span><span class="tok-punc">.</span><span class="tok-prop">orientation</span><span class="tok-punc">.</span><span class="tok-prop">type</span><span class="tok-punc">);</span></div>
<div class="so-shape-wrap">
<div class="so-shape" id="soShape"></div>
</div>
<div class="so-shape-caption" id="soShapeCaption">click a value below, or read the live one above</div>
<div class="so-values-hint">click any value to preview it on the screen above</div>
<div class="so-values" id="soValues">
<div class="so-value-row" data-val="landscape-primary">landscape-primary</div>
<div class="so-value-row" data-val="landscape-secondary">landscape-secondary</div>
<div class="so-value-row" data-val="portrait-primary">portrait-primary</div>
<div class="so-value-row" data-val="portrait-secondary">portrait-secondary</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-screenorient')
|| document.querySelector('.infographic-screenorient');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const shape = wrapper.querySelector('#soShape');
const shapeCaption = wrapper.querySelector('#soShapeCaption');
const valueRows = wrapper.querySelectorAll('.so-value-row');
const CAPTIONS = {
'landscape-primary': 'Wide, right-side up — the default landscape rotation.',
'landscape-secondary': 'Wide, but flipped 180° — landscape upside-down.',
'portrait-primary': 'Tall, right-side up — the default portrait rotation.',
'portrait-secondary': 'Tall, but flipped 180° — portrait upside-down.'
};
function applyShape(type) {
if (type.indexOf('landscape') === 0) {
shape.style.width = '96px';
shape.style.height = '62px';
} else {
shape.style.width = '62px';
shape.style.height = '96px';
}
shape.classList.toggle('is-secondary', type.indexOf('secondary') !== -1);
shapeCaption.innerHTML = 'showing: <strong>' + type + '</strong> — ' + CAPTIONS[type];
}
function previewType(type) {
valueRows.forEach(r => r.classList.toggle('is-previewed', r.dataset.val === type));
applyShape(type);
}
valueRows.forEach(row => {
row.addEventListener('click', () => previewType(row.dataset.val));
});
previewType('landscape-primary');
})();
</script>Detect Orientation Change
<div class="infographic-orientchange">
<style>
.infographic-orientchange {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--good-soft: #e1f2ea;
--mono-font: 'IBM Plex Mono', monospace;
--display-font: 'Fraunces', Georgia, serif;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
overflow-x: hidden;
}
.infographic-orientchange[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--good-soft: #16281f;
}
.infographic-orientchange * { box-sizing: border-box; }
.infographic-orientchange h1 { font-family: var(--display-font); font-weight: 600; margin: 0; }
.infographic-orientchange p { margin: 0; }
.infographic-orientchange button { font-family: inherit; }
.oc-icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.15em; stroke: currentColor; flex-shrink: 0; }
.oc-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.oc-hero { text-align: center; margin-bottom: 1.1rem; }
.oc-hero h1 { font-size: clamp(1.3rem, 4.5vw, 1.75rem); }
.oc-hero p { color: var(--ink-soft); margin-top: 0.4rem; font-size: 0.86rem; }
.oc-code { background: #1e1e1e; color: #d4d4d4; border-radius: 5px; padding: 0.6rem 0.8rem; font-family: var(--mono-font); font-size: 0.72rem; margin: 0 auto 1.3rem; max-width: 340px; text-align: left; transition: box-shadow 0.25s ease; }
.oc-code.is-firing { box-shadow: 0 0 0 2px var(--accent); }
.tok-fn { color: #dcdcaa; }
.tok-punc { color: #d4d4d4; }
.tok-var { color: #9cdcfe; }
.tok-prop { color: #9cdcfe; }
.tok-kw { color: #569cd6; }
.tok-str { color: #ce9178; }
.oc-stage { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; margin-bottom: 1.3rem; }
.oc-shape-wrap { position: relative; height: 100px; display: flex; align-items: center; justify-content: center; }
.oc-shape { display: inline-block; border: 2px solid var(--accent); border-radius: 5px; background: var(--accent-soft); transition: width 0.4s ease, height 0.4s ease; width: 96px; height: 62px; position: relative; }
.oc-shape::after { content: ""; position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); width: 14px; height: 3px; border-radius: 2px; background: var(--accent); opacity: 0.5; }
.oc-shape.is-secondary::after { top: 4px; bottom: auto; }
.oc-current { text-align: center; font-family: var(--mono-font); font-size: 0.72rem; color: var(--ink-soft); min-height: 1.2em; }
.oc-current strong { color: var(--accent); }
.oc-btn { display: flex; align-items: center; gap: 0.45rem; margin: 0 auto; background: var(--accent); color: #fff; border: none;
border-radius: 5px; padding: 0.55rem 1.1rem; font-size: 0.82rem; font-weight: 600; cursor: pointer; transition: opacity 0.15s ease, transform 0.1s ease; }
.oc-btn:hover { opacity: 0.88; }
.oc-btn:active { transform: scale(0.97); }
.oc-btn:disabled { opacity: 0.55; cursor: default; }
.oc-log-label { text-align: center; font-family: var(--mono-font); font-size: 0.64rem; color: var(--ink-soft); margin: 1.3rem 0 0.5rem; text-transform: uppercase; letter-spacing: 0.04em; }
.oc-log { max-width: 420px; margin: 0 auto; border: 1px solid var(--line); border-radius: 5px; background: var(--paper-alt);
min-height: 6.4rem; max-height: 9.5rem; overflow-y: auto; padding: 0.5rem 0.7rem; font-family: var(--mono-font); font-size: 0.7rem; }
.oc-log-empty { color: var(--ink-soft); opacity: 0.7; }
.oc-log-entry { display: flex; gap: 0.5rem; padding: 0.2rem 0; color: var(--ink-soft); animation: oc-fade-in 0.25s ease; }
.oc-log-entry .oc-log-idx { color: var(--good); flex-shrink: 0; }
.oc-log-entry .oc-log-text { color: var(--ink); }
@keyframes oc-fade-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: translateY(0); } }
.oc-note { text-align: center; font-size: 0.8rem; color: var(--ink-soft); padding-top: 1.4rem; max-width: 520px; margin: 0 auto; }
.oc-note strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-orientchange *, .infographic-orientchange *::before, .infographic-orientchange *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="oc-wrap">
<div class="oc-code" id="ocCode"><span class="tok-var">screen</span><span class="tok-punc">.</span><span class="tok-prop">orientation</span><span class="tok-punc">.</span><span class="tok-prop">onchange</span> <span class="tok-punc">=</span> <span class="tok-punc">()</span> <span class="tok-punc">=></span> <span class="tok-punc">{</span><br> <span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-str">"Orientation changed"</span><span class="tok-punc">);</span><br><span class="tok-punc">};</span></div>
<div class="oc-stage">
<div class="oc-shape-wrap">
<div class="oc-shape" id="ocShape"></div>
</div>
<div class="oc-current" id="ocCurrent">now: <strong>landscape-primary</strong></div>
<button class="oc-btn" id="ocRotateBtn" type="button">
<svg class="oc-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 3v6h-6"/></svg>
Rotate device
</button>
</div>
<div class="oc-log-label">onchange fires →</div>
<div class="oc-log" id="ocLog">
<div class="oc-log-empty">nothing yet — rotate the device above</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-orientchange')
|| document.querySelector('.infographic-orientchange');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const shape = wrapper.querySelector('#ocShape');
const current = wrapper.querySelector('#ocCurrent');
const btn = wrapper.querySelector('#ocRotateBtn');
const codeBlock = wrapper.querySelector('#ocCode');
const log = wrapper.querySelector('#ocLog');
const SEQUENCE = ['landscape-primary', 'portrait-primary', 'landscape-secondary', 'portrait-secondary'];
let idx = 0;
let count = 0;
let firing = false;
function applyShape(type) {
if (type.indexOf('landscape') === 0) {
shape.style.width = '96px';
shape.style.height = '62px';
} else {
shape.style.width = '62px';
shape.style.height = '96px';
}
shape.classList.toggle('is-secondary', type.indexOf('secondary') !== -1);
}
function addLogEntry(type) {
count += 1;
if (count === 1) log.innerHTML = '';
const row = document.createElement('div');
row.className = 'oc-log-entry';
row.innerHTML = '<span class="oc-log-idx">#' + count + '</span>' +
'<span class="oc-log-text">"Orientation changed" \u2014 now ' + type + '</span>';
log.appendChild(row);
log.scrollTop = log.scrollHeight;
}
btn.addEventListener('click', () => {
if (firing) return;
firing = true;
btn.disabled = true;
idx = (idx + 1) % SEQUENCE.length;
const type = SEQUENCE[idx];
applyShape(type);
current.innerHTML = 'now: <strong>' + type + '</strong>';
codeBlock.classList.add('is-firing');
setTimeout(() => {
addLogEntry(type);
codeBlock.classList.remove('is-firing');
btn.disabled = false;
firing = false;
}, 260);
});
})();
</script>🧠 Screen vs Window Size
<div class="infographic-screenwindow">
<style>
.infographic-screenwindow {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--good-soft: #e1f2ea;
--mono-font: 'IBM Plex Mono', monospace;
--display-font: 'Fraunces', Georgia, serif;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
overflow-x: hidden;
}
.infographic-screenwindow[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--good-soft: #16281f;
}
.infographic-screenwindow * { box-sizing: border-box; }
.infographic-screenwindow h1 { font-family: var(--display-font); font-weight: 600; margin: 0; }
.infographic-screenwindow p { margin: 0; }
.infographic-screenwindow button { font-family: inherit; }
.ws-icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.15em; stroke: currentColor; flex-shrink: 0; }
.ws-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.ws-hero { text-align: center; margin-bottom: 1.1rem; }
.ws-hero h1 { font-size: clamp(1.3rem, 4.5vw, 1.8rem); }
.ws-hero p { color: var(--ink-soft); margin-top: 0.4rem; font-size: 0.86rem; }
.ws-device-row { display: flex; gap: 0.5rem; justify-content: center; margin-bottom: 1.4rem; }
.ws-device-btn { display: flex; align-items: center; gap: 0.4rem; border: 1px solid var(--line); background: var(--paper);
color: var(--ink-soft); padding: 0.5rem 1rem; font-size: 0.8rem; font-weight: 600; border-radius: 6px; cursor: pointer; }
.ws-device-btn.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.ws-stage { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; margin-bottom: 1.1rem; }
.ws-screen-wrap { height: 260px; display: flex; align-items: center; justify-content: center; }
.ws-screen { position: relative; border: 2px dashed var(--line); border-radius: 6px; background: var(--paper-alt);
transition: width 0.4s ease, height 0.4s ease; }
.ws-screen-tag { position: absolute; top: -1.5rem; left: 0; font-family: var(--mono-font); font-size: 0.64rem; color: var(--ink-soft); }
.ws-window { position: absolute; top: 0; left: 0; background: var(--accent-soft); border: 2px solid var(--accent);
border-radius: 3px; overflow: hidden; touch-action: none; }
.ws-window-bar { height: 12px; background: var(--paper); border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 3px; padding: 0 5px; }
.ws-window-bar .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--ink-soft); opacity: 0.5; }
.ws-resize-handle { position: absolute; right: 0; bottom: 0; width: 16px; height: 16px; cursor: nwse-resize;
touch-action: none; }
.ws-resize-handle::after { content: ""; position: absolute; right: 3px; bottom: 3px; width: 8px; height: 8px;
border-right: 2px solid var(--accent); border-bottom: 2px solid var(--accent); opacity: 0.7; }
.ws-legend { display: flex; gap: 1.1rem; justify-content: center; flex-wrap: wrap; font-family: var(--mono-font); font-size: 0.68rem; color: var(--ink-soft); }
.ws-legend span { display: inline-flex; align-items: center; gap: 0.35rem; }
.ws-swatch { width: 11px; height: 11px; border-radius: 2px; display: inline-block; }
.ws-swatch.screen { border: 2px dashed var(--line); background: var(--paper-alt); }
.ws-swatch.window { border: 2px solid var(--accent); background: var(--accent-soft); }
.ws-readout { max-width: 460px; margin: 1.2rem auto 1rem; display: flex; flex-direction: column; gap: 0.4rem; }
.ws-readout-row { display: flex; justify-content: space-between; gap: 0.6rem; font-family: var(--mono-font);
font-size: 0.76rem; border: 1px solid var(--line); border-radius: 5px; padding: 0.45rem 0.75rem; }
.ws-readout-row .ws-label { color: var(--ink-soft); }
.ws-readout-row .ws-val { color: var(--accent); font-weight: 700; }
.ws-readout-row.is-window .ws-val { color: var(--good); }
.ws-code { background: #1e1e1e; color: #d4d4d4; border-radius: 5px; padding: 0.6rem 0.8rem; font-family: var(--mono-font);
font-size: 0.7rem; margin: 0 auto 1rem; max-width: 420px; text-align: left; white-space: pre-line; }
.tok-fn { color: #dcdcaa; }
.tok-punc { color: #d4d4d4; }
.tok-var { color: #9cdcfe; }
.tok-prop { color: #9cdcfe; }
.tok-str { color: #ce9178; }
.ws-note { text-align: center; font-size: 0.8rem; color: var(--ink-soft); max-width: 560px; margin: 0 auto; }
.ws-note strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-screenwindow *, .infographic-screenwindow *::before, .infographic-screenwindow *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ws-wrap">
<div class="ws-device-row">
<button class="ws-device-btn is-active" data-device="desktop" type="button">
<svg class="ws-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/></svg>
Desktop monitor
</button>
<button class="ws-device-btn" data-device="mobile" type="button">
<svg class="ws-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="2" width="12" height="20" rx="2"/><path d="M11 18h2"/></svg>
Mobile phone
</button>
</div>
<div class="ws-stage">
<div class="ws-screen-wrap">
<div class="ws-screen" id="wsScreen">
<div class="ws-window" id="wsWindow">
<div class="ws-window-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>
<div class="ws-resize-handle" id="wsHandle"></div>
</div>
</div>
</div>
<div class="ws-legend">
<span><span class="ws-swatch screen"></span>screen (can't drag)</span>
<span><span class="ws-swatch window"></span>window (drag the corner)</span>
</div>
</div>
<div class="ws-readout">
<div class="ws-readout-row is-screen">
<span class="ws-label">screen.width, screen.height</span>
<span class="ws-val" id="wsScreenVal">1920, 1080</span>
</div>
<div class="ws-readout-row is-window">
<span class="ws-label">window.innerWidth, window.innerHeight</span>
<span class="ws-val" id="wsWindowVal">1440, 810</span>
</div>
</div>
<div class="ws-code"><span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-str">"Screen:"</span><span class="tok-punc">,</span> <span class="tok-var">screen</span><span class="tok-punc">.</span><span class="tok-prop">width</span><span class="tok-punc">,</span> <span class="tok-var">screen</span><span class="tok-punc">.</span><span class="tok-prop">height</span><span class="tok-punc">);</span>
<span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-str">"Window:"</span><span class="tok-punc">,</span> <span class="tok-var">window</span><span class="tok-punc">.</span><span class="tok-prop">innerWidth</span><span class="tok-punc">,</span> <span class="tok-var">window</span><span class="tok-punc">.</span><span class="tok-prop">innerHeight</span><span class="tok-punc">);</span></div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-screenwindow')
|| document.querySelector('.infographic-screenwindow');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const deviceBtns = wrapper.querySelectorAll('.ws-device-btn');
const screenEl = wrapper.querySelector('#wsScreen');
const windowEl = wrapper.querySelector('#wsWindow');
const handle = wrapper.querySelector('#wsHandle');
const screenVal = wrapper.querySelector('#wsScreenVal');
const windowVal = wrapper.querySelector('#wsWindowVal');
const note = wrapper.querySelector('#wsNote');
const DEVICES = {
desktop: {
label: 'Desktop monitor',
real: { w: 1920, h: 1080 },
displayPx: { w: 280, h: 158 },
windowFrac: { w: 0.75, h: 0.75 },
minFrac: 0.25,
note: '<strong>screen.*</strong> describes the physical display and never changes. <strong>window.inner*</strong> is the visible viewport \u2014 it shrinks with every resize, split-screen, or zoom.'
},
mobile: {
label: 'Mobile phone',
real: { w: 390, h: 844 },
displayPx: { w: 122, h: 224 },
windowFrac: { w: 1, h: 0.94 },
minFrac: 0.4,
note: 'Mobile browsers are usually fullscreen, so <strong>window.inner*</strong> nearly equals <strong>screen.*</strong> \u2014 only the address bar trims a little height.'
}
};
let deviceKey = 'desktop';
let winFracW, winFracH;
let dragging = false, startX = 0, startY = 0, startW = 0, startH = 0;
function updateReadout() {
const d = DEVICES[deviceKey];
screenVal.textContent = d.real.w + ', ' + d.real.h;
const realW = Math.round(d.real.w * winFracW);
const realH = Math.round(d.real.h * winFracH);
windowVal.textContent = realW + ', ' + realH;
}
function applyWindowSize() {
const d = DEVICES[deviceKey];
const px_w = Math.round(d.displayPx.w * winFracW);
const px_h = Math.round(d.displayPx.h * winFracH);
windowEl.style.width = px_w + 'px';
windowEl.style.height = px_h + 'px';
updateReadout();
}
function setDevice(key) {
deviceKey = key;
const d = DEVICES[key];
screenEl.style.width = d.displayPx.w + 'px';
screenEl.style.height = d.displayPx.h + 'px';
winFracW = d.windowFrac.w;
winFracH = d.windowFrac.h;
applyWindowSize();
deviceBtns.forEach(b => b.classList.toggle('is-active', b.dataset.device === key));
note.innerHTML = d.note;
}
handle.addEventListener('pointerdown', (e) => {
dragging = true;
handle.setPointerCapture(e.pointerId);
startX = e.clientX;
startY = e.clientY;
startW = windowEl.getBoundingClientRect().width;
startH = windowEl.getBoundingClientRect().height;
e.preventDefault();
});
handle.addEventListener('pointermove', (e) => {
if (!dragging) return;
const d = DEVICES[deviceKey];
const minPx = d.displayPx.w * d.minFrac;
const minPxH = d.displayPx.h * d.minFrac;
let newW = Math.min(d.displayPx.w, Math.max(minPx, startW + (e.clientX - startX)));
let newH = Math.min(d.displayPx.h, Math.max(minPxH, startH + (e.clientY - startY)));
winFracW = newW / d.displayPx.w;
winFracH = newH / d.displayPx.h;
applyWindowSize();
});
function stopDrag() { dragging = false; }
handle.addEventListener('pointerup', stopDrag);
handle.addEventListener('pointercancel', stopDrag);
deviceBtns.forEach(btn => {
btn.addEventListener('click', () => setDevice(btn.dataset.device));
});
setDevice('desktop');
})();
</script>🎯 Practical Use Cases
Use Case | Why |
|---|---|
Responsive logic | Large screens vs small |
Fullscreen apps | Use full resolution |
Orientation apps | Mobile/tablet UI |
Analytics | Device type detection |
⭐ Important Notes
screendoes not change on resizeWindow resize affects
innerWidth, notscreenMainly used for device-level decisions
✅ Summary
screengives physical display infoPart of BOM under
windowUseful for responsive and device-aware apps