create multicolor icons. Icomoon

后端 未结 4 550
感情败类
感情败类 2020-12-17 03:43

It\'s been so hard to find any clear information about how to create icons with two colors (facebook -white and blue-, google- white and red.....). The customer wants to be

相关标签:
4条回答
  • 2020-12-17 04:13

    IcoMoon itself generates the CSS for stacking font glyphs. It doesn't use :before and :after (which is a good solution for 2 colors). Instead, it uses a more general approach with multiple spans. It works well for cases where you want to have more than one color. All you need to do is import a multicolor SVG to IcoMoon. It'll take care of the rest. Here's a demo of its output: https://codepen.io/Keyamoon/pen/vXxJgq

    0 讨论(0)
  • 2020-12-17 04:14

    Solution 1: Not using a font

    You haven't said much about what you're actually doing. Building a website? A web-interface for a customer to edit an icon in the content management system of a website? I'm guessing.

    It sounds like you're over-complicating things by thinking about fonts at all. They are usually monochromatic animals. Usually.

    Why not just use an SVG? You can easily build or load one in Javascript, and edit it from Javascript; there are many online demos and I've provided another one here. Changing two colours would be pretty trivial, then.

    Here is a quick way to build an SVG in a page, and even offer it for download as a standalone file:

    <!DOCTYPE html>
    <html><head>
    		<title>Chess SVG Builder</title>
    		<script type="text/javascript">
    window.addEventListener("load", function() {
    	// Draw board
    		var	svg = document.getElementsByTagName("svg")[0],
    			sz = Math.min(svg.clientWidth, svg.clientHeight),
    			sqr = sz / 11, smSqr = sqr / 2,
    			xSmO = (svg.clientWidth - sz) / 2, ySmO = (svg.clientHeight - sz) / 2,
    			xO = (svg.clientWidth - 8 * sqr) / 2, yO = (svg.clientHeight - 8 * sqr) / 2;
    		svg.innerHTML = "";
    		for (var x = 0; x < 22; x++) for (var y = x % 2; y < 3; y += 2)
    				svg.innerHTML += '<rect x="' + (xSmO + smSqr * x) + '" y="' + (ySmO + smSqr * y) + '" width="' + smSqr + '" height="' + smSqr + '" style="fill:#eee;" />';
    		for (var x = 0; x < 3; x++) for (var y = x % 2; y < 19; y += 2)
    				svg.innerHTML += '<rect x="' + (xSmO + smSqr * x) + '" y="' + (ySmO + smSqr * y) + '" width="' + smSqr + '" height="' + smSqr + '" style="fill:#eee;" />';
    		for (var x = 19; x < 22; x++) for (var y = x % 2; y < 19; y += 2)
    				svg.innerHTML += '<rect x="' + (xSmO + smSqr * x) + '" y="' + (ySmO + smSqr * y) + '" width="' + smSqr + '" height="' + smSqr + '" style="fill:#eee;" />';
    		for (var x = 0; x < 22; x++) for (var y = 20 - x % 2; y < 22; y += 2)
    				svg.innerHTML += '<rect x="' + (xSmO + smSqr * x) + '" y="' + (ySmO + smSqr * y) + '" width="' + smSqr + '" height="' + smSqr + '" style="fill:#eee;" />';
    		for (var x = 0; x < 8; x++) for (var y = 1 - x % 2; y < 8; y += 2)
    				svg.innerHTML += '<rect x="' + (xO + sqr * x) + '" y="' + (yO + sqr * y) + '" width="' + sqr + '" height="' + sqr + '" style="fill:#700;" />';
    		svg.innerHTML += '<rect x="' + xO + '" y="' + yO + '" width="' + 8 * sqr + '" height="' + 8 * sqr + '" style="fill:none; stroke-width:1; stroke:#000;" />';
    	// Print pieces
    		svg.style.fontSize = sqr + "px";
    		var	numInstances = [1, 1, 2, 2, 2, 8],
    	       		horz = [4, 3, 0, 7, 2, 5, 6, 1],
    	       		pieceNum = 0;
    		for (var code = 12; code < 24; code++)
    			for (var lp = 0; lp < numInstances[code % 6]; lp++) {
    				var pN = pieceNum % 16;
    				var	x = xO + sqr * (0.5 + (Math.floor(pieceNum / 8) % 2 == 0 ? horz[pieceNum % 8] : pieceNum % 8)),
    					y = yO + sqr * (0.9 + 7 * (1 - Math.floor(pieceNum / 16)) - Math.floor((pieceNum % 16) / 8) * (1 - 2 * Math.floor(pieceNum / 16)));
    				svg.innerHTML += '<text x="' + x + '" y="' + y + '" text-anchor="middle">&#98' + code + '</text>';
    				pieceNum++;
    			}
    	// Make downloadable
    		var	serializer = new XMLSerializer(),
    			source = serializer.serializeToString(svg);
    		if (!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/))
    			source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
    		if (!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/))
    			source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
    		source = '<?xml version="1.0" standalone="no"?>' + source;
    		document.getElementsByTagName("a")[0].href = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source);
    });
    		</script>
    	</head><body>
    		<svg width="550" height="550">
    		</svg><br />
    		<a>Download as a file</a>
    </body></html>

    As you can see, I actually do have an interest in building multi-coloured fonts. I want my chess pieces to retain their semantic meaning to the computer, and so I 'write' them with the Unicode characters from 9812 onwards. And if your display's font is like mine, you'll see monochromatic pieces with gaps in them; it's a crude attempt to simulate a second colour; red squares interfere with the look of the pieces, and a chess position would be unreadable.

    On own my display, 'white' pieces on red squares actually don't have a speck of white anywhere inside them; therefore I do not think I am nitpicking, here... I think it's fair to ask that the white king should be white.

    Solution 2: Using a font

    Still use an SVG to define the font, but there will be a lot more manual reading involved.

    Don't SVG fonts allow multiple colours in a single glyph? I'm not sure of the exact inheritance rules, and that seems relevant for you. Read and experiment?

    w3c glyph spec

    If I've understood what I'm reading, changing length-typed values from css can be confusing, because on a glyph defined the way you need, it would actually use the glyph's local coordinate system(?) But colours should be safe.

    I may have some code samples later, whenever I get onto this myself. I think it may involve altering the SVG from Javascript; I can't imagine CSS being able to control all the colours of such a customised font. It seems likely to me that 'inherit' is the property to use for a default colour, while other colours used in the glyph would need JS? More here later perhaps, when I know.

    0 讨论(0)
  • 2020-12-17 04:29

    Creating multicolored icon fonts with icomoon is fairly easy but it combines them from multiple glyphs off course and seems to have no knowledge of a "default" color (the color which can be changed from the parent class) - so we need do define it as inherit in the CSS :

    1) Create your SVGs with your favorite vector app like Inkscape or Adobe Illustrator.

    Important : Icomoon (and anything else) will use one glyph for each colored path in the SVG, so make sure to join the pathes with the same color and don't use too many colors …

    Illustrator makes it easy to join compound pathes : https://www.youtube.com/watch?v=jbc3q9bfOH8 and to join objects: https://graphicdesign.stackexchange.com/questions/999/how-do-i-combine-two-objects-into-one-in-illustrator …

    2) Make your icomoon font.

    3) Determine your "default" color in the CSS - lets say it is rgb(62, 55, 60);:

    In [class^="icon-"], [class*=" icon-"] { add

    /* default color */
    color: rgb(62, 55, 60);
    

    and remove every other line reading

    color: rgb(62, 55, 60);
    

    or to be explicit change it to

    color: inherit;
    

    That's it.

    When I only use two colors (e.g. the darkgrey and orange) properly joined I would never get more than two children in the icon and I could change the darkgrey from the root node <span class="icon-myIconName"> ...

    Here is a working codepen with a 2-color font used with only one element where you can change the color …

    0 讨论(0)
  • 2020-12-17 04:36

    The example in the link you provided is quite clear. You create 2 SVGs. One for each of the 2 colors in your icon, and add them as two different characters to the font. (\e006 and \e0007 in the example)

    Then you use both the :before selector and the :after selector to add the characters using different colors. Each selector is using a different character and a different color.

    The letter-spacing: -1 causes the characters to overlap.

    I took their jsfiddle example and fixed it to work with font awesome: http://jsfiddle.net/p44zf3se/

    Update

    I am not sure why my previous answer was not enough, but here is another example. I can't upload it to jsfiddle because the font cannot be served from another site. So just take the html below + download the free IcoMoon font from: http://github.com/Keyamoon/IcoMoon-Free/raw/master/Font/IcoMoon-Free.ttf

    <html>
    <head>
    <style>
    @font-face  {
        font-family: 'IcoMoon-Free';
        src: url('IcoMoon-Free.ttf') format('truetype');
        font-style: normal;
        font-weight: normal;
        font-variant: normal;
        text-transform: none;
        line-height: 1;
        -webkit-font-smoothing: antialiased;
    }
    
    .facebook-icon {
        font-family: 'IcoMoon-Free';
    }
    .facebook-icon:after {
        content:"\ea8e";
        color:#F33;
        font-size:6em;
    }
    .facebook-icon:before {
        content:"\ea8c";
        color:#0C0;
        font-size:6em;
        letter-spacing:-0.5em;
    } 
    </style>
    </head>
    <body>
    <div class="facebook-icon"></div>
    </body>
    </html>
    
    0 讨论(0)
提交回复
热议问题