v157 · blink · css & svg rendering

object-fit and object-position apply to SVG documents in <object> and <embed>

Chrome 157 updates Blink's embedded content rendering pipeline so that standalone SVG documents loaded via <object data="diagram.svg"> or <embed src="diagram.svg"> respect CSS object-fit and object-position on the host element — matching <img> instead of ignoring both properties and stretching the SVG across the entire content box.

concepts

  1. <object> vs <embed> vs <img> parity lab

    Load the exact same intrinsic-sized SVG (width="120" height="80") side-by-side inside 240×160 <object>, <embed>, and <img> containers. Switch object-fit (contain, cover, fill, none, scale-down) and object-position while inspecting live contentDocument and getScreenCTM() matrices.

  2. Interactive SVG focal-point cropper

    Use object-fit: cover and object-position: X% Y% sliders to pan across an <object> technical diagram while keeping internal SVG elements live and DOM-inspectable via objectElement.contentDocument — something <img> cannot do.

  3. preserveAspectRatio two-stage negotiation matrix

    Explore how CSS object-fit and object-position on the outer <object>/<embed> element (Stage 1: concrete object size and alignment) compose with the inner root <svg viewBox preserveAspectRatio> attribute (Stage 2: SVG viewBox-to-viewport transform).

why it shipped

Developers choose <object type="image/svg+xml"> or <embed> over <img> whenever an embedded SVG needs scriptable DOM access via contentDocument, interactive internal targets, or independent stylesheet execution. Historically, however, Blink applied CSS object-fit and object-position to <img>, <video>, and <canvas>, while treating <object> and <embed> hosting SVG documents like subframes that always filled 100% of the element's content box.

As a result, setting object-fit: none or object-fit: cover; object-position: 80% 20% on an <object> containing an SVG with intrinsic dimensions (such as width="120" height="80") was ignored: the nested SVG viewport was always forced to the full width and height of the <object> box. Chrome 157 aligns <object> and <embed> SVG sizing with the HTML specification's embedded content rendering rules and CSS Images Module Level 3.

the CSS & DOM contract

object.schematic,
embed.schematic {
  width: 240px;
  height: 160px;
  object-fit: none;          /* Keeps 120x80 intrinsic SVG size instead of stretching */
  object-position: 80% 20%;  /* Aligns concrete object box inside the 240x160 host */
}

// Inside same-origin or data-URI , the internal SVG CTM reflects the
// positioned concrete object box while keeping full DOM access:
const svgRoot = objectEl.contentDocument.documentElement;
const ctm = svgRoot.getScreenCTM(); // ctm.a === 1, ctm.d === 1 when object-fit: none
  

  

research notes

  • Two-stage sizing pipeline: First, CSS Replaced Element sizing computes the concrete object size and offset within the <object> or <embed> content box using the SVG's intrinsic dimensions/aspect ratio plus object-fit and object-position. Second, the SVG document renders into that concrete object rectangle using its own viewBox and preserveAspectRatio.
  • When it is observable: The difference is immediately measurable whenever the SVG has fixed intrinsic dimensions (e.g. width="120" height="80" with object-fit: none or scale-down) or an intrinsic aspect ratio that differs from the host <object>/<embed> box (with object-fit: contain, cover, or custom object-position).

references