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

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");
});

Related

How to define CSS style for ALL types of SVG'S structure?

I have many SVG's on my page, that I imported as (in React):
import { ReactComponent as Logo } from "./../../../images/example.svg";
And them I use them this way:
<div className='someClassName activeClassName?'>
<Logo />
</div>
But all of them are different in their structure.
What do I mean? Some of SVG's are looks like:
<svg>
<path/>
</svg>
some like:
<svg>
<g>
<g>
<path/>
</g>
</g>
</svg>
some looks like:
<svg>
<g>
<circle/>
<triangle/>
</g>
</svg>
And there are millions of types like this.
I have a 'activeClassName' which fill SVG in different color, when it's active, but to make it work with all my SVG's, I have to describe my classname styles kinda like this:
&--active {
svg {
fill: $primaryBlue !important;
path {
fill: $primaryBlue !important;
}
g {
fill: $primaryBlue !important;
g path {
fill: $primaryBlue !important;
}
}
}
}
This looks awful. How can I change, for example, the fill option for all of those SVG's? Please, help me... thanks
As #Robert Longson and #chrwahl pointed out:
removing fill attributes from your svg child elements is recommended.
Not sure, how you could "pre/postprocess" your imported svg component.
In plain js you could easily query your child elements and remove attributes like so:
let svgAsset = document.querySelector(".svgAsset");
// query child elements – maybe includeother svg primitives like circles/rects
let svgChildEls = svgAsset.querySelectorAll("g, path, circle, rect, polygon");
function removeFills(els = svgChildEls) {
els.forEach(function (el, i) {
el.removeAttribute("fill");
});
}
function addElClass(els = svgChildEls) {
els.forEach(function (el, i) {
let nodeName = el.nodeName.toLowerCase();
if(nodeName!='g'){
el.classList.add("svgChild");
}
});
}
function toggleActive(){
svgAsset.classList.toggle('svgActive');
svgAsset.classList.toggle('svgInactive');
}
svg{
display:inline-block;
width:200px;
}
/* inactive */
.svgInactive{
fill: #ccc;
}
.svgActive{
fill: orange;
}
.svgActive
.svgChild{
fill: blue;
}
<p>
<button onclick="toggleActive()">toggle active</button>
<button onclick="removeFills()">Remove fill attributes</button>
<button onclick="addElClass()">Add element Class</button>
</p>
<div class="svgWrp">
<svg class="svgAsset svgInactive" viewBox="0 0 100 100">
<path id="path0" fill="red" d="M0 0 l50 0 l0 50 l-50 0 z" />
<path id="path1" class="hasClass" fill="green" d="M33 33 l50 0 l0 50 l-50 0 z" />
<g fill="purple">
<circle id="" cx="66.666%" cy="33.333%" r="25%" fill="none" stroke="#000" stroke-width="2" />
</g>
</svg>
</div>
In the above example I've also included <g> elements and other shape primitives like polygons:
let svgChildEls = svgAsset.querySelectorAll("g, path, circle, rect, polygon");
You benefit from a lower css specificity – so you don't need nested selectors like
svg g path{ ... }
Manually checking and optimizing your svg source material is always the best approach, since you can't expect graphics from different sources to have a coherent structure.
E.g svgs generated by GUI applications tend to have slightly quirky markup including way to many <g> nesting, unsused or too many transforms (making it hard to get or manipulate x/y offsets) etc.

Making a smooth Sinusoidal wave with CSS animation and SVG worknig for someone elses SVG but not mine?

Animation of the problem (theirs vs mine). More context below:
I have gotten some code off of JSFiddle and it is as follows:
HTML:
<article id="main">
<div class="ocean">
<div class="wave"></div>
</div>
</article>
CSS:
.ocean {
height: 5%;
width:100%;
position:absolute;
bottom:0;
left:0;
background: #015871;
}
.wave {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/85486/wave.svg) repeat-x;
position: absolute;
width: 6400px;
top:-198px;
height:198px;
animation: wave 2s linear infinite;
}
#keyframes wave {
100% {
margin-left: -1600px;
}
}
article{
width:100%;
height:100vh;
}
Now with me, I have the exact same code, but I changed out the source to an svg that I made by changing the 'background' attribute in the '.wave' class as follows:
background: url("...\my_svg.svg");
Then this is the code for that SVG:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 65">
<defs>
<style>.cls-1{stroke:#000;stroke-miterlimit:10;}</style>
</defs>
<title>bkg-side</title>
<g id="Layer_1" data-name="Layer 1">
<path class="cls-1" d="M1600.3,58.38c-64.8,0-177.4-9.65-400-28.94S866.52.5,800.4.5C735.6.5,623,10.15,400.45,29.44S66.62,58.38.5,58.38v6.89l1600,.23"/>
</g>
</svg>
Now as you'll see, there is a smooth transition for the svg that I am using and a not-so-smooth transition with the SVG that I made. Theirs will scroll infinitely to the side or at least look like it is while mine will 'reset' after the set amount of time for the animation (in this case, 5 seconds). The only difference in code is which SVG is being used and I have no idea why their SVG will scroll to the side infinitely and look like a smooth curve, while with mine, it resets and gets choppy every 5 seconds. Does it have something to do with the SVG code in of itself?
EDIT: the ends DO touch each other forming a consistent curve with both images, and I have put my image in the top left corner of Illustrator and hit 'Export Selection...'. The consistancy is there, but with this one, the wave goes on without resetting while mine DOES reset from the beginning.
It's because your wave is in the middle of a large SVG, with space all around it. Whereas theirs occupies the full width of the SVG.
When you repeat-x theirs, the left and right edges of each repeat meet up. Yours have large gaps on the left and right.
You need to move your wave shape to the left edge of the SVG and trim the page size to match the width.
Based on Paul's comment, and by comparing the svg files, I found that THEIR svg didn't have a viewbox attribute and had a width attribute, while mine DID have a viewbox attribute and didn't have a width attribute. I set the with to be the value of the margin-left value in the #key-frames animation and presto!
My old svg:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 65">
<defs>
<style>.cls-1{stroke:#000;stroke-miterlimit:10;}</style>
</defs>
<title>bkg-side</title>
<g id="Layer_1" data-name="Layer 1">
<path class="cls-1" d="M1600.3,58.38c-64.8,0-177.4-9.65-400-28.94S866.52.5,800.4.5C735.6.5,623,10.15,400.45,29.44S66.62,58.38.5,58.38v6.89l1600,.23"/>
</g>
</svg>
My new svg:
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="66">
<defs>
<style>.cls-1{stroke:#000;stroke-miterlimit:10;}</style>
</defs>
<title>bkg-side</title>
<g id="Layer_1" data-name="Layer 1">
<path class="cls-1" d="M1600.3,58.38c-64.8,0-177.4-9.65-400-28.94S866.52.5,800.4.5C735.6.5,623,10.15,400.45,29.44S66.62,58.38.5,58.38v6.89l1600,.23"/>
</g>
</svg>

Cannot Change SVG <use> icon size when linked to <symbol>

I'm trying to use an SVG symbol in my mark-up, but I can't get the CSS to increase the size of the symbol being rendered inside a element?
I have a twitter logo defined in a set of tags, and then I'm referencing this with an xlink:href inside use tags. The icon is showing, but when I add CSS to the #box1 div holding the element the symbol isn't increasing or decreasing in size and seems to only rendering at the viewBox size.
Also, the SVG element itself when I hover it with the dev tools is rendering at 300 x 150px - but there is nothing on in the code with these measurements.
I'm really confused — any help would be awesome.
#box1 {
height: 10rem;
width: 10rem;
}
<defs style="display: none;">
<svg id="twitter" viewBox="0 0 19.19 15.95">
<symbol id="twitter-symbol"><title>twitter</title>
<path id="twitter-path" d="M19.19,1.92a8.76,8.76,0,0,1-2.28.64A3.9,3.9,0,0,0,18.63.32a6.87,6.87,0,0,1-2.52,1A3.87,3.87,0,0,0,13.23,0,4,4,0,0,0,9.32,4,3.41,3.41,0,0,0,9.44,5,11,11,0,0,1,1.32.72a4.29,4.29,0,0,0-.52,2A4,4,0,0,0,2.56,6.12,3.61,3.61,0,0,1,.76,5.6v0a4,4,0,0,0,3.16,4,4.35,4.35,0,0,1-1,.16,4.9,4.9,0,0,1-.76-.08,4,4,0,0,0,3.68,2.8A7.79,7.79,0,0,1,.92,14.19a6.78,6.78,0,0,1-.92,0A10.83,10.83,0,0,0,6,16c7.24,0,11.19-6.16,11.19-11.47V4a6.83,6.83,0,0,0,2-2" fill="#000">
</path>
</symbol>
</svg>
</defs>
<div id="box1">
<svg>
<use xlink:href="#twitter-symbol"/>
</svg>
</div>
The <defs>is an svg element. It always goes inside the svg. I've made a few changes and now it works. Please run the code and take a look at what I've done.
#box1 {
height: 10rem;
width: 10rem;
}
#twitter{display:none;}
<svg id="twitter">
<defs>
<symbol id="twitter-symbol"><title>twitter</title>
<path id="twitter-path" d="M19.19,1.92a8.76,8.76,0,0,1-2.28.64A3.9,3.9,0,0,0,18.63.32a6.87,6.87,0,0,1-2.52,1A3.87,3.87,0,0,0,13.23,0,4,4,0,0,0,9.32,4,3.41,3.41,0,0,0,9.44,5,11,11,0,0,1,1.32.72a4.29,4.29,0,0,0-.52,2A4,4,0,0,0,2.56,6.12,3.61,3.61,0,0,1,.76,5.6v0a4,4,0,0,0,3.16,4,4.35,4.35,0,0,1-1,.16,4.9,4.9,0,0,1-.76-.08,4,4,0,0,0,3.68,2.8A7.79,7.79,0,0,1,.92,14.19a6.78,6.78,0,0,1-.92,0A10.83,10.83,0,0,0,6,16c7.24,0,11.19-6.16,11.19-11.47V4a6.83,6.83,0,0,0,2-2" fill="#000">
</path>
</symbol>
</defs>
</svg>
<div id="box1">
<svg viewBox="0 0 19.19 15.95" width="24">
<use xlink:href="#twitter-symbol"/>
</svg>
</div>
I hope it helps.
You're using inline SVG code within your HTML, so I believe that SVG path needs a viewbox defined within it. For example, if you add viewBox="0 0 60 55" within your HTML SVG tag, you'll notice that the size will start to adjust. So edit this part of your HTML
<svg viewBox="0 0 60 55">
<use xlink:href="#twitter-symbol"/>
</svg>
To expand on your note where you found the size listed as 300x150, this is the default standard size that applies to HTML inline SVG code (per HTML5 specs). This differs sometimes depending on the browser.
Keep in mind, there a are a few different methods you can use when handling SVGs. Check out the guide below where they give a nice run down on SVG and how to manipulate it's size. You might find an alternative way that you would prefer to use.
https://css-tricks.com/scale-svg/

Fill external imported svg file

I'm using Angular 5 and i would fill my white svg image.
I have a svg file like this:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>ic_calendar</title><g id="Level_2" data-name="Level 2"><g id="screen"><path d="M18.5,5.11a2.55,2.55,0,0,0-.58-1.68,2.27,2.27,0,0,0-1.7-.71H14.85v-1a.68.68,0,1,0-1.35,0v1H6.39v-1A.67.67,0,0,0,5.72,1,.68.68,0,0,0,5,1.68v1H3.75A2.15,2.15,0,0,0,1.5,5.09V16.4a2.71,2.71,0,0,0,.69,2A2.08,2.08,0,0,0,3.7,19H16.34a2.14,2.14,0,0,0,2.15-2.26C18.51,15.07,18.5,5.57,18.5,5.11Zm-15.65,0h0c0-.71.27-1,.9-1H5v1a.69.69,0,0,0,.68.68.68.68,0,0,0,.67-.68v-1H13.5v1a.68.68,0,1,0,1.35,0v-1H16.2a1,1,0,0,1,.71.26,1.17,1.17,0,0,1,.24.72V6.84H2.85Zm14.3,11.64c0,.78-.52.9-.81.91H3.7a.73.73,0,0,1-.56-.2,1.49,1.49,0,0,1-.29-1V8.2h14.3Z" style="fill:#fff"/><rect width="20" height="20" style="fill:none"/></g></g></svg>
So, i'm importing it through this code:
<svg class="myClass">
<use xlink:href="assetFolder/ic_calendar.svg#Level_2"></use>
</svg>
However, i can't change the svg image style and i can't fill it.
I tried, via sass, to add the following:
svg { fill: blue; }
or
path { fill: blue; }
But nothing...
Can anyone help me?
Thanks
Presentation attributes svg have the highest priority and can not
be changed with thecss. Therefore, they need to be removed if you
want to change the color of the svg objects from the external table
CSS
When using the <use> command, svg objects fall into the shadow DOM
In order to stylize these objects, you must use forced inheritance
path {
fill:inherit;
stroke:inherit;
}
Below is an example where objects are called from the <defs> section with the use command and stylized from the external table css
path {
fill:inherit;
stroke:inherit;
}
#screen {
fill:dodgerblue;
}
rect {fill:#D5D5D5;}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<title>ic_calendar</title>
<defs>
<g id="screen">
<rect id="rect1" width="20" height="20" />
<path d="M18.5,5.11a2.55,2.55,0,0,0-.58-1.68,2.27,2.27,0,0,0-1.7-.71H14.85v-1a.68.68,0,1,0-1.35,0v1H6.39v-1A.67.67,0,0,0,5.72,1,.68.68,0,0,0,5,1.68v1H3.75A2.15,2.15,0,0,0,1.5,5.09V16.4a2.71,2.71,0,0,0,.69,2A2.08,2.08,0,0,0,3.7,19H16.34a2.14,2.14,0,0,0,2.15-2.26C18.51,15.07,18.5,5.57,18.5,5.11Zm-15.65,0h0c0-.71.27-1,.9-1H5v1a.69.69,0,0,0,.68.68.68.68,0,0,0,.67-.68v-1H13.5v1a.68.68,0,1,0,1.35,0v-1H16.2a1,1,0,0,1,.71.26,1.17,1.17,0,0,1,.24.72V6.84H2.85Zm14.3,11.64c0,.78-.52.9-.81.91H3.7a.73.73,0,0,1-.56-.2,1.49,1.49,0,0,1-.29-1V8.2h14.3Z" />
</g>
</defs>
<use xlink:href="#screen" />
</svg>
You have an inline style on your svg path - style="fill:#fff". Inline styles take precedence over styles in a CSS stylesheet. But thats what !important is for!
either update your style to this:
path { fill: blue !important; }
OR simply remove the inline styling.

Raised border in SVG

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>

Resources