Stacking SVG's ontop of each other in a DIV - html

I"m looking to stack these three images ontop of each other. I don't care if they're showing as they're animated and two will pop out horizontally from the side of each.
I however am getting an issue.
Please see attached photo:
All three SVG's are contained within the below structure:
<ImageContainer>
<MainIcon />
<JobListingIcon />
<SingularListing />
</ImageContainer>;
This is within a flex box:
const ImageContainer = styled.div`
width: 90%;
height: 400px;
margin-top: 20px;
background-color: #636388;
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
`;
I don't understand why they're being shown this way, and I have tried to have all 3 SVG's positioned absolute, but nothing.
What's the way to stack these? It it not a flex box? Potentially something like a MUI grid?
Sorry!

The problem with a phrase like "on top of each other" is that it is ambiguous. Do you mean:
vertically arranged on the page, or
one covers the other
It sounds like you might mean the second one. You can achieve that with absolute positioning.
parent <-- make this "position: relative;"
child )
child ) make either (or both) of these "position: absolute; top: 0;"
If those child elements are <svg> elements, then you'll also need to make them display: block, since SVGs are display: inline-block by default.
Demo
.parent {
position: relative;
width: 100px;
height: 150px;
}
svg {
display: block;
}
.svg-two {
position: absolute;
top: 0;
}
<div class="parent">
<svg class="svg-one" width="100" height="100">
<rect x="0" y="0" width="100" height="100" fill="linen"/>
<circle cx="50" cy="50" r="40" fill="red"/>
</svg>
<svg class="svg-two" width="100" height="150">
<rect x="20" y="0" width="60" height="150" fill="limegreen"/>
</svg>
</div>

Related

How can I make an <svg> element scale to a parent element's height?

I have an <svg> element within a wrapping element.
I want the <svg> to fill the height of the wrapping element, however I cannot seem to get this to work.
I have tried the following:
.image-banner__overlay {
height: 90%;
position: absolute;
z-index: 999;
}
svg {
height: 100%;
background-color: black;
}
path {
fill: red;
height: 100%;
}
<div class="cell small-12 medium-6 image-banner__image-wrapper">
<div class="image-banner__overlay">
<svg>
<path d="M91.91,125c0-50.63,10.58-95.75,27.07-125H69.22V250H119C102.49,220.75,91.91,175.63,91.91,125Z" transform="translate(-69.22)" />
</svg>
</div>
<div class="image-banner__image" style="#backgroundImage">
</div>
</div>
But the <svg> seems to only ever take up a max of about 75% of the space, eg:
I've tried using viewBox, eg:
height="100%" width="100%" viewBox="0 0 100 100" preserveAspectRatio="none"
But this makes the SVG way too big (overflows the parent element).
Would anyone know how I could get this to stretch the complete height of the parent element (without turning it into an <img>)?
Here's a viewbox for you, I know it's horrible but you should read up on it!
.image-banner__overlay {
height: 90%;
position: absolute;
z-index: 999;
}
svg {
height: 100%;
background-color: black;
}
path {
fill: red;
height: 100%;
}
<div class="cell small-12 medium-6 image-banner__image-wrapper">
<div class="image-banner__overlay">
<svg viewbox="0 0 80 250">
<path d="M91.91,125c0-50.63,10.58-95.75,27.07-125H69.22V250H119C102.49,220.75,91.91,175.63,91.91,125Z" transform="translate(-69.22)" />
</svg>
</div>
<div class="image-banner__image" style="#backgroundImage">
</div>
</div>

Scale SVG along other content with CSS flexbox

I want to display a rectangular SVG between two vertically aligned DIVs, so that the SVG takes up as much space as possible (but keeps its aspect ratio). As the SVG itself is dynamically generated, I have to use the <svg> HTML tag to include it (and i.e. can't use an <img> tag).
So I tried to use flexbox, but the SVG doesn't stick to the rules and gets too large:
html, body, .parent {
height: 100%;
}
.parent {
display: flex;
flex-flow: column nowrap;
}
.contentSVG {
flex-grow: 1;
}
<div class="parent">
<div class="contentA">
content A
</div>
<div class="contentSVG">
<!-- arbritrary SVG -->
<svg viewBox="0 0 10 10">
<circle cx="5" cy="5" r="5" fill="red" />
</svg>
</div>
<div class="contentB">
content B
</div>
</div>
If I replaced the SVG with some other content the example works as expected.
Do you have any idea how I can realize this without any JS involved?
You need to add width:100%;height:100% to the SVG and min-height:0 to the parent to allow the shrink effect
html, body, .parent {
height: 100%;
margin:0;
}
.parent {
display: flex;
flex-flow: column nowrap;
}
.contentSVG {
flex-grow: 1;
min-height:0;
}
svg {
width:100%;
height:100%;
}
<div class="parent">
<div class="contentA">
content A
</div>
<div class="contentSVG">
<!-- arbritrary SVG -->
<svg viewBox="0 0 10 10">
<circle cx="5" cy="5" r="5" fill="red" />
</svg>
</div>
<div class="contentB">
content B
</div>
</div>

Equivalent to background position percentage (%) in SVG

I have an SVG image that has the equivalent of background-size: cover; assigned to it using preserveAspectRatio="xMidYMid slice".
However on phone devices less than 737px I'd like to move this image to the left within its container. If was was using the CSS background property I would just do background-position: 85%; or similar.
Is there an equivalent way of doing this with SVG images?
Codepen: https://codepen.io/emilychews/pen/Zqragv
Many thanks in advance for any help.
body {
margin: 0;
padding: 0;
display: flex;
width: 100%;
height: 100vh;
justify-content: center;
align-items: center;
}
#section-1, .home-image-wrapper {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.home-image, .home-image-wrapper {
position: absolute;
right: 0;
}
#home-image-1 {right: 0%}
<section id="section-1">
<div class="home-image-wrapper">
<svg class="home-image" id="home-image-1" width="60%" height="100%">
<image xlink:href="https://i.postimg.cc/9XdQKYF1/dimon-blr-309444-unsplash.jpg" x="0" y="0" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"/>
</svg>
</div>
</section>
Setting position on svg elements
If you just want to change the svg element on a container (assuming <g> element).
You can apply a simple transform on any element:
Example:
<svg viewBox="0 0 100 100" width="300px">
<!--black rect-->
<g>
<rect x="0" y="0" width="20" height="20" />
</g>
<!--blue rect-->
<g transform="translate(20)" fill="#08a">
<rect x="0" y="20" width="20" height="20" />
</g>
</svg>
In SVG you can set the viewBox attribute. This defines the x, y, width and height of the visible part of the SVG. Let's say your jpg image has a width of 200 and a height of 100. In this case you set viewBox="0 0 200 100" by default to the <svg> element. On phone devices you can change the the viewBox value to something like 50 0 100 100, which would only display the middle 100 pixels of the image.
You can find more on the viewBox attribute here: http://jonibologna.com/svg-viewbox-and-viewport/

Svg clipPath to clip a div doesn't work in Safari when i duplicate it

I have created a clip path that I reuse on multiple divs in the page. I use the property clipPathUnits="objectBoundingBox" to make it apply to each div based on its position.
It works great in Chrome and Firefox. When I tried it in safari it only works based on the first div. Meaning that it works well the first time than when i call it again the boudingbox is still based on the first Div. I realized this when i gave a negative margin to the second div until it overlaped with the first one partial then I could see it.
Here is an example of the issue:
.bar {
height: 100px;
width: 100px;
}
.block {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: white;
z-index: 100;
display: block;
clip-path: url(#clipping);
-webkit-clip-path: url(#clipping);
}
<svg style="background: blue; height: 0px; overflow: hidden;">
<defs>
<clipPath id="clipping" clipPathUnits="objectBoundingBox">
<path fill="#FFFFFF" d="M0.501,0.971c-0.014,0-0.027-0.003-0.04-0.011l-0.34-0.194c-0.024-0.014-0.04-0.041-0.04-0.069L0.081,0.306
c0-0.028,0.015-0.055,0.04-0.069L0.458,0.04c0.013-0.007,0.026-0.011,0.04-0.011s0.027,0.003,0.04,0.011l0.339,0.194
c0.025,0.014,0.041,0.041,0.041,0.069l0.001,0.391c0,0.028-0.015,0.055-0.04,0.069L0.542,0.96C0.529,0.968,0.515,0.971,0.501,0.971z
" />
</clipPath>
</defs>
</svg>
<div class="bar" style="background: blue;">
<div class="block">
</div>
</div>
<div class="bar" style="background: green;">
<div class="block">
</div>
</div>
http://codepen.io/appteamio/pen/WbdRgx
I'm I doing something wrong or is it a Safari issue.If sois there any work aroung.
thanks

How to force this div to span the height of viewport?

This jsFiddle shows the problem. I have not managed to prevent the div0 div from "collapsing" its top margin with that of its sibling, div1. (HTML below.)
I want div0 to span the entire viewport vertically, and the red rect inside it to appear flush against the top left corner of the viewport. (The placement of div1 and its contents is exactly as desired, and should not be changed in any way.)
I have tried to disable the collapsing of margins by putting borders around both div0 and div1, but, as the jsFiddle shows, this has made no difference.
Here's the relevant HTML:
<!doctype html>
<body>
<div id="div0">
<svg id="svg0" width="50px" height="50px">
<g>
<rect x="0px" y="0px"
width="50px" height="50px" style="fill:red;"></rect>
</g>
</svg>
</div>
<div id="div1">
<div id="div2">
<svg id="svg1" width="100px" height="100px"></svg>
</div>
</div>
Here is a solution for you. I added a .wrapper class, with a absolute position, to contain the elements and maintain elasticity in your document. I also added overflow: hidden to your div0 id to prevent the red svg rect from flowing outside of that containing div.
Here is an updated >>>JSFiddle<<<
HTML:
<div class="wrapper">
<div id="div0">
<svg id="svg0" width="50px" height="50px">
<g>
<rect x="0" y="0" width="50px" height="50px"></rect>
</g>
</svg>
</div>
<div id="div1">
<div id="div2">
<svg id="svg1" width="100px" height="100px"></svg>
</div>
</div>
</div>
CSS:
body {
margin: 0;
padding: 0;
}
.wrapper {
position: relative;
width: 100%;
height: 100%;
border: 1px solid blue;
}
#div0 {
position: absolute;
top: 0;
left: 0;
width: 30%;
height: 100%;
background-color: yellow;
border: 1px solid blue;
overflow: hidden;
}
#div1 {
margin-top: 20px;
border: 1px solid green;
background: lightgray;
min-height: 27px;
display: -webkit-flex;
display: flex;
}
#div2 {
background: black;
margin: 0px auto;
}
rect {
fill: red;
}
#div0 {
height:100vh;
}
You can use the vh for viewport height.
OK, I found the solution: comment out the position:relative in the CSS for body. This is illustrated in this revision of the original fiddle. Notice that the only difference between this and the original fiddle is the commented-out line just mentioned.
(I'm ashamed to say that I found this solution by blind trial-and-error; I have no idea of why the new version works and the original one didn't.)