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>
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>
Why <svg>'s 1px stroke-width is wider than <div>'s 1px border-width?
Is it possible to create an <svg> that looks exactly like the <div>below?
<svg>
<rect x="10" y="10" width="100" height="100" stroke-width="1" stroke="red" fill="white" />
</svg>
<div style="margin: 0 0 10px 10px; width: 100px; height: 100px; border: 1px solid red">
</div>
That's just antialiasing. You can turn it off if you want via the shape-rendering CSS property. Adjusting the co-ordinates by 0.5px may also work.
<svg>
<rect x="10" y="10" width="100" height="100" stroke-width="1" stroke="red" fill="white" shape-rendering="crispEdges" />
</svg>
<div style="margin: 0 0 10px 10px; width: 100px; height: 100px; border: 1px solid red">
</div>
I have an SVG within a web page, it consists of images + text
<object data="/infographic/timeline.svg" type="image/svg+xml">
<img src="/infographic/timeline.svg" alt="Timeline">
</object>
All the images are responsive, but the text isn't, so the text becomes really, REALLY small.
snippet of SVG (its massive)
<defs>
<style>
.cls-1 {
font-size: 60.014px;
}
.cls-1, .cls-10 {
opacity: 0.69;
}
.cls-1, .cls-10, .cls-4, .cls-5, .cls-7, .cls-8, .cls-9 {
fill: #ffffff;
}
.cls-1, .cls-10, .cls-3, .cls-4, .cls-5, .cls-6, .cls-7, .cls-9 {
text-anchor: middle;
}
.cls-1, .cls-3, .cls-6 {
font-family: "Roboto";
}
.cls-2 {
font-size: 32.014px;
}
.cls-3 {
font-size: 14.089px;
}
.cls-3, .cls-6 {
fill: #db7426;
}
.cls-4, .cls-6 {
font-size: 32px!important;
}
.cls-10, .cls-4, .cls-5, .cls-7, .cls-8, .cls-9 {
font-family: Roboto;
}
.cls-5 {
font-size: 24px;
}
.cls-5, .cls-8, .cls-9 {
font-weight: 400;
}
.cls-6 {
font-weight: 600;
}
.cls-10, .cls-7 {
font-size: 18.75px;
font-weight: 300;
}
.cls-7 {
opacity: 0.4;
}
.cls-8, .cls-9 {
font-size: 22px;
}
</style>
</defs>
<text id="Who_are_you_what_do_you_do_what_s_your_why_What_s_been_keepi" data-name="Who are you, what do you do, what’s your why? What’s been keepi" class="cls-8" x="397.706" y="535.325">Who are you, what do you do, what’s your why?<tspan x="397.706" dy="26.4">What’s been keeping you lying awake at night. </tspan></text>
Is there anyway I can get the text size to increase as the SVG/screen width gets smaller?
Any help would be greatly appreciated.
It's not possible with pure SVG (at least not yet). The only solution would be to either:
inline the SVG and manipulate the size of the text with javascript.
inline the SVG and control the size of the text with media queries (see below).
Add CSS to the SVG and use media queries there (see below).
use media queries to switch SVGs when the page gets small
Example of option 2: Using media queries with inlined SVGs
text {
font-size: 10px;
}
#media (max-width: 400px) {
text {
font-size: 20px;
}
}
<svg viewBox="0 0 100 100" width="100%" height="100%">
<circle cx="50" cy="50" r="50" fill="orange"/>
<text x="50" y="60" text-anchor="middle">Testing</text>
</svg>
Example of option 3: Using media queries in CSS in the SVGs
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100%" height="100%">
<style>
text {
font-size: 10px;
}
#media (max-width: 400px) {
text {
font-size: 20px;
}
}
</style>
<circle cx="50" cy="50" r="50" fill="orange"/>
<text x="50" y="60" text-anchor="middle">Testing</text>
</svg>
This is possible using the foreignObject svg element in a html context and some adjustment of the viewBow.
On this demos, the text stay selectable:
.demo {
overflow: auto;
resize: both;
border:1px black solid;
width: 230px;
height: 130px
}
.svgtext {
font-size: 28rem;
height:100%;
width:100%
}
<div class="demo">
<svg x="0" y="30" viewBox="0 0 100 100" width="100%" height="100%">
<foreignObject x="12" y="23" height="100%" width="100%">
<div class"svgtext">
Hello world!
</div>
</foreignObject>
</svg>
</div>
Use preserveAspectRatio to control the resizing behavior:
.demo {
overflow: auto;
resize: both;
border:1px black solid;
width: 230px;
height: 130px
}
.svgtext {
font-size: 28rem;
height:100%;
width:100%
}
<div class="demo">
<svg preserveAspectRatio="none" x="0" y="30" viewBox="0 0 100 100" width="100%" height="100%">
<foreignObject x="12" y="23" height="100%" width="100%">
<div class"svgtext">
Hello world!
</div>
</foreignObject>
</svg>
</div>