Cutting hole in DIV with background image [duplicate] - html

Is there an elegant, some kind of an easy way to switch the circle's background with the div's background under them?
I want the circles to apply the div "one" image background, but the div "one" to be invisible(not the visibility:hidden ofc).
I don't need to hardcore the heck out of it, I want an elegant/sort of an easy way to make this.
IE10/11 support and above.
.one {
position: relative;
width: 500px;
height: 300px;
background-image: url("https://ak5.picdn.net/shutterstock/videos/11223065/thumb/1.jpg");
}
.two,
.three {
position: absolute;
top: 50%;
transform: translate(0%, -50%);
left: 15px;
width: 100px;
height: 100px;
border-radius: 50%;
background: #fff;
}
.three {
left: initial;
right: 15px;
}
<div class="one">
<div class="two"></div>
<div class="three"></div>
</div>

I don't think there is an easy CSS solution for this but you can use SVG:
body {
background: linear-gradient(to right, blue, red)
}
<svg width="500" height="300">
<defs>
<!-- define the mask-->
<mask id="hole">
<rect width="100%" height="100%" fill="white"/>
<!-- the first hole -->
<circle r="50" cx="100" cy="150" fill="black"/>
<!-- the second hole -->
<circle r="50" cx="400" cy="150" fill="black"/>
</mask>
<!-- define the background image -->
<pattern id="img" patternUnits="userSpaceOnUse" width="500" height="300">
<image xlink:href="https://ak5.picdn.net/shutterstock/videos/11223065/thumb/1.jpg" x="0" y="0" width="500" height="300" />
</pattern>
</defs>
<!-- create a rect, fill it with the image and apply the above mask -->
<rect fill="url(#img)" width="100%" height="100%" mask="url(#hole)" />
</svg>

Related

calc() as SVG coordinate does not re-render when parent width changes

The Issue
In the following HTML code, I'm using the css calc() function to make an SVG line a percentage of the width of the parent container, minus a constant 20px:
<button onclick="myOnClick()">Click me</button>
<div id="my-div">
<svg xmlns="http://www.w3.org/2000/svg">
<line
x1="0px"
x2="calc(100% - 20px)"
y1="30px"
y2="50px"
stroke="#0000FF"
strokeWidth="10px"
/>
</svg>
</div>
When the button is clicked, the width of the parent container is changed.
function myOnClick() {
document.getElementById("my-div").style.width = "400px";
}
The expected behavior is that the line should change its ending coordinate to take into account the new width of the container. However, the line does not change width.
If you go into the element inspector and then change the x2 of the line to another value, then back to calc(100% - 20px), the line DOES update and takes on the new width of the container. This leads me to believe this is a rendering bug in Chrome.
Other Cases
Curiously, when I change one of the y coordinates to a percentage, rather than a pixel value, it works as expected:
<button onclick="myOnClick()">Click me</button>
<div id="my-div">
<svg xmlns="http://www.w3.org/2000/svg">
<line
x1="0px"
x2="calc(100% - 20px)"
y1="30px"
y2="100%" <-- LINE CHANGED
stroke="#0000FF"
strokeWidth="10px"
/>
</svg>
</div>
function myOnClick() {
document.getElementById("my-div").style.width = "400px";
}
#my-div {
width: 200px;
height: 500px;
background-color: red;
position: relative;
}
svg {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
}
<button onclick="myOnClick()">Click me</button>
<div id="my-div">
<svg xmlns="http://www.w3.org/2000/svg">
<line
x1="0px"
x2="calc(100% - 20px)"
y1="30px"
y2="100%"
stroke="#0000FF"
strokeWidth="10px"
/>
<line
x1="0px"
x2="calc(100% - 20px)"
y1="30px"
y2="50px"
stroke="#0000FF"
strokeWidth="10px"
/>
</svg>
</div>
Question
Is this expected behavior, or is this a bug in Chrome that should be reported?
This question only pertains to Chrome, as Firefox and Safari do not seem to support the calc() function for SVG components.
As calc() doesn't work for svg attributes in Firefox or Safari, you could get a similar layout
by applying padding to the parent <svg>
function myOnClick() {
document.getElementById("my-div").style.width = "400px";
}
#my-div {
width: 200px;
height: 500px;
background-color: red;
position: relative;
}
svg {
width: 100%;
height: 100%;
box-sizing: border-box;
padding-right: 20px;
}
<button onclick="myOnClick()">Click me</button>
<div id="my-div">
<svg xmlns="http://www.w3.org/2000/svg">
<line
x1="0px"
x2="100%"
y1="30px"
y2="100%"
stroke="#0000FF"
strokeWidth="10px"
/>
<line
x1="0px"
x2="100%"
y1="30px"
y2="50px"
stroke="#0000FF"
strokeWidth="10px"
/>
</svg>
</div>
calc() is a CSS function and the x2 attribute is not a presentation attribute (can not be used in CSS) and can only take a length, number or percentage.
What if the width of the SVG was 100% - 20px like in this example:
function myOnClick() {
document.getElementById("my-div").style.width = "400px";
}
#my-div {
width: 200px;
height: 200px;
border: thin solid black;
display: flex;
align-items: flex-end;
flex-direction: column;
}
svg {
width: calc(100% - 20px);
height: 100%;
}
<button onclick="myOnClick()">Click me</button>
<div id="my-div">
<svg xmlns="http://www.w3.org/2000/svg">
<line x1="0" y1="30"
x2="100%" y2="50"
stroke="#0000FF"
stroke-width="10" />
</svg>
</div>

Stacking SVG's ontop of each other in a DIV

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>

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

Fixed SVG height & variable (100%) width

I'm trying to put a svg object on my html page and I want it to have a 100% width and a fixed height.
In my fiddle you can see that the height of the dark-grey object changes according to the window proportions. (This is not what I want)
http://jsfiddle.net/Lq207ery/6/
HTML
<body>
<!-- HEADER -->
<header>
<div class="logo"></div>
<div class="triangle">
<svg data-type="vertical_parallax" data-speed="2" x="0px" y="0px" width="410" height="410" viewBox="0 0 310 310" style="-webkit-transform: translate3d(0px, 0px, 0px); transform: translate3d(0px, 0px, 0px);">
<g>
<!--<polyline stroke="#222" fill="none" stroke-width="1" points="0,210 0,210 310,0 "></polyline>-->
<polyline fill="#CC0000" points="0,0 0,200 300,0 "></polyline>
</g>
</svg>
</div>
<div class="nav">
<svg width="100%" viewBox="0 0 10 10" preserveAspectRatio="xMinYmin">
<polygon fill="#222" stroke-width="0" points="0,1.5 0,0 10,0 15,0 " />
</svg>
</div>
</header>
<!-- CONTENT -->
CSS
body {
margin: 0;
}
header svg {
display: block;
margin: 0;
}
header .triangle {
z-index: 200;
}
header .logo {
margin-top: -90px;
}
header .nav {
position: absolute;
top:0;
left:0;
width:100%;
z-index:-1;
}
Give your SVG element a fixed height. If you do not do this the height of the element will change proportional to the width.
Adjust your viewBox to crop to the height of your content.
Fix your preserveAspectRatio value to have the proper case-sensitive value, e.g. xMinYMin (not xMinYmin).
Demo: http://jsfiddle.net/Lq207ery/8/
If you want your dark grey triangle to stretch (not preserving its aspect ratio) then instead use preserveAspectRatio="none".
Demo: http://jsfiddle.net/Lq207ery/9/
You explanation is somewhat short, but you could do it like this :
HTML Code :
<header>
<div class="triangle">
<svg x="0px" y="0px" width="410" height="410" viewBox="0 0 310 310">
<g>
<polyline fill="#CC0000" points="0,0 0,200 300,0"/>
</g>
</svg>
</div>
<div class="nav"></div>
</header>
CSS Code :
html, body {
margin: 0;
}
header {
position: relative;
}
header .triangle {
position: relative;
z-index: 2;
}
header .nav {
position: absolute;
top:0;
left:0;
width: 2000px; // big screens
height: 100px;
background-image:url('data:image/svg+xml;utf8,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%22150px%22%20height%3D%2215px%22%20viewBox%3D%220%200%20150%2015%22%3E%3Cg%3E%3Cpolygon%20fill%3D%22%23222%22%20points%3D%220%2C15%200%2C0%20100%2C0%20150%2C0%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E');
background-size: cover;
background-position: bottom left;
z-index: 1;
}
SVG before url encoding :
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="150px" height="15px" viewBox="0 0 150 15">
<g>
<polygon fill="#222" points="0,15 0,0 100,0 150,0"/>
</g>
</svg>
Demo : http://jsfiddle.net/sparkup/21uaffpy/
Or line this maybe : http://jsfiddle.net/sparkup/21uaffpy/18/
In addition I'd like to add If the svg has the viewBox and preserveAspectRatio all set, another place possibility is to use a container div and font-size something like:
<div style="height: 50px; width: 50px; fontSize: 50px">
<svg>...</svg>
</div>