Conditional visibility based on which device, operating system, or browser the visitor is using.
Copy this javascript code and insert before the </body> tag of your project.
const OU_CFG = {
showAttr: 'ou-device-show-if',
hideAttr: 'ou-device-hide-if',
debug: false
};
document.addEventListener('DOMContentLoaded', () => {
const DETECT = {
mobile: () => /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
tablet: () => /iPad|Android|Silk/i.test(navigator.userAgent) && !/Mobile/i.test(navigator.userAgent),
desktop: () => !(/Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)),
touch: () => ('ontouchstart' in window) || (navigator.maxTouchPoints > 0),
portrait: () => matchMedia('(orientation: portrait)').matches,
landscape:() => matchMedia('(orientation: landscape)').matches,
ios: () => /iPad|iPhone|iPod/.test(navigator.userAgent),
android: () => /Android/.test(navigator.userAgent),
macos: () => /Mac OS X/.test(navigator.userAgent) && !/iPad|iPhone|iPod/.test(navigator.userAgent),
windows: () => /Win/.test(navigator.platform),
linux: () => /Linux/.test(navigator.platform),
chrome: () => (/Chrome|CriOS/i.test(navigator.userAgent)) && !/Edg|OPR/i.test(navigator.userAgent),
firefox: () => /Firefox/i.test(navigator.userAgent),
safari: () => /Safari/i.test(navigator.userAgent) && !/Chrome|Chromium|Edg|OPR|CriOS/i.test(navigator.userAgent),
edge: () => /Edg/i.test(navigator.userAgent),
opera: () => /OPR|Opera/i.test(navigator.userAgent),
};
const TAG_DEFAULT_DISPLAY = {
DIV:'block', SECTION:'block', ARTICLE:'block', HEADER:'block', FOOTER:'block', NAV:'block',
UL:'block', OL:'block', LI:'list-item',
SPAN:'inline', A:'inline', STRONG:'inline', EM:'inline', SMALL:'inline',
IMG:'inline-block', SVG:'inline-block', CANVAS:'inline-block', BUTTON:'inline-block',
INPUT:'inline-block', SELECT:'inline-block', TEXTAREA:'inline-block',
TABLE:'table', THEAD:'table-header-group', TBODY:'table-row-group', TFOOT:'table-footer-group',
TR:'table-row', TD:'table-cell', TH:'table-cell'
};
function getTokens() {
const t = [];
for (const [k, fn] of Object.entries(DETECT)) { try { if (fn()) t.push(k); } catch(_){} }
if (OU_CFG.debug) console.log('[ou] tokens:', t);
return t;
}
function matchesRule(value, tokens) {
if (!value) return false;
const list = String(value).toLowerCase().trim().split(/\s+/).filter(Boolean);
return list.some(tok => tokens.includes(tok));
}
function readAttr(el, name) {
return el.getAttribute(name) ?? el.getAttribute('data-' + name) ?? '';
}
function ensureBaseline(el) {
if (el.dataset.ouDisplayBaseline) return;
const computed = getComputedStyle(el).display;
if (computed && computed !== 'none') {
el.dataset.ouDisplayBaseline = computed;
} else {
const tag = el.tagName.toUpperCase();
el.dataset.ouDisplayBaseline = TAG_DEFAULT_DISPLAY[tag] || 'block';
}
}
function showEl(el) {
ensureBaseline(el);
el.style.setProperty('display', el.dataset.ouDisplayBaseline, 'important');
}
function hideEl(el) {
el.style.setProperty('display', 'none', 'important');
}
function applyVisibility() {
const tokens = getTokens();
const selector = [`[${OU_CFG.showAttr}]`,`[${OU_CFG.hideAttr}]`,`[data-${OU_CFG.showAttr}]`,`[data-${OU_CFG.hideAttr}]`].join(',');
document.querySelectorAll(selector).forEach(el => {
const showVal = readAttr(el, OU_CFG.showAttr);
const hideVal = readAttr(el, OU_CFG.hideAttr);
let visible = true;
if (hideVal && matchesRule(hideVal, tokens)) visible = false;
if (visible && showVal) visible = matchesRule(showVal, tokens);
visible ? showEl(el) : hideEl(el);
if (OU_CFG.debug) console.log('[ou]', { el, showVal, hideVal, visible, baseline: el.dataset.ouDisplayBaseline });
});
}
applyVisibility();
window.addEventListener('load', applyVisibility);
window.addEventListener('resize', applyVisibility);
window.addEventListener('orientationchange', applyVisibility);
});
Conditional visibility based on which device, operating system, or browser the visitor is using.