ef-fit-scale
Attributes
pausedbooleanPause scale calculations (useful during animations)
falseProperties
contentChildHTMLElement | nullFirst content element (excludes style, script, display:none)
scaleInfo{ scale: number, containerWidth: number, containerHeight: number, contentWidth: number, contentHeight: number }Current scale calculation result
Functions
computeFitScale(input: ScaleInput): ScaleOutput | nullPure function to compute scale and centering for given dimensions
ScaleOutput | nullResponsive container that scales content to fit while preserving aspect ratio.
Basic Usage
Scale content to fit container:
<div class="w-full h-[400px] border border-gray-300 rounded overflow-hidden bg-gray-100"><ef-fit-scale class="w-full h-full"><div class="w-[1920px] h-[1080px] bg-blue-500 text-white flex items-center justify-center text-4xl">1920×1080 Content</div></ef-fit-scale></div>
Content scales down to fit the container while maintaining its 16:9 aspect ratio.
How It Works
Fit scale automatically:
- Observes container size
- Reads content natural dimensions
- Calculates scale factor to fit
- Centers content with translate
- Applies transform to content
Content Detection
Fit scale finds the first content element, ignoring:
<style>tags<script>tags<meta>tags- Elements with
display: none - Elements with
display: contents
<ef-fit-scale><style>/* Ignored */</style><script>/* Ignored */</script><div><!-- This is the content --></div></ef-fit-scale>
Natural Dimensions
For media elements (ef-video, ef-image), fit scale uses natural dimensions:
<ef-fit-scale class="w-full h-[400px]"><ef-video src="https://assets.editframe.com/bars-n-tone.mp4"></ef-video></ef-fit-scale>
Video scales based on its native resolution, not CSS dimensions.
getNaturalDimensions Method
Media elements can provide natural dimensions:
class MyMediaElement extends HTMLElement {getNaturalDimensions() {return { width: 1920, height: 1080 };}}
Fit scale calls this method if available.
Responsive Scaling
Fit scale updates automatically when:
- Container resizes
- Content resizes
- Content child changes
<div class="flex flex-col gap-4"><div class="w-full h-[300px] border border-gray-300 rounded overflow-hidden bg-gray-100"><ef-fit-scale class="w-full h-full"><div class="w-[800px] h-[600px] bg-green-500 text-white flex items-center justify-center text-2xl">800×600 (4:3)</div></ef-fit-scale></div><div class="w-full h-[300px] border border-gray-300 rounded overflow-hidden bg-gray-100"><ef-fit-scale class="w-full h-full"><div class="w-[1920px] h-[1080px] bg-blue-500 text-white flex items-center justify-center text-2xl">1920×1080 (16:9)</div></ef-fit-scale></div></div>
Different aspect ratios scale correctly.
Scale Calculation
Fit scale uses contain logic (like object-fit: contain):
import { computeFitScale } from '@editframe/elements';const result = computeFitScale({containerWidth: 800,containerHeight: 600,contentWidth: 1920,contentHeight: 1080});// result = {// scale: 0.4166, // Scale down to fit// translateX: 0, // Centered horizontally// translateY: 75 // Centered vertically// }
Scale Formula
const containerRatio = containerWidth / containerHeight;const contentRatio = contentWidth / contentHeight;const scale = containerRatio > contentRatio? containerHeight / contentHeight // Limited by height: containerWidth / contentWidth; // Limited by width
Centering
Content is centered after scaling:
const scaledWidth = contentWidth * scale;const scaledHeight = contentHeight * scale;const translateX = (containerWidth - scaledWidth) / 2;const translateY = (containerHeight - scaledHeight) / 2;
Applied Transform
Fit scale applies transform to content child:
.content {width: 1920px;height: 1080px;transform: translate(0px, 75px) scale(0.4166);transform-origin: top left;}
Transform origin is top-left for correct positioning.
Pause Calculations
Pause scale updates during animations:
<ef-fit-scale paused><!-- Scale calculations paused --></ef-fit-scale>
const fitScale = document.querySelector('ef-fit-scale');// PausefitScale.paused = true;// ResumefitScale.paused = false; // Recalculates immediately
Zero Dimension Warning
Fit scale warns when container has zero dimensions:
// Console warning if container is 0×0// "Container has zero dimensions (0×0). Content will be invisible."
Ensure all ancestors have resolved height:
html, body {height: 100%;}
Scale Info
Access current scale calculation:
const fitScale = document.querySelector('ef-fit-scale');console.log(fitScale.scaleInfo);// {// scale: 0.4166,// containerWidth: 800,// containerHeight: 600,// contentWidth: 1920,// contentHeight: 1080// }
Content Child
Access the content element:
const fitScale = document.querySelector('ef-fit-scale');const content = fitScale.contentChild;console.log(content.tagName); // 'EF-VIDEO'
Observers
Fit scale uses three observers:
- Container ResizeObserver: Tracks container size
- Content ResizeObserver: Tracks content size
- MutationObserver: Tracks child list changes
All observers clean up on disconnect.
Video Integration
For ef-video elements, fit scale sets explicit canvas dimensions:
// Breaks circular dependencycanvas.style.width = `${naturalWidth}px`;canvas.style.height = `${naturalHeight}px`;
This prevents video from collapsing to 0×0 when using width: auto.
Layout Properties
Fit scale applies container styles:
ef-fit-scale {display: grid;width: 100%;height: 100%;grid-template-columns: 100%;grid-template-rows: 100%;overflow: hidden;box-sizing: border-box;contain: layout paint style;position: relative;}
Grid layout simplifies content positioning.
Performance
Scale calculations use:
- Fixed precision: Values rounded to 4 decimal places
- Change detection: Only updates when values change
- RAF deferral: Initial calculation deferred to allow layout
// Internal precision handlingtransform: `translate(${translateX.toFixed(4)}px, ${translateY.toFixed(4)}px) scale(${scale.toFixed(4)})`;
Cleanup
Fit scale removes transform when disconnected:
// On disconnectcontent.style.width = '';content.style.height = '';content.style.transform = '';content.style.transformOrigin = '';
Content returns to normal layout.
Comparison with object-fit
ef-fit-scale:
- Works with any element
- JavaScript-based scaling
- Provides scale info
- Can be paused
CSS object-fit:
- Only works with replaced elements (img, video)
- CSS-based scaling
- No JavaScript API
- Always active
Nested Fit Scale
Multiple fit scales can nest:
<ef-fit-scale class="w-full h-full"><ef-timegroup class="w-[1920px] h-[1080px]"><ef-fit-scale class="w-full h-full"><ef-video src="video.mp4"></ef-video></ef-fit-scale></ef-timegroup></ef-fit-scale>
Each fit scale scales its own content independently.
Behavior
- Automatically observes container and content size changes
- Recalculates scale on resize using ResizeObserver
- Centers content within container
- Maintains content aspect ratio
- Uses CSS transform for scaling (GPU-accelerated)
- Handles nested content elements
- Ignores non-visible elements (display: none, etc.)
Important Notes
- FitScale is a light DOM component (no shadow DOM)
- Content should have explicit dimensions (width/height)
- Works with any content, not just Editframe elements
- Scale updates automatically on window resize
- Use
pausedattribute to temporarily stop recalculation - Returns
nullfromcomputeFitScalefor invalid dimensions - Uses
contain: layout paint stylefor performance - Content is centered both horizontally and vertically