Category: number Since: 1.0.0 Tags: aspect-ratio, dimensions, ratio, calculation, image
getAspectRatio
Computes the aspect ratio from given dimensions.
Usage
import { getAspectRatio } from "@petr-ptacek/js-core";
const aspectRatio = getAspectRatio(1920, 1080);
console.log(aspectRatio); // 1.7777777777777777 (16:9 ratio)
const square = getAspectRatio(400, 400);
console.log(square); // 1 (1:1 ratio)
const portrait = getAspectRatio(300, 400);
console.log(portrait); // 0.75 (3:4 ratio)Why This Utility Exists
Aspect ratio calculations are fundamental in image processing, responsive design, and media handling. While the math is simple (width / height), this utility provides proper input validation, throws descriptive errors for invalid inputs, and ensures consistent behavior across different contexts where aspect ratios are needed.
Signature
function getAspectRatio(width: number, height: number): number;Parameters
width(number): Width dimension. Must be a positive finite number.height(number): Height dimension. Must be a positive finite number.
Return Type
Returns a number representing the aspect ratio calculated as width / height.
Common aspect ratio values:
1.777...(16:9 widescreen)1.333...(4:3 traditional)1.0(1:1 square)0.75(3:4 portrait)
Throws
- Throws
Errorwhenwidthis not a positive finite number - Throws
Errorwhenheightis not a positive finite number
Design Notes
The implementation uses assertPositiveFinite helper to validate both dimensions before calculation. This ensures:
- Input validation: Prevents invalid calculations with zero, negative, or non-finite numbers
- Clear error messages: Provides descriptive errors identifying which parameter is invalid
- Type safety: Guarantees the return value is a valid positive number
- Consistency: Uses the same validation pattern as other dimension utilities
The formula width / height follows the standard mathematical definition where values greater than 1 indicate landscape orientation and values less than 1 indicate portrait orientation.
When To Use
Use getAspectRatio when you need:
- aspect ratio calculations for image resizing
- responsive layout calculations
- media format validation
- cropping or scaling operations
- consistent aspect ratio representation across your application
When Not To Use
Avoid when:
- you need the inverse ratio (height/width) - calculate directly or use a different utility
- working with already calculated aspect ratios
- dimensions can legitimately be zero or negative (use direct division)
- you need rounded or formatted aspect ratio values (combine with other utilities)
Summary
getAspectRatio provides a simple, validated way to compute aspect ratios from dimensions with proper error handling for edge cases and consistent behavior across different scaling and layout scenarios.
Snippets
basic.ts
import { getAspectRatio } from "@petr-ptacek/js-core";
// common aspect ratios
const widescreen = getAspectRatio(1920, 1080);
console.log("16:9 widescreen:", widescreen); // 1.7777777777777777
const traditional = getAspectRatio(1024, 768);
console.log("4:3 traditional:", traditional); // 1.3333333333333333
const square = getAspectRatio(400, 400);
console.log("1:1 square:", square); // 1
const portrait = getAspectRatio(600, 800);
console.log("3:4 portrait:", portrait); // 0.75
// ultra-wide and cinematic ratios
const ultrawide = getAspectRatio(3440, 1440);
console.log("21:9 ultrawide:", ultrawide); // 2.388888888888889
const cinematic = getAspectRatio(2048, 858);
console.log("2.39:1 cinematic:", cinematic); // 2.387645787545787image-analysis.ts
import { getAspectRatio } from "@petr-ptacek/js-core";
// image analysis and classification
function analyzeImageDimensions(width: number, height: number) {
const aspectRatio = getAspectRatio(width, height);
let orientation: string;
let category: string;
// determine orientation
if (aspectRatio > 1) {
orientation = "landscape";
} else if (aspectRatio < 1) {
orientation = "portrait";
} else {
orientation = "square";
}
// categorize common ratios
if (Math.abs(aspectRatio - 1.777) < 0.01) {
category = "16:9 widescreen";
} else if (Math.abs(aspectRatio - 1.333) < 0.01) {
category = "4:3 traditional";
} else if (Math.abs(aspectRatio - 1) < 0.01) {
category = "1:1 square";
} else if (Math.abs(aspectRatio - 0.75) < 0.01) {
category = "3:4 portrait";
} else if (aspectRatio > 2) {
category = "ultra-wide";
} else {
category = "custom ratio";
}
return {
width,
height,
aspectRatio,
orientation,
category,
};
}
// example images
const images = [
{ name: "Desktop wallpaper", width: 1920, height: 1080 },
{ name: "Instagram post", width: 1080, height: 1080 },
{ name: "Phone screenshot", width: 375, height: 812 },
{ name: "Traditional photo", width: 800, height: 600 },
{ name: "Ultrawide monitor", width: 3440, height: 1440 },
];
images.forEach(({ name, width, height }) => {
const analysis = analyzeImageDimensions(width, height);
console.log(`${name}:`, {
ratio: analysis.aspectRatio.toFixed(3),
orientation: analysis.orientation,
category: analysis.category,
});
});
// Output:
// Desktop wallpaper: { ratio: '1.778', orientation: 'landscape', category: '16:9 widescreen' }
// Instagram post: { ratio: '1.000', orientation: 'square', category: '1:1 square' }
// Phone screenshot: { ratio: '0.462', orientation: 'portrait', category: 'custom ratio' }
// Traditional photo: { ratio: '1.333', orientation: 'landscape', category: '4:3 traditional' }
// Ultrawide monitor: { ratio: '2.389', orientation: 'landscape', category: 'ultra-wide' }responsive-layout.ts
import { getAspectRatio } from "@petr-ptacek/js-core";
// responsive layout helper
class ResponsiveContainer {
private width: number;
private height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
get aspectRatio(): number {
return getAspectRatio(this.width, this.height);
}
// check if content fits without letterboxing/pillarboxing
canFitContent(contentWidth: number, contentHeight: number): boolean {
const containerRatio = this.aspectRatio;
const contentRatio = getAspectRatio(contentWidth, contentHeight);
// content fits if its ratio is between container ratio bounds
// (allowing for some small floating point tolerance)
return Math.abs(containerRatio - contentRatio) < 0.001;
}
// determine how content will be displayed
getDisplayMode(contentWidth: number, contentHeight: number) {
const containerRatio = this.aspectRatio;
const contentRatio = getAspectRatio(contentWidth, contentHeight);
if (Math.abs(containerRatio - contentRatio) < 0.001) {
return "perfect fit";
} else if (contentRatio > containerRatio) {
return "letterboxed"; // black bars top/bottom
} else {
return "pillarboxed"; // black bars left/right
}
}
// suggest optimal dimensions for content
getOptimalContentSize(targetWidth?: number, targetHeight?: number) {
const ratio = this.aspectRatio;
if (targetWidth) {
return {
width: targetWidth,
height: Math.round(targetWidth / ratio),
};
} else if (targetHeight) {
return {
width: Math.round(targetHeight * ratio),
height: targetHeight,
};
} else {
// suggest based on container dimensions
return {
width: this.width,
height: this.height,
};
}
}
}
// usage examples
const videoPlayer = new ResponsiveContainer(800, 450); // 16:9 player
console.log("Player aspect ratio:", videoPlayer.aspectRatio.toFixed(3)); // 1.778
// test different video formats
const videos = [
{ name: "YouTube video", width: 1920, height: 1080 },
{ name: "Old TV show", width: 640, height: 480 },
{ name: "Vertical TikTok", width: 608, height: 1080 },
{ name: "Square Instagram", width: 1080, height: 1080 },
];
videos.forEach(({ name, width, height }) => {
const mode = videoPlayer.getDisplayMode(width, height);
const fits = videoPlayer.canFitContent(width, height);
console.log(`${name}: ${mode} (perfect fit: ${fits})`);
});
// generate optimal thumbnail sizes
const thumbnailSizes = [200, 400, 600].map((width) => videoPlayer.getOptimalContentSize(width));
console.log("Optimal thumbnail sizes:", thumbnailSizes);
// [
// { width: 200, height: 113 },
// { width: 400, height: 225 },
// { width: 600, height: 338 }
// ]