1366 × 768 reduces to 683:384, which is 0.05% wider than 16:9. A calculator that prints "683:384" is correct and useless. One that prints "16:9" is wrong. That gap is one of three places where image tools get aspect ratios wrong. The other two are rounding the second side, and forgetting what a crop between 4:3 and 16:9 costs.
Below are the rules we settled on for an aspect ratio calculator, the code, and the cases where those rules still give an awkward answer. Every number in the tables comes from running the code in this post.
Step 1: reduce by the greatest common divisor
const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b)); function exactRatio(w, h) { const g = gcd(w, h); return [w / g, h / g]; } exactRatio(1920, 1080); // [16, 9] exactRatio(1366, 768); // [683, 384] That part is not controversial. The trouble starts when you decide what to show a person.
Step 2: decide when the exact answer is the wrong answer
The rule we use:
- If both reduced terms are 40 or less, show the exact ratio (16:9, 8:5, 4:3).
- Otherwise, find the closest ratio from a short list of names people search for. If it is within 1%, show "≈ 16:9".
- Otherwise, show a decimal like 2.37:1.
const NAMED = [ [1, 1], [4, 5], [3, 4], [2, 3], [9, 16], [4, 3], [3, 2], [16, 9], [21, 9], [5, 4], [16, 10], [1200, 628, '1.91:1'], ]; function nearest(w, h) { const t = w / h; let best = NAMED[0], off = Infinity; for (const r of NAMED) { const d = Math.abs(r[0] / r[1] - t) / t; if (d < off) { off = d; best = r; } } return { name: best[2] ?? `${best[0]}:${best[1]}`, off: off * 100 }; } function label(w, h) { const [a, b] = exactRatio(w, h); if (a <= 40 && b <= 40) return `${a}:${b}`; const near = nearest(w, h); if (near.off < 1) return `≈ ${near.name}`; const r = w / h; return r >= 1 ? `${r.toFixed(2)}:1` : `1:${(1 / r).toFixed(2)}`; } Run over common sizes:
| Size | Exact | Shown | Note |
|---|---|---|---|
| 1920x1080 | 16:9 | 16:9 | |
| 1366x768 | 683:384 | ≈ 16:9 | 0.05% off 16:9 |
| 1440x900 | 8:5 | 8:5 | also called 16:10 |
| 1280x1024 | 5:4 | 5:4 | |
| 4032x3024 | 4:3 | 4:3 | a 12 MP phone photo |
| 6000x4000 | 3:2 | 3:2 | |
| 1080x1350 | 4:5 | 4:5 | |
| 2560x1080 | 64:27 | 2.37:1 | 1.56% off 21:9 |
| 3440x1440 | 43:18 | 2.39:1 | 2.33% off 21:9 |
| 1200x628 | 300:157 | ≈ 1.91:1 | |
| 1200x630 | 40:21 | 40:21 | see below |
Two things in that table are worth knowing even if you never build a calculator.
"21:9" monitors are not 21:9. 21:9 is 2.33:1. A 2560x1080 screen is 2.37:1 and a 3440x1440 screen is 2.39:1. If your crop presets offer 21:9 and someone uses one for a 3440x1440 wallpaper, the image is narrower than the screen, so it gets bars on the sides or is zoomed and cropped. That is why the 1% threshold does not snap these to 21:9: the difference is big enough to matter.
The rule is inconsistent for link preview images. 1200x628 shows "≈ 1.91:1", but 1200x630 shows "40:21", because 40 and 21 pass the "small terms" check. Both are the same kind of image. We left it, because 40:21 is exact and the 1% rule never runs for it, but a check against named ratios before the small-terms check would fix it. If you copy this code, decide which you prefer.
The 40 cutoff and the 1% threshold are our choices, not a standard. A smaller name list or a tighter threshold changes the output.
Step 3: round the other side for what comes next
Pick 16:9 and a width of 1000, and the height is 562.5. Most code rounds that to 563. That is fine for a JPEG. It breaks H.264 video with the usual yuv420p pixel format, which needs both sides to be even:
$ ffmpeg -f lavfi -i color=c=black:s=1000x563 -frames:v 1 -c:v libx264 -pix_fmt yuv420p odd.mp4 [libx264 @ 0x143e335b0] height not divisible by 2 (1000x563) The same command with 1000x562 works (ffmpeg 7.1.1). If the image might end up in a video, round to the nearest even number instead:
const heightFor = (w, rw, rh, { even = false } = {}) => { const h = (w * rh) / rw; return even ? Math.round(h / 2) * 2 : Math.round(h); }; heightFor(1000, 16, 9); // 563 heightFor(1000, 16, 9, { even: true }); // 562 heightFor(1366, 16, 9); // 768 (exact value is 768.375) Show people when a height is rounded. Our calculator's list of common sizes writes 1080 x ≈608 for 16:9, because the exact height is 607.5. Its two input boxes still round silently, which we should fix.
Step 4: tell people what a crop between 4:3 and 16:9 costs
Going from 4:3 to 16:9, or from 16:9 to 4:3, keeps exactly 75% of the pixels. The math is the same both ways, (9/16) ÷ (3/4) = (4/3) ÷ (16/9) = 0.75:
- 4032x3024 cropped to 16:9 becomes 4032x2268. It loses 756 rows.
- 1920x1080 cropped to 4:3 becomes 1440x1080. It loses 480 columns.
A centered crop from 4:3 to 16:9 takes 12.5% off the top and 12.5% off the bottom, which is often where a person's head or feet are. So a crop tool that converts between them should let people choose which quarter to lose, not just center the crop.
Where this code runs
These rules are what CropDen's aspect ratio calculator uses, including the cases above where they fall short. When you need the crop itself, CropDen's 4:3 cropper lets you drag the image inside the frame to choose what gets cut, and runs in the browser without uploading the image.
What it does not do: it does not know about your output format, so the even-number rounding for video is up to you.
