Is it possible to change svg viewBox value using CSS? - css

I want to change the svg value of the viewBox using CSS when the window width is 660px.
viewBox="0 0 230 87" => viewBox="0 0 100 87".Is it possible to change svg viewBox value using CSS ?

You can only change presentation attributes through CSS. viewBox is not one of these.
What you can do however is to use <symbol> elements to define "views" over the scene.
Indeed, <symbol> does have a viewBox attribute, so you can use this element to point to the whole scene, and then use one <use> element per such "view" and control via CSS when this <use> is displayed:
svg {
border: 1px solid;
border-color: yellow;
}
#media (max-width:500px) {
svg { border-color: green; }
#small-use { display: block; }
#big-use { display: none; }
}
#media (min-width:501px) {
#small-use { display: none; }
#big-use { display: block; }
}
<svg>
<!-- we wrap the whole scene in one symbol -->
<symbol id="scene">
<rect fill="blue" x="0" y="0" width="500" height="500"/>
<rect fill="red" x="0" y="0" width="50" height="50" />
</symbol>
<!-- following symbols will define our "views" -->
<symbol id="small-view" viewBox="0 0 60 60">
<use href="#scene"/>
</symbol>
<symbol id="big-view" viewBox="0 0 500 500">
<use href="#scene"/>
</symbol>
<!-- append all the views, CSS will determine which to display -->
<use href="#small-view" id="small-use"/>
<use href="#big-view" id="big-use"/>
</svg>
<p>Change the window's size to trigger the "change of viewBox"</p>

If you want to change SVG width, you can set width property on svg tag
<svg width="40" height="40" viewBox="0 0 40 40">...</svg>
or, you can add CSS style on it.
<svg viewBox="0 0 40 40" style="width:80px; height: 80px">...</svg>
If you edit viewBox, your SVG shape might be destroyed.

Related

How can i add backgroung image in the following svg?

From this website
https://smooth.ie/blogs/news/svg-wavey-transitions-between-sections
i generated the following svg
<div style="height: 100%; overflow: hidden;" class='parent' ><svg viewBox="0 0 500 150" preserveAspectRatio="none" style="height: 100%; width: 100%;"><path d="M213.19,0.00 C152.69,70.06 270.03,70.06 202.98,150.00 L500.00,150.00 L500.00,0.00 Z" style="stroke: none; fill: #08f;"></path></svg></div>
the problem is that when i try to add background image for example here on the parent class
.parent {
background-image: url('../../../assets/images/calendar.png');
}
then the image is hidden behind the blue color of the svg.How can i 'insert' this image to be on the blue svg color image ?
As name says - it's "background-image" so it always is on the background of selected element.
I suggest that you should make an <img> tag in parent element and style it so that .parent would have attribute position: relative and img should have position: absolute.
Also remember to set top and left/right position for <img>.
it's Answered here https://stackoverflow.com/a/3798797/9017484
You can do it by making the background into a pattern:
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
<image href="wall.jpg" x="0" y="0" width="100" height="100" />
</pattern>
</defs>
your code should be something like this:
<div style="height: 100%; overflow: hidden;" class='parent' >
<svg viewBox="0 0 500 150" preserveAspectRatio="none" style="height: 100%; width: 100%;">
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
<image href="ImageFile.jpg" x="0" y="0" width="100" height="100" />
</pattern>
</defs>
<path d="M213.19,0.00 C152.69,70.06 270.03,70.06 202.98,150.00 L500.00,150.00 L500.00,0.00 Z" style="stroke: none; fill: url(#img1);"></path>
</svg>
</div>
change the opacity level so the color is lower opacity. something like this perhaps.
background {
backgroundColor:blue,
opacity: 0.5;
}

SVG styling problems with <use>

I'm trying to change, with CSS, the size and color of an SVG element that's being rendered with <use>. The SVG in question:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="#000000" fill-rule="evenodd" d="<all the actual svg path info>" clip-rule="evenodd"/>
</svg>
I do not have permission to change the contents of the SVG itself.
The way I'm using the SVG:
<svg>
<use xlink:href="#myIcon"></use>
</svg>
I've fought with this for hours, read through a pretty comprehensive article on the subject, and I still haven't had any success. I've tried applying classes to both the use element and the outer svg element, as well as referencing the path element inside. I can't seem to do anything to override the provided styles. How can I change the width, height, and fill color with this arrangement?
For the size it's easy if you correctly set the viewBox and then you adjust the width/height.
For the coloration you can rely on blending mode since the color of the SVG is black.
.icon {
display: inline-block;
background: #fff;
position: relative;
}
.icon::after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background:var(--c);
mix-blend-mode:lighten;
}
.icon>svg {
display: block;
}
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<symbol id="myIcon">
<path fill="#000" d="M81,40.933c0-4.25-3-7.811-6.996-8.673c-0.922-5.312-3.588-10.178-7.623-13.844 c-2.459-2.239-5.326-3.913-8.408-4.981c-0.797-3.676-4.066-6.437-7.979-6.437c-3.908,0-7.184,2.764-7.979,6.442 c-3.078,1.065-5.939,2.741-8.396,4.977c-4.035,3.666-6.701,8.531-7.623,13.844C22.002,33.123,19,36.682,19,40.933 c0,2.617,1.145,4.965,2.957,6.589c0.047,0.195,0.119,0.389,0.225,0.568l26.004,43.873c0.383,0.646,1.072,1.04,1.824,1.04 c0.748,0,1.439-0.395,1.824-1.04L77.82,48.089c0.105-0.179,0.178-0.373,0.225-0.568C79.855,45.897,81,43.549,81,40.933z M49.994,11.235c2.164,0,3.928,1.762,3.928,3.93c0,2.165-1.764,3.929-3.928,3.929s-3.928-1.764-3.928-3.929 C46.066,12.997,47.83,11.235,49.994,11.235z M27.842,36.301c0.014,0,0.027,0,0.031,0c1.086,0,1.998-0.817,2.115-1.907 c0.762-7.592,5.641-13.791,12.303-16.535c1.119,3.184,4.146,5.475,7.703,5.475c3.561,0,6.588-2.293,7.707-5.48 c6.664,2.742,11.547,8.944,12.312,16.54c0.115,1.092,1.037,1.929,2.143,1.907c2.541,0.013,4.604,2.087,4.604,4.631 c0,1.684-0.914,3.148-2.266,3.958H25.508c-1.354-0.809-2.268-2.273-2.268-3.958C23.24,38.389,25.303,36.316,27.842,36.301z M50.01,86.723L27.73,49.13h44.541L50.01,86.723z" fill-rule="evenodd" clip-rule="evenodd"/>
</symbol>
</svg>
<!-- your code -->
<div class="icon" style="--c:red;">
<svg viewBox="0 0 100 125" width="100">
<use xlink:href="#myIcon"></use>
</svg>
</div>
<div class="icon" style="--c:green;">
<svg viewBox="0 0 100 125" width="150">
<use xlink:href="#myIcon"></use>
</svg>
</div>
<div class="icon" style="--c:blue;">
<svg viewBox="0 0 100 125" width="200">
<use xlink:href="#myIcon"></use>
</svg>
</div>
Save svg as a image with svg format then add the color and width or whatever you want to your img then add this to the html file as a img tag and display: none the svg code.
If you can't reach the html code then you can't do anything.

Svg inside another svg can't change height with css

Example
In this example I've posted, I have two svg elements, each with a nested element with its own viewbox.
svg {
background-color: orange;
}
#inline {
background-color: yellow;
}
#in-css {
width: 50px;
}
<svg viewbox="0 0 300 300" width=100 height=100>
<rect x=50 y=30 width=100 height=100></rect>
<svg id="inline" width="50px" viewbox="50 50 100 100">
<rect width=50 height=50 x=80 y=80></rect>
</svg>
</svg>
<svg viewbox="0 0 300 300" width=100 height=100>
<rect x=50 y=30 width=100 height=100></rect>
<svg id="in-css" viewbox="50 50 100 100">
<rect width=50 height=50 x=80 y=80></rect>
</svg>
</svg>
Problem
Setting the width or height attribute of the inner svg works if I do it inline, but I can't set it if I try targeting that element with css. Does anybody know why? I'm using chrome for reference if that helps :)

CSS padding property for svg elements

I can't figure out how the CSS padding property is interpreted for svg elements. The following snippet (jsFiddle):
<!DOCTYPE html>
<meta charset="utf-8">
<title>noob d3</title>
<style>
svg{background-color:beige;
padding:0px 0px 50px 50px;}
rect{fill:red;
stroke:none;
shape-rendering:crispEdges;}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
d3.select("body")
.append("svg")
.attr("width", 155)
.attr("height", 105)
.append("g")
.append("rect")
.attr("class", "frame")
.attr("x", 50)
.attr("y", 50)
.attr("width", 50)
.attr("height", 50);
</script>
</body>
... displays significantly differently in Firefox and Chrome. What's worse, neither display really makes sense to me: the size of the displayed svg element (the "beige" rectangle) looks to be significantly bigger than what I expected.
So my question is two-fold: 1) How is the padding property of an svg element supposed to affect where things get drawn within it? 2) Is there a polyfill that will ensure that both Chrome and Firefox both handle padding in the same way?
AFAIK, the SVG standard doesn't specify anything like padding, which is why it's handled inconsistently. Just set the SVG to the size you want (with padding) and maybe add a rect to make it appear like you want it to appear.
From my experience (granted, still very little as I am still learning SVG), I have strayed away from using padding wherever that I could do so. It was suggested to me when I was first learning SVG that I use margin in place of padding, if possible.
This is also because you can use display: block; and margin: 0 auto; to make the left and right sides of an SVG to fit directly into the middle of the screen.
There is no padding or margin, but you can set x and y attributes such that the elements inside or outside get a padding and margin. For example, if an element starts at (0,0), starting at (10, 10) will automatically give a margin of 10.
You can apply padding to parent svg elements
The padding as described by the OP actually works – albeit, not as desired.
Outermost <svg> will be rendered with padding (won't work for nested svgs).
But: child elements (e.g the <rect>) won't be re-aligned according to – unlike HTML DOM elements.
svg {
background-color: beige;
max-height:20em;
}
.pdd{
padding: 0px 0px 50px 50px;
}
rect {
fill: red;
stroke: none;
shape-rendering: crispEdges;
}
.borderBox{
box-sizing: border-box;
}
.overflow{
overflow:visible
}
<p>Rendered size: 205 x 155 – padding added to initial dimensions </p>
<svg class="pdd" width="155" height="105">
<g>
<rect class="frame" x="50" y="50" width="50" height="50" />
</g>
</svg>
<p>Rendered size: 155 x 105; cropped</p>
<svg class="pdd borderBox" width="155" height="105">
<g>
<rect class="frame" x="50" y="50" width="50" height="50" />
</g>
</svg>
<p>Rendered size: 155 x 105; cropped; overflow visible</p>
<svg class="pdd borderBox overflow" width="155" height="105">
<g>
<rect class="frame" x="50" y="50" width="50" height="50" />
</g>
</svg>
Usecase: padding for fluid svg layouts
So, padding doesn't work well for fixed widths/heights.
However, it can be handy for flexible/fluid layouts – provided you're using relative (percentage) units for svg child elements.
*{
box-sizing:border-box;
}
svg{
border:1px solid #ccc;
}
svg {
background-color: lightblue;
padding:0 10px;
overflow:visible;
}
.svg2 {
padding:10px;
}
.svg3 {
padding:0px;
}
.resize{
resize:both;
overflow:auto;
padding:1em;
border:1px solid #ccc;
}
<p>resize me :</p>
<div class="resize">
<svg id="svg" width="100%" height="40" xmlns="http://www.w3.org/2000/svg">
<circle cx="0" cy="10" r="5" />
<circle cx="0" cy="30" r="5" />
<circle cx="50%" cy="10" r="5" />
<circle cx="50%" cy="30" r="5" />
<circle cx="100%" cy="10" r="5" />
<circle cx="100%" cy="30" r="5" />
</svg>
</div>
<div class="resize">
<svg class="svg2" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<!-- align path center to x/y =0 by adding viewBox offset width/2 height/2 -->
<symbol class="icon icon-home" id="iconHome" viewBox="20 20 40 40" overflow="visible">
<path d="M36.4 22.2l-5.2 0l0 13l-3.4 0l0-16.7l-7.7-8.7l-7.7 8.7l0 16.7l-3.4 0l0-13l-5.2 0l16.4-17.4z"></path>
</symbol>
<use x="0" y="0%" href="#iconHome" width="20" height="20" />
<use x="0" y="100%" href="#iconHome" width="20" height="20" />
<use x="50%" y="0%" href="#iconHome" width="20" height="20" />
<use x="50%" y="100%" href="#iconHome" width="20" height="20" />
<use x="100%" y="0%" href="#iconHome" width="20" height="20" />
<use x="100%" y="100%" href="#iconHome" width="20" height="20" />
</svg>
</div>
Based on what I was able to try on firefox and chromium: the specified width and height for an svg include the padding.
In other terms, if you want an image of 20*20px with a padding of 10px on each side, you should set the width to 20+10*2 = 40px (same thing with the height) and the padding to 10px
Note : 20+10*2 : 20 is the width you want, 10 is your padding and you double it because you want it on both sides.
The best solution is open Inkscape (or other SVG editor) and change dimension

Using CSS approach how to set an image to fill a path in SVG?

I want to create a CSS class to fill a path with image that can be applied on any SVG path and fill that path with image. The image must be stretch to fit that path.
To achieve this; I create a pattern with image tag and set the width and height as 100%. but the image takes 100% of the whole screen instead of objectBoundingBox of the container (in this case svg tag).
Below is the sample code:
.myClass {
fill: url(#image);
stroke: red;
stroke-width: 5;
}
<svg id='pattern' xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<pattern id='image' x=0 y=0 width="100%" height="100%" patternUnits='objectBoundingBox'>
<image xlink:href='myImage.png' x=0 y=0 width="100%" height="100%" preserveAspectRatio="none"></image>
</pattern>
</defs>
</svg>
<svg id='triangle' xmlns="http://www.w3.org/2000/svg" version="1.1" width='300px' height='300px'>
<path d='M0 0 L300 0 L300 300 Z' class='myClass'></path>
</svg>
May be I am doing something wrong.
Please suggest any solution for this problem.
Here's your thing working - http://jsfiddle.net/eAfTc/
.myClass {
fill: url(#image);
stroke: red;
stroke-width: 5;
}
<svg id='pattern' xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<pattern id='image' width="1" height="1" viewBox="0 0 100 100" preserveAspectRatio="none">
<image xlink:href='http://dummyimage.com/600x400/abc/333' width="100" height="100" preserveAspectRatio="none"></image>
</pattern>
</defs>
</svg>
<svg id='triangle' xmlns="http://www.w3.org/2000/svg" version="1.1" width='300px' height='300px'>
<path d='M0 0 L300 0 L300 300 Z' class='myClass'></path>
</svg>
Note that there's a patternContentUnits and a patternUnits, they do different things. Personally I prefer to use a viewBox for defining the coordinate system.
Here's a new example showing the pattern applied to various elements of different sizes and aspect ratios, it also gets rid of the first svg fragment.
Update: I added 'preserveAspectRatio' to the <pattern> element, and a new example showing the stretching and scaling.

Resources