Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVG images have no width and height parameters which causes layout shifts #2865

Closed
jmartsch opened this issue Nov 18, 2020 · 5 comments
Closed
Labels

Comments

@jmartsch
Copy link

jmartsch commented Nov 18, 2020

Bug Description

How to get the width and height of a SVG image?
Google Lighthouse complains:
Image elements do not have explicit width and height
Set an explicit width and height on image elements to reduce layout shifts and improve CLS. Learn more
https://web.dev/optimize-cls/?utm_source=lighthouse&utm_medium=devtools#images-without-dimensions

How do I set (or get) width and height for my svg images?
Here is the code that I use:

{{ image }}
<img src="{{ url }}" width="" height="" class="mx-auto lazyload">
 {{ /image }}

I know there is a special tag for svg's to inline them, but this is not what I need, and even counterproductive because of the complexity of the SVG image.
And I can not set the height and width to just some values, because then the reserved space has not the correct aspect ratio or size.
All my SVG's have a viewBox attribute, so it should be easy to get the required dimensions from this attribute.

Is there a way to do this with Statamic?
I think the dimensions and/or the aspect ratio should be saved in the meta information of the SVG asset when you upload it, so it can be used with an image tag.

How to Reproduce

Upload a SVG to your assets folder and output it in a template

Extra Detail

Video of the problem
https://www.youtube.com/embed/VDhIxPUoQ8Y

Environment

Statamic 3.0.28 Pro
Laravel 8.15.0
PHP 7.4.12
cnj/seotamic 2.0.2
octoper/statamic-inline-assets 4.0.2
rias/statamic-markdown-highlight 1.0.4
spatie/statamic-responsive-images 1.4.0
statamic/ssg 0.2.0

@jmartsch
Copy link
Author

jmartsch commented Dec 3, 2020

Push!?

@jasonvarga
Copy link
Member

Pull!?

Until we're able to implement something, you could consider writing a tag that would read the viewBox from the svg.

@duncanmcclean
Copy link
Member

I've built out a tag that should help you work around the issue until it's properly supported in Statamic.

Create App\Tags\SvgViewbox.php, with the following contents:

<?php

namespace App\Tags;

use Statamic\Tags\Tags;

class SvgViewbox extends Tags
{
    protected $regexPattern = "#viewbox=[\"']\d* \d* (\d*+(\.?+\d*)) (\d*+(\.?+\d*))#i";

    // {{ svg_viewbox:width :url="image_url" }}
    public function width()
    {
        $url = $this->params->get('url');

        if (! str_contains($url, 'http')) {
            $url = config('app.url') . '/' . $url;
        }

        $svg = file_get_contents($url);

        preg_match($this->regexPattern, $svg, $viewBox);

        return (float) $viewBox[1];
    }

    // {{ svg_viewbox:height :url="image_url" }}
    public function height()
    {
        $url = $this->params->get('url');

        if (! str_contains($url, 'http')) {
            $url = config('app.url') . '/' . $url;
        }

        $svg = file_get_contents($url);

        preg_match($this->regexPattern, $svg, $viewBox);

        return (float) $viewBox[3];
    }
}

Then in your Antlers templates, you can reference it like this:

width {{ svg_viewbox:width url="/assets/site/scratches.svg" }}
height {{ svg_viewbox:height url="/assets/site/scratches.svg" }}

Just pass in the asset's URL as the url parameter. Hopefully it should work for you.

@jmartsch
Copy link
Author

Thank you @damcclean. It works now. It would be great if this was a core feature, without requiring a special tag. Cheers

@jasonvarga
Copy link
Member

This is now available in 3.1 beta.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants