Draw a line that doesn't get thicker when image stretches - css

Is there a way in SVG to draw a line that keeps thin when the image is stretched?
I'm using a SVG image as a CSS background, something like this:
<svg ... preserveAspectRatio="none" viewBox="0 0 15 15">
<line x1="0" y1="15" x2="15" y2="0"
color="#000" stroke="#333" stroke-width="1" />
</svg>
(A diagonal line). I'm stretching this image through a rectangular element, and when the element is bigger, the line gets thicker, but I need an always-thin line.
Possible? Something like "thin" lines in flash.

In browsers that implement SVG 1.2T you can have a non-scaling stroke Opera and Webkit support this as does Firefox from version 15.
<!-- via property -->
<line … vector-effect="non-scaling-stroke" />
<!-- via CSS -->
<style>
line { vector-effect:non-scaling-stroke }
</style>
<line … />

Related

How to centre this SVG word

Trying to figure out how to centre this SVG text horizontally and vertically in the viewport
(The element needs to remains central across different viewport sizes)
Tried using the viewbox panning but I can't get everything aligned - part of the SVG remains cut off/incorrectly scaled
Also looking to set the font size to the same rem value as other standard text elements on the page.
SVG text is used as there's a 'slice' GSAP animation happening to it.
<div class="stage">
<svg id="demo" xmlns="http://www.w3.org/2000/svg" width="2000" height="800" viewBox="0 0 1000 800">
<defs>
<pattern id="slicePattern" patternUnits="userSpaceOnUse" width="3000" height="800" x="0" y="0"><text transform="translate(500 400)" text-anchor="middle" font-size="220" fill="#fff">SLICE</text>
</pattern>
</defs>
<g fill="url(#slicePattern)">
<polygon id="slide1" points="0,150 551,150 201,400 0,400" />
<polygon id="slide2" points="549,150 1000,400 999,400 1000,150" />
<polygon points="200,400 550,150 1000,400" />
</g>
<line x1="550" y1="150" x2="200" y2="400" stroke-width="1" stroke="white"/>
<line x1="550" y1="150" x2="1000" y2="400" stroke-width="1" stroke="white"/>
</svg>
</div>
The standard text to match to is 2.5em. Setting the SVG text to that it doesn't size the same. Also can't correctly pan the viewbox to centre the svg text in the viewport. I need this to be responsive centering also.
In short, I don't understand the effect the text transform properties are having on the element, or how this relates to the viewport/viewbox values.
For making the whole svg responsive:
svg{
width:100%;
height:auto
}
For the text, It has already text-anchor set to middle which is correct. You need to specify the position of the text by setting x and y values.
<text text-anchor="middle" x="50" y="0">The Text</text>
The font-size in svg has nothing to do with the default font-size of the css. It's relative to the viewBox of your svg. SVG functions as a separate image file. But you can have access to its style attributes by css.

Svg adds padding on resize bug -SVG/CSS

If I use a SVG and I resize it using CSS, I get a weird effect. If I change the width, the image will take up a lot of blank space vertically. If it I change the height, the image will take a lot of blank space horizontally. How can I fix that?
#item{
width: calc(30px + 3vw);
background-color: red;
}
<svg id="item"
width="100mm"
height="100mm"
viewBox="0 0 100 99.999997"
version="1.1">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
showgrid="false"/>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-197)">
<rect
style="opacity:1;fill:#ff6600;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.56531394;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4485"
width="100"
height="100"
x="0"
y="197" />
</g>
</svg>
Note: I made the image using inkscape and got rid of the useless XML.
Resizing svg is different than regular image in jpg or png. In svg if you remove dimensions (in your case width/height set to 100mm) your svg will adapt to container width easily and generally will be scalable.
Try with this svg and you should be able to resize it with no problems using only width or height.
By the way, I minified the code and removed all unnecessary tags to focus only on relevant code. If you inline this svg into html you can also remove xmlns.
svg{width:110px} /*your custom dimensions here*/
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect style="fill:#ff6600;stroke:red;stroke-width:0.565;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0" width="100" height="100"/>
</svg>
I set a stroke color to red so you can see it. If you don't need a stroke just remove all elements with "stroke".

Viewbox placement in referencing SVG symbols and CSS dimensions

I edited my initial cry of despair into something more to the technical point, in order to turn it into a Q&A.
I'm using SVG symbols that I reference in the document with use elements. I'm styling these with CSS. I don't want to set both height and width in the CSS, I want to set only one of them with the other one scaling accordingly.
I do set a viewBox attribute on the symbol. But the graphic does not scale correctly.
<!DOCTYPE html>
<html>
<head>
<title>SVG Symbols</title>
<style>
body { margin: 20px; }
.svg-large { width: 500px; fill: yellow;}
</style>
</head>
<body>
<svg style="display:none;">
<symbol id="scary-smiley" viewBox="0 0 20 20">
<circle cx="10" cy="10" r="9.5" stroke-width="1"
stroke="black" />
<circle cx="6" cy="7" r="1.5" fill="black"/>
<circle cx="14" cy="7" r="1.5" fill="black"/>
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Teeth_by_David_Shankbone.jpg/320px-Teeth_by_David_Shankbone.jpg"
width="10" height="5.2" x="5" y="11"/>
</symbol>
</svg>
<svg class="svg-large">
<use xlink:href="#scary-smiley"/>
</svg>
</body>
</html>
The code below has been tested in current Firefox, Chrome and a Webkit-based browser named Midori.
For some reason, defining the viewBox on the symbol element does not have the full desired effect in Firefox and Chrome. It does have some effect, though, as it makes the element scaleable. So, if you want set both width and height in CSS, you can do that.
If the viewBox element is specified only on the symbol and you set only one of width or height, then in Firefox and Chrome the other dimension is set according the default object size in HTML 5 whis is 300x150 px. So, in the example in the question, you get a 500x150 px element and the graphic is scaled to fit that rectangle.
If you want to define only one width or height with the other one scaling accordingly, then defining viewBox on the referencing SVG element works:
<!DOCTYPE html>
<html>
<head>
<title>SVG Symbols</title>
<style>
body { margin: 20px; }
.svg-large { width: 500px; fill: yellow;}
</style>
</head>
<body xmlns:xlink="http://www.w3.org/1999/xlink">
<svg style="display:none;">
<symbol id="scary-smiley">
<circle cx="10" cy="10" r="9.5" stroke-width="1"
stroke="black" />
<circle cx="6" cy="7" r="1.5" fill="black"/>
<circle cx="14" cy="7" r="1.5" fill="black"/>
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Teeth_by_David_Shankbone.jpg/320px-Teeth_by_David_Shankbone.jpg"
width="10" height="5.2" x="5" y="11"/>
</symbol>
</svg>
<svg class="svg-large" viewBox="0 0 20 20">
<use xlink:href="#scary-smiley"/>
</svg>
</body>
</html>
Firefox' and Chrome's behaviour is standard compliant, according to the SVG 2 specification, according to which the <svg><use .../></svg> clause establishes a new SVG viewport.

bug with transform scale svg line in firefox

I'm having trouble finding a good work-around for a bug in Firefox. The bug happens when doing a transform scale on a line in SVG.
I'd like to be able to specify changing the length of a line in a transform so I can animate the transition of the transform using css. In Firefox, doing a Transform Scale causes the line to shift. I've tried playing with the transform-origin property to see if I could recenter it, but haven't found any values that worked.
Here is the html code that renders the problem. Works in Safari and Chrome, not in Firefox:
<!DOCTYPE html>
<html>
<head>
<title>Firefox Bug</title>
<meta charset="utf-8" />
</head>
<body>
<svg width="600" height="600" style="border: solid blue 1px;" viewBox="290 290 20 20">
<g style="transform: translate(300px, 300px)">
<path d="M -1 0 L 1 0" stroke="blue" stroke-width="1" style="transform: scale(1, 1);"/>
<path d="M -1 0 L 1 0" stroke="red" stroke-width="1" />
</g>
</svg>
</body>
</html>
Here is what the issue looks like in Safari/Chrome:
Here is what it looks like in Firefox:
The red line segment should completely cover the blue, but in Firefox, the blue segment gets shifted to the side. Already filed the bug in bugzilla. Would love it if anyone had a good workaround for this, that let's me use the scale property without shifting the lines.

Transparent background for SVG

I am working with SVGs, and would like to create one with a transparent background. The following example, should appear as just a white circle with a path in it. However, the whole 300px white canvas appears as a square, how do I get the result I want, as I can't really see where the canvas is defined?
<?xml version="1.0"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" height="300" width="300" version="1.1" xml:space="preserve">
<circle fill="#FFFFFF" cx="150.267" cy="149.854" r="111.303" fill-opacity="1"/>
<g transform="translate(0.000000,632.000000) scale(0.100000,-0.100000)" fill-opacity="1">
<path fill="#54534A" d="M2204.344,4414.691v-122.67h81.643h81.642l-1.237,6.804c-0.619,3.505-1.649,10.515-2.474,15.462l-1.443,8.659
h-61.438h-61.644v38.141v38.141h54.635h54.635v16.493v16.494h-54.635h-54.635v36.079v36.08h60.613h60.407l1.443,10.515
c0.825,5.979,2.062,13.401,2.68,16.493l1.237,5.979h-80.818h-80.612V4414.691z"/>
<!-- Other paths omitted -->
</g>
</svg>
Appears as a 300 x 300px rectangle with a transparent background here with a smaller white circle inside and the letter E(path).
You sure you're not giving the svg element a white background with CSS by accident?
The canvas is the <svg> element itself, you can change its background using CSS:
svg {
background: red;
}

Resources