SVG fill with css variables - css

I am trying to use CSS variables in my SVG (which is set as a background image) for the fill color, but am having difficulty in getting it to work. It shows the default black, but when I inspect it I can see that the css variable is there and showing my desired color.
HTML
<div class="test">
Testing the css variable color
</div>
<div class="icon">
</div>
CSS
:root {
--primary-color: hsl(332, 61%, 78%);
}
div {
width: 100px;
height: 100px;
}
.test {
background: var(--primary-color);
}
.icon {
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='var(--primary-color)' /%3E%3C/svg%3E");
}
Here is a codepen to check out!
I've seen CSS Variables being used in SVG here but I'm not sure if it's possible to do with background images? I'm new to both using SVG and CSS variables so I'm not sure if I'm doing something wrong... Would love some insight as to why it's not rendering the color properly!

Now you can include SVG as mask-image instead of background. Don't forget set background color from css variables for .icon block.
.icon {
background: var(--primary-color);
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' /%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' /%3E%3C/svg%3E");
}
You can check it in this CodePan
Here is information from Caniuse about mask-image
And here documentation about mask property

Okay here we go... I will first explain why it does not work and then I will show an alternative.
Why your approach doesn't work
In your example the svg is not part of the DOM. So you cannot use css to modify the attributes of the svg.
What you are doing is adding an inline-style to the svg in your url. Since the browser does not recognise --primary-color as a color it doesn't work.
An alternative approach
An alternative approach is to put the svg in the html and fake a background. I did this by absolute positioning the svg and moving it to the background with z-index.
Do note you will have to modify the svg or the positioning to place the background in the way you want. Normally you would use background-size for this. But with some effort you can replicate this behaviour within the svg or position it better by using css.
:root {
--primary-color: hsl(332, 61%, 78%);
}
div {
width: 100px;
height: 100px;
}
.test {
background: var(--primary-color);
}
.icon{ /*postion relative for absolute positioning to work*/
position: relative;
}
.icon>svg{
position: absolute;
top: 0px;
right: 0px;
left: 0px;
bottom: 0px;
z-index: -1;
}
.icon>svg>path{ /*target the image with css*/
fill: var(--primary-color);
}
<div class="test">
Testing the css variable color
</div>
<div class="icon">
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129' id='background'><path d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z'/> </svg>
<p>Text goes here...</p>
</div>

Don't include svg as background, by doing that you don't have control over it's fill, instead try adding it inline in html and via css you can control the fill via css variable, please check the working example below, hope it helps :)
:root {
--primary-color: hsl(332, 61%, 78%);
}
div {
width: 100px;
height: 100px;
}
.test {
background: var(--primary-color);
}
.icon {
color: var(--primary-color);
fill: currentColor;
width: 64px;
height: 64px;
}
<div class="test">
Testing the css variable color
</div>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 129 129">
<path d="m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z"/>
</svg>

Using the <symbol> tag and CSS variables
CSS variables inherit the fill property. Therefore, it is possible to assign (declare) a variable inside the <symbol> tag, the value of which can be subsequently changed many times for each instance of the svg element.
<symbol id="monstr">
<rect width="100%" height="100%" fill="transparent" />
<path id="face" fill="var(--color-face)" d="M15.4,34.1L24,37l8.6-2.9c1.9-0.6,3-2.6,2.6-4.6L33,20H15l-2.2,9.5C12.3,31.5,13.5,33.5,15.4,34.1z"/>
<path id="nose" fill="var(--color-nose)" d="M29,30l-3-3h-4l-3,3v7c0,1.1,0.9,2,2,2h6c1.1,0,2-0.9,2-2V30z"/>
Each path, circle, ellips, etc. can be assigned its own variable fill = "var (- color-face)" for fill and then change its value in the external style sheet:
.monstr-colors { --color-face: #7986CB; --color-nose: #9FA8DA; }
This technique creates powerful and flexible styling options for multicolor svg.
For example, for one state of an icon, we can assign one color scheme, and with : hover, assign a different color set to the same icon.
.monstr-colors {
--color-face: #7986CB;
--color-nose: #9FA8DA;
}
.monstr-colors:hover {
--color-face: #3F8B4D;
--color-nose: #58C46C;
)
Below is an example, according to your taste, the color scheme of the image is easily created and changed:
.monstr-colors {
--color-face: #7986CB;
--color-nose: #9FA8DA;
--color-hair-right:#3949AB;
--color-hair-right2:#3949AB;
--color-hair-left:#3949AB;
--color-hair-left2:#3949AB;
--color-eye-right:#1A237E;
--color-pupil-right:#77006B;
--color-eye-left:#1A237E;
--color-pupil-left:#77006B;
--color-ellipse1:#9FA8DA;
--color-ellipse2:#7986CB;
--color-ellipse3:#C5CAE9;
}
.monstr-colors:hover {
--color-face: #3F8B4D;
--color-nose: #58C46C;
--color-hair-right:gold;
--color-hair-right2:#FFBB00;
--color-hair-left:gold;
--color-hair-left2:#FFBB00;
--color-eye-right:#77006B;
--color-pupil-right:#FF4151;
--color-eye-left:#77006B;
--color-pupil-left:#FF4151;
--color-ellipse1:#FFDD00;
--color-ellipse2:#C1A700;
--color-ellipse3:#FFEE7D;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="192" height="192" viewBox="0 0 48 48" >
<symbol id="monstr">
<rect width="100%" height="100%" fill="transparent" />
<path id="face" fill="var(--color-face)" d="M15.4,34.1L24,37l8.6-2.9c1.9-0.6,3-2.6,2.6-4.6L33,20H15l-2.2,9.5C12.3,31.5,13.5,33.5,15.4,34.1z"/>
<path id="nose" fill="var(--color-nose)" d="M29,30l-3-3h-4l-3,3v7c0,1.1,0.9,2,2,2h6c1.1,0,2-0.9,2-2V30z"/>
<path id="hair-right" fill="var(--color-hair-right)" d="M31,7c-0.5,0-1,0.4-1,1c0,0,0,0,0,0c-0.4,0-0.8,0.2-0.9,0.6c-0.2,0.5,0,1.1,0.6,1.3 C30,10.1,40,14.4,40,32.4V37c0,0.6,0.4,1,1,1s1-0.4,1-1v-4.6c0-14.4-6.1-20.7-9.5-23.1C35.9,10.3,44,14.7,44,34c0,0.6,0.4,1,1,1 s1-0.4,1-1C46,7.7,31.6,7,31,7z"/>
<path id="hair-right2" fill="var(--color-hair-right2)" d="M29.5,10.1c-0.5-0.3-1.1-0.1-1.3,0.4c-0.3,0.5-0.1,1.1,0.4,1.4c0.1,0,7.5,4.3,7.5,20.1v8c0,0.6,0.4,1,1,1 s1-0.4,1-1v-8C38,14.9,29.8,10.3,29.5,10.1z"/>
<path id="hair-left" fill="var(--color-hair-left)" d="M18.4,9.9c0.5-0.2,0.8-0.8,0.6-1.3C18.8,8.2,18.4,8,18,8c0,0,0,0,0,0c0-0.6-0.5-1-1-1C16.4,7,2,7.7,2,34 c0,0.6,0.4,1,1,1s1-0.4,1-1c0-19.6,8.1-23.8,11.6-24.7C12.2,11.6,6,17.9,6,32.4V37c0,0.6,0.4,1,1,1s1-0.4,1-1v-4.6 C8,14.4,18,10.1,18.4,9.9z"/>
<path id="hair-left" fill="var(--color-hair-left2)" d="M18.5,10.1C18.2,10.3,10,14.9,10,32v8c0,0.6,0.4,1,1,1s1-0.4,1-1v-8c0-15.8,7.4-20.1,7.5-20.1 c0.5-0.3,0.7-0.9,0.4-1.4C19.6,10,19,9.9,18.5,10.1z"/>
<path id="eye-right" fill="var(--color-eye-right)" d="M25,24.9c0,0,0.2,1.3,0.6,1.7s3.3,2.5,5.9-0.9c1.2-1.5,0.6-3.8,0.6-3.8S29.4,24.1,25,24.9z"/>
<circle id="pupil-right" cx="28" cy="25" r="1.5" fill="var(--color-pupil-right)" />
<path id="eye-left" fill="var(--color-eye-left)" d="M15.8,21.8c0,0-0.6,2.3,0.6,3.8c2.6,3.4,5.5,1.4,5.9,0.9c0.4-0.4,0.6-1.7,0.6-1.7 C18.6,24.1,15.8,21.8,15.8,21.8z"/>
<circle id="pupil-left" fill="var(--color-pupil-left)" cx="20" cy="25" r="1.5" fill="red" />
<ellipse id="ellipse1" fill="var(--color-ellipse1)" cx="24" cy="15" rx="12" ry="10"/>
<ellipse id="ellipse2" fill="var(--color-ellipse2)" cx="24" cy="13.8" rx="10" ry="7.8"/>
<ellipse id="ellipse3" fill="var(--color-ellipse3)" cx="24.2" cy="12.2" rx="8" ry="6.2"/>
</symbol>
<svg class="monstr-colors">
<use xlink:href="#monstr" />
</svg>
</svg>
Below is a combined example with styling three instances of the same image.
Each instance of the created <use xlink: href = "# monstr"/> has its own color scheme, which is linked to the nested svg class.
<div class="container">
<svg class="color-monstr">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
<div class="container2">
<svg class="color-monstr2">
<use xlink:href="#monstr" transform="scale(2)" />
</svg>
</div>
<div class="container3">
<svg class="color-monstr3">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
With :hover, each instance replaces the color scheme with the color scheme of the adjacent instance.
.parent {
position:relative;
}
.container {
width:400px;
height:400px;
position:absolute;
top:0;
}
.container2 {
position: absolute;
top:0;
left:150px;
}
.container3 {
position: absolute;
top:0;
left:240px;
}
.color-monstr {
--color-ears: #459E48;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#4CAF50;
--circle-horn-left:#8BC34A;
--circle-horn-right:#8BC34A;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#173027;
}
.color-monstr:hover {
--color-ears: #504F7A;
--color-horn-right: #504FF6;
--color-horn-left: #504FF6;
--color-face:#807FC4;
--circle-horn-left:#FF00AE;
--circle-horn-right:#FF00AE;
--eye-right:#FFDBF4;
--eye-left:#FFDBF4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFDBF4;
}
.color-monstr2 {
--color-ears: #504F7A;
--color-horn-right: #504FF6;
--color-horn-left: #504FF6;
--color-face:#807FC4;
--circle-horn-left:#FF00AE;
--circle-horn-right:#FF00AE;
--eye-right:#FFDBF4;
--eye-left:#FFDBF4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFDBF4;
}
.color-monstr2:hover {
--color-ears: #770051;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#FFDD00;
--circle-horn-left:#D0FF00;
--circle-horn-right:#A0C400;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFF9C4;
}
.color-monstr3 {
--color-ears: #770051;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#FFDD00;
--circle-horn-left:#D0FF00;
--circle-horn-right:#A0C400;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFF9C4;
}
.color-monstr3:hover {
--color-ears: #459E48;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#4CAF50;
--circle-horn-left:#8BC34A;
--circle-horn-right:#8BC34A;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#173027;
}
<div class="parent">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" >
<symbol id="monstr">
<path id="ears"
fill="var(--color-ears)"
d="M12,31c-2.3,0-3.7-3.2-4-5c0.7-1.3,3.3-2,4-2c5.7-2.4,17.8-2.9,24,0c0.7,0,3.3,0.7,4,2c-0.3,1.8-1.7,5-4,5 C33.6,32.8,14.7,34.2,12,31z"/>
<g>
<path id="horn-right"
fill="var(--color-horn-right)" d="M40,8c-0.6,0-1,0.4-1,1c0,2.7-3.3,5-6,5c-0.6,0-1,0.4-1,1s0.4,1,1,1c3.7,0,8-3.1,8-7C41,8.4,40.6,8,40,8z"/>
<path id="horn-left"
fill="var(--color-horn-left)" d="M8,8c0.6,0,1,0.4,1,1c0,2.7,3.3,5,6,5c0.6,0,1,0.4,1,1s-0.4,1-1,1c-3.7,0-8-3.1-8-7C7,8.4,7.4,8,8,8z"/>
</g>
<path id="face"
fill="var(--color-face)" d="M12,31v-7c0-9.2,5.3-16,12-16s12,6.8,12,16v7c-1.2,5.6-7,12-12,12S13.2,36.6,12,31z"/>
<g>
<circle id="circle-horn-left" fill="var(--circle-horn-left)" cx="8" cy="9" r="3"/>
<circle id="circle-horn-right" fill="var(--circle-horn-right)" cx="40" cy="9" r="3"/>
</g>
<g>
<ellipse id="eye-right" fill="var(--eye-right)" cx="29" cy="26" rx="2" ry="4"/>
<ellipse id="eye-left" fill="var(--eye-left)" cx="19" cy="26" rx="2" ry="4"/>
</g>
<g>
<circle id="pupil-right" fill="var(--pupil-right)" cx="29" cy="27" r="1"/>
<circle id="pupil-left" fill="var(--pupil-left)" cx="19" cy="27" r="1"/>
</g>
<path id="mouth" fill="var(--mouth)" d="M24,33c-4,0-5.8,3-5.8,3s2.6,0,5.8,0s5.8,0,5.8,0S28,33,24,33z"/>
</symbol>
</svg>
<div class="container">
<svg class="color-monstr">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
<div class="container2">
<svg class="color-monstr2">
<use xlink:href="#monstr" transform="scale(2)" />
</svg>
</div>
<div class="container3">
<svg class="color-monstr3">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
</div>

Here is a better way or how I color my SVGs. As Inline SVGs have a bitter taste on readability of the rest of the code and adding them as background or mask, they can not be colored by a dark theme switch. Include them externally and load them inside an html object:
<object id="background-anim" class="svg" aria-hidden="true" data="./media/Background-fluid-lines-anim.svg" type="image/svg+xml"></object>
This SVG is now added externally.
To set the colors you need to set for the desired colors a class inside of the SVG.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080">
<defs>
<style>
.svg-element__clrText{
fill:rgb(255,255,255);
}
.svg-element__clrPrimary{
fill:rgb(155,155,155);
}
.svg-element__clrBackground{
fill:rgb(55,55,55);
}
</style>
</defs>
<path class="svg-element__clrText"></path>
</svg>
In your paths, you will set those classes to the desired elements that should adapt colors.
Now you will manipulate those fill values with JavaScript and add the correct CSS Custom Porperties:
/*Optional: Listening to the clicked switch if you have one*/
document.querySelectorAll('.theme-toggle').forEach((toggle) => {
toggle.addEventListener('click', () => themeToggle);
});
window.themeToggle = function themeToggle() {
document.documentElement.classList.toggle('darkMode');
//this .darkmode{} class changes the values of my variables set to white mode in the ':root{}' in the css file
loadTheme()
}
function loadTheme(){
/* For loading more than just the colors */
loadThemeIcon();
loadSVGColors();
}
/* Now here comes the important part */
function loadSVGColors() {
const svgs = document.querySelectorAll('.svg'); //getting NodeList of SVGs
const style = getComputedStyle(document.body), //getting CSS variables inside of js
svgs.forEach(svg => {
element = svg.contentDocument; //get the actual svg that is loaded into the object element
const clrText = svg.querySelectorAll('.svg-element__textClr'), //searching inside of the SVG after my classes
textClr.forEach(element => { //NodeList to Array
element.style.fill = style.getPropertyValue('--clr-text');//whatever variables you have set or you can toggle a class that has only this css variable inside
});
/* [...and so on]*/
const primeClr = element.querySelectorAll('.svg-element__primeClr');
primeClr.forEach(e => {
e.style.fill = style.getPropertyValue('--clr-primary');
});
});
}
I guess there is a better performance when you add the SVGs inside the HTML with fill: var(--clr-text), however after having 50kb of code per SVG leads to lots of scrolling
I know this goes further than the question but I would have been glad to find this before under these SO posts.

I stumbled upon this for a very similar case and want to share a completely different approach.
Use the css multi background feature (MDN Docs)
First you need to make the part of your svg that you want to color transparent with fill="transparent"
Now you can just specify multiple backgrounds, where one can be your variable, for example
body {
background: url('path/to/your/svg/or/data-url'), var(--background);
}

If you need to control only one color, you can use currentColor keyword in the fill property and change it through css color property.
.icon {
color: var(--primary-color);
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='currentColor' /%3E%3C/svg%3E");
}

<path class="class-name"/>
:root {
--color : #123456;
}
.class-name {
fill : var(--color)
}
try this

Related

Trying to animate 2 parts of svg based on hover on whole svg

I'm trying to animate the Facebook SVG icon when on hover but I can only animate separate parts of the image. Although I need to animate the whole image on hover. Here's the SVG code:
#fb-rect:hover {
fill: white;
}
#fb-path:hover {
stroke: black;
fill: black;
}
<div style="background-color: red">
<svg width="41" height="40" viewBox="0 0 41 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="fb-outer">
<rect id="fb-rect" x="1" y="0.5" width="39" height="39" stroke="white" />
<g id="fb-inner">
<path id="fb-path"
d="M22.2456 21.7899V31H18.0148V21.7899H14.5V18.0555H18.0148V16.6967C18.0148 11.6524 20.122 9 24.5806 9C25.9475 9 26.2892 9.21967 27.0377 9.39867V13.0925C26.1997 12.946 25.9638 12.8646 25.0932 12.8646C24.0599 12.8646 23.5067 13.1575 23.0022 13.7352C22.4978 14.3129 22.2456 15.3136 22.2456 16.7456V18.0636H27.0377L25.7522 21.7981H22.2456V21.7899Z"
fill="white" />
</g>
</g>
</svg>
</div>
I also have the gif demonstrating what I want to achieve:
Try this code
#fb-outer:hover #fb-rect {
fill: white;
}
#fb-outer:hover #fb-path {
stroke: black;
fill: black;
}
u can also add the position absolute:
<div style="background-color: red; position: absolute;">

OpenLayers Icon className SVG - Change Fill Via CSS?

I'm trying to use CSS classes in openlayers to change an svg fill colour:
eg say in open layers I have
style = new Style({
image: new Icon({
src: styleConfig.image.src,
scale: styleConfig.image.scale,
offset: [styleConfig.offsetX, styleConfig.offsetY],
className: 'icon--blue'
}),
zIndex: styleConfig.zIndex
});
and then I have an SVG like so:
<svg xmlns="http://www.w3.org/2000/svg" width="49" height="44" viewBox="0 0 580 515" class="icon--blue"><circle fill="inherit" cx="475" cy="106.9" r="102.9"/><g class="cat"><circle fill="inherit" cx="475" cy="106.9" r="102.9"/></g></svg>
and some CSS like so:
.icon--blue circle {
fill: #0000ff !important;
}
.icon--blue .cat {
display: none;
}
Try as I might I cannot get the css based fill effect to be applied. I was wondering if this is supported?
Also the hiding of the grouping with the class name of "cat" also doesn't work.
Seeing is OpenLayers is rendering to canvas, debugging this kind of stuff is very difficult.
Start with a Proof of Concept SVG in a JSFiddle or CodePen, to get your SVG and CSS selectors right.
Learn CSS Specificity to understand why the .inner circle below is green and not red;
Most likely no need for fill attribute and hardly ever !important
<style>
svg {
width: 25%;
}
circle {
fill: green;
stroke: red;
}
#outer {
fill: blue;
}
.inner {
fill: red;
}
.hidden {
display: none;
}
</style>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<circle id="outer" cx="10" cy="10" r="8" />
<g class="inner">
<circle cx="10" cy="10" r="4" />
</g>
<circle class="hidden" cx="15" cy="15" r="4" />
</svg>

How do I make an image shrink to fit inside a fixed position flex box modal

How do I make an image shrink to fit inside a fixed position flex box modal?
When trying the below the image overlaps the header/footer. It needs to work for images both tall, or wide, and in IE.
.modal-dialog {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.modal-content {
display: flex;
flex-direction: column;
height: 100%;
}
.modal-header {
background: red;
margin: 20px;
}
.modal-body {
background: green;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0 20px;
}
.modal-footer {
background: blue;
margin: 20px;
}
<div class="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
header
</div>
<div class="modal-body">
<img src="https://via.placeholder.com/900x1200" />
</div>
<div class="modal-footer">
footer
</div>
</div>
</div>
</div>
Note this is a simple example, and I am really using a complicated SVG, not an image tag, so I can't use a background image.
You can use good old position: absolute with max-width and max-height:
/* for demonstration I have replaced all irrelavant styles with this */
.modal-body {
width: 80vw;
height: 60vh;
margin: 10% auto 0;
background: green;
}
/* parent must be positioned */
.modal-body {
position: relative;
}
/* size and center */
.modal-body img {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
max-width: 100%;
max-height: 100%;
margin: auto;
}
<div class="modal-body">
<img src="https://via.placeholder.com/900x1200" />
</div>
Just a reminder but by default images try to maintain their aspect ratios, so simply setting a percentage width will allow an inlined image to grow to the proper height OR setting only the height to a percentage will maintain the width.
The key is to only set ONE dimension and let the browser figure out the rest.
This is especially true if you set the sizes Inline using the appropriate HTML structure.
<div class="modal-body">
<img src="https://via.placeholder.com/900x1200" width="100%" />
</div>
Now you just set the max-width of the container with CSS and everything is happy. That should be true of any use of the img tag. Meaning if you use an SVG in the img src attribute you'll get it to function like an image. That said, I believe you lose SVG interactions if you do it that way.
So assuming you're going to actually drop the SVG into your code, you need to do a bit of work to the SVG.
Note how most SVG's have hard-coded heights and widths in the header Simply removing the hard-coded height/width "should" make the SVG scale correctly since the view-box keeps the proportions of the image.
<svg width="299px" height="138px" viewBox="0 0 299 138" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="example">
<rect id="Rectangle" fill="#D8D8D8" x="0" y="0" width="299" height="138"></rect>
<circle id="Oval" fill="#46BEC6" cx="53" cy="50" r="26"></circle>
<circle id="Oval-Copy" fill="#46BEC6" cx="105" cy="76" r="26"></circle>
<circle id="Oval-Copy-2" fill="#46BEC6" cx="165" cy="95" r="26"></circle>
<circle id="Oval-Copy-3" fill="#46BEC6" cx="217" cy="63" r="26"></circle>
<circle id="Oval-Copy-4" fill="#46BEC6" cx="269" cy="32" r="26"></circle>
</g>
</g>
</svg>
<svg viewBox="0 0 299 138" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="example">
<rect id="Rectangle" fill="#D8D8D8" x="0" y="0" width="299" height="138"></rect>
<circle id="Oval" fill="#46BEC6" cx="53" cy="50" r="26"></circle>
<circle id="Oval-Copy" fill="#46BEC6" cx="105" cy="76" r="26"></circle>
<circle id="Oval-Copy-2" fill="#46BEC6" cx="165" cy="95" r="26"></circle>
<circle id="Oval-Copy-3" fill="#46BEC6" cx="217" cy="63" r="26"></circle>
<circle id="Oval-Copy-4" fill="#46BEC6" cx="269" cy="32" r="26"></circle>
</g>
</g>
</svg>
If you don't know which one needs to be set (like in the case of a dynamic image) you'll need to measure it with javascript before applying the correct measurement. Something along these lines:
fixImage(){
var img = findTheImageInTheDom;
if (img.width > img.height){
img.width = "100%";
} else {
img.height = "100%";
}

What is wrong with my SVG Path Code?

I'm following this code pen but the author's code doesn't work for my own custom SVG from Illustrator. The original author puts a fill as an inline CSS style on the SVG path code. The white hover fill won't work if I don't make the SVG path code to white.
By default - The image is invisible but should be color #788F9B.
On hover it works:
a svg:hover #bino {
fill: #fff;
}
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 209.84 136.85">
<path id="bino" d="M58.07,139.42a23.28,23.28,0,0,1-23.13-18.92v2.63a22.71,22.71,0,0,0,23.13,21.55A22.34,22.34,0,0,0,81.2,123.15v-2.66A22.86,22.86,0,0,1,58.07,139.42Z" transform="translate(-10.14 -29.37)" style="fill:#29aae1" />
<path d="M172.65,139.42a23.28,23.28,0,0,1-23.13-18.92v2.63a22.71,22.71,0,0,0,23.13,21.55,22.34,22.34,0,0,0,23.13-21.52v-2.66A23.28,23.28,0,0,1,172.65,139.42Z" transform="translate(-10.14 -29.37)" style="fill:#29aae1" />
<path d="M204.72,82.65h0l-43.63-47.3a29.17,29.17,0,0,0-24.18-4.2,21,21,0,0,0-16.29,21v2.63a15.35,15.35,0,0,0-4.73-1.05,14,14,0,0,0-6.31,1.58l0.53-4.2a21,21,0,0,0-16.29-21,29.75,29.75,0,0,0-23.65,4.73L25.48,83.18h0a47.88,47.88,0,1,0,80.42,35.22v-5.26a11.25,11.25,0,0,0,8.94,4.2,11.93,11.93,0,0,0,9.46-4.73v5.78a47.83,47.83,0,0,0,95.66,0A46.83,46.83,0,0,0,204.72,82.65ZM58.07,151.51a33.11,33.11,0,1,1,33.11-33.11h0a33,33,0,0,1-32.8,33.11H58.07Zm114.58,0a33.11,33.11,0,1,1,33.11-33.11h0A33,33,0,0,1,173,151.51h-0.32Z" transform="translate(-10.14 -29.37)" style="fill:#fff" />
</svg>
</a>
It doesn't work because the style attributes in HTML have precedence over the CSS stylesheet. Hence the color never changes.
You can solve this by defining the initial color in your stylesheet instead:
#bino {
fill: #29aae1;
}
a:hover #bino {
fill: #fff;
}
A working example:
a {
display: block;
width: 166px;
padding: 30px;
}
a:hover {
background-color: #166584;
}
.bino {
fill: #29aae1;
}
#binocular {
fill: #788F9B;
}
a:hover #binocular {
fill: #fff;
}
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 209.84 136.85">
<path class="bino" d="M58.07,139.42a23.28,23.28,0,0,1-23.13-18.92v2.63a22.71,22.71,0,0,0,23.13,21.55A22.34,22.34,0,0,0,81.2,123.15v-2.66A22.86,22.86,0,0,1,58.07,139.42Z" transform="translate(-10.14 -29.37)" />
<path class="bino" d="M172.65,139.42a23.28,23.28,0,0,1-23.13-18.92v2.63a22.71,22.71,0,0,0,23.13,21.55,22.34,22.34,0,0,0,23.13-21.52v-2.66A23.28,23.28,0,0,1,172.65,139.42Z" transform="translate(-10.14 -29.37)" />
<path id="binocular" d="M204.72,82.65h0l-43.63-47.3a29.17,29.17,0,0,0-24.18-4.2,21,21,0,0,0-16.29,21v2.63a15.35,15.35,0,0,0-4.73-1.05,14,14,0,0,0-6.31,1.58l0.53-4.2a21,21,0,0,0-16.29-21,29.75,29.75,0,0,0-23.65,4.73L25.48,83.18h0a47.88,47.88,0,1,0,80.42,35.22v-5.26a11.25,11.25,0,0,0,8.94,4.2,11.93,11.93,0,0,0,9.46-4.73v5.78a47.83,47.83,0,0,0,95.66,0A46.83,46.83,0,0,0,204.72,82.65ZM58.07,151.51a33.11,33.11,0,1,1,33.11-33.11h0a33,33,0,0,1-32.8,33.11H58.07Zm114.58,0a33.11,33.11,0,1,1,33.11-33.11h0A33,33,0,0,1,173,151.51h-0.32Z" transform="translate(-10.14 -29.37)" />
</svg>
</a>

SVG icons: Styling using CSS based on context

is it possible to style paths of SVG icons using CSS based on their context?
My SVG icon consists of 2 paths:
<g id="shape-codepen">
<path class="outer-ring" d="..."></path>
<path class="inner-logo" d="..."></path>
</g>
I use them in HTML as follow:
<svg class="shape-codepen"><use xlink:href="#shape-codepen"></use></svg>
<svg class="shape-codepen-red"><use xlink:href="#shape-codepen"></use></svg>
Basic styles:
.outer-ring { fill: #999; }
.inner-logo { fill: #666; }
But I want to change the partial color of the second one as it is in a different context, i.e.
.shape-codepen-red .outer-ring { fill: #f00; }
But is doesn't work.
Here is a simple pencode illustration my problem:
http://codepen.io/anon/pen/eZVGgv
Is it possible to change partially color of a path of an icon based on it's context? How?
No...you can't access the internal parts like that. You need two use elements. One for the ring, and a second for the inner shape.
Then address them separately.
Codepen Demo
.hide {
display: none;
}
.icon {
width: 75px;
height: 75px;
}
body {
padding: 20px;
}
.red .red {
fill: red;
}
.blue .blue {
fill: blue;
}
<svg class="hide">
<defs>
<g id="shape-codepen-ring">
<path class="outer-ring" d="M50,0C22.385,0,0,22.385,0,50c0,27.615,22.385,50,50,50c27.614,0,50-22.385,50-50C100,22.385,77.615,0,50,0z M50,91.789
C26.958,91.789,8.212,73.042,8.212,50C8.212,26.958,26.958,8.212,50,8.212c23.042,0,41.788,18.747,41.788,41.789
C91.788,73.042,73.042,91.789,50,91.789z"></path>
</g>
<g id="shape-codepen-shape">
<path class="inner-logo" d="M80.893,40.234c-0.006-0.039-0.016-0.076-0.022-0.115c-0.013-0.075-0.027-0.15-0.046-0.223
c-0.012-0.044-0.028-0.086-0.042-0.128c-0.021-0.065-0.042-0.13-0.068-0.193c-0.018-0.044-0.039-0.088-0.059-0.13
c-0.028-0.06-0.057-0.119-0.09-0.175c-0.024-0.042-0.051-0.083-0.076-0.124c-0.036-0.055-0.073-0.109-0.112-0.161
c-0.029-0.039-0.06-0.078-0.091-0.115c-0.042-0.049-0.086-0.098-0.132-0.143c-0.035-0.036-0.069-0.072-0.106-0.104
c-0.049-0.044-0.099-0.086-0.15-0.127c-0.04-0.031-0.079-0.062-0.12-0.091c-0.016-0.01-0.029-0.023-0.044-0.033L51.474,19.531
c-0.893-0.595-2.055-0.595-2.947,0L20.267,38.371c-0.015,0.01-0.028,0.023-0.044,0.033c-0.042,0.029-0.081,0.06-0.12,0.091
c-0.052,0.041-0.102,0.083-0.15,0.127c-0.037,0.032-0.071,0.068-0.106,0.104c-0.046,0.045-0.09,0.094-0.132,0.143
c-0.031,0.038-0.062,0.077-0.092,0.115c-0.039,0.052-0.076,0.106-0.111,0.161c-0.027,0.041-0.052,0.082-0.076,0.124
c-0.033,0.057-0.062,0.115-0.09,0.175c-0.021,0.042-0.042,0.086-0.06,0.13c-0.026,0.063-0.047,0.128-0.068,0.193
c-0.014,0.042-0.029,0.084-0.042,0.128c-0.02,0.073-0.032,0.148-0.046,0.223c-0.006,0.039-0.016,0.076-0.021,0.115
c-0.016,0.114-0.024,0.229-0.024,0.346V59.42c0,0.117,0.009,0.233,0.024,0.348c0.005,0.038,0.015,0.077,0.021,0.114
c0.014,0.075,0.027,0.149,0.046,0.223c0.012,0.043,0.028,0.086,0.042,0.128c0.021,0.065,0.042,0.13,0.068,0.195
c0.018,0.044,0.039,0.086,0.06,0.129c0.028,0.06,0.058,0.118,0.09,0.177c0.024,0.041,0.049,0.082,0.076,0.122
c0.035,0.056,0.072,0.109,0.111,0.161c0.029,0.041,0.061,0.078,0.092,0.115c0.042,0.049,0.086,0.098,0.132,0.144
c0.035,0.036,0.069,0.071,0.106,0.104c0.048,0.044,0.099,0.086,0.15,0.127c0.039,0.031,0.078,0.062,0.12,0.091
c0.016,0.01,0.029,0.023,0.044,0.032l28.259,18.84c0.446,0.297,0.96,0.447,1.474,0.447c0.513,0,1.027-0.149,1.473-0.447
l28.259-18.84c0.015-0.009,0.028-0.022,0.044-0.032c0.042-0.029,0.081-0.06,0.12-0.091c0.051-0.041,0.102-0.083,0.15-0.127
c0.037-0.033,0.071-0.068,0.106-0.104c0.046-0.046,0.09-0.095,0.132-0.144c0.031-0.037,0.062-0.075,0.091-0.115
c0.04-0.052,0.076-0.105,0.112-0.161c0.025-0.041,0.051-0.081,0.076-0.122c0.033-0.059,0.062-0.117,0.09-0.177
c0.02-0.042,0.041-0.085,0.059-0.129c0.026-0.065,0.047-0.13,0.068-0.195c0.014-0.042,0.03-0.085,0.042-0.128
c0.02-0.074,0.033-0.148,0.046-0.223c0.006-0.037,0.016-0.076,0.022-0.114c0.014-0.115,0.023-0.231,0.023-0.348V40.581
C80.916,40.464,80.907,40.348,80.893,40.234z M52.657,26.707l20.817,13.877l-9.298,6.221l-11.519-7.706V26.707z M47.343,26.707
v12.393l-11.518,7.706l-9.299-6.221L47.343,26.707z M24.398,45.554L31.046,50l-6.648,4.446V45.554z M47.343,73.294L26.525,59.417
l9.299-6.219l11.518,7.704V73.294z M50,56.286L40.603,50L50,43.715L59.397,50L50,56.286z M52.657,73.294V60.902l11.519-7.704
l9.298,6.219L52.657,73.294z M75.602,54.447L68.955,50l6.647-4.446V54.447z"></path>
</g>
<path id="shape-twitter" d="M100.001,17.942c-3.681,1.688-7.633,2.826-11.783,3.339
c4.236-2.624,7.49-6.779,9.021-11.73c-3.965,2.432-8.354,4.193-13.026,5.146C80.47,10.575,75.138,8,69.234,8
c-11.33,0-20.518,9.494-20.518,21.205c0,1.662,0.183,3.281,0.533,4.833c-17.052-0.884-32.168-9.326-42.288-22.155
c-1.767,3.133-2.778,6.773-2.778,10.659c0,7.357,3.622,13.849,9.127,17.65c-3.363-0.109-6.525-1.064-9.293-2.651
c-0.002,0.089-0.002,0.178-0.002,0.268c0,10.272,7.072,18.845,16.458,20.793c-1.721,0.484-3.534,0.744-5.405,0.744
c-1.322,0-2.606-0.134-3.859-0.379c2.609,8.424,10.187,14.555,19.166,14.726c-7.021,5.688-15.867,9.077-25.48,9.077
c-1.656,0-3.289-0.102-4.895-0.297C9.08,88.491,19.865,92,31.449,92c37.737,0,58.374-32.312,58.374-60.336
c0-0.92-0.02-1.834-0.059-2.743C93.771,25.929,97.251,22.195,100.001,17.942L100.001,17.942z"></path>
<g id="shape-youtube">
<path class="youtube" d="M98.77,27.492c-1.225-5.064-5.576-8.799-10.811-9.354C75.561,16.818,63.01,15.993,50.514,16
c-12.495-0.007-25.045,0.816-37.446,2.139c-5.235,0.557-9.583,4.289-10.806,9.354C0.522,34.704,0.5,42.574,0.5,50.001
c0,7.426,0,15.296,1.741,22.509c1.224,5.061,5.572,8.799,10.807,9.352c12.399,1.32,24.949,2.145,37.446,2.14
c12.494,0.005,25.047-0.817,37.443-2.14c5.234-0.555,9.586-4.291,10.81-9.352c1.741-7.213,1.753-15.083,1.753-22.509
S100.51,34.704,98.77,27.492 M67.549,52.203L43.977,64.391c-2.344,1.213-4.262,0.119-4.262-2.428V38.036
c0-2.548,1.917-3.644,4.262-2.429l23.572,12.188C69.896,49.008,69.896,50.992,67.549,52.203"></path>
</g>
</defs>
</svg>
<svg viewBox="0 0 100 100" class="icon red">
<use xlink:href="#shape-codepen-shape"></use>
<use xlink:href="#shape-codepen-ring" class="red"></use>
</svg>
<svg viewBox="0 0 100 100" class="icon blue">
<use xlink:href="#shape-codepen-shape"></use>
<use xlink:href="#shape-codepen-ring" class="blue"></use>
</svg>
Note: Chris Coyier actually covers this in his Lodge SVG course of videos

Resources