gohugoio / hugo

The world’s fastest framework for building websites.

Home Page:https://gohugo.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

imageConfig with SVG images

XhmikosR opened this issue · comments

Hi.

I'd like to ask if it's possible to add support for SVG images in imageConfig. I know SVG are vectors but there are cases SVGs still use width and height along with viewBox. Not sure if Go allows this or not, just thinking out loud.

Thanks!

Do you have any references saying that this is relevant for SVG?

What do you mean by "relevant"? Width and height apply to SVG too.

Maybe this helps? https://css-tricks.com/scale-svg/#article-header-id-2

FWIW, you can do this in a pretty clever way using dict. I learned this from @budparr. You could also use a shortcode for content since you're not technically resizing the svg the way you are with png/jpg/etc. Optimizing svgs is another story. But here's an example of what I mean:

https://github.com/gohugoio/gohugoioTheme/blob/master/layouts/partials/home-page-sections/installation.html#L26

That is for inlined SVG :) I'm talking about using SVG with an img tag.

That is for inlined SVG

Right. 1 less HTTP request. Even better.

Here's not the place or the time to discuss the pros and cons of inlining stuff. Hint: http/2.

What do you mean by "relevant"? Width and height apply to SVG too.

I mean:

  • For a JPG image Width and Height in imageConfig returns the actual pixel count.
  • The above has nothing to do with scaling.
  • In my head, an SVG image does not have any of those properties until it gets rasterized.

So by relevant I mean this: Am I right or wrong in the last bullet point above?

  • In my head, an SVG image does not have [width or height] until it gets rasterized.

SVG elements can and do declare intrinsic widths and heights. I make images like this in a text editor.

Here's not the place or the time to discuss the pros and cons of inlining stuff. Hint: http/2.

I think with your "hint," you just did.

Please stop polluting the issue with useless comments.

@XhmikosR I'm curious as to the use case where these values would be returned. Icon list? Image library?

I'm curious as to the use case where these values would be returned.

height and width attributes in img tags so the browser doesn't have to start downloading the images to know how space they'll take up. It's a page-layout-speed optimization.

Ah, I see. Thanks you to you both. I knew about other formats being affected (i.e., jpg and png), but I had no idea this affected SVG since it's just XML at the end of the day. Seems I am always learning something new about SVGs 😄 I had red the Bellamy-Royds article above and have always followed its advice to avoid these attributes altogether.

So, any news about this, guys?

commented

This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help.
If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open.
If this is a feature request, and you feel that it is still relevant and valuable, please tell us why.
This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

I'd still like to see this added, if it's not a lot of work.

height and width attributes in img tags so the browser doesn't have to start downloading the images to know how space they'll take up. It's a page-layout-speed optimization.

This became even more relevant with the recent introduction of browser support for the HTML-native lazy loading attribute I think.

When we use Markdown Render Hooks to add the loading="lazy" attribute together with width and height attributes auto-calculated by imageConfig as described in this fine blog post (to allow the browser to calculate proper page layout before loading the images, thus avoiding page repaints), we then cannot include SVG images using Markdown anymore. If we try it anyway, Hugo throws an error like the following (imageConfig: image: unknown format):

execute of template failed: template: _default/_markup/render-image.html:4:146: executing "_default/_markup/render-image.html" at <imageConfig (add "static/" .Destination)>: error calling imageConfig: image: unknown format

Since Go template code is always entirely evaluated regardless of conditional statements, I don't know of any easy workaround to still support SVG images.

I think SVG is the only image format supported by the HTML <img> tag that lacks imageConfig support.

I also wouldn't mind seeing this for the exact reasons mentioned, lazyloading SVG and minimizing reflow. Is there some other function like readFile that could be used to parse an SVG for its width and height attributes?

@jcackowski
I use lazyload for all images. I wanted to prevent layout reflow so I needed image ratio.
As a workaround to read image size and ratio of any kind of image, I created a partial image-size.html:

{{ $width := 1 }}
{{ $height := 1 }}
{{ if strings.HasSuffix . ".svg"}}
    {{ $svgContent := (resources.Get .).Content }}
    {{ $viewBoxSizes := split (index (split (index (split $svgContent `viewBox=`) 1) `"`) 1) ` ` }}
    {{ $width = float (index $viewBoxSizes 2) }}
    {{ $height = float (index $viewBoxSizes 3) }}
{{ else }}
    {{ $image := (resources.Get .) }}
    {{ $width = float $image.Width }}
    {{ $height = float $image.Height }}
{{ end }}

{{ return (dict "width" $width "height" $height "hRatio" (div $height $width) "wRatio" (div $width $height)) }}

Then I created another partial as responsive-image.html:

{{ $image := resources.Get .image }}
{{ $size := partial "image-size.html" .image}}
{{ $style := print "padding-top: " (mul $size.hRatio 100) "%;"}}
<div class="aspect-ratio-box" style="{{$style | safeCSS}}">
    <img class="aspect-ratio-box-inside lazyload" data-src="{{ ($image | fingerprint).RelPermalink }}" alt="{{ .alt }}">
</div>

I can use it in a shortcode like this:

{{ partial "responsive-image.html" (dict "image" (.Get "image") "alt" (.Get "imageAlt") )}}

Please note that this relies on images stored in the assets folder. Plus it only uses the viewBox of the SVG, not the actual width and height.
You can tweak it to support more cases. For me, it was enough. I hope it helps.
(For CSS see CSS-TRICKS and for JS see npm lazyload)

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.