How to set svg width and svg height by percent?
I solved my problem.
I change my code to this and this is working:
<svg style="width:100%;height:100%;">
<line x1="100%" y1="0%" x2="0%" y2="100%" style="stroke: rgb(234, 243, 234);stroke-width: 5;"></line>
</svg>
Forcing an SVG to resize based on percentage height
With a lot of help, I was able make this javascript solution. I hope this helps anyone who wants to get a row of svgs that are fully responsive to the height and width of the screen. Note that because the text in the footer containing the SVGs is not completely responsive to height, the svgs disappear at the smallest media heights. If you want it fully responsive, you should make the text divs height-dependent.
Here is the codepen: http://codepen.io/ihatecoding/pen/vGrVQd
Here is the snippet:
$(document).ready(scaleSVG);$(window).on('resize', scaleSVG);
function scaleSVG() { var scale = 0.9; var $eyCol = $(".ey-col-svg"); var eyWidth = $eyCol.width(); var eyHeight = $eyCol.height(); var maxHeight = .4 * $(window).height();
if(eyHeight < eyWidth && eyHeight < maxHeight) $(".areaSVG").height(maxHeight);
var imageWidth = scale * $eyCol.width(); var imageHeight = $eyCol.height(); var tot = imageWidth > imageHeight ? imageHeight : imageWidth; //var imageHeight = 0.5*$(".ey-col-svg").height();
$(".areaSVG").css("width", tot); $(".areaSVG").css("height", tot);};
#footer { text-align: center; position: fixed; vertical-align: middle; bottom: 0; left: 0; z-index: 5000; width: 100%; max-height: 40vh;}
.areaSVG { /* this is the height setting I wanted to be a percentage */ /*height: 30%; <------ there*/ overflow: visible; box-sizing: content-box; backgroud-color: Grey;}
.ey-col-svg { display: block; height: calc(100% - 30px); max-height: calc(40vh - 2vw - 63px); padding: 0 0; margin:0; text-align: center; background-color: Red;}
.ey-nav-bar { background-color: MediumVioletRed ! important; width: 100% !important; height: 100%; overflow: hidden; text-align: center;}
.ey-row-scale { text-align: center; padding-left: 2.5%; padding-right: 2.5%; display: block; background-color: Orange; max-width: 95%; height: calc(100% - 28px); overflow: hidden;}
.ey-col-1 { text-align: center; background-color: Green; width: 20%; height: 100%; margin: 0; padding: 0; display: inline-block; border-collapse: collapse;}
.ey-text-content { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; display: block; text-align: center; white-space: nowrap; font-size: 2vw; height: calc(2vw + 5px); line-height: calc(2vw + 5px); color: black; z-index: 10000;}
#linkTextCell { text-align: center; width: 100%; height: 28px; line-height: 28px; vertical-align: middle; font-size: 150%; display: block; color: White; background-color: Blue;}
#content { font-size: 2vw;}
.fillDark{fill:DimGray;}.fillWhite{fill:White;}.strokeDark{stroke:DimGray;}.strokeWhite{stroke:White;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<div id="content"> <p>Javascript solution to scaling svgs. This isn't perfect. At the very smallest heights the SVGs disappear (because the text isn't scaling in response to hight). But, with a bit of work you can customize this to your needs.</p> </div>
<div id="footer">
<div id="linkTextCell" class="navText hideRow"> Links:</div>
<div class="ey-nav-bar"> <div class="ey-row-scale">
<div class="ey-col-1"> <a class = "eSVG areaAnchor" href="#">
<div class="ey-col-svg">
<svg class="areaSVG" viewBox="20 0 37 73" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <path id="circle-background" opacity="0.4196" fill="#FFFFFF" enable-background="new " d=" M4.193,37.492c0-18.987,15.419-34.38,34.44-34.38c19.021,0,34.439,15.393,34.439,34.38c0,18.987-15.418,34.381-34.439,34.381 C19.613,71.873,4.193,56.48,4.193,37.492L4.193,37.492z" /> <path id="sclera" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M11.41,38.895c27.619-31.029,41.313-9.542,49.646-2.012c-4.306,6.07-12.69,27.49-46.392,9.919c0,0-5.375-3.548-5.641-4.75 C12.787,37.379,11.41,38.895,11.41,38.895z" /> <ellipse id="iris" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" cx="38.196" cy="36.63" rx="16.202" ry="15.686" /> <ellipse id="pupil" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" cx="38.529" cy="36.954" rx="5.628" ry="5.449" /> <path id="eyelid" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M56.955,26.227c5.438,2.787,12.803,9.595,12.803,9.595s-2.338,3.235-5.677,2.588c-4.027,3.396-13.345,29.705-49.417,8.393 c33.702,17.571,42.086-3.849,46.392-9.919c-8.333-7.53-22.026-29.018-49.646,2.012c0,0-2.94,1.806-4.112-1.456 c-1.172-3.261,2.481-0.477,4.009-2.911c1.527-2.434,3.674-3.557,7.682-6.792c-4.008,0.646-7.348,3.558-7.348,3.558 c10.521-10.835,31.379-17.498,53.107-4.205C64.748,27.089,59.404,26.119,56.955,26.227z" /></svg>
</div>
<div class="ey-text-content navText">Link 1</div> </a>
</div>
<div class="ey-col-1"> <a class = "sSVG areaAnchor" href="#">
<div class="ey-col-svg"> <svg class="areaSVG" viewBox="20 0 37 73" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <path id="circle-background" opacity="0.4196" fill="#FFFFFF" enable-background="new " d=" M4.193,37.492c0-18.987,15.419-34.38,34.44-34.38c19.021,0,34.439,15.393,34.439,34.38c0,18.987-15.418,34.381-34.439,34.381 C19.613,71.873,4.193,56.48,4.193,37.492L4.193,37.492z" /> <path id="sclera" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M11.41,38.895c27.619-31.029,41.313-9.542,49.646-2.012c-4.306,6.07-12.69,27.49-46.392,9.919c0,0-5.375-3.548-5.641-4.75 C12.787,37.379,11.41,38.895,11.41,38.895z" /> <ellipse id="iris" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" cx="38.196" cy="36.63" rx="16.202" ry="15.686" /> <ellipse id="pupil" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" cx="38.529" cy="36.954" rx="5.628" ry="5.449" /> <path id="eyelid" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M56.955,26.227c5.438,2.787,12.803,9.595,12.803,9.595s-2.338,3.235-5.677,2.588c-4.027,3.396-13.345,29.705-49.417,8.393 c33.702,17.571,42.086-3.849,46.392-9.919c-8.333-7.53-22.026-29.018-49.646,2.012c0,0-2.94,1.806-4.112-1.456 c-1.172-3.261,2.481-0.477,4.009-2.911c1.527-2.434,3.674-3.557,7.682-6.792c-4.008,0.646-7.348,3.558-7.348,3.558 c10.521-10.835,31.379-17.498,53.107-4.205C64.748,27.089,59.404,26.119,56.955,26.227z" /> </svg> </div>
<div class="ey-text-content navText">Link 2</div>
</a>
</div>
<a class = "wSVG areaAnchor" href="#">
<div class="ey-col-1">
<div class="ey-col-svg"> <svg class="areaSVG" viewBox="20 0 37 73" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <path id="circle-background" opacity="0.4196" fill="#FFFFFF" enable-background="new " d=" M4.193,37.492c0-18.987,15.419-34.38,34.44-34.38c19.021,0,34.439,15.393,34.439,34.38c0,18.987-15.418,34.381-34.439,34.381 C19.613,71.873,4.193,56.48,4.193,37.492L4.193,37.492z" /> <path id="sclera" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M11.41,38.895c27.619-31.029,41.313-9.542,49.646-2.012c-4.306,6.07-12.69,27.49-46.392,9.919c0,0-5.375-3.548-5.641-4.75 C12.787,37.379,11.41,38.895,11.41,38.895z" /> <ellipse id="iris" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" cx="38.196" cy="36.63" rx="16.202" ry="15.686" /> <ellipse id="pupil" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" cx="38.529" cy="36.954" rx="5.628" ry="5.449" /> <path id="eyelid" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M56.955,26.227c5.438,2.787,12.803,9.595,12.803,9.595s-2.338,3.235-5.677,2.588c-4.027,3.396-13.345,29.705-49.417,8.393 c33.702,17.571,42.086-3.849,46.392-9.919c-8.333-7.53-22.026-29.018-49.646,2.012c0,0-2.94,1.806-4.112-1.456 c-1.172-3.261,2.481-0.477,4.009-2.911c1.527-2.434,3.674-3.557,7.682-6.792c-4.008,0.646-7.348,3.558-7.348,3.558 c10.521-10.835,31.379-17.498,53.107-4.205C64.748,27.089,59.404,26.119,56.955,26.227z" /> </svg> </div> <div class="ey-text-content navText">Link 3</div>
</div> </a>
<div class="ey-col-1"> <a class = "nSVG areaAnchor" href="#">
<div class="ey-col-svg"> <svg class="areaSVG" viewBox="20 0 37 73" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <path id="circle-background" opacity="0.4196" fill="#FFFFFF" enable-background="new " d=" M4.193,37.492c0-18.987,15.419-34.38,34.44-34.38c19.021,0,34.439,15.393,34.439,34.38c0,18.987-15.418,34.381-34.439,34.381 C19.613,71.873,4.193,56.48,4.193,37.492L4.193,37.492z" /> <path id="sclera" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M11.41,38.895c27.619-31.029,41.313-9.542,49.646-2.012c-4.306,6.07-12.69,27.49-46.392,9.919c0,0-5.375-3.548-5.641-4.75 C12.787,37.379,11.41,38.895,11.41,38.895z" /> <ellipse id="iris" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" cx="38.196" cy="36.63" rx="16.202" ry="15.686" /> <ellipse id="pupil" class="fillWhite" fill-rule="evenodd" clip-rule="evenodd" cx="38.529" cy="36.954" rx="5.628" ry="5.449" /> <path id="eyelid" class="fillDark" fill-rule="evenodd" clip-rule="evenodd" stroke-width="0.25" stroke-miterlimit="8" d=" M56.955,26.227c5.438,2.787,12.803,9.595,12.803,9.595s-2.338,3.235-5.677,2.588c-4.027,3.396-13.345,29.705-49.417,8.393 c33.702,17.571,42.086-3.849,46.392-9.919c-8.333-7.53-22.026-29.018-49.646,2.012c0,0-2.94,1.806-4.112-1.456 c-1.172-3.261,2.481-0.477,4.009-2.911c1.527-2.434,3.674-3.557,7.682-6.792c-4.008,0.646-7.348,3.558-7.348,3.558 c10.521-10.835,31.379-17.498,53.107-4.205C64.748,27.089,59.404,26.119,56.955,26.227z" /> </svg> </div>
<div class="ey-text-content navText">Link 4</div> </a>
</div>
</div> </div>
</div>
How can I make an svg scale with its parent container?
To specify the coordinates within the SVG image independently of the scaled size of the image, use the viewBox
attribute on the SVG element to define what the bounding box of the image is in the coordinate system of the image, and use the width
and height
attributes to define what the width or height are with respect to the containing page.
For instance, if you have the following:
<svg>
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
It will render as a 10px by 20px triangle:
Now, if you set only the width and height, that will change the size of the SVG element, but not scale the triangle:
<svg width=100 height=50>
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
If you set the view box, that causes it to transform the image such that the given box (in the coordinate system of the image) is scaled up to fit within the given width and height (in the coordinate system of the page). For instance, to scale up the triangle to be 100px by 50px:
<svg width=100 height=50 viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
If you want to scale it up to the width of the HTML viewport:
<svg width="100%" viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
Note that by default, the aspect ratio is preserved. So if you specify that the element should have a width of 100%, but a height of 50px, it will actually only scale up to the height of 50px (unless you have a very narrow window):
<svg width="100%" height="50px" viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
If you actually want it to stretch horizontally, disable aspect ratio preservation with preserveAspectRatio=none
:
<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
(note that while in my examples I use syntax that works for HTML embedding, to include the examples as an image in StackOverflow I am instead embedding within another SVG, so I need to use valid XML syntax)
SVG - percentage height and width does not work in HTML5
If you set the width and height of the html and body elements you can get either result regardless of the presence of the html DOCTYPE
body, html {
padding:0;
margin:0;
height: auto;
width: 100%;
}
or
body, html {
padding:0;
margin:0;
height: 100%;
width: 100%;
}
legacy rendering simply has a different default for the default html height property. Both cases "work" provided you understand that, it's just a case of which one you want.
You may also want to make the svg element display: block e.g.
svg {
display: block;
}
Scale SVG width to height (100% of parent)
It is easier to adjust the spaces in a container when you set its box-sizing
property to border-box
first to make sure that your containers maintain the same height and width when you adjust their margin
and padding
. To make it scale horizontally, just add width: 100%;
to your #map-svg
. To make it stay on 100 viewport without the overflow, what I did was to set the #wrapper-div
to have a height
of 100vh
, made the header
absolute and set the height
of #map-svg
the same with #wrapper-div
's height, added some padding as well to avoid overlapping of header and the map. Check the snippet below for your reference:
let path = d3.geoPath()
let svg = d3.select("#map-svg")
.attr("preserveAspectRatio", "xMidYMid meet")
.attr("viewBox", "0 0 960 600")
d3.json("https://cdn.jsdelivr.net/npm/us-atlas@3/counties-albers-10m.json").then(
function(us) {
svg.selectAll("path.county")
.data(topojson.feature(us, us.objects.counties).features)
.join("path")
.attr("id", function(d) {
return d["id"]
})
.attr("class", "county")
.attr("fill", "#E7E7E8")
.attr("stroke", "#FFFFFF")
.attr("stroke-linejoin", "round")
.attr("stroke-width", "0.3")
.attr("d", path)
}
)
* {
margin: 0;
padding: 0;
border: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
#wrapper-div {
height: 100vh;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
outline: 1px solid red;
}
#header-div {
background-color: lightblue;
-webkit-flex: 0 0 auto;
flex: 0 0 auto;
position: absolute;
width: 100%;
}
#map-div {
background-color: lightgreen;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
}
#map-svg {
background-color: lightpink;
padding: 1.5rem 0 .5rem;
width: 100%;
height: 100vh;
}
<body>
<div class="container-fluid" id="wrapper-div">
<div class="container-fluid" id="header-div">
HEADER TEXT
</div>
<div class="container-fluid" id="map-div">
<svg id="map-svg"></svg>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/topojson@3"></script>
<script src="./index.js"></script>
</body>
How can I convert the width of SVG from percent to pixel?
To achieve this you can use calc()
. This will let you perform calculations when specifying CSS property values.
So your code should be something like this:
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var svgNS = svg.namespaceURI;
svg.setAttribute('id', 'idsvg');
svg.setAttribute('width', 'calc(100% - 20px)');
svg.setAttribute('height', '100%');
NOTE: Keep in mind, you can't use calc(100% - 20px)
for height
in your particular case because the result will be unknown. So it's better to use calc(100vh - 20px)
or 100%
itself.
SVG aspect ratio is preserved when width is greater than height despite of the preventive setting
If I've understood correctly, you want the svg to change aspect ratio such that the diagonal line is always wholly in view.
Your svg is structured correctly to do this with preserveAspectRatio="none"
on an image drawn with user units for the line and viewbox matching.
The reason your svg is extending beyond the page height is because the container div extends beyond the page height.
I've added a class to the parent div containing the svg and styled it to have height of 100vh
( minus a nominal pixel value to ensure scroll bars don't show). I also gave the div a border so you can see it now occupies the viewable screen and the SVG remders the line from top left to bottom right corners.
On a resizable page, the div will resize and the svg will change aspect ratio to always occupy it.
.svgFrame {
border: 1px solid red;
width: 100%;
height: calc(100vh - 20px);
}
<div class="svgFrame" style="grid-row: 2; grid-column: 1; display: grid;">
<svg width="100%" height="100%" viewBox="0 0 1000 1000" preserveAspectRatio="none">
<polyline points="0,0 1000,1000" stroke="blue" stroke-width="5px" />
</svg>
</div>
Related Topics
In Sass, What's The Difference Between The @Mixin and @Extend Directives
What's The Difference Between Line-Height:1.5 and Line-Height:150% in CSS
Page-Break-After Not Working in Flexboxes
CSS: Placing an Arrow/Triangle with Border on The Top of My Drop Down Menu
React-Datepicker Input Width Will Not Adjust to 100%
Separate Sentence to One Word Per Line
How Does 'Flex-Grow:0' Get Interpreted
CSS Filter Grayscale Not Working in Firefox
Text-Decoration: Underline Vs Border-Bottom
Column Are Full Width in Ie 8 - CSS Bootstrap
When to Use Gwt Ensureinjected()
Margin: Auto Not Working in Ie
CSS3 Transition Fadein with Display:None
How to Move Bootstrap 3 Carousel Caption Below Images
Any Programs to Generate CSS Classes from Your HTML