π What is BOM?
BOM (Browser Object Model) allows JavaScript to interact with the browser itself, not just the web page.
It provides objects to control:
Browser window
URL
History
Screen
User actions (alerts, navigation, etc.)
π¦ Main BOM Objects
windowThe top-level object of the browser
All BOM objects are part of
window
window.alert("Hello!");locationUsed to get or change the current URL
console.log(location.href); location.reload();historyManages browser navigation (back/forward)
history.back(); history.forward();navigatorProvides browser and device information
console.log(navigator.userAgent);screenGives screen size information
console.log(screen.width, screen.height);
π BOM vs DOM
BOM | DOM |
|---|---|
Controls browser | Controls HTML document |
Deals with window, URL, history | Deals with elements, tags |
Browser-related | Page-related |
<div class="infographic-bomdomart">
<style>
.infographic-bomdomart {
--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-bomdomart[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-bomdomart * { box-sizing: border-box; }
.infographic-bomdomart h1 { font-family: var(--display-font); font-weight: 600; margin: 0; }
.infographic-bomdomart p { margin: 0; }
.infographic-bomdomart button { font-family: inherit; }
.ba-icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.15em; stroke: currentColor; flex-shrink: 0; }
.ba-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.ba-hero { text-align: center; margin-bottom: 1.3rem; }
.ba-hero h1 { font-size: clamp(1.35rem, 4.5vw, 1.9rem); }
.ba-hero p { color: var(--ink-soft); margin-top: 0.45rem; font-size: 0.86rem; max-width: 480px; margin-left: auto; margin-right: auto; }
.ba-panels { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; margin-bottom: 1.1rem; }
@media (max-width: 640px) {
.ba-panels { grid-template-columns: 1fr; }
}
.ba-panel-title { display: flex; align-items: center; justify-content: center; gap: 0.4rem; font-family: var(--mono-font); font-weight: 700; font-size: 0.86rem; margin-bottom: 0.6rem; }
.ba-panel[data-side="bom"] .ba-panel-title { color: var(--accent); }
.ba-panel[data-side="dom"] .ba-panel-title { color: var(--good); }
.ba-panel-title .ba-icon { width: 15px; height: 15px; }
/* --- BOM browser chrome illustration --- */
.ba-browser { border: 1.5px solid var(--line); border-radius: 8px; overflow: hidden; background: var(--paper); }
.ba-browser svg { display: block; width: 100%; height: auto; }
.ba-hotspot { cursor: pointer; transition: opacity 0.15s ease; }
.ba-hotspot rect, .ba-hotspot circle, .ba-hotspot path.ba-hs-shape { transition: fill 0.2s ease, stroke 0.2s ease; }
.ba-hotspot:hover .ba-hs-shape, .ba-hotspot.is-active .ba-hs-shape { fill: var(--accent-soft); stroke: var(--accent); }
.ba-hotspot:hover .ba-hs-icon, .ba-hotspot.is-active .ba-hs-icon { stroke: var(--accent); }
/* --- DOM nested tag illustration --- */
.ba-dom-tree { border: 1.5px solid var(--line); border-radius: 8px; padding: 0.9rem; background: var(--paper-alt); min-height: 220px; }
.ba-tag-box { border: 1.5px dashed var(--line); border-radius: 6px; padding: 0.55rem 0.55rem 0.55rem; position: relative; margin-top: 0.9rem; cursor: pointer; transition: border-color 0.2s ease, background 0.2s ease; background: var(--paper); }
.ba-tag-box:first-child { margin-top: 0; }
.ba-tag-pill { position: absolute; top: -0.65rem; left: 0.5rem; background: var(--paper); padding: 0 0.35rem; font-family: var(--mono-font); font-size: 0.66rem; font-weight: 700; color: var(--ink-soft); }
.ba-tag-box.is-active { border-color: var(--good); border-style: solid; background: var(--good-soft); }
.ba-tag-box.is-active > .ba-tag-pill { color: var(--good); }
.ba-tag-inner { display: flex; flex-direction: column; gap: 0.55rem; }
.ba-leaf { border: 1px solid var(--line); border-radius: 5px; padding: 0.4rem 0.5rem; font-size: 0.7rem; color: var(--ink-soft); background: var(--paper); text-align: center; }
.ba-legend { min-height: 4rem; max-width: 620px; margin: 0.3rem auto 1.3rem; text-align: center; background: var(--paper-alt); border-left: 3px solid var(--line); border-radius: 4px; padding: 0.75rem 1rem; font-size: 0.82rem; color: var(--ink-soft); line-height: 1.5; transition: border-color 0.2s ease; }
.ba-legend strong { color: var(--ink); font-family: var(--mono-font); }
.ba-legend.ba-legend-bom { border-left-color: var(--accent); }
.ba-legend.ba-legend-dom { border-left-color: var(--good); }
.ba-note { text-align: center; font-size: 0.8rem; color: var(--ink-soft); padding-top: 0.5rem; max-width: 580px; margin: 0 auto; }
.ba-note strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-bomdomart *, .infographic-bomdomart *::before, .infographic-bomdomart *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ba-wrap">
<div class="ba-panels">
<div class="ba-panel" data-side="bom">
<div class="ba-panel-title">
<svg class="ba-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M10 4v4"/><path d="M2 8h20"/><path d="M6 4v4"/></svg>
BOM β the browser
</div>
<div class="ba-browser">
<svg viewBox="0 0 300 190" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="300" height="190" fill="var(--paper)"/>
<rect x="0" y="0" width="300" height="46" fill="var(--paper-alt)"/>
<!-- traffic light dots (navigator/menu hotspot) -->
<g class="ba-hotspot" data-part="navigator">
<rect class="ba-hs-shape" x="4" y="4" width="46" height="20" rx="5" fill="transparent" stroke="transparent" stroke-width="1.5"/>
<circle cx="14" cy="14" r="4" fill="#e0645a"/>
<circle cx="27" cy="14" r="4" fill="#e0b04a"/>
<circle cx="40" cy="14" r="4" fill="#5cb87a"/>
</g>
<!-- back/forward (history hotspot) -->
<g class="ba-hotspot" data-part="history">
<rect class="ba-hs-shape" x="4" y="27" width="52" height="16" rx="4" fill="transparent" stroke="transparent" stroke-width="1.5"/>
<path class="ba-hs-icon" d="M14 30 L9 35 L14 40" fill="none" stroke="var(--ink-soft)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
<path class="ba-hs-icon" d="M28 30 L33 35 L28 40" fill="none" stroke="var(--ink-soft)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
<path class="ba-hs-icon" d="M43 35 a5 5 0 1 1 -1.5 -3.5" fill="none" stroke="var(--ink-soft)" stroke-width="1.4" stroke-linecap="round"/>
</g>
<!-- address bar (location hotspot) -->
<g class="ba-hotspot" data-part="location">
<rect class="ba-hs-shape" x="62" y="27" width="234" height="16" rx="8" fill="var(--paper)" stroke="var(--line)" stroke-width="1.2"/>
<rect class="ba-hs-icon" x="70" y="31.5" width="7" height="6" rx="1.5" fill="none" stroke="var(--ink-soft)" stroke-width="1.3"/>
<path class="ba-hs-icon" d="M71.5 31.5 v-2 a2 2 0 0 1 4 0 v2" fill="none" stroke="var(--ink-soft)" stroke-width="1.3"/>
<text x="84" y="38.5" font-family="var(--mono-font)" font-size="7.5" fill="var(--ink-soft)">codeveda.dev/lesson</text>
</g>
<!-- page canvas (whole window hotspot) -->
<g class="ba-hotspot" data-part="window">
<rect class="ba-hs-shape" x="10" y="56" width="280" height="122" rx="4" fill="var(--paper-alt)" stroke="var(--line)" stroke-width="1.2" stroke-dasharray="4 3"/>
<text x="150" y="122" font-family="var(--mono-font)" font-size="9" fill="var(--ink-soft)" text-anchor="middle">the page β see DOM β</text>
</g>
<!-- screen/monitor corner tag -->
<g class="ba-hotspot" data-part="screen">
<rect class="ba-hs-shape" x="255" y="4" width="42" height="20" rx="5" fill="transparent" stroke="transparent" stroke-width="1.5"/>
<rect class="ba-hs-icon" x="262" y="8" width="16" height="11" rx="1.5" fill="none" stroke="var(--ink-soft)" stroke-width="1.4"/>
<line class="ba-hs-icon" x1="267" y1="21" x2="273" y2="21" stroke="var(--ink-soft)" stroke-width="1.4"/>
</g>
</svg>
</div>
</div>
<div class="ba-panel" data-side="dom">
<div class="ba-panel-title">
<svg class="ba-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>
DOM β the page
</div>
<div class="ba-dom-tree">
<div class="ba-tag-box" data-part="html">
<span class="ba-tag-pill"><html></span>
<div class="ba-tag-inner">
<div class="ba-tag-box" data-part="body">
<span class="ba-tag-pill"><body></span>
<div class="ba-tag-inner">
<div class="ba-leaf" data-part="header"><header></div>
<div class="ba-leaf" data-part="main"><div class="content"></div>
<div class="ba-leaf" data-part="footer"><footer></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="ba-legend" id="baLegend">Click any part of either illustration β the address bar, the back button, an HTML tag β to see what it actually is.</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-bomdomart')
|| document.querySelector('.infographic-bomdomart');
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 INFO = {
navigator: { side: 'bom', html: '<strong>window.navigator</strong> β info about the browser itself: name, version, online status.' },
history: { side: 'bom', html: '<strong>window.history</strong> β the back/forward stack for this tab.' },
location: { side: 'bom', html: '<strong>window.location</strong> β the current URL, and tools to read or change it.' },
window: { side: 'bom', html: '<strong>window</strong> β the whole browser tab. This dashed area is where the DOM lives, but the frame around it is BOM territory.' },
screen: { side: 'bom', html: '<strong>window.screen</strong> β the physical display: resolution and available space.' },
html: { side: 'dom', html: '<strong><html></strong> β the root element of the DOM tree. Everything else nests inside it.' },
body: { side: 'dom', html: '<strong><body></strong> β holds everything visible on the page.' },
header: { side: 'dom', html: '<strong><header></strong> β one element node, same as any other tag: readable and editable via the DOM.' },
main: { side: 'dom', html: '<strong><div class="content"></strong> β just another DOM node with a class attribute.' },
footer: { side: 'dom', html: '<strong><footer></strong> β another child of <body> in the tree.' }
};
const legend = wrapper.querySelector('#baLegend');
const hotspots = wrapper.querySelectorAll('.ba-hotspot');
const tagBoxes = wrapper.querySelectorAll('[data-part].ba-tag-box, [data-part].ba-leaf');
function clearActive() {
hotspots.forEach(h => h.classList.remove('is-active'));
tagBoxes.forEach(t => t.classList.remove('is-active'));
}
function show(part, el) {
const info = INFO[part];
if (!info) return;
clearActive();
if (el) el.classList.add('is-active');
legend.innerHTML = info.html;
legend.classList.remove('ba-legend-bom', 'ba-legend-dom');
legend.classList.add(info.side === 'bom' ? 'ba-legend-bom' : 'ba-legend-dom');
}
hotspots.forEach(hs => {
hs.addEventListener('click', () => show(hs.dataset.part, hs));
});
tagBoxes.forEach(tb => {
tb.addEventListener('click', (e) => {
e.stopPropagation();
show(tb.dataset.part, tb);
});
});
})();
</script>β Key Point
BOM is not standardized like DOM
Supported by all modern browsers
Used for navigation, alerts, and browser control