| Server IP : 195.179.238.23 / Your IP : 216.73.216.138 Web Server : LiteSpeed System : Linux us-imm-web1061.main-hosting.eu 4.18.0-553.109.1.lve.el8.x86_64 #1 SMP Thu Mar 5 20:23:46 UTC 2026 x86_64 User : u629643714 ( 629643714) PHP Version : 8.2.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/u629643714/domains/abboshon.com/public_html/tools/ |
Upload File : |
const elements = {
pixelValue: document.getElementById('pixelValue'),
rootFontSize: document.getElementById('rootFontSize'),
parentFontSize: document.getElementById('parentFontSize'),
designWidth: document.getElementById('designWidth'),
designHeight: document.getElementById('designHeight'),
containerWidth: document.getElementById('containerWidth'),
containerHeight: document.getElementById('containerHeight'),
useCase: document.getElementById('useCase'),
remValue: document.getElementById('remValue'),
emValue: document.getElementById('emValue'),
vwValue: document.getElementById('vwValue'),
vhValue: document.getElementById('vhValue'),
viewportWidthPercentValue: document.getElementById('viewportWidthPercentValue'),
viewportHeightPercentValue: document.getElementById('viewportHeightPercentValue'),
containerWidthPercentValue: document.getElementById('containerWidthPercentValue'),
containerHeightPercentValue: document.getElementById('containerHeightPercentValue'),
cssOutput: document.getElementById('cssOutput'),
recommendationBox: document.getElementById('recommendationBox'),
remFormula: document.getElementById('remFormula'),
emFormula: document.getElementById('emFormula'),
vwFormula: document.getElementById('vwFormula'),
vhFormula: document.getElementById('vhFormula'),
percentWidthFormula: document.getElementById('percentWidthFormula'),
percentHeightFormula: document.getElementById('percentHeightFormula'),
resetBtn: document.getElementById('resetBtn'),
copyCssBtn: document.getElementById('copyCssBtn')
};
const defaults = {
pixelValue: 32,
rootFontSize: 16,
parentFontSize: 16,
designWidth: 1440,
designHeight: 1024,
containerWidth: 1200,
containerHeight: 800,
useCase: 'auto'
};
function parsePositiveNumber(input) {
const value = Number(input.value);
return Number.isFinite(value) && value > 0 ? value : null;
}
function round(value, decimals = 4) {
if (!Number.isFinite(value)) return null;
return Number.parseFloat(value.toFixed(decimals));
}
function formatUnit(value, unit, decimals = 4) {
if (!Number.isFinite(value)) return 'Invalid input';
return `${round(value, decimals)}${unit}`;
}
function setErrorOutputs() {
const ids = [
'remValue', 'emValue', 'vwValue', 'vhValue',
'viewportWidthPercentValue', 'viewportHeightPercentValue',
'containerWidthPercentValue', 'containerHeightPercentValue'
];
ids.forEach((id) => {
elements[id].textContent = 'Invalid input';
elements[id].classList.add('error');
});
elements.cssOutput.textContent = 'Enter positive numbers in every field to generate CSS suggestions.';
elements.recommendationBox.innerHTML = '<span class="error">One or more fields are invalid.</span>';
elements.remFormula.textContent = 'rem = px ÷ root font size';
elements.emFormula.textContent = 'em = px ÷ parent font size';
elements.vwFormula.textContent = 'vw = (px ÷ design width) × 100';
elements.vhFormula.textContent = 'vh = (px ÷ design height) × 100';
elements.percentWidthFormula.textContent = '% width = (px ÷ container width) × 100';
elements.percentHeightFormula.textContent = '% height = (px ÷ container height) × 100';
}
function clearErrorState() {
[
elements.remValue,
elements.emValue,
elements.vwValue,
elements.vhValue,
elements.viewportWidthPercentValue,
elements.viewportHeightPercentValue,
elements.containerWidthPercentValue,
elements.containerHeightPercentValue
].forEach(el => el.classList.remove('error'));
}
function getRecommendation(useCase, values) {
const { rem, em, vw, vh, containerWidthPercent, containerHeightPercent } = values;
const auto = `
<strong>Auto suggestion:</strong> For most site typography, use <strong>${formatUnit(rem, 'rem')}</strong>.
For width-based layout values from your design, <strong>${formatUnit(vw, 'vw')}</strong> or
<strong>${formatUnit(containerWidthPercent, '%')}</strong> is usually stronger.
For height-based design translation, use <strong>${formatUnit(vh, 'vh')}</strong> or
<strong>${formatUnit(containerHeightPercent, '%')}</strong> when the parent height is controlled.
`;
const typography = `
<strong>Typography:</strong> Use <strong>${formatUnit(rem, 'rem')}</strong> as the default choice.
Use <strong>${formatUnit(em, 'em')}</strong> only when the text needs to scale from a parent component.
`;
const spacing = `
<strong>Spacing:</strong> Usually <strong>${formatUnit(rem, 'rem')}</strong> is the safest for margins, padding,
and section rhythm. Use <strong>${formatUnit(vw, 'vw')}</strong> only when you intentionally want the spacing to scale with viewport width.
`;
const width = `
<strong>Width / layout:</strong> Use <strong>${formatUnit(containerWidthPercent, '%')}</strong> when the element belongs to a known container.
Use <strong>${formatUnit(vw, 'vw')}</strong> when it should scale relative to the full design width.
`;
const height = `
<strong>Height / vertical layout:</strong> Use <strong>${formatUnit(containerHeightPercent, '%')}</strong> when the parent has a set height.
Otherwise <strong>${formatUnit(vh, 'vh')}</strong> is better for viewport-related vertical sizing.
`;
const map = { auto, typography, spacing, width, height };
return map[useCase] || auto;
}
function update() {
const pixelValue = parsePositiveNumber(elements.pixelValue);
const rootFontSize = parsePositiveNumber(elements.rootFontSize);
const parentFontSize = parsePositiveNumber(elements.parentFontSize);
const designWidth = parsePositiveNumber(elements.designWidth);
const designHeight = parsePositiveNumber(elements.designHeight);
const containerWidth = parsePositiveNumber(elements.containerWidth);
const containerHeight = parsePositiveNumber(elements.containerHeight);
if (!pixelValue || !rootFontSize || !parentFontSize || !designWidth || !designHeight || !containerWidth || !containerHeight) {
setErrorOutputs();
return;
}
clearErrorState();
const rem = pixelValue / rootFontSize;
const em = pixelValue / parentFontSize;
const vw = (pixelValue / designWidth) * 100;
const vh = (pixelValue / designHeight) * 100;
const viewportWidthPercent = (pixelValue / designWidth) * 100;
const viewportHeightPercent = (pixelValue / designHeight) * 100;
const containerWidthPercent = (pixelValue / containerWidth) * 100;
const containerHeightPercent = (pixelValue / containerHeight) * 100;
elements.remValue.textContent = formatUnit(rem, 'rem');
elements.emValue.textContent = formatUnit(em, 'em');
elements.vwValue.textContent = formatUnit(vw, 'vw');
elements.vhValue.textContent = formatUnit(vh, 'vh');
elements.viewportWidthPercentValue.textContent = formatUnit(viewportWidthPercent, '%');
elements.viewportHeightPercentValue.textContent = formatUnit(viewportHeightPercent, '%');
elements.containerWidthPercentValue.textContent = formatUnit(containerWidthPercent, '%');
elements.containerHeightPercentValue.textContent = formatUnit(containerHeightPercent, '%');
const cssLines = [
`/* Based on ${pixelValue}px */`,
`font-size: ${formatUnit(rem, 'rem')};`,
`font-size: ${formatUnit(em, 'em')}; /* parent-based */`,
`width: ${formatUnit(vw, 'vw')};`,
`height: ${formatUnit(vh, 'vh')};`,
`width: ${formatUnit(containerWidthPercent, '%')}; /* container-based */`,
`height: ${formatUnit(containerHeightPercent, '%')}; /* container-based */`
];
elements.cssOutput.textContent = cssLines.join('\n');
elements.recommendationBox.innerHTML = getRecommendation(elements.useCase.value, {
rem,
em,
vw,
vh,
containerWidthPercent,
containerHeightPercent
});
elements.remFormula.textContent = `${pixelValue}px ÷ ${rootFontSize}px = ${round(rem)}rem`;
elements.emFormula.textContent = `${pixelValue}px ÷ ${parentFontSize}px = ${round(em)}em`;
elements.vwFormula.textContent = `(${pixelValue}px ÷ ${designWidth}px) × 100 = ${round(vw)}vw`;
elements.vhFormula.textContent = `(${pixelValue}px ÷ ${designHeight}px) × 100 = ${round(vh)}vh`;
elements.percentWidthFormula.textContent = `(${pixelValue}px ÷ ${containerWidth}px) × 100 = ${round(containerWidthPercent)}%`;
elements.percentHeightFormula.textContent = `(${pixelValue}px ÷ ${containerHeight}px) × 100 = ${round(containerHeightPercent)}%`;
}
async function copyText(text) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch {
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
const success = document.execCommand('copy');
document.body.removeChild(textArea);
return success;
}
}
function bindCopyButtons() {
document.querySelectorAll('.copy-btn').forEach(button => {
button.addEventListener('click', async () => {
const targetId = button.dataset.copyTarget;
const value = document.getElementById(targetId)?.textContent || '';
if (!value || value === 'Invalid input') return;
const original = button.textContent;
const success = await copyText(value);
button.textContent = success ? 'Copied' : 'Failed';
setTimeout(() => {
button.textContent = original;
}, 1200);
});
});
}
function bindEvents() {
[
elements.pixelValue,
elements.rootFontSize,
elements.parentFontSize,
elements.designWidth,
elements.designHeight,
elements.containerWidth,
elements.containerHeight,
elements.useCase
].forEach(el => {
el.addEventListener('input', update);
el.addEventListener('change', update);
});
elements.resetBtn.addEventListener('click', () => {
Object.entries(defaults).forEach(([key, value]) => {
elements[key].value = value;
});
update();
});
elements.copyCssBtn.addEventListener('click', async () => {
const original = elements.copyCssBtn.textContent;
const success = await copyText(elements.cssOutput.textContent);
elements.copyCssBtn.textContent = success ? 'Copied' : 'Failed';
setTimeout(() => {
elements.copyCssBtn.textContent = original;
}, 1200);
});
}
bindCopyButtons();
bindEvents();
update();