Add SVG logo on top of SVG background - html

I am wanting to add an SVG logo that I have (I have the SVG code also) on top of a rectangle with a radial background colour that also contains some title text, however I'm unsure of how to do this.
For context, I am using React-PDF, so the syntax is slightly different.
Currently I have
<Svg width="555" height="80" viewBox="0 0 555 80">
<Defs>
<RadialGradient id="header-rectangle" cx="0" cy="0" fr="1">
<Stop stopColor="#A01858"/>
<Stop offset="1" stopColor="#87005F"/>
</RadialGradient>
</Defs>
<Rect width="555" height="80" rx="8" fill="url(#header-rectangle)"/>
<Text style={styles.svg} x={`${555-20}px`} y="50%" textAnchor="end" dominantBaseline="middle">Some title here</Text>
</Svg>
I then also have my SVG logo (shortened here for conciseness):
<Svg width="80" height="52" viewBox="0 0 80 52" fill="none">
<Path d="M0 47.6941V37.8042C0... fill="green"/>
...
</Svg
I am wondering how I can add the logo to the main piece...
I have attempted to place the full <Svg>/*logo*/</Svg> to the main section, but this produced an error:
I have also tried moving all of the <Path> pieces into the main block, without the <Svg> wrapper, which did work to some extent, but then I found that I didn't know how to move them down and right...
This is the example:
<Svg width="555" height="80" viewBox="0 0 555 80">
<Defs>
<RadialGradient id="header-rectangle" cx="0" cy="0" fr="1">
<Stop stopColor="#A01858"/>
<Stop offset="1" stopColor="#87005F"/>
</RadialGradient>
</Defs>
<Rect width="555" height="80" rx="8" fill="url(#header-rectangle)"/>
<Text style={styles.svg} x={`${555-20}px`} y="50%" textAnchor="end" dominantBaseline="middle">Some title here</Text>
<Path d="M0 47.6941V37.8042C0... fill="green"/>
/* rest of the logo svg paths here */
</Svg>

You can wrap your logo in a group and apply a transform to it
<svg width="555" height="80" viewBox="0 0 555 80">
<defs>
<radialGradient id="header-rectangle" cx="0" cy="0" fr="1">
<stop stop-color="#A01858"/>
<stop offset="1" stop-color="#87005F"/>
</radialGradient>
</defs>
<rect width="555" height="80" rx="8" fill="url(#header-rectangle)"/>
<text x="500" y="50%" text-anchor="end" dominant-baseline="middle">Some title here</text>
<g transform="translate(20,10) scale(0.5 0.5)">
<path d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z" fill="green" />
</g>
</svg>

Related

Is there any way i can draw vertical multiple lines in svg?

I want to get something like this
i have tried using strokeDashoffset and strokeDasharray but i still can't get it, ik that i can draw multiple lines but i will have a script that will have to fill these lines
any ideas how can i make them? thanks
i don't know if you need it but here is what i tried:
<svg id="edilRW8EQ5h1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 54 12.5" shape-rendering="geometricPrecision" text-rendering="geometricPrecision">
<path strokeDasharray="10, 10" strokeDashoffset="10" pathLength="500" d="M0,6.25h54v2.134695h-54L0,6.25" fill="white" stroke="#3f5787" stroke-width="0.5"/>
</svg>
This looks a lot like a <pattern>. Here I use the pattern on a <rect> and at the same time the <rect> also has a mask. The mask has a gradient that controls the the whiteness.
It looks a bit like a meter. The "value" of the meter can now be controlled by the value of the two stop elements in the gradient (here 76%).
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 8">
<defs>
<pattern id="p1" viewBox="0 0 6 10" width="5%" height="100%">
<path transform="translate(4 0) rotate(10)" d="M 0 0 V 10"
stroke-width="4" stroke="white" stroke-linecap="round"/>
</pattern>
<linearGradient id="g1" gradientTransform="rotate(1.5)">
<stop offset="0" stop-opacity=".2" stop-color="white" />
<stop offset="76%" stop-opacity="1" stop-color="white" />
<stop offset="76%" stop-opacity=".2" stop-color="white" />
<stop offset="100%" stop-opacity=".2" stop-color="white" />
</linearGradient>
<mask id="m1">
<rect width="50" height="8" fill="url(#g1)"/>
</mask>
</defs>
<rect width="50" height="8" fill="black"/>
<rect width="50" height="8" fill="url(#p1)" mask="url(#m1)"/>
</svg>

How to draw an arc inside another circle using svg

I am trying to achieve The following image:
How do I achieve this fill?
How do I end my circle at the edge of the outer circle? My attempt to adjust the position of the canvas is not to be working.
<svg width="173" height="172" xmlns="http://www.w3.org/2000/svg">
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="175" width="175" y="-1" x="-1"/>
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
</g>
</g>
<g>
<title>Layer 1</title>
<ellipse stroke="#000" ry="85" rx="85" id="svg_1" cy="86" cx="86" stroke-width="1.5" fill="#fff"/>
<ellipse stroke="#000" ry="88" rx="88" id="svg_5" cy="88" cx="15" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="none"/>
<line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="svg_3" y2="170" x2="86" y1="2" x1="82" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="none"/>
</g>
</svg>
The code above produces the following:
Here's how you should do it, explainatory comments attatched:
<svg width="173" height="172" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- clip path-->
<clipPath id="clip">
<ellipse id="circle" ry="85" rx="85" cy="86" cx="86" />
</clipPath>
<!-- gradient -->
<linearGradient id="gradient" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#000" />
<stop offset="100%" stop-color="#fff" />
</linearGradient>
</defs>
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="175" width="175" y="-1" x="-1" />
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%" />
</g>
</g>
<g>
<title>Layer 1</title>
<!-- same shape of the #circle in #clip, adding stroke and fill -->
<use xlink:href="#circle" stroke="#000" stroke-width="1.5" fill="#fff" />
<!-- using clip path, same shape of above -->
<ellipse clip-path="url(#clip)" stroke="#000" ry="88" rx="88" id="svg_5" cy="88" cx="15" stroke-width="1.5" fill="url(#gradient)" />
<line clip-path="url(#clip)" stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="svg_3" y2="170" x2="86" y1="2" x1="82" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="none" />
</g>
</svg>
use this, I created this with adobe Illustrator.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="165px"
height="165px" viewBox="0 0 165 165" style="enable-background:new 0 0 165 165;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#000000;stroke-width:1.5;}
.st1{fill:url(#SVGID_1_);stroke:#000000;stroke-width:1.5;}
.st2{fill:none;stroke:#000000;stroke-width:1.5;}
.st3{fill:url(#SVGID_2_);stroke:#000000;stroke-width:1.5;}
</style>
<defs>
</defs>
<path class="st0" d="M164.3,82.5c0,45.1-36.6,81.8-81.8,81.8c-10.8,0-21.2-2.1-30.6-5.9c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7c9.5-3.8,19.8-5.9,30.6-5.9C127.6,0.8,164.3,37.3,164.3,82.5z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="51.875" y1="158.32" x2="51.875" y2="6.68">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#000000"/>
</linearGradient>
<path class="st1" d="M103,82.5c0,20.8-7.7,39.7-20.5,54.1c-8.3,9.4-18.8,16.9-30.6,21.7c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7C63.7,11.5,74.2,19,82.5,28.4C95.3,42.8,103,61.7,103,82.5z"/>
<line class="st2" x1="82.5" y1="0.8" x2="82.5" y2="164.3"/>
</svg>
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="165px"
height="165px" viewBox="0 0 165 165" style="enable-background:new 0 0 165 165;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#000000;stroke-width:1.5;}
.st1{fill:url(#SVGID_1_);stroke:#000000;stroke-width:1.5;}
.st2{fill:none;stroke:#000000;stroke-width:1.5;}
.st3{fill:url(#SVGID_2_);stroke:#000000;stroke-width:1.5;}
</style>
<defs>
</defs>
<path class="st0" d="M164.3,82.5c0,45.1-36.6,81.8-81.8,81.8c-10.8,0-21.2-2.1-30.6-5.9c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7c9.5-3.8,19.8-5.9,30.6-5.9C127.6,0.8,164.3,37.3,164.3,82.5z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="51.875" y1="158.32" x2="51.875" y2="6.68">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#000000"/>
</linearGradient>
<path class="st1" d="M103,82.5c0,20.8-7.7,39.7-20.5,54.1c-8.3,9.4-18.8,16.9-30.6,21.7c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7C63.7,11.5,74.2,19,82.5,28.4C95.3,42.8,103,61.7,103,82.5z"/>
<line class="st2" x1="82.5" y1="0.8" x2="82.5" y2="164.3"/>
</svg>

how to pass clear html elements(as text format) to backend(express js)

I need to pass an <svg></svg> element to backend as clear text using angular HTTP.
for example, I have an angular-html page with a <svg> element,
<div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 540 320">
<defs>
<path id="Triangle" d="M120 20 L 220 193.205 L 20 193.205 Z" stroke="red" fill="url(#radial)"/>
<path id="Maths" d="M250,50C380,50 350,150 480,150" stroke="green" fill="none"/>
<path id="Chemistry" transform="translate(-200,0) scale(1.5)" d="M250,50C380,50 350,150 480,150" stroke="blue" fill="none"/>
<path id="Path" d="M20,240 C40,280 60,280 200,230 A100 100 0 0 1 300,260 L 330,280 Q 400,320 500,200" stroke="orange" fill="none"/>
<linearGradient id="linear" x1="0" x2="1" gradientUnits="objectBoundingBox">
<stop stop-color="green" offset="0"/>
<stop stop-color="red" offset="1"/>
</linearGradient>
<radialGradient id="radial" cx="0.5" cy="0.6667" r="0.6" gradientUnits="objectBoundingBox">
<stop stop-color="orange" offset="0.2"/>
<stop stop-color="yellow" offset="1"/>
</radialGradient>
<pattern id="pattern" width="4" height="4" patternUnits="userSpaceOnUse">
<rect width="4" height="4"/>
<rect width="2" height="2" fill="red"/>
<rect x="2" y="2" width="2" height="2" fill="red"/>
</pattern>
</defs>
<rect x="2%" y="2%" width="96%" height="96%" fill="url(#linear)" fill-opacity="0.3" stroke="orange" stroke-width="2" stroke-dasharray="5 2 2 2 5 5"/>
<use xlink:href="#Triangle"/>
<use xlink:href="#Maths"/>
<use xlink:href="#Chemistry"/>
<use xlink:href="#Path"/>
<text textLength="600px" lengthAdjust="spacingAndGlyphs" fill="url(#pattern)">
<textPath xlink:href="#Triangle" font-size="20" font-family="serif" font-weight="bold" textLength="600px" lengthAdjust="spacingAndGlyphs">Text adjusted around a triangle</textPath>
</text>
<text font-family="sans-serif">
<textPath xlink:href="#Maths" font-size="30" fill="blue" text-anchor="middle" startOffset="50%">Maths x<tspan font-size="20" baseline-shift="super">2</tspan> + y<tspan font-size="20" baseline-shift="super">2</tspan> = z<tspan font-size="20" baseline-shift="super">2</tspan>!</textPath>
<textPath xlink:href="#Chemistry" font-size="30" fill="green" text-anchor="middle" startOffset="50%">Chemistry 2H<tspan font-size="20" baseline-shift="sub">2</tspan> + O<tspan font-size="20" baseline-shift="sub">2</tspan> -> 2H<tspan font-size="20" baseline-shift="sub">2</tspan>O</textPath>
<textPath xlink:href="#Path" font-size="30" fill="purple" dominant-baseline="middle" text-anchor="middle" startOffset="50%">Text centered on a complex path</textPath>
</text>
</svg>
</div>
Is it possible to pass the svg to backend with angular HTTP.
You can use ViewChild for selecting svg element and then by outerHTML access the HTML.
Demo
Set reference to svg in HTML,
<svg #svgElement ...
Get data from reference,
#ViewChild('svgElement', {static: true}) svgElement: ElementRef;
onClick() {
console.log(this.svgElement.nativeElement.outerHTML)
}

How to keep SVG the same size during browser zoom in/out

I have a landing page with an SVG image as the background. I'd like to lock its size in place so if the browser is zoomed in or out it doesn't change. It looks crappy zoomed out.k
Here's an svg example from Twitter of the functionality I'm talking about. If you open this svg code in a browser, the twitter bird doesn't change size if you command&+/- and zoom out.
<svg class="twitterIcon-bird" viewBox="0 0 1208 982" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 45.2 (43514) - http://www.bohemiancoding.com/sketch -->
<title>bird</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Final-Horizon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-286.000000, -117.000000)" fill-rule="nonzero" fill="#1B95E0">
<path d="M1493.75308,233.195911 C1449.31783,252.922544 1401.56126,266.207828 1351.43951,272.19627 C1402.61804,241.549536 1441.92034,192.987798 1460.3889,135.116296 C1412.53168,163.498493 1359.49119,184.130942 1303.02874,195.252335 C1257.88897,147.093181 1193.42514,117 1122.16771,117 C962.190754,117 844.636121,266.258151 880.768067,421.202806 C674.896491,410.886582 492.324484,312.253414 370.089808,162.341063 C305.17308,273.705962 336.423691,419.391176 446.731805,493.16476 C406.171431,491.856361 367.925917,480.734968 334.561738,462.165765 C331.844294,576.95263 414.122472,684.342008 533.287442,708.245454 C498.413572,717.706186 460.218381,719.9204 421.368991,712.47259 C452.871217,810.904465 544.358512,882.514158 652.854997,884.52708 C548.686294,966.201382 417.443793,1002.68559 286,987.186091 C395.653915,1057.48739 525.940278,1098.50067 665.838342,1098.50067 C1125.89162,1098.50067 1385.81015,709.956437 1370.10936,361.469352 C1418.52012,326.494836 1460.53987,282.864756 1493.75308,233.195911 Z" id="bird"></path>
</g>
</g>
</svg>
Here's my image's svg info that I'd like to behave similarly. You might need to copy and paste this into a file and view in a browser. It's a curved image with multiple layers.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient x1="18.4268546%" y1="27.9722359%" x2="82.7977891%" y2="77.3056038%" id="linearGradient-1">
<stop stop-color="#1E87F0" offset="0%"></stop>
<stop stop-color="#1E3E5C" offset="100%"></stop>
</linearGradient>
<linearGradient x1="18.4268546%" y1="28.295015%" x2="82.7977891%" y2="76.9054869%" id="linearGradient-2">
<stop stop-color="#1E87F0" offset="0%"></stop>
<stop stop-color="#1E3E5C" offset="100%"></stop>
</linearGradient>
<path d="M0.882548395,15.7999936 L1.20671504,819.366633 C336.735572,860.919994 594.34158,794.683198 774.024741,620.656245 C932.62388,467.049615 996.276998,527.683301 1151.1184,531.228148 C1305.9598,534.772995 1508.44994,684.094916 1631.51564,783.962916 C1713.55944,850.541583 1650.01507,594.487275 1440.88255,15.7999936 L0.882548395,15.7999936 Z" id="path-3"></path>
<linearGradient x1="10.0537047%" y1="28.3217065%" x2="117.215768%" y2="106.344139%" id="linearGradient-5">
<stop stop-color="#1E87F0" offset="0%"></stop>
<stop stop-color="#1E3E5C" offset="100%"></stop>
</linearGradient>
<path d="M12.04293,25 L6.90201099,735.285212 C159.518234,768.654318 306.462792,773.140482 447.735683,748.743705 C773.312884,692.518943 874.037615,533.915834 1153.33439,533.901355 C1339.53225,533.891702 1497.8173,596.686321 1628.18954,722.285212 L1464.16913,25 L12.04293,25 Z" id="path-6"></path>
</defs>
<g id="Landing-page" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Landing-page---v2">
<g id="Bitmap" transform="translate(-12.000000, -25.000000)">
<path d="M60.8501735,0.107667822 L60.8501735,687.900102 C293.733255,762.384295 480.221381,787.428003 620.314551,763.031226 C943.172971,706.806464 1004.024,482.419288 1280.98847,482.404809 C1557.95294,482.39033 1520.08109,690.064545 1643.14678,789.932545 C1725.19058,856.511212 1677.75838,593.236253 1500.85017,0.107667822 L60.8501735,0.107667822 Z" id="Mask-Copy" fill="url(#linearGradient-1)" fill-rule="nonzero" opacity="0.12"></path>
<mask id="mask-4" fill="white">
<use xlink:href="#path-3"></use>
</mask>
<use id="Mask-Copy-2" fill="url(#linearGradient-2)" fill-rule="nonzero" opacity="0.12" xlink:href="#path-3"></use>
<mask id="mask-7" fill="white">
<use xlink:href="#path-6"></use>
</mask>
<use id="Mask" fill="url(#linearGradient-5)" fill-rule="nonzero" xlink:href="#path-6"></use>
</g>
</g>
</g>
</svg>
What changes can I make to my svg file to make it behave like the twitter svg?
This will give you the viewBox, now I leave it to you to put your markup in that viewbox - since it is off center.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 5000 5000">
<defs>
<linearGradient x1="18.4268546%" y1="27.9722359%" x2="82.7977891%" y2="77.3056038%" id="linearGradient-1">
<stop stop-color="#1E87F0" offset="0%"></stop>
<stop stop-color="#1E3E5C" offset="100%"></stop>
</linearGradient>
<linearGradient x1="18.4268546%" y1="28.295015%" x2="82.7977891%" y2="76.9054869%" id="linearGradient-2">
<stop stop-color="#1E87F0" offset="0%"></stop>
<stop stop-color="#1E3E5C" offset="100%"></stop>
</linearGradient>
<path d="M0.882548395,15.7999936 L1.20671504,819.366633 C336.735572,860.919994 594.34158,794.683198 774.024741,620.656245 C932.62388,467.049615 996.276998,527.683301 1151.1184,531.228148 C1305.9598,534.772995 1508.44994,684.094916 1631.51564,783.962916 C1713.55944,850.541583 1650.01507,594.487275 1440.88255,15.7999936 L0.882548395,15.7999936 Z" id="path-3"></path>
<linearGradient x1="10.0537047%" y1="28.3217065%" x2="117.215768%" y2="106.344139%" id="linearGradient-5">
<stop stop-color="#1E87F0" offset="0%"></stop>
<stop stop-color="#1E3E5C" offset="100%"></stop>
</linearGradient>
<path d="M12.04293,25 L6.90201099,735.285212 C159.518234,768.654318 306.462792,773.140482 447.735683,748.743705 C773.312884,692.518943 874.037615,533.915834 1153.33439,533.901355 C1339.53225,533.891702 1497.8173,596.686321 1628.18954,722.285212 L1464.16913,25 L12.04293,25 Z" id="path-6"></path>
</defs>
<g id="Landing-page" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Landing-page---v2">
<g id="Bitmap" transform="translate(-12.000000, -25.000000)">
<path d="M60.8501735,0.107667822 L60.8501735,687.900102 C293.733255,762.384295 480.221381,787.428003 620.314551,763.031226 C943.172971,706.806464 1004.024,482.419288 1280.98847,482.404809 C1557.95294,482.39033 1520.08109,690.064545 1643.14678,789.932545 C1725.19058,856.511212 1677.75838,593.236253 1500.85017,0.107667822 L60.8501735,0.107667822 Z" id="Mask-Copy" fill="url(#linearGradient-1)" fill-rule="nonzero" opacity="0.12"></path>
<mask id="mask-4" fill="white">
<use xlink:href="#path-3"></use>
</mask>
<use id="Mask-Copy-2" fill="url(#linearGradient-2)" fill-rule="nonzero" opacity="0.12" xlink:href="#path-3"></use>
<mask id="mask-7" fill="white">
<use xlink:href="#path-6"></use>
</mask>
<use id="Mask" fill="url(#linearGradient-5)" fill-rule="nonzero" xlink:href="#path-6"></use>
</g>
</g>
</g>
</svg>

SVG rect as background to text [duplicate]

I want to color the background of svg text similar to background-color in css
I was only able to find documentation on fill, which colors the text itself
Is it even possible?
You could use a filter to generate the background.
<svg width="100%" height="100%">
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow" result="bg" />
<feMerge>
<feMergeNode in="bg"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50">solid background</text>
</svg>
No this is not possible, SVG elements do not have background-... presentation attributes.
To simulate this effect you could draw a rectangle behind the text attribute with fill="green" or something similar (filters). Using JavaScript you could do the following:
var ctx = document.getElementById("the-svg"),
textElm = ctx.getElementById("the-text"),
SVGRect = textElm.getBBox();
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rect.setAttribute("x", SVGRect.x);
rect.setAttribute("y", SVGRect.y);
rect.setAttribute("width", SVGRect.width);
rect.setAttribute("height", SVGRect.height);
rect.setAttribute("fill", "yellow");
ctx.insertBefore(rect, textElm);
The solution I have used is:
<svg>
<line x1="100" y1="100" x2="500" y2="100" style="stroke:black; stroke-width: 2"/>
<text x="150" y="105" style="stroke:white; stroke-width:0.6em">Hello World!</text>
<text x="150" y="105" style="fill:black">Hello World!</text>
</svg>
A duplicate text item is being placed, with stroke and stroke-width attributes. The stroke should match the background colour, and the stroke-width should be just big enough to create a "splodge" on which to write the actual text.
A bit of a hack and there are potential issues, but works for me!
Instead of using a <text> tag, the <foreignObject> tag can be used, which allows for XHTML content with CSS.
No, you can not add background color to SVG elements. You can do it programmatically with d3.
var text = d3.select("text");
var bbox = text.node().getBBox();
var padding = 2;
var rect = self.svg.insert("rect", "text")
.attr("x", bbox.x - padding)
.attr("y", bbox.y - padding)
.attr("width", bbox.width + (padding*2))
.attr("height", bbox.height + (padding*2))
.style("fill", "red");
Answer by Robert Longson (#RobertLongson) with modifications:
<svg width="100%" height="100%">
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow"/>
<feComposite in="SourceGraphic" operator="xor"/>
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50"> solid background </text>
<text x="20" y="50" font-size="50">solid background</text>
</svg>
and we have no bluring and no heavy "getBBox" :)
Padding is provided by white spaces in text-element with filter.
It's worked for me
Going further with #dbarton_uk answer, to avoid duplicating text you can use paint-order=stroke style:
<svg>
<line x1="100" y1="100" x2="350" y2="100" style="stroke:grey; stroke-width: 100"/>
<text x="150" y="105" style="stroke:white; stroke-width:0.5em; fill:black; paint-order:stroke; stroke-linejoin:round">Hello World!</text>
</svg>
Note the stroke-linejoin:round which is needed to avoid seeing spikes for the W sharp angle.
You can combine filter with the text.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>SVG colored patterns via mask</title>
</head>
<body>
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter x="0" y="0" width="1" height="1" id="bg-text">
<feFlood flood-color="white"/>
<feComposite in="SourceGraphic" operator="xor" />
</filter>
</defs>
<!-- something has already existed -->
<rect fill="red" x="150" y="20" width="100" height="50" />
<circle cx="50" cy="50" r="50" fill="blue"/>
<!-- Text render here -->
<text filter="url(#bg-text)" fill="black" x="20" y="50" font-size="30">text with color</text>
<text fill="black" x="20" y="50" font-size="30">text with color</text>
</svg>
</body>
</html>
this is my favorite hack (not sure it should work). It refer an element that is not yet displayed, and it works pretty well
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 620 40" preserveAspectRatio="xMidYMid meet">
<defs>
<filter x="-0.02" y="0" width="1.04" height="1.1" id="removebackground">
<feFlood flood-color="#00ffff"/>
</filter>
</defs>
<!--Draw the text-->
<use xlink:href="#mygroup" filter="url(#removebackground)" />
<g id="mygroup">
<text id="text1" x="9" y="20" style="text-anchor:start;font-size:14px;">custom text with background</text>
<line x1="200" y1="18" x2="200" y2="36" stroke="#000" stroke-width="5"/>
<line x1="120" y1="27" x2="203" y2="27" stroke="#000" stroke-width="5"/>
</g>
</svg>
For those wondering how to apply padding to a text element when it has a background like in the Robert's answer, do the following:
<svg>
<defs>
<filter x="-0.1" y="-0.1" width="1.2" height="1.2" id="solid">
<feFlood flood-color="#171717"/>
<feComposite in="SourceGraphic" operator="xor" />
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50">Hello</text>
</svg>
In the example above, filter's x and y positions can be used as transform: translate(-10%, -10%) would, and width and height values can be read as 120% and 120%. So we made background 20% bigger, and offsetted it -10%, so background is now 10% bigger on each side of the text.
The previous answers relied on doubling up text and lacked sufficient whitespace.
By using atop and I was able to get the results I wanted.
This example also includes arrows, a common use case for SVG text labels:
<svg viewBox="-105 -40 210 234">
<title>Size Guide</title>
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="white"></feFlood>
<feComposite in="SourceGraphic" operator="atop"></feComposite>
</filter>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z"></path>
</marker>
</defs>
<g id="garment">
<path id="right-body" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 0 l30 0 l0 154 l-30 0"></path>
<path id="right-sleeve" d="M30 0 l35 0 l0 120 l-35 0" fill="none" stroke-linejoin="round" stroke="black" stroke-width="1"></path>
<use id="left-body" href="#right-body" transform="scale(-1,1)"></use>
<use id="left-sleeve" href="#right-sleeve" transform="scale(-1,1)"></use>
<path id="collar-right-top" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 -6.5 l11.75 0 l6.5 6.5"></path>
<use id="collar-left-top" href="#collar-right-top" transform="scale(-1,1)"></use>
<path id="collar-left" fill="white" stroke="black" stroke-width="1" stroke-linejoin="round" d="M-11.75 -6.5 l-6.5 6.5 l30 77 l6.5 -6.5 Z"></path>
<path id="front-right" fill="white" stroke="black" stroke-width="1" d="M18.25 0 L30 0 l0 154 l-41.75 0 l0 -77 Z"></path>
<line x1="0" y1="0" x2="0" y2="154" stroke="black" stroke-width="1" stroke-dasharray="1 3"></line>
<use id="collar-right" href="#collar-left" transform="scale(-1,1)"></use>
</g>
<g id="dimension-labels">
<g id="dimension-sleeve-length">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="85" y1="0" x2="85" y2="120" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="85" y="60" class="dimension" text-anchor="middle" dominant-baseline="middle"> 120 cm</text>
</g>
<g id="dimension-length">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-85" y1="0" x2="-85" y2="154" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="-85" y="77" text-anchor="middle" dominant-baseline="middle" class="dimension"> 154 cm</text>
</g>
<g id="dimension-sleeve-to-sleeve">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-65" y1="-20" x2="65" y2="-20" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="0" y="-20" text-anchor="middle" dominant-baseline="middle" class="dimension"> 130 cm </text>
</g>
<g title="Back Width" id="dimension-back-width">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-30" y1="174" x2="30" y2="174" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="0" y="174" text-anchor="middle" dominant-baseline="middle" class="dimension"> 60 cm </text>
</g>
</g>
</svg>
An obvious workaround to the problem of the blur produced by the filter effect is to render the <text> two times: once for the background (with transparent characters) and once for the characters (without a background filter).
For me, this was the only way to make the text readable in Safari.
<svg width="100%" height="100%">
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow" />
</filter>
<g transform="translate(20, 50)" font-size="50">
<text aria-hidden="true" fill="none" filter="url(#solid)">solid background</text>
<text fill="blue">solid background</text>
</g>
</svg>
The aria-hidden="true" attribute is there to prevent screen readers from speaking the text twice, if the user uses a screen reader.
You can add style to your text:
style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
text-shadow: rgb(255, 255, 255) -2px -2px 0px, rgb(255, 255, 255) -2px 2px 0px,
rgb(255, 255, 255) 2px -2px 0px, rgb(255, 255, 255) 2px 2px 0px;"
White, in this example.
Does not work in IE :)