Scale an SVG to it's viewBox or smaller - css

I have an inline <SVG> that defines it's viewBox but not it's height or width. I used to set width/height to the same values as the viewBox while creating the SVG; the benefit is that the final image is scaled to the SVG's natural units, which I want; the problem is that a fixed width/height might overflow the parent container in the final page. Removing width/height from the <SVG> causes the image to be rendered as large as the parent container allows, which is almost always larger than the SVG's natural units.
Is there a way to scale an <SVG> to it's natural units, yet scale it down (!) if the parent container is too small?

If you're not bound to using the inline svg (and not bound to IE scaling...), an svg in <img> is your friend.
When an SVG file has a viewBox, and it is embedded within an <img>,
browsers will (nearly always) scale the image to match the aspect
ratio defined in the viewBox.
HTML
<figure>
<figcaption><code>img</code>, auto size</figcaption>
<div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/91525/potofgold.svg">
</div>
</figure>
Result
Inline SVG scaling support is not as far... Read from this amazing article to learn more about how this works See point 4 for a wide-support solution. It recommends using a padding-bottom hack, which is common in iframe-embeds also.

Related

Pagespeed warning - Use explicit width and height on image elements

I want to set a responsive image in my webpage using tailwind css. I have provided sufficient classes to make it work on different screen sizes. Now I am getting the following error in page-speed.
How can I eliminate the warning?
Try to use Tailwind aspect ratio.
It work fine
You can eliminate this warning by adding width and height to your images like this:
<img loading="lazy" src="assets/image/brainstorm/svg" alt="brainstorm" width="400" height="200" class="w-5/6 mx-auto" />
Basically adding width and height directly to html img tag prevents layout shifts, even if img is not loaded yet. It's especially important when img is lazy-loaded. More info here
Just adding height and width attributes and classes won't work, you have to crop the images as well to its exact dimension. For example if you have set 100px height and width, the image height and width should also be 100px.
Background
This warning exists to prevent layout shift when images load. Currently, the images have the classes w-5/6 mx-auto. This is enough to make the images responsive, but before the images are loaded, the browser doesn't know how tall the image is. Hence, when the image loads, there will be layout shift.
You then need to tell the browser how wide and tall the image should be before it loads. There a few ways of doing this.
With known dimensions
If you know the height of the image, I'd recommend following fromaline's answer.
<img src='assets/image/brainstorm.svg' alt='nature' class='w-5/6 mx-auto border' width='300' height='300' />
Because we've defined the display width with w-5/6, the image will be responsive. The width='300' and height='300' properties are then used for the aspect ratio.
Here's a link from the Tailwind playground to show you how it's both responsive and removes layout shift: https://play.tailwindcss.com/rjz9ylFNl5?size=482x720
With unknown dimensions
If you don't know the width and height of your images and you need them to be responsive, you need to essentially create a container with a fixed aspect ratio. I'd recommend looking at the aspect ratio plugin.
<div class='w-5/6 aspect-w-16 aspect-h-9 mx-auto'>
<img src='assets/image/brainstorm.svg' alt='nature' class='object-cover w-full h-full' />
</div>
Again, a link to a Tailwind Playground demo: https://play.tailwindcss.com/2zmPJixbrO?size=584x720

How can I use SVG fragments and set background-size: cover?

I have a problem with sizing of SVG image when I use fragments.
When I set background-size: cover the image does not covers available space in the container.
Here is a demo.
Is it possible to use SVG fragments and be able to use contain and cover in background-size with proper behaviour?
The issue is that you're not specifying the width and height of the parent SVG. Chrome has a bug that requires height and width to be specified for fragments to handle img related CSS techniques, not sure what the source of the info was but CSS Tricks documented it here. I think the height and width only needs to be specified in the parent SVG where the use tag is.
You can see here that setting the height and width for the svg tag in sprite.svg gives uniform behavior between both versions.
https://codesandbox.io/s/svg-fragment-background-position-problem-i75l3?fontsize=14&hidenavigation=1&theme=dark

Data URI image sizing (auto height)

I use Unveil.js to lazy load images. To save time/space, I use a base64 placeholder image:
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-src="https://unsplash.it/1000/500?image=631" width="1000" height="500" data-unveil="true" />
The problem I'm experiencing is how the placeholder image gets resized. It seems to always maintain an aspect ratio of 1 which is a problem for responsive sites.
So if the image tag above is inside of a <div> with width 50% and the <div>'s calculated width is 500px (total viewport width is 1000px) then the image will overflow the <div> unless I use max-width: 100%; height: auto; and then a non-data URI image will correctly scale and maintain its aspect ratio.
However, the data URI image always remains square, regardless of width/height attributes in the <img> tag or CSS rules. This causes some jumping around on slower servers because the image that gets lazy loaded by Unveil.js is not always square.
I setup a quick fiddle to demonstrate the sizing differences (without Unveil.js): http://jsfiddle.net/silb3r/7bnfqkko/1/
And one with Unveil.js: http://jsfiddle.net/silb3r/2eff5thm/ (you may need to manually throttle your connection to see the issue)
Is anyone familiar with a way to ensure that the data URI maintains the aspect ratio of the original image? Preferably without adding more jQuery, but I am open to anything.
Thank you for any suggestions.
Well, your CSS overwrites the width and height set via HTML attributes, and so the intrinsic image dimensions come into play, and those are 1×1 pixels. And therefor setting height:auto naturally results in a square image, no matter what.
If you know the aspect ratio for your images beforehand (and you seem to do, assuming those width and height HTML attribute values you used are not completely arbitrary – otherwise, a few lines of server-side code could read them from the image files, if it needs to be more dynamic), then you can use what’s called the “padding-top hack” to create a placeholder that will use the correct aspect ratio.

Display SVG keeping the original font-size

i have several svg's included in and image tag on my homepage.
My svg's are resized to the parent div container, which is 30em's wide.
My problem now is that i have svg's are not of the same width and all of them are scaled to a width of 30em.
See this example:
jsfiddle.net/xpgz44oL/
The displayed font-size should be the same for every svg.
How can i achieve this?
Assuming the original drawings were done at the same scale, you could look at the viewBox widths and set each image to that width (or a multiple of that width if you want them bigger).
<div>
<img src="http://www.austrokamin.at/media/dw/zeichnungen/laengenelement-1000mm-dw-zeichnung.svg" width="158.95px"/>
<img src="http://www.austrokamin.at/media/dw/zeichnungen/dachdurchfuehrung-20-35-grad-dw-zeichnung.svg" width="239.19"/>
</div>

Scaling SVG of Unknown Size

I would like to display an svg image inside a block of fixed size. I would like to show the image undistorted and as large as possible within the block. My problem is that the image is supplied by the user, so I do not know its dimensions. Is there any way to do this with CSS only?
No you cannot do this using CSS only. The attributes that tell the browser how to scale an SVG to fill its parent container are defined in the SVG itself. There are four attributes in particular that control the scaling:
width
height
viewBox
preserveAspectRatio
The first two can be overridden with CSS, but the last two cannot. If you have no control over the SVG, then you can't guarantee that it has a viewBox or preserveAspectRatio.
You could, however, manipulate the viewBox and preserveAspectRatio attributes with Javascript.

Resources