Gap in vertical repeat of svg background - html

I have a simple div, with an SVG set as background image with vertical repeat. On Chrome and Firefox, depending on the screen size, I see a gap in varying sizes (please resize the window).
https://jsfiddle.net/bartadaniel/ejtvy7po/9/
.bg {
width: 50%;
height: 2000px;
display: block;
background-repeat: repeat;
background-size: contain;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='272' height='171' viewBox='0 0 272 171'> <rect class='cls-1' width='272' height='171' fill='green'/></svg>");
}
<div class="bg"></div>
Is there a reason for this?

That's happening due to a combination of background-size:contain and the pixel dimensions of your svg.
You're seeing the browser try to scale the image so that nothing overflows the bounds of your <div>. When you combine that scaling with image pixel dimensions of 171 (can't be evenly multiplied into 2000px) you get lines showing you the sub pixels you're browser is trying to display.
Simply remove the background-size:contain to solve it.
Edit:
In the case where you need to contain width, there are a few tricks to help get a better result.
Make the background image dimensions multiples of 10. Square would be best with something like 100x100px but it could also be a rectangle (try to get close to your target width) like 1000x100px.
Set background-size: 100% auto instead of contain. This will stretch the image proportionalty to fill the container width.
Use background-repeat: repeat-y to force a vertical repeat so the browser is only doing the math on one axis.

It is a problem of subpixel rendering.
Each browser rounds differently and SVG subpixel rendering is pretty messed up.
I suggest you to edit your SVG content to make it slightly bigger than your viewbox.
<svg xmlns='http://www.w3.org/2000/svg' width='272' height='171' viewBox='0 0 272 171'>
<rect class='cls-1' y='-.5' width='272' height='172' fill='green'/>
</svg>
Obviously this trick doesn't work for all the background SVG, but might be useful in your case.

Unfortunately, the only solution that reliably tackled this issue was to convert the SVG to a pixel-based format, like JPG. Apparently, the browsers have no problem scaling pixels but causes side effects at edges when scaling vector-based formats.

If your SVG will still look acceptable with less anti-aliasing, you can change the anti-aliasing of the shapes in your SVG using the shape-rendering property. Example:
<rect shape-rendering="crispEdges">
You can use this on these elements: <circle>, <ellipse>, <line>, <path>, <polygon>, <polyline>, and <rect>.

Related

Printing an SVG from HTML in landscape mode

Okay so my setup is a window object created on the fly.
I'm writing to it with window.document.write() and building out this:
<style>
#page{
size: landscape;
max-height: 100%;
max-width: 100%;}
svg{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
display: block;
overflow: visible;
transform: scale(1, 1.3737);}
</style>
and then I clone the SVG from the page it's on and document.write(svgClone.innerHTML).
I end up with this: https://jsfiddle.net/je0ssLm2/1/
Please excuse the mess but that contains the entire code for the SVG and displays how it renders. The reason I'm scaling by 1.3737 on the Y axis is because the image is 1280 x 720 but 1280 x 989 is close to an aspect ratio of 1:3 which is approximately the AR of US letter.
Anyway, as you can see the display is not very attractive, and when it prints for some reason the margins are very large and the image is quite small and not quite centered in the screen. Is there some crucial CSS I am missing? This is driving me nuts, I've seen a few other answers about this and tried various but I just can't get it to print correctly.
I'm not as worried about size as I am positioning. I can monkey with the scaling to get the size right but if I make the image bigger then I'll cut off axis labels or the title because the graph doesn't center on the page. I also ALWAYS get an extra blank page, which isn't the end of the world but definitely isn't desirable.
You need to modify attributes on the <svg> element for a clean solution.
SVG has two attributes that let you describe scale-to-fit operations declaratively without computing transforms yourself: viewBox and preserveAspectRatio.
Instead of the attributes you have
<svg width="1280" height="720">
you can write
<svg viewBox="0 0 1280 720" preserveAspectRatio="none">
If you cannot get at the source text, you can simply wrap the <svg> in a second one:
<svg viewBox="0 0 1280 720" preserveAspectRatio="none">
<svg width="1280" height="720">...</svg>
</svg>,
and, as long as you define sensible sizes, should work in all media, including the page the SVG originally comes from.
The area defined by the viewBox in SVG userspace coordinates will then be fitted into the size of the <svg> element itself - since you have it defined in CSS with width:100%;height:100%;, it is fitted into the containing element.
preserveAspectRatio="none" does the uneven scaling for you. This didn't work before because as a default, the aspect ratio was preserved (and only after being scaled-down-to-fit, the CSS transform cut in).

Prevent inline SVG pixel snapping in chrome

I have an svg that I'm using to show a wavy edge on a div. The svg needs to display as the same with as the div but due to some sub pixel snapping/rounding the alignment varies as you resize. Firefox seems to work fine. See demo:
https://jsfiddle.net/meojwnLv/
When using the svg as a background image with background-size:100% auto; it scales correctly but I want to be able to change the color so need it to be inline.
How can I prevent this from happening?
Thanks
It looks like Chrome is snapping the height and width of the SVG object to integer values. Since the SVG's width is much larger than its height, every 1px change in the height of the SVG is causing the width to change by about 10px.
viewBox="20 20 900 66"
There's an easy workaround for this — just make the SVG taller:
viewBox="20 20 900 500"
Here's an updated JSFiddle.

SVG won't render as CSS background-image

I am trying to implement a close button using a SVG image as background-image. Below is the code I am using:
.close-button {
width: 16px;
height: 16px;
background-image: url(data:image/svg+xml;base64,[The data for the image]);
background-size: 16px 16px;
background-position: center center;
}
<span class="close-button"></span>
You can test it here.
It becomes a 16 by 16 span but the image does not render. Why is this happening? Also, the image is originally black-filled. I want to change its fill to white. Is there any way to achieve this?
So, my questions are:
Why doesn't the image render as background?
How to change the SVG fill on :hover? (given my configuration - available in the link above)
You need to set either the width and height, or the viewBox attribute on the <svg>. I would recommend the viewBox, because you do not to scale the graphics to fit in. Of course you are free to set all of them, but that easily leads to confusion for your purposes.
Please note, to gain an SVG that fits into each element, do not use width and height and use viewBox. Here is a nice explanation for the viewBox.
For the SVG you posted a possible viewBox could roughly be like that:
<svg viewBox="16 104 170 170" >
I do not know how you generate your SVG but to fix those Issues I use inkscape. Just open the file > document Properties > resize document to content and save.
Than, if you want, open the svg in an text editor, create a such a viewBox="0 0 <value of width> <value of height>" and remove the width and height attributes.
Good Luck!

Sprites with background position and width percentage in responsive design

I am designing an app with CSS3/HTML5 with a responsive design.
For performance, I use sprites instead of normal images. So, I use background-image and background-position. On entire app the aspect ratio is maintained.
In a width with pixels and background-position with percentage, the image shows nice. But in a width with percentage and background-position, the image looks bad sometimes (when sprite has more than two images).
The sprite size 102px x 918 px;
Each image in the sprite size 102px x 102px;
The cross red is the last image in the sprite when 9 images.
See bad background-position:
It's the same but with 637px shows nice:
Anybody know how to fix it with CSS3?
UPDATE:
My problem is with a percentage in the width and background-position.
background-position: 0 100%; // Show the second image in the sprite.
background-position: 0 700%; // Show image 8 in the sprite but sometimes, in some width, the image showed is the image 8 and a little image 7.
The problem is with background-size: cover. The browser doesn't render a correct width and height. To fix it i use:
background-size: 100% 900%; // 100% to adjust to width and 900% is to mantain proportions in the height. (9 images of 102px in this case)
I tested in chrome 26.
Percentage value are best suitable for mobile devices compared to fixed pixels. Check this question for better understanding of pixel vs percentage.

Change image resolution in html

<style>
#text{
background-image:url('/../image.jpg');
<<image-resolution:???>>
}
</style>
I have a CSS where I use an image as the background. [width = 5000p, height = 3000px, horizontal and vertical resolution = 72dpi]
The image appears with a very big size and the pic does not cover the screen completely. Is there a way I can change the size/resolution of the image using image-resolution or any other method?
You should be able to use the background-size CSS property to change the size of your image.
#text{
background-image:url('/../image.jpg');
background-size: 100px 100px;
}
First of all image-resolution tag belongs to css3 and all the browsers might not support this but if you want to do this then try to provide image resolution like this :
<style>
image-resolution: 72dpi;
</style>
All the best....
Tiffon gave you the correct answer. But in the "real world" you'll never use such a big image for a repeated background.
Typical sizes are, for example:
200px X 200px (repeat)
10px X 1000px (repeat-x)
2000px X 10px (repeat-y)
Of course, you have also to consider the weight of the images: 40/50Kb could be an approsimative max size.
In conclusion, instead of use the css rule, I suggest to you to resize and compress (JPG compression, from 50% to 80%) the image. You can do that with software like Paint or FastStone Resizer, a very useful freeware.