Raised border in SVG - css

I'm attempting create a SVG that expands with the amount of text I enter into it. I have three bars that I'm attempting to wrap with an outline, but the bars aren't melding into the outline, I'm getting a raised edge:
I have create a fiddle with my SVG code, please let me know how I can smooth those borders out. Also, if anyone has a better idea to how to create a SVG button that scales with text, please don't hesitate to let me know!
body { background-color: #13171a; }
g{
/*g element expands with text child element, so we'll apply the outline here */
outline: 1px solid #ffdb00;
}
g text { fill: #fff }
<svg
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="svg2"
viewBox="0 0 744 1052"
height="297mm"
width="210mm">
<g
id="layer1">
<path
id="path4150"
d="m 70,77 0,45"
style="fill:none;fill-rule:evenodd;stroke:#ffdb00;stroke-width:6;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path4152"
d="m 85,77 0,45"
style="fill:none;fill-rule:evenodd;stroke:#ffdb00;stroke-width:6;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;" />
<path
id="path4150-6"
d="m 58,77 0,45"
style="fill:none;fill-rule:evenodd;stroke:#ffdb00;stroke-width:6;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1" />
<text
id="text4169"
y="113.27509"
x="101.77287"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="113.27509"
x="101.77287"
id="tspan4171">TEST TEXT</tspan></text>
</g>
</svg>

Related

How do I make svg path hover area bigger

What I have:
#poly-1:hover {
stroke: green;
}
<svg width="1000" height="500" id="chart-main-canvas" style="background-color: bisque; z-index:5000;">
<path id="poly-1" d="M 5,10 C 24,88 60.99999999999998,322 100,400 C 139,478 149,470 200,400 C 251,330 295,30.000000000000007 355,50 C 415,70 470.99999999999994,410 500,500" fill="none" stroke="red" style="z-index:6000;"></path>
</svg>
If I hover exactly on path, which is a tricky task, line it will change color to green.
What I want to do is to make hover area of this path bigger, so I could move my cursor somewhere +-5px near the path area and it will still change color.
The only two ways I know I could do is:
Make stroke-width bigger, but I don't want its actual size with red color to increade.
With my main path create invisible duplicating path that has bigger stroke-width and add condition that if I hover on it - my main path will change color.
But there is any simple way to do it?
This answer is practically your second option.
I'm putting the path #poly-1 in the defs and use it first with a wide stroke-width and no stroke. In order to make it sensitive to the mouse I'm using pointer-events="stroke"
<use xlink:href="#poly-1" stroke-width="10" pointer-events="stroke"/>
Next comes another use - the visible one - with a red stroke.
I'm putting both use elements in a group. The stroke of the second use element changes when I'm mousing over the group.
#group .use {
stroke: red
}
#group:hover .use {
stroke: green;
}
<svg width="1000" height="500" id="chart-main-canvas" style="background-color: bisque; z-index:5000;">
<defs>
<path id="poly-1" d="M 5,10 C 24,88 61,322 100,400 C 139,478 149,470 200,400 C 251,330 295,30 355,50 C 415,70 471,410 500,500" fill="none" >
</path>
</defs>
<g id="group">
<use xlink:href="#poly-1" stroke-width="10" pointer-events="stroke"/>
<use class="use" xlink:href="#poly-1" />
</g>
</svg>
I added stroke width for color change to highlight.
please try this..
#poly-1:hover {
stroke: green !important;
stroke-width:2px;
}
<svg width="1000" height="500" id="chart-main-canvas" style="background-color: bisque; z-index:5000;">
<path id="poly-1" d="M 5,10 C 24,88 60.99999999999998,322 100,400 C 139,478 149,470 200,400 C 251,330 295,30.000000000000007 355,50 C 415,70 470.99999999999994,410 500,500" fill="none" stroke="red" style="z-index:6000;"></path>
</svg>

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.

CSS Clip-path positioning issues

I have created a fairly simple shape using an SVG element which is then put into my CSS using clip-path. It should make the corners rounded for me but for some reason only 1 of the corners does the effect perfectly.
This is the shape:
<svg height="500" width="500">
<path fill="#555555" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
</svg>
This is what happens when i use it as a clip-path
body {
background: #555;
}
img {
clip-path: url(#svgPath);
-webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
<defs>
<clipPath id="svgPath">
<path fill="#FFFFFF" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
</clipPath>
</defs>
</svg>
<img src="https://dummyimage.com/500" />
It seems to work perfectly within FireFox but shows the corners aren't cut correctly in Chrome apart from the bottom right corner.
The default units for the clip-path is userSpaceOnUse and this seems to calculate the coordinates of the path with reference to the root element. This is the reason why the clip-path seems like it is producing an incorrect output. Nullifying the margin and padding on the root element or absolutely positioning the element (like in the below snippet) should solve the issue.
body {
background: #555;
}
img {
position: absolute;
top: 0px;
left: 0px;
clip-path: url(#svgPath);
-webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
<defs>
<clipPath id="svgPath">
<path fill="#FFFFFF" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
</clipPath>
</defs>
</svg>
<img src="http://lorempixel.com/500/500/" />
However, in a real life scenario the actual element that has to be clipped could be present anywhere within the body and hence I think it is a much better approach to use the objectBoundingBox as the units like in the below snippet:
body {
background: #555;
}
img {
clip-path: url(#svgPath);
-webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
<defs>
<clipPath id="svgPath" clipPathUnits="objectBoundingBox">
<path fill="#FFFFFF" d="M0.1,0 L0.9,0 Q1,0 1,0.1 L1,0.8 Q1,0.9 0.9,0.9 L0.4,0.9 L0.35,1 L0.3,0.9 L0.1,0.9 Q0,0.9 0,0.8 L0,0.1 Q0,0 0.1,0z" />
</clipPath>
</defs>
</svg>
<img src="https://dummyimage.com/500" />
As mentioned in the question itself, this behavior is visible only in Chrome and not Firefox for reasons unknown to me. Firefox produces an output similar to the expected one even when (a) extra padding + margin is added to the body and (b) when the image itself is wrapped inside another container which also has padding + margin.
The only case where Firefox's output matches with Chrome is when a padding is added directly to the img tag itself. I believe this happens because padding is part of the element and thus affects the coordinates.

How can I affect a non-child element on hover?

So I'm trying to make it so that when you hover a list item, it changes the color of the corresponding svg shape. Since these are elements in separate divs is it possible to do this with just css?
Here's a Codepen of what I have so far:
http://codepen.io/rewerbj/pen/LVLRaK
Would I then have to give each svg section a different class name?
I've tried:
.region-list li:hover + .map-shape {
fill: #213A46;
}
That didn't work so I'm not sure if I'm going to have to use jQuery and if so what the most dynamic way to do this would be.
Any suggestions are welcome. Thank you!
You can not do this since the (+) sibling operator only works in adjacent div.
so to achieve this effect either you have to change your HTML in such a way so that shape comes just after the menu or you have to use Jquery
If you want to do this with CSS only you would have to restructure your titles to be adjacent to your SVG map pieces using the + operator (you can read more about that here). Here is an example of your code if you decide to go this route.
HTML
<div class="region-map-wrap">
<div class="region-map">
<div class="title1"><span class="num">1</span><span class="city">one</span></div>
<svg class="item1" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="97.907px" height="102.533px" viewBox="0 0 97.907 102.533" enable-background="new 0 0 97.907 102.533"
xml:space="preserve">
<g>
<polygon class="map-shape" fill="#009A8B" stroke="#000000" stroke-miterlimit="10" points="4.559,101.959 0.513,25.768 33.772,0.623 97.33,47.07
84.834,90.274 "/>
<circle fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" cx="43.626" cy="55.002" r="24.27"/>
<text transform="matrix(1 0 0 1 35.839 65.252)" fill="#FFFFFF" font-family="'OpenSans'" font-size="28.0337">1</text>
</g>
</svg>
</div>
</div>
CSS
.title1 {
font-size: 18px;
font-family: verdana;
}
.title1:hover + .item1 .map-shape {
fill: #213A46;
}
Also added a JS.Fiddle if you want to play with it. Notice that the title is now just above your SVG item.
EDIT:
Messed around with JQuery using this Fiddle and you can hover SVG elements by setting the Attribute Fill element to a hexadecimal value.
$('.region-list .item').hover(function(){
$(this).addClass('active');
$('.region-map .map-shape').attr("fill", "#ff0000");
}, function(){
$(this).removeClass('active');
$('.region-map .map-shape').attr("fill", "#009A8B");
});

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

Resources