Stacking font-awesome icons within SVG - svg

I'm trying to embed some font-awesome icons within a D3 visualization which is using SVG. I've found some solutions that get me part of the way such as:
How do I include a font awesome icon in my svg?
Adding FontAwesome icons to a D3 graph
These are a great starting point but seem to only work with a basic character. What I'd like to do however is use some of the font-awesome stacking features to make composite icons. Has anyone ever tried to do this before in SVG? Or is this simply not going to be possible?
When I've tried to put an example together, I've had to include the characters in 2 different text elements (I really wanted them inside one) and I feel like I'm now in a whole world of pain with regards to manually sizing or positioning myself. Does anyone have a possible resolution on how this might be achievable?
I've included where I've got to so far, red being the desired output, green being the SVG.
span {
border: thin solid red;
}
svg {
border: thin solid green;
}
text {
fill: black;
font-family: 'FontAwesome';
}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<span class="fa-stack fa-lg">
<i class="fa fa-circle-o fa-stack-2x"></i>
<i class="fa fa-info fa-stack-1x"></i>
</span>
<svg width="100" height="100">
<text x="50" y="50">&#xf10c</text>
<text x="50" y="50"">&#xf129</text>
</svg>

If you look at the css of fa-stack-1x and fa-stack-2x, you'll see that there is some "manual" positioning going on. You can translate those into valid SVG. On the "outer" stack:
text-anchor="middle" style="font-size: 2em" alignment-baseline="middle"
And inner stack:
text-anchor="middle" alignment-baseline="middle"
Produces:
span {
border: thin solid red;
}
svg {
border: thin solid green;
}
text {
fill: black;
font-family: 'FontAwesome';
}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<span class="fa-stack fa-lg">
<i class="fa fa-circle-o fa-stack-2x"></i>
<i class="fa fa-info fa-stack-1x"></i>
</span>
<svg width="100" height="100">
<text x="50" y="50" text-anchor="middle" style="font-size: 2em" alignment-baseline="middle">&#xf10c</text>
<text x="50" y="50" text-anchor="middle" alignment-baseline="middle" >&#xf129</text>
</svg>

Related

How to make copied SVGs as clear as they are displayed?

I'm displaying SVGs in <img> tags. With viewBox these images could be scaled without losing clarity. However, when I copy these images (and paste them into PowerPoint, etc.), they won't be as clear as they are displayed.
How could I make copied images clear? And could this be done without using a canvas?
Example SVG markup:
<svg id="mol-638318-0540814976"
xmlns="http://www.w3.org/2000/svg" width="84" height="40" viewBox="0 0 84 40">
<style>
#mol-638318-0540814976 text {
dominant-baseline: central;
text-anchor: middle;
font-size: 16px;
font-family: serif;
fill: black;
}
#mol-638318-0540814976 line {
stroke: black;
}
</style>
<text x="26" y="20">C</text>
<text x="58" y="20">C</text>
<line x1="32" y1="20" x2="52" y2="20"></line>
</svg>
Thanks!

Mask Image with SVG Shape and add a Border

Not sure this is possible, so I have a back-up plan (use a background image and :after to mask one of 3x transarent PNGs with the border in the image and use nth-child to change them).
Here's what I'm trying to accomplish. I know clip-path will give me the image mask, but I need the curved edges and the border color, too. Which I don't think is possible in pure CSS.
<!DOCTYPE html>
<html>
<style>
img {
max-width: 100%;
display: block;
}
.container {
width: 300px;
height: 300px;
margin: 1em auto;
}
.frame-border {
stroke: #10c020;
stroke-width: 4;
}
</style>
<body>
<div class="container">
<svg viewBox="-10 -10 120 120">
<defs>
<mask id="mask">
<rect fill="#000000" x="0" y="0" width="300" height="300"></rect>
<path id="Path_611" data-name="Path 611" d="M1,38a12.225,12.225,0,0,1,2.558-3.025L41.351,13.462A21.12,21.12,0,0,1,46.733,12.4a14.319,14.319,0,0,1,4.81.765L89.2,34.814A7.333,7.333,0,0,1,92,37a7.273,7.273,0,0,1,1,3.4v45.3A6.741,6.741,0,0,1,92,89a12.9,12.9,0,0,1-3.015,2.945L50.42,110.628a8.953,8.953,0,0,1-3.688.786,13.383,13.383,0,0,1-4.153-.992L4.2,92.012A12.105,12.105,0,0,1,1,89a7.112,7.112,0,0,1-1-3.581V41.534A9.569,9.569,0,0,1,1,38Z" transform="translate(1.502 -10.892)" fill="#FFFFFF"/>
</mask>
</defs>
<image mask="url(#mask)"
xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://randomuser.me/api/portraits/women/47.jpg" width="100" height="100">
</image>
<g class="frame-border" fill="none">
<path id="Path_611" data-name="Path 611" d="M1,38a12.225,12.225,0,0,1,2.558-3.025L41.351,13.462A21.12,21.12,0,0,1,46.733,12.4a14.319,14.319,0,0,1,4.81.765L89.2,34.814A7.333,7.333,0,0,1,92,37a7.273,7.273,0,0,1,1,3.4v45.3A6.741,6.741,0,0,1,92,89a12.9,12.9,0,0,1-3.015,2.945L50.42,110.628a8.953,8.953,0,0,1-3.688.786,13.383,13.383,0,0,1-4.153-.992L4.2,92.012A12.105,12.105,0,0,1,1,89a7.112,7.112,0,0,1-1-3.581V41.534A9.569,9.569,0,0,1,1,38Z" transform="translate(1.502 -10.892)" stroke-linecap="round" />
</g>
</svg>
</div>
</body>
</html>

SVG Fixed Sized Element Positioned Relatively within Viewbox

In the example SVG below, how can the marker/pin (red circle) be given a fixed size (say in pixels) whilst at the same time being relatively positioned within its parent viewbox? That is, so that the marker/pin is always visually the same size but can easily be positioned relative part of the map we are viewing.
We've added the code to a fiddle here: https://jsfiddle.net/krbgxqtm/13/
Additional comments:
We would like to avoid the use of client-side code (i.e JavaScript).
We will not always know the container's dimensions exactly due to the responsive positioning it will be within.
We've seen examples of using CSS background-image for achieving the sizing, but this will not satisfy the size of the surrounding hyperlink.
Since your pin is a circle you can use a very short line stroke-linecap="round" vector-effect="non-scaling-stroke". The stroke-linecap="round" will give the line the aspect of a circle. The vector-effect="non-scaling-stroke" will keep the line unscaled.
Aditional observation:
If you intend to use a symbol the viewBox this is NOT correct: viewBox="0 0 10px 10px" Don't use px units. Also
svg {
background-color: khaki;
border: solid 1px #9c9c9c;
}
.container {
background-color: #9ecae1;
border: solid 1px #2c3e50;
margin-top: 20px;
width: 200px;
height: 150px;
}
.container-2 {
width: 400px;
height: 150px;
}
.container-3 {
width: 250px;
height: 300px;
}
.svg-container {
width: 100%;
height: 100%;
}
.outline {
fill: #9c9c9c;
}
<svg width="0" height="0">
<defs>
<path id="country-PT" class="country" stroke="#141414" stroke-opacity="1" stroke-width="1" stroke-linecap="miter" stroke-linejoin="miter" fill="#4F4F4F" fill-opacity="1" fill-rule="evenodd" d="M93 531L101 527L101 532L119 530L119 534L124 536L115 544L117 555L114 557L116 560L114 565L108 565L115 574L110 583L113 586L115 586L109 595L110 601L104 604L96 602L92 603L94 596L93 582L95 583L95 581L89 583L90 579L86 578L87 569L91 566L95 546z"></path>
<g id="pin" class="pin-container" >
<line x1="10" x2="10.1" y1="10" y2="10" stroke-width="10" stroke="red" stroke-linecap="round" vector-effect="non-scaling-stroke" transform="translate(-5,-5)" />
</g>
</defs>
</svg>
<div class="container">
<svg class="svg-container" viewBox="85 525 43 83" >
<!-- Country -->
<rect class="outline" x="85" y="525" width="43" height="83" />
<use href="#country-PT"/>
<!-- Marker -->
<a href="#goToA">
<use x="85" y="574" href="#pin"/>
</a>
</svg>
</div>
<div class="container container-2">
<svg class="svg-container" viewBox="85 540 21.5 41.5" preserveAspectRatio="xMidYMid meet">
<!-- Country -->
<rect class="outline" x="85" y="525" width="43" height="83" />
<use href="#country-PT"/>
<!-- Marker -->
<a href="#goToA">
<use x="85" y="574" href="#pin"/>
</a>
</svg>
</div>
<div class="container container-3">
<svg class="svg-container" viewBox="85 540 20 40" preserveAspectRatio="xMidYMid meet">
<!-- Country -->
<rect class="outline" x="85" y="525" width="43" height="83" />
<use href="#country-PT"/>
<!-- Marker -->
<a href="#goToA">
<use x="85" y="574" href="#pin"/>
</a>
</svg>
</div>

Centering multiple blocks of <svg> elements

If I have two stacked blocks of text within svg, with the second being larger, the second one gets cut off.
<div id="fixed-target" style="display:block; margin:0 auto; width:100%; height:103px; border:0px solid #000; overflow-x:auto; ">
<svg width="654" height="83">
<text text-anchor="middle" x="50%" y="59" font-family="Abbey" font-size="60px"
style="font:bold 80px Arial; color:#fff; fill:rgb(0,0,0);">
<tspan dy="15">Some test text</tspan>
</text>
</svg>
</div>
<div id="fixed-target" style="display:block; margin:0 auto; width:100%; height:103px; border:0px solid #000; overflow-x:auto; ">
<svg width="654" height="83">
<text text-anchor="middle" x="50%" y="59" font-family="Abbey" font-size="60px"
style="font:bold 80px Arial; color:#fff; fill:rgb(0,0,0);">
<tspan dy="15">A very very very long block of test text</tspan>
</text>
</svg>
</div>
How can I mark this up so the longer one is not cut off?
You've basically got 3 options here
Increase the width of the <svg> element. You could make it 100% which would be the size of the <svg> element's container.
Make the font smaller so the text fits in the <svg> element
Use more <tspan> elements to display the text over multiple lines
I've just made the second <svg> element arbitrarily wider below.
<div id="fixed-target" style="display:block; margin:0 auto; width:100%; height:103px; border:0px solid #000; overflow-x:auto; ">
<svg width="654" height="83">
<text text-anchor="middle" x="50%" y="59" font-family="Abbey" font-size="60px"
style="font:bold 80px Arial; color:#fff; fill:rgb(0,0,0);">
<tspan dy="15">Some test text</tspan>
</text>
</svg>
</div>
<div id="fixed-target" style="display:block; margin:0 auto; width:100%; height:103px; border:0px solid #000; overflow-x:auto; ">
<svg width="1554" height="83">
<text text-anchor="middle" x="50%" y="59" font-family="Abbey" font-size="60px"
style="font:bold 80px Arial; color:#fff; fill:rgb(0,0,0);">
<tspan dy="15">A very very very long block of test text</tspan>
</text>
</svg>
</div>

Hover on svg text not working

Creating a svg from adobe xd and trying to create a hover effect for the svg can change fill: colors on hover.
# Heres the svg code #
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1563 3492 45 45">
<defs>
<style>
.cls-1 {
fill: #79bf73;
font-size: 45px;
font-family: SegoeMDL2Assets, Segoe MDL2 Assets;
}
</style>
</defs>
<text id="E1CC" class="cls-1" transform="translate(1563 3537)"><tspan x="0" y="0"></tspan></text>
</svg>
# Heres the html code #
<div class="play">
<img src="http:localhost/mockup3/images/E101.svg" height="42" width="42">
</div>
# Heres the css code #
svg text #E101:hover{
fill: #003565;
}
SVGs inserted as img can't have interaction, they behave as images. To fix this, simply put the full SVG code inline. Cleaned up the code a bit, as these tools often produce ugly code.
HTML
<div class="play">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1563 3492 45 45" width="42" height="42">
<text id="E1CC" class="cls-1" transform="translate(1563 3537)"><tspan x="0" y="0"></tspan></text>
</svg>
</div>
CSS
svg text {
fill: #79bf73;
font-size: 45px;
font-family: SegoeMDL2Assets, Segoe MDL2 Assets;
}
svg text:hover{
fill: #003565;
}
Keep in mind the icon will only be visible with the font Segoe MDL2 Assets installed.

Resources