Placing image inside SVG, removes the SVG - html

I have this HTML code:
<div class="shape-wave fill-accent">
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 -30 1200 150" preserveAspectRatio="none">
<filter id="dropshadow" y="-100%" height="300%">
<feGaussianBlur in="SourceAlpha" stdDeviation="9"/>
<feOffset dx="0" dy="-2" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="2"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<path class="shape-fill" filter="url(#dropshadow)" d="M985.66,92.83C906.67,72,823.78,31,743.84,14.19c-82.26-17.34-168.06-16.33-250.45.39-57.84,11.73-114,31.07-172,41.86A600.21,600.21,0,0,1,0,27.35V120H1200V95.8C1132.19,118.92,1055.71,111.31,985.66,92.83Z"></path>
</svg>
</div>
and this CSS code:
.shape-wave {
position: absolute;
top: 0;
left: 0;
width: 100%;
overflow: hidden;
line-height: 0;
transform: rotate(180deg);
}
.shape-wave svg {
position: relative;
display: block;
width: calc(100% + 1.3px);
height: 40px;
}
#media (min-width: 720px) {
.shape-wave svg {
height: 70px;
}
}
.fill-accent {
fill: url(/Background.png);
}
When I try to use .fill-accent on the SVG element to fill it with the background image, the SVG completely disappears from the page instead replaced with the below elements background.
what I'm trying to do is have this wave shape filled with the same background image (background.png) as the element above it so it looks like a fluent transition to the next section although I cannot seem to get it to take the image, it works fine when it's just a solid colour.
also sorry I know this is probably a bit of a mess, first time coding HTML really, I'll try to clean it up at the end.

Related

Create curved background with box-shadow [duplicate]

I am thinking how to style a squizzed box like this:
I found that I can achieve a similar result with pseudo elements and border-radius as percentage.
Here is the CodePen: https://codepen.io/micu22/pen/eYzpmqR
And here is the code:
div {
background: lightblue;
padding: 10px 20px;
border-radius: 8px;
position: relative;
}
div::after,
div::before {
content: "";
position: absolute;
background: white;
width: 100%;
height: 20px;
left: 0;
}
div::before {
top: -17px;
border-radius: 50%;
}
div::after {
bottom: -17px;
border-radius: 50%;
}
But maybe there is an easier or just more elegant solution?
I would do it like below, using gradient coloration and an SVG filter:
.box {
width:200px;
height:250px;
background:
/* v-- adjust the 15% here */
radial-gradient(50% 15% at top, transparent 98.5%,lightblue) top,
radial-gradient(50% 15% at bottom,transparent 98.5%,lightblue) bottom;
background-size:100% 51%;
background-repeat:no-repeat;
filter: url('#goo');
}
<div class="box"></div>
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs> <!-- adjust the the 13 here --v -->
<filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="13" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
It depends on how the content is going to exist. If this is a fixed height container, I'd probably opt for a solution using an SVG background.
I think the most elegant (or at least intrinsic) solution would involve using clipping paths. This would allow you to create an SVG of the exact shape you want and clip the container or background image for the container so that you aren't disguising a still technically visible part of the element.
Clippy is a great tool if you've never worked with clipping masks before.

How to hide reusable svg with filter that has filterUnits="userSpaceOnUse"

I want to hide a reusable svg, height: 0 and width: 0 does the job, but when I have a filter with filterUnits="userSpaceOnUse" it hides the svg that is using the filter. How can I hide the reusable svg without hiding the svg that is using the filter?
.reusable-svgs{
height: 0;
width: 0;
position: absolute;
}
svg{
overflow: visible;
}
div{
width: 50px;
height: 50px;
}
rect{
filter: url(#shadow);
fill: yellow;
}
<svg class="reusable-svgs">
<filter id="shadow" width="200%" height="200%" y="-60%" x="-60%" filterUnits="userSpaceOnUse">
<feDropShadow dx="0.4" dy="0" stdDeviation="4" />
</filter>
</svg>
<div>
<svg viewbox="0 0 20 20"><rect height="20" width="20"/></svg>
</div>

Apply Glow Effect Filter to Anchor Tag with Transparent Path Child SVG

I would like to create an image map by using an SVG to create the clickpoints. I have been asked to add a glow to the anchor on hover, which I'm currently doing by applying a filter to the anchor tag with CSS on hover. However, the glow only works if the path that is a child of the anchor has a solid fill color, as seen in this CodePen. The SVG used is the following:
<svg version="1.1"
viewBox="0 0 3686 2074"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="white-glow"
x="-5000%"
y="-5000%"
width="10000%"
height="10000%">
<feFlood result="flood"
flood-color="#00bbdc"
flood-opacity="1"></feFlood>
<feComposite in="flood"
result="mask"
in2="SourceGraphic"
operator="in"></feComposite>
<feMorphology in="mask"
result="dilated"
operator="dilate"
radius="10"></feMorphology>
<feGaussianBlur in="dilated"
result="blurred"
stdDeviation="5"></feGaussianBlur>
<feMerge>
<feMergeNode in="blurred"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<style>
a {
text-decoration: none;
}
path:hover {
filter: url(#white-glow);
}
a:hover {
filter: url(#white-glow);
text-decoration: none;
fill: #00BBDC;
font-weight: bold;
}
a:hover text {
filter: invert(62%) sepia(97%) saturate(3198%) hue-rotate(150deg) brightness(98%) contrast(101%);
font-weight: bold;
}
</style>
</defs>
<g>
<a href="google.com"
target="_top">
<path d="m473.3 564.3-0.6911 207 412.4 78.63-0.4043-180.9z"
style="fill:white;stroke-opacity:0;"
cursor="pointer"
pointer-events="all" />
<text transform="rotate(10.2 222.2 851.7)"
style="fill:#808080;font-family:'sans-serif';font-size:40px;line-height:1.25;shape-inside:url(#rect898);white-space:pre"
xml:space="preserve">
<tspan x="304.74805"
y="648.91602">
<tspan>Ask the experts</tspan>
</tspan>
</text>
</a>
</g>
</svg>
However, I would like to accomplish the same glow effect on hover while giving the path a fill value of "transparent".
Could you please give me some guidance as to how to proceed in order to accomplish the same end result that was referenced before while keeping the fill value of the path within the anchor tag to "transparent"? I've read the following Smashing Magazine article in which the author talks about the difference between painted and visible SVG elements. Also, according to an answer to How to have a drop shadow on a transparent rect svg,
You can't do this if the original is a fully transparent shape - because of reasons - but you can do this starting from an almost completely transparent original shape and end up with a fully transparent shape surrounded by a normal drop shadow.
I used the work around provided and published a Codepen demo with it. However, the "Text" child in the anchor tag gets hidden on hover although it's still present in the SVG. Indeed, the filter is blurring away the text. Could you please tell me is there is any other way?
Thanks for your share of expertise on this one.
If you want to retain the contents of the original graphic, then you need to add another line to your filter which pastes the original content on top of your glow.
.container {
position: relative;
max-width: 100%;
width: 100%;
height: auto;
background-size: contain;
background-repeat: no-repeat;
margin: 0;
background:orange;
}
<div class="container">
<svg version="1.1"
viewBox="0 0 3686 2074"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="white-glow"
x="-5000%"
y="-5000%"
width="10000%"
height="10000%">
<feFlood result="flood"
flood-color="#00bbdc"
flood-opacity="1"></feFlood>
<feComposite in="flood"
result="mask"
in2="SourceGraphic"
operator="in"></feComposite>
<feMorphology in="mask"
result="dilated"
operator="dilate"
radius="10"></feMorphology>
<feGaussianBlur in="dilated"
result="blurred"
stdDeviation="5"></feGaussianBlur>
<feMerge>
<feMergeNode in="blurred"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<filter id="trans-shadow">
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 100 0"
result="boostedInput"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite operator="out" in2="boostedInput"/>
<feComposite operation="over" in2="SourceGraphic"/>
</filter>
</defs>
<style>
a {
text-decoration: none;
}
a:hover {
filter: url(#trans-shadow);
text-decoration: none;
fill: #00BBDC;
font-weight: bold;
}
a:hover text {
filter: invert(62%) sepia(97%) saturate(3198%) hue-rotate(150deg) brightness(98%) contrast(101%);
font-weight: bold;
}
</style>
<g>
<a href="google.com"
target="_top" pointer-events="all" >
<path d="m473.3 564.3-0.6911 207 412.4 78.63-0.4043-180.9z"
style="fill:white;fill-opacity="0.01"stroke-opacity:0;" visibility="visible"
/>
<text transform="rotate(10.2 222.2 851.7)"
style="fill:#808080;font-family:'sans-serif';font-size:40px;line-height:1.25;shape-inside:url(#rect898);white-space:pre"
xml:space="preserve">
<tspan x="304.74805"
y="648.91602">
<tspan>Ask the experts</tspan>
</tspan>
</text>
</a>
</g>
</svg>
</div>

SVG mask not loading initially in Chrome

Working on a project which is using a SVG mask on the homepage hero component but for some reason the text in the mask only shows when I resize the window. It's not showing on the initial page load. This is happening only in Chrome (latest version).
You can view the example on the STAGING environment here: https://staging.erwconstructions.com.au/
HTML Markup is:
<section data-component="mask-hero" class="in-view mask-hero">
<picture>
<img src="https://staging.erwconstructions.com.au/wp-content/uploads/2020/07/home-hero.jpg" alt="Home">
<svg width="100%" height="100%" viewBox="0 0 100% 100%">
<defs>
<linearGradient id="gradient">
<stop offset="100%" stop-color="black" />
</linearGradient>
<mask id="mask">
<rect width="100%" height="100%" fill="#fff" />
<text x="0" y="50%">
<tspan x="5vw" dy="-.1em">Building</tspan>
<tspan x="5vw" dy="1em">Redefined</tspan>
</text>
</mask>
</defs>
<rect width="100%" height="100%" fill="url(#gradient)" fill-opacity="0.9" mask="url(#mask)" />
</svg>
</picture>
</section>
The CSS is:
[data-component="mask-hero"] {
height: 100vh;
padding: 0;
background: none;
& picture {
display: block;
height: 100vh;
& img {
height: 100%;
object-fit: cover;
object-position: center;
position: fixed;
will-change: transform;
width: 100%;
z-index: -1;
}
& svg {
display: block;
height: 100%;
}
& text {
font-family: var(--defaultFont);
font-weight: var(--bold);
font-size: 3em;
#media (--app-breakpoint-2) {
font-size: 6em;
}
#media (--app-breakpoint-4) {
font-size: 8em;
}
#media (--app-breakpoint-5) {
font-size: 14em;
}
}
}
}
For some reason there is also a console error regarding the viewBox, even though the correct attributes are set on the SVG:
Error: <svg> attribute viewBox: Expected number, "0 0 100% 100%".
Any help would be greatly appreciated.
Thanks,
Dayne
By the given error, I'd guess to problem is with the viewBox. It should be given an absolute number in px, not percent. Like <svg viewBox="0 0 100 100">
Have you tried using javascript to make it work ?
This code below adds background color to white on rect inside svg code to show the text when the page has loaded.
var svgRect = document.querySelector('svg rect');document.addEventListener("DOMContentLoaded", function(){ setTimeout(function() { svgRect.style.backgroundColor = 'white'; }, 500); });

How to give border radius to make an element look like this image?

I am trying to make .main-div like this image
.main-div {
width: 100px;
height: 100px;
background-color: Red;
border-radius: 30px/20px;
}
<div class="main-div"></div>
My JSFiddle is here.
You can do a trick using a pseudo element and achieve that shape
body {
background: lightgray;
}
.main-div {
position: relative;
display: inline-block;
width: 110px;
height: 100px;
background-color: red;
border-radius: 30%/50%;
background: url(https://i.stack.imgur.com/CWoXa.png) center center no-repeat;
background-size: 110px 110px;
}
.main-div::after {
content: '';
position: absolute;
left: 5px;
top: -5px;
width: 100px;
height: 110px;
background: inherit;
background-size: inherit;
border-radius: 50%/30%;
}
.main-div+.main-div {
background: gray;
}
<div class="main-div"></div>
<div class="main-div"></div>
As Justinas remarked in their answer, the border of your example image does not look like it can be recreated with border-radius alone. This is because the outline is not an ellipse.
It is possible to do this, with good browser support, using SVG as follows.
/* set size of and center SVG */
svg {
display: block;
width: 200px;
height: 200px;
margin: 0 auto;
}
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="outline">
<!-- use Bezier curves to define outline -->
<path d="M 0 100
C 0 0, 40 0, 100 0
C 160 0, 200 0, 200 100
C 200 200, 160 200, 100 200
C 40 200, 0 200, 0 100
Z" />
</clipPath>
</defs>
<image x="0" y="0" width="200" height="200"
xlink:href="https://placehold.it/200"
clip-path="url(#outline)" />
</svg>
This uses clipping in SVG with the clipPath element. You can define any path to use for the clipping. I have used four Bezier curves here. You can tweak where the control points are, or change this to use something entirely different if you wish.
An extra bonus of this approach is that it is now easy to apply other (advanced) filters, for example blurring the image or applying a drop shadow.
/* set size of and center SVG */
svg {
display: block;
width: 204px;
height: 204px;
margin: 0 auto;
}
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="outline">
<!-- use Bezier curves to define outline -->
<path d="M 0 100
C 0 0, 40 0, 100 0
C 160 0, 200 0, 200 100
C 200 200, 160 200, 100 200
C 40 200, 0 200, 0 100
Z" />
</clipPath>
<filter id="dropshadow" x="-30%" y="-30%"
width="160%" height="160%"
color-interpolation-filters="sRGB">
<!-- define color of shadow here -->
<feComponentTransfer in="SourceAlpha">
<feFuncR type="linear" slope="0"
intercept="0.518"></feFuncR>
<feFuncG type="linear" slope="0"
intercept="0.698"></feFuncG>
<feFuncB type="linear" slope="0"
intercept="0.867"></feFuncB>
</feComponentTransfer>
<!-- define blur of shadow here -->
<feGaussianBlur stdDeviation="2" />
<!-- we can offset the shadow -->
<feOffset result="shadow" dx="1" dy="1" />
<!-- put shadow below original content -->
<feBlend in="SourceGraphic"
in2="shadow" mode="normal" />
</filter>
</defs>
<g transform="translate(2, 2)"
filter="url(#dropshadow)">
<image x="0" y="0" width="200" height="200"
xlink:href="https://placehold.it/200"
clip-path="url(#outline)" />
</g>
</svg>
Your image radius does not look like standard CSS border radius. If yes, than you need to use image preprocessing (in back-end side, e.g. GD or stand-alone tool like Photoshop) or use Clipping Mask with limited support. Using border radius you can have similar effect.
.main-div {
width: 100px;
height: 100px;
background-color: red;
border-radius: 40%;
overflow: hidden;
position: relative;
}
.main-div img {
width: 100%;
position: absolute;
left: -50px;
top: -50px;
margin-top: 50%;
margin-left: 50%;
}
<div class="main-div">
<img src="http://lorempixel.com/200/200/"/>
</div>
Add this style. You can change border-radius as per your requirements:
div {
border: 2px solid #a1a1a1;
padding: 10px 15px; `enter code here`
background: #dddddd;
width: 100px;
border-radius: 55px;
}
.element {
border-radius: 50px;
overflow: hidden;
}
<img src="https://image.ibb.co/irvmO5/html5.png" alt="html5" border="0" class="element"><br /><a target='_blank' href='https://imgbb.com/'>Rounded rectangle clip mask</a>