Problem/Motivation

Many SVG files get exported without width and height attributes. This module will then apply a default value of 64 for both attributes.
As setting these attributes on the <img> tag gets more and more important these days, we should make another attempt to retrieve width and height through the viewBox attribute.

Proposed resolution

In svg_image_get_image_file_dimensions(), try to read width and height from the viewBox attribute if the first attempt is not successful.

Issue fork svg_image-3227734

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mrshowerman created an issue. See original summary.

mrshowerman’s picture

Here's a first patch.

mrshowerman’s picture

Assigned: mrshowerman » Unassigned
Status: Active » Needs review
mrshowerman’s picture

StatusFileSize
new1.07 KB
new558 bytes
qazema’s picture

We applied the patch on a Drupal 9.4.5 installation and it works well.

FalkNisius made their first commit to this issue’s fork.

FalkNisius’s picture

Sorry, that I react late. Thanks for the work.

My team runs in the issue with missing width and height, and the approach should be changed.

The actual code prefers the width and height attribute from the svg-tag. Most exporters write 100% to that attributes, and it results to a width and height of 100 pixel, because the code strips the % sign.

The viewBox attribute is more usual and should be preferred if it exists.

The code depends on the letter case of the attributes, that is not always given, that viewBox is written as camel case.

The first two values of viewBox should not be ignored, they can have positive and negative values. The values in the viewBox can be float. We have to build a difference between the right and left corner values. At least the absolute values of the difference should be used.

bronismateusz’s picture

Version: 8.x-1.x-dev » 3.x-dev
Priority: Normal » Major
Status: Needs review » Needs work

I tested patch #4 and it only works when the image style uses crop or scale and crop. Then the values for width and height are actually passed on correctly. If these filters are not applied, then these attributes are missing, for the img field.
In addition, I also see that the rotate or desaturate filter does not work either.

bronismateusz’s picture

I have prepared a patch that fixes the addition of width and height attributes for the other filters in the image style.

milos.kroulik made their first commit to this issue’s fork.

mrshowerman’s picture

Left a few notes on the MR.

jennypanighetti’s picture

MR#32 as a patch worked great for me!

firewaller’s picture

Status: Needs work » Reviewed & tested by the community

The MR#32 changes work for us as well!

krystianbrzoza made their first commit to this issue’s fork.

jennypanighetti’s picture

MR#32 fails to apply on the latest version drop, 3.2.3. Needs to be rebased.

Nevermind, @krystianbrzoza already did this in https://git.drupalcode.org/project/svg_image/-/merge_requests/58 :)

anybody’s picture

Priority: Major » Normal
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

This is not major and it should have tests.

amangrover90 made their first commit to this issue’s fork.

amangrover90’s picture

I'm using drupal/svg_image in a Drupal distribution and hit the layout-shift problem this issue addresses. I applied MR 58's viewBox extraction patch and validated it works, but noticed a remaining gap: even with correct dimensions extracted, the front-end <img> on a rendered Drupal page still ships no width/height attributes.

The reason: the image field item's width/height properties are populated by the image toolkit on save, which can't parse SVG — so $item->width and $item->height are always empty, and that's what ImageThemeHooks::preprocessImageFormatter() maps onto the rendered <img>. The dimensions from svg_image_get_image_file_dimensions() are consumed by the widget preview and renderAsImg()'s svg_attributes, but never reach the <img> attributes on a standard page render.

To close that gap I added a hook_preprocess_image implementation that sets attributes['width']/['height'] directly for SVG files when they aren't already set. The core theme's own preprocess (which maps $variables['width']/['height'] onto attributes) runs before module hooks, so setting $variables['width'] in a module hook has no effect — attributes must be set directly. The guard (!isset($variables['width']) && !isset($variables['attributes']['width'])) makes it a no-op for rasters and for SVGs that already have explicit dimensions from another path.

I pushed this as a second commit on the MR 58 branch (07e5d4e) so it can be reviewed alongside the viewBox extraction. Combined, the two commits:

  1. Derive width/height from viewBox when explicit attributes are absent (or reject percentage values instead of miscasting them as pixels) — the original MR 58 change.
  2. Surface those dimensions onto the rendered <img> via hook_preprocess_image — the new commit.

I validated both cases end-to-end: a viewBox-only SVG (viewBox="0 0 24 24") now renders <img width="24" height="24"> on the media view page, and a percentage-width SVG does not miscast 100% to 100.

Happy to split the second commit into a separate issue/MR if the maintainer prefers to land them independently.