Using SVG Icons - css

I'm using use my own SVG icons and I'm trying to find the best way of using them.
I would like to keep the color but also adjust it if needed to match a theme or on when using hover.
I have tried using the following script which changes the following into an embedded SVG but as I load my scripts at the bottom of my HTML doc, I get a horrible jumping effect.
$(function(){
jQuery('img.svg').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if(typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Check if the viewport is set, else we gonna set it if we can.
if(!$svg.attr('viewBox') && $svg.attr('height') && $svg.attr('width')) {
$svg.attr('viewBox', '0 0 ' + $svg.attr('height') + ' ' + $svg.attr('width'))
}
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
});
svg {width: 350px; height: 350px;}
svg path {fill: #000 !important;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img src="https://upload.wikimedia.org/wikipedia/commons/f/f8/Windows_logo_-_2012_%28red%29.svg" alt="Microsoft" width="350" />
I've then tried to embed the the SVG by copying the code from Illustrator but the only way I can edit the colours is if I delete them in the html doc as my css won't override them.
What is the best way while keeping them from jumping?

Inline SVGs would be best IMO.
Export your SVGs using Illustrator (if you have troubles, follow this excellent guide by Colin Lord).
Then remove the colors from your SVG code and set them only using CSS.
If you have trouble overriding your colors you can give your SVGs IDs for more specifity.

If you go down the embedded route (which is my preferred option) - you don't actually need the majority of the HTML that Illustrator usually throws out.
Here is an example of your SVG with the most minimal code, then you can just use CSS to change the colours how you wish :-)
svg {
width: 350px;
height: 350px;
}
svg path {
fill: #000;
transform-origin: 0 0;
transform: scale(3)
}
#svg3 path {
fill: turquoise;
}
#svg3:hover path {
fill: green;
}
<svg id="svg2">
<path d="m0,12.402,35.687-4.8602,0.0156,34.423-35.67,0.20313zm35.67,33.529,0.0277,34.453-35.67-4.9041-0.002-29.78zm4.3261-39.025,47.318-6.906,0,41.527-47.318,0.37565zm47.329,39.349-0.0111,41.34-47.318-6.6784-0.0663-34.739z" id="path4"/>
</svg>
<!-- Another exmaple below using CSS to change the colours -->
<svg id="svg3">
<path d="m0,12.402,35.687-4.8602,0.0156,34.423-35.67,0.20313zm35.67,33.529,0.0277,34.453-35.67-4.9041-0.002-29.78zm4.3261-39.025,47.318-6.906,0,41.527-47.318,0.37565zm47.329,39.349-0.0111,41.34-47.318-6.6784-0.0663-34.739z" id="path4"/>
</svg>

Related

How to create a Radial Dial menu in a Website?

I am trying to create a Radial Dial type menu, similar to the picture here (the highlighted top section should be on hover):
Googling about radial menu or radial dial menu doesn't result to anything similar to this.
I am currently using Elementor pro with WordPress. So I can add custom HTML/CSS/JavaScript as well if required.
I was thinking of creating 3-4 buttons and then somehow try to transform them into a semi circle and then position them together. However that creates a lot of manual effort of resizing everything if a menu items is added/removed. Also, it will be a nightmare to make the website responsive.
You could use SVG for your radial buttons, with a little js to handle the onclicks.
I created this svg code from adobe illustrator, but you may be able to find online svg code generators if you don't have adobe illustrator.
See example below with css hovers using ids on PATHs... you can use classes and other html attributes to get your desired result...
PATH {
fill: gray;
stroke: #000;
stroke-miterlimit: 10;
}
PATH:hover {
cursor: pointer;
}
PATH#option_a:hover {
fill: red;
}
PATH#option_b:hover {
fill: green;
}
PATH#option_c:hover {
fill: blue;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200">
<path id="option_a" d="M600.5,104.1c-276.1,0-500,223.9-500,500h100c0-220.9,179.1-400,400-400s400,179.1,400,400h100c0-276.1-223.9-500-500-500Z"/>
<path id="option_b" d="M600.5,1004.1v100c276.1,0,500-223.9,500-500h-100c0,220.9-179.1,400-400,400Z"/>
<path id="option_c" d="M200.5,604.1H100.5c0,276.1,223.9,500,500,500v-100c-220.9,0-400-179.1-400-400Z"/>
</svg>
Answer to your comment, yeah sure so many things are possible with SVG. Though I am not guna lie, having Adobe Illustrator as tool makes SVG design a lot easier!
So I added arrows to my original SVG code (using Adobe Illustrator), and then created new SVG file code including arrows. From this new SVG code I took the d attribute from my paths and added them to my original SVG paths as a data-d attribute...
Then using a little jQuery, on path hover, I switch the current d attribute with my data-d attribute...
// on ready
$(function() {
// on any segment mouse enter path
$('.segment').on('mouseenter', function(e) {
// temporally store hover-state data-d attribute coordinates
let d = $(this).attr('data-d');
// override data-d attribute value with original d attribute coordinates
$(this).attr('data-d', $(this).attr('d'));
// set d attribute with temporally stored hover-state coordinates
$(this).attr('d', d);
// on any segment mouse leave path
}).on('mouseleave', function(e) {
// temporally store original-state data-d attribute coordinates
let d = $(this).attr('data-d');
// override data-d attribute value with hover-state d attribute coordinates
$(this).attr('data-d', $(this).attr('d'));
// set d attribute with temporally stored original-state coordinates
$(this).attr('d', d);
});
});
SVG {
display: block;
width: 300px;
margin: 0 auto;
}
PATH {
fill: gray;
stroke: #000;
stroke-miterlimit: 10;
}
PATH:hover {
cursor: crosshair;
}
PATH#segment_r:hover {
fill: red;
}
PATH#segment_g:hover {
fill: green;
}
PATH#segment_b:hover {
fill: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200">
<path
class="segment"
id="segment_r"
d="M600.5,104.1c-276.1,0-500,223.9-500,500h100c0-220.9,179.1-400,400-400s400,179.1,400,400h100c0-276.1-223.9-500-500-500Z"
data-d="M630.4,105l-29.9-29.9L570.6,105c-262.2,15.5-470.1,233-470.1,499.1h100c0-220.9,179.1-400,400-400
s400,179.1,400,400h100C1100.5,338,892.6,120.4,630.4,105z"
/>
<path
class="segment"
id="segment_g"
d="M600.5,1004.1v100c276.1,0,500-223.9,500-500h-100c0,220.9-179.1,400-400,400Z"
data-d="M974.6,935.9c78.4-88.3,125.9-204.5,125.9-331.8h-100c0,220.9-179.1,400-400,400v100
c127.3,0,243.5-47.6,331.8-125.9h42.3V935.9z"
/>
<path
class="segment"
id="segment_b"
d="M200.5,604.1H100.5c0,276.1,223.9,500,500,500v-100c-220.9,0-400-179.1-400-400Z"
data-d="M600.5,1004.1c-220.9,0-400-179.1-400-400h-100c0,127.3,47.6,243.5,125.9,331.8v42.3h42.3
c88.3,78.4,204.5,125.9,331.8,125.9V1004.1z"
/>
</svg>
Here is fiddle version... https://jsfiddle.net/joshmoto/f9wg57u1/
I love SVG code. So much is possible.
My example is probably a little heavy (hence using JS), I'm sure someone could recreate this with pure SVG and CSS.
But Adobe Illustrator makes things so much easier from a visual design point of view when creating SVG's.
Update: I've changed the path hover state cursor to crosshair so
you can see how the segment arrow is also included in the hover area
before mouseleave event.

SVG shadow-root is closed

I have tried to animate an svg-sprite with CSS.
I’ve created a sprite and injected it from gulp:
gulp.task('svgstore', function () {
var svgs = gulp
.src('app/svg/*.svg')
.pipe(svgmin(function (file) {
return {
plugins: [{
cleanupIDs: {
minify: true
}
}]
}
}))
.pipe(svgstore({ inlineSvg: true }));
function fileContents (filePath, file) {
return file.contents.toString();
}
return gulp
.src('app/*.html')
.pipe(inject(svgs, { transform: fileContents }))
.pipe(gulp.dest('app/'))
});
…and inserted images from the sprite to HTML:
<svg class="icon-ufo" >
<use xlink:href="img/sprite.svg#ufo" aria-hidden="true"></use>
</svg>
And it works well, but the following image shows the shadow DOM is closed.
How I can to animate some styles of this SVG without JavaScript? But if JavaScript is the only way, how to do it better?
The DOM of the referenced element is not part of the DOM of the referencing HTML page. It has isolated style sheets.
But the shadow element inherits styles from the referencing <use> element. This means that as long as the referenced element does not set the styles itself in the sprite or in a style sheet associated with the sprite, you can change (and animate) every inheritable style property on the icon by styling the <use> element.
You could use "currentColor" property in your fill attribute to styling:
and styles for "icon-ufo" class will be like
.icon-ufo {
color: green;
}
.icon-ufo:hover {
color: red;
}

styling svgs that are inline of css

.player
{
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'><line x1='1' y1='1' x2='9' y2='9' stroke='red'/><line x1='1' y1='9' x2='9' y2='1' stroke='red'/></svg>");
width: 100%;
height: 100%;
display: inline-block;
}
.one
{
fill: black;
}
.two
{
stroke: white;
}
Elements with the player class will have a background image that is an svg. If there are elements with both the player and the one or two class, is it possible to change the style of the svg if it's inlined like so? If not, how would I do a simple color change by having classes? Ideally, I wouldn't want to introduce any more markup in the html and prevent http accesses for such a small svg file.
As Douglas wrote, you can style only IMG elements with inline "src".
I use this technique:
Use common image with the path to your SVG:
<img src="my.svg" alt="">
Transform the "src" to inline style using JavaScript (jQuery):
$('img').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if(typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
Style your SVG using CSS:
path {
fill: #f00;
}
Done.
In order to modify your SVG with CSS, you have to use inline SVG, you can't modify it with a class if you use it as a background-image to an element.
If you want to make your authoring look cleaned up you can use a server side script to push the SVG's markup to your page (such as PHP's file_get_contents()).
Since there's no way around this, just compress your SVG as much as possible (I like this tool, there's some other good ones on the source I attached) and then write your svg as cleanly as possible, it shouldn't be that bloated looking if it's a small file.
Source: https://css-tricks.com/using-svg/
Sorry I couldn't be the bearer of better news.

Change foundation svg color on hover

Hello so I've seen a lot of codes regarding the hover color change on svg's but I can't get it to work. The thing is I am using foundation icons, and here is a sample code:
<img src="svgs/fi-mail.svg">
Any idea on changing the color on hover?
You have to convert the SVG into a native <svg> tag and then you need to apply DOM traversal and CSS to change it. I have a quick snippet, that I modified from elsewhere, and you can use it to change the properties.
You need to make the SVG to be an inline SVG. You can make use of
this script, by adding a class svg to the image:
/*
* Replace all SVG images with inline SVG
*/
jQuery('img.svg').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if(typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
And then, now if you do:
.logo-img path {
fill: #000;
}
Or may be:
.logo-img path {
background-color: #000;
}
This works!
Reference: img src SVG changing the fill color
You cannot change the color of an SVG that is included via an IMG tag. You can only modify inline SVG through CSS.
But the Zurb Foundation Icons are normally included as web-font, where each icon is just a simple text character, which can be styled as any other text. The idea to include a single SVG icon via an IMG tag deviates from the Foundation documentation. Please refer to the „How to use“ section in the docs-article you linked above…

Auto-resize an image in CSS without replacing HTML width / height attributes?

I'm trying to make an image fit nicely on different screen sizes without breaking the layout. The following bit of CSS helps:
.viewer .main img {
max-width: 100%;
height: auto;
}
But the trouble is this image changes. I use a bit of Javascript to create a new img element each time the image changes, instead of reusing the existing one. (This seems a little more reliable for what I'm doing). The browser doesn't know the image's size until it is loaded, creating an obvious flicker in the interim. I deal with that by setting the image's width and height attributes in HTML. Without the above CSS rule, that works fine.
With that CSS, the flickering is still there. For some reason, when I create a new img element, the CSS seems to be causing the browser to ignore its width and height attributes, so. It ends up as ignorant of the aspect ratio as it was before.
Here's a jsfiddle to illustrate the situation:
http://jsfiddle.net/7sDtN/
One of the images in there is very very big (138 MB), so be careful if you're on a metered connection :)
What I would love is to get the image to scale according to those dimensions I set in HTML. Preferably in a nice way. A Javascript solution isn't the end of the world (I'm already using it, for course), but if there's an elegant CSS solution that would be very nice.
I ended up solving this in a roundabout way by wrapping the image in a dedicated container, along with some strange looking javascript to keep it in place as the image loads. The dimensions for that container are calculated as in Sven's answer, but ultimately it lets the browser take over. This way layout changes are kept fairly minimal and we end up only doing this crazy stuff for the bit of time between images.
Here's a big wad of code, for completedness:
function Viewer(container) {
var viewer = this;
container = $(container);
var pictureBox = $('.picture', container);
var img = $('<img>').appendTo(pictureBox);
var hide = function() {
/* [snip] */
}
var getPictureDisplayHeight = function(picture) {
var ratio = picture.data.h / picture.data.w;
var displayWidth = Math.min(pictureBox.width(), picture.data.w);
var displayHeight = Math.min(displayWidth * ratio, picture.data.h);
return displayHeight;
}
var stopLoadingTimeoutId = undefined;
var stopLoadingTimeout = function() {
container.removeClass('loading');
}
var showPicture = function(picture) {
var imgIsChanging = img.data('picture') != picture;
container.show();
/* This code expects to be cleaned up by stopLoadingTimeout or onImgLoaded, which will not fire if img src doesn't change */
if (imgIsChanging) {
container.addClass('loading');
window.clearTimeout(stopLoadingTimeoutId);
stopLoadingTimeoutId = window.setTimeout(stopLoadingTimeout, 3000);
}
pictureBox.css({
'min-height' : pictureBox.height()
});
var displayHeight = getPictureDisplayHeight(picture);
if (displayHeight > pictureBox.height()) {
/* Grow pictureBox if necessary */
pictureBox.stop(true, false);
pictureBox.animate({
'height' : displayHeight
}, 150);
}
/* I wish I could set width and height here, but it causes the current image to stretch */
img.attr({
'src' : picture.fullPath
}).data('picture', picture);
}
var onImgLoaded = function(event) {
/* The load event might not be fired, so nothing here should be essential */
var picture = img.data('picture');
container.removeClass('loading');
var displayHeight = getPictureDisplayHeight(picture);
pictureBox.stop(true, false);
pictureBox.animate({
'min-height' : 0,
'height' : displayHeight
}, 150, function() {
pictureBox.css('height', 'auto');
});
window.clearTimeout(stopLoadingTimeoutId);
}
var onImgClicked = function(event) {
selectNextPicture();
}
var onPictureSelectedCb = function(picture) {
if (picture) {
showPicture(picture);
} else {
hide();
}
}
var init = function() {
img.on('click', onImgClicked);
img.on('load', onImgLoaded);
}
init();
}
Relevant HTML:
<div class="viewer" style="display: none;">
<div class="picture"></div>
<div class="caption"><div class="caption-text"></div></div>
</div>
And CSS:
.viewer .picture img {
display: block;
margin: 0 auto;
max-width: 100%;
height: auto;
}
This way we leave space around the image that is either the size of the next image or the size of the current image, and never the smaller size that seems to happen before a new image is loaded (which kept happening for some reason). There are probably a million solutions to this, and mine doesn't feel especially straight-forward, so I'm certainly curious to see others :)
If I understand you right, you can achieve your goal by using the following code
HTML
<div id="Wrapper">
<img id="MyPic" src="http://www.davidstorey.tv/wp-content/uploads/2012/05/image.php_.jpeg" alt="" width="300" height="200" />
</div>
CSS
body{
width:100%;
}
#Wrapper{
width:98%;
border:1px solid red;
}
jQuery
$("document").ready(function(){
var ratio=$("#MyPic").width() / $("#MyPic").height();
$("#MyPic").css("width","100%");
$("#MyPic").css("height", $("#MyPic").width()/ratio+"px");
});
Here is the link to jsfiddle

Resources