flexbox child are not preserving its height when viewport shrinks - css

I have 6 svg icons each contained in a div and also I have a general container that contains all of them with a width of 50%, three of these icons have a square aspect and the other three have a rectangle aspect.
As you can see in the code all the icons have a height of 80px but when the viewport shrinks the icons with rectangle aspect become smaller than their square siblings and that's not what I want, I want that all icons preserve the height (and the width), and if they are going to shrink then they all should preserve the height ratio i.e. they all should remain with the same height.
This is an issue that occurs only in chrome, in firefox it doesn't happen, though I didn't test it on other browsers.
Removing the 50% width from the container fixes this but I need to specify a width for reasons that are not relevant to the question.
.general-container{
background-color: peachpuff;
display: flex;
flex-direction: row;
width: 50%;
justify-content: space-between;
margin: 0 auto;
}
.icon-container{
display: block;
margin: 0 2px;
height: 80px;
}
<div class="general-container">
<div class="icon-container">
<svg width="100%" height="100%" viewBox="0 0 41 41" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-237.288,-229.987)">
<rect x="237.288" y="229.987" width="40.678" height="40.678"/>
</g>
</svg>
</div>
<div class="icon-container">
<svg width="100%" height="100%" viewBox="0 0 69 41" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-293.041,-229.987)">
<g transform="matrix(1.67742,0,0,1,-104.99,0)">
<rect x="237.288" y="229.987" width="40.678" height="40.678"/>
</g>
</g>
</svg>
</div>
<div class="icon-container">
<svg width="100%" height="100%" viewBox="0 0 41 41" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-237.288,-229.987)">
<rect x="237.288" y="229.987" width="40.678" height="40.678"/>
</g>
</svg>
</div>
<div class="icon-container">
<svg width="100%" height="100%" viewBox="0 0 69 41" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-293.041,-229.987)">
<g transform="matrix(1.67742,0,0,1,-104.99,0)">
<rect x="237.288" y="229.987" width="40.678" height="40.678"/>
</g>
</g>
</svg>
</div>
<div class="icon-container">
<svg width="100%" height="100%" viewBox="0 0 41 41" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-237.288,-229.987)">
<rect x="237.288" y="229.987" width="40.678" height="40.678"/>
</g>
</svg>
</div>
</div>

Chrome has a history ([1], [2], [3]) of being a bit less magical about flex-basis: auto (which is present by default on all of your .icon-containers) than other browsers. Firefox is managing to look into your SVG and notice its actual proportions, while Chrome is stopping at <svg width="100%" height="100%"> and assuming a 1:1 aspect ratio on every icon for flexbox negotiation.
You'll have to give Chrome enough information to make the right decision. I tried some permutations of setting the width and height attributes on your <svg>s themselves, but that doesn't seem to work well in your case. Instead, it seems that setting the flex-basis on the .icon-containers is needed.
Here's the basic way I got it to work in Chrome, simply going off of the even/odd pattern. (This is in addition to your existing CSS.) In production, you would of course need to use different classes to assign the different flex-basises:
.icon-container{
flex-basis: 80px;
}
.icon-container:nth-child(even){
flex-basis: 134.63px;
}
Hopefully someone else can come up with an approach that adjusts the SVGs directly.

Related

SVG is not talking FULL 'width' of container

I am trying to make my svg full with width of the screen (container) but its not working. Could someone help me - please?
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320" preserveAspectRatio="none" class="first-svg">
<path fill="#27187F" fill-opacity="1" d="M0,192L60,170.7C120,149,240,107,360,106.7C480,107,600,149,720,170.7C840,192,960,192,1080,170.7C1200,149,1320,107,1380,85.3L1440,64L1440,320L1380,320C1320,320,1200,320,1080,320C960,320,840,320,720,320C600,320,480,320,360,320C240,320,120,320,60,320L0,320Z"></path>
</svg>
css
.first-svg {
width: 100%;
height: 200px;
}
I am suing bootstrap for this project I am working (only for practice)
I have done the following and it seemed to work - I added the SVG inside a row.
<div class="row">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320" preserveAspectRatio="none" class="first-svg">
<path fill="#27187F" fill-opacity="1" d="M0,192L60,170.7C120,149,240,107,360,106.7C480,107,600,149,720,170.7C840,192,960,192,1080,170.7C1200,149,1320,107,1380,85.3L1440,64L1440,320L1380,320C1320,320,1200,320,1080,320C960,320,840,320,720,320C600,320,480,320,360,320C240,320,120,320,60,320L0,320Z"></path>
</svg>
</div>

CSS stacking context affecting SVG opacity?

I came across an "issue happening on Safari" raised which finally lead me to discover a very different behaviour on some scenario on Chromium based browsers vs. Firefox vs. Safari, with 3 different results. But I can't really find any reference on specifications about if there is any reason for what any of them do or which is the right behaviour.
Scenario can be checked on this snippet - code is not much interesting, preview is.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
<symbol id="flag" viewBox="0 0 600 200">
<defs>
<linearGradient id="prefix__e" x1="27.243%" x2="72.757%" y1="67.663%" y2="32.348%">
<stop offset="0%"/>
<stop offset="100%" stop-opacity="0"/>
</linearGradient>
<path id="prefix__a" d="M0 0H700V600H0z"/>
</defs>
<g style="mix-blend-mode:multiply" fill="none" fill-rule="evenodd">
<mask id="prefix__b" fill="#fff">
<use xlink:href="#prefix__a"/>
</mask>
<g style="mix-blend-mode:multiply" mask="url(#prefix__b)">
<g>
<g>
<path fill="#592C82" d="M349.941 0L0 95.825 0 469.766 0 977.167 350.059 1071.707 700 977.167 700 95.825 700 95.706z" transform="matrix(1 0 0 -1 0 600) translate(0 95.043)"/>
<path fill="url(#prefix__e)" fill-opacity=".6" d="M349.941 0L0 95.825 0 469.766 0 977.167 350.059 1071.707 700 977.167 700 95.825 700 95.706z" transform="matrix(1 0 0 -1 0 600) translate(0 95.043)"/>
</g>
</g>
</g>
</g>
</symbol>
</svg>
<div>
<div style="background: blue; height: 40px">below svg is at same stacking context</div>
<div style=" transform: none">
<svg width="300" height="100" style="margin-left: 50px; margin-top: -20px;">
<use xlink:href="#flag"></use>
</svg>
</div>
<hr>
<div style="background: blue; height: 40px">below svg has own stacking context (translate)</div>
<div style=" transform: translate(0, 0 );">
<svg width="300" height="100" style="margin-left: 50px; margin-top: -20px;">
<use xlink:href="#flag"></use>
</svg>
</div>
<hr>
<div style="background: blue; height: 40px">below svg has own stacking context (opacity)</div>
<div style=" filter: opacity(100%);">
<svg width="300" height="100" style="margin-left: 50px; margin-top: -20px;">
<use xlink:href="#flag"></use>
</svg>
</div>
</div>
SVG is purple semi transparent, blue divs are just behind the SVG. When SVG is transparent and overlaps other HTML content, it sometimes allows to see the content below, sometimes it doesn't. My conclusions are next:
On Chromium based browsers, transparency works as expected - mixing colours with the background element until the SVG is placed in a different stacking context, then opacity stops allowing seeing behind elements from other stacking contexts.
On Safari for Mac, it seems to work similar to Chromium but maybe in a buggy way? When in the same stacking context transparency works. If you move the SVG into a new stacking context using some properties like filter transparency stops, but other properties don't stop the transparency - like transform.
On Firefox, transparency simply don't work, elements behind the transparent SVG are not visible through it, even on same stacking context.
Any idea about the specs saying something about this?
Thank you in advance.

SVG styling problems with <use>

I'm trying to change, with CSS, the size and color of an SVG element that's being rendered with <use>. The SVG in question:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="#000000" fill-rule="evenodd" d="<all the actual svg path info>" clip-rule="evenodd"/>
</svg>
I do not have permission to change the contents of the SVG itself.
The way I'm using the SVG:
<svg>
<use xlink:href="#myIcon"></use>
</svg>
I've fought with this for hours, read through a pretty comprehensive article on the subject, and I still haven't had any success. I've tried applying classes to both the use element and the outer svg element, as well as referencing the path element inside. I can't seem to do anything to override the provided styles. How can I change the width, height, and fill color with this arrangement?
For the size it's easy if you correctly set the viewBox and then you adjust the width/height.
For the coloration you can rely on blending mode since the color of the SVG is black.
.icon {
display: inline-block;
background: #fff;
position: relative;
}
.icon::after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background:var(--c);
mix-blend-mode:lighten;
}
.icon>svg {
display: block;
}
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<symbol id="myIcon">
<path fill="#000" d="M81,40.933c0-4.25-3-7.811-6.996-8.673c-0.922-5.312-3.588-10.178-7.623-13.844 c-2.459-2.239-5.326-3.913-8.408-4.981c-0.797-3.676-4.066-6.437-7.979-6.437c-3.908,0-7.184,2.764-7.979,6.442 c-3.078,1.065-5.939,2.741-8.396,4.977c-4.035,3.666-6.701,8.531-7.623,13.844C22.002,33.123,19,36.682,19,40.933 c0,2.617,1.145,4.965,2.957,6.589c0.047,0.195,0.119,0.389,0.225,0.568l26.004,43.873c0.383,0.646,1.072,1.04,1.824,1.04 c0.748,0,1.439-0.395,1.824-1.04L77.82,48.089c0.105-0.179,0.178-0.373,0.225-0.568C79.855,45.897,81,43.549,81,40.933z M49.994,11.235c2.164,0,3.928,1.762,3.928,3.93c0,2.165-1.764,3.929-3.928,3.929s-3.928-1.764-3.928-3.929 C46.066,12.997,47.83,11.235,49.994,11.235z M27.842,36.301c0.014,0,0.027,0,0.031,0c1.086,0,1.998-0.817,2.115-1.907 c0.762-7.592,5.641-13.791,12.303-16.535c1.119,3.184,4.146,5.475,7.703,5.475c3.561,0,6.588-2.293,7.707-5.48 c6.664,2.742,11.547,8.944,12.312,16.54c0.115,1.092,1.037,1.929,2.143,1.907c2.541,0.013,4.604,2.087,4.604,4.631 c0,1.684-0.914,3.148-2.266,3.958H25.508c-1.354-0.809-2.268-2.273-2.268-3.958C23.24,38.389,25.303,36.316,27.842,36.301z M50.01,86.723L27.73,49.13h44.541L50.01,86.723z" fill-rule="evenodd" clip-rule="evenodd"/>
</symbol>
</svg>
<!-- your code -->
<div class="icon" style="--c:red;">
<svg viewBox="0 0 100 125" width="100">
<use xlink:href="#myIcon"></use>
</svg>
</div>
<div class="icon" style="--c:green;">
<svg viewBox="0 0 100 125" width="150">
<use xlink:href="#myIcon"></use>
</svg>
</div>
<div class="icon" style="--c:blue;">
<svg viewBox="0 0 100 125" width="200">
<use xlink:href="#myIcon"></use>
</svg>
</div>
Save svg as a image with svg format then add the color and width or whatever you want to your img then add this to the html file as a img tag and display: none the svg code.
If you can't reach the html code then you can't do anything.

How to position my svg image to the center of browser

I generated a simple svg image and loaded it to Chrome. Meant to position it to the center of browser(even when the browser resizing), but so far have failed on this.
Have referred to some articles about viewport/viewbox setting, and some Q&As on this site(https://stackoverflow.com/questions/8639383/how-do-i-center-an-svg-in-a-div;https://stackoverflow.com/questions/13373169/align-svg-to-center-of-screen), but haven't got it done. Maybe I missed something, since I am very new to this.
Here is the full code for this svg image:
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="100%"
height="100%"
viewBox="0 -700 1080 1920"
preserveAspectRatio="xMidYMid meet"
version="1.1"
id="mysvg"
>
<g
id="group" >
<circle
r="500"
style="fill:#ffb721;fill-opacity:1"
cy="0"
cx="0"
id="path" />
<circle
style="fill:#f71c17;fill-opacity:1;"
id="path2"
cx="0"
cy="0"
r="250" />
</g>
</svg>
I expect this image could stay at the center of the browser, even during browser resizing.
I think this is what you want?
The SVG will be position in the center even the browser resized and scroll
ON GLOBAL CSS
CSS:
#container {
top: 50%;
left: 50%;
position: fixed;
transform: translate(-50%, -50%);
}
INSIDE SVG
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 439.29 439.29" width="100%" height="100%">
<g id="group">
<circle cx="219.64" cy="219.64" r="219.64" style="fill: #ffb721" id="path"/>
<circle cx="219.64" cy="219.64" r="108.32" style="fill: #f71c17" id="path2"/>
</g>
</svg>
Your SVG needs a little modification to center it in the ViewBox.
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
width: 300px;
height: 300px;
background-color: rgba(red, .3);
}
<div class="container">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="100%"
height="100%"
viewBox="-540 -960 1080 1920"
preserveAspectRatio="xMidYMid meet"
version="1.1"
id="mysvg"
>
<g
id="group" >
<circle
r="500"
style="fill:#ffb721;fill-opacity:1"
cy="0"
cx="0"
id="path" />
<circle
style="fill:#f71c17;fill-opacity:1;"
id="path2"
cx="0"
cy="0"
r="250" />
</g>
</svg>
</div>

Svg inside another svg can't change height with css

Example
In this example I've posted, I have two svg elements, each with a nested element with its own viewbox.
svg {
background-color: orange;
}
#inline {
background-color: yellow;
}
#in-css {
width: 50px;
}
<svg viewbox="0 0 300 300" width=100 height=100>
<rect x=50 y=30 width=100 height=100></rect>
<svg id="inline" width="50px" viewbox="50 50 100 100">
<rect width=50 height=50 x=80 y=80></rect>
</svg>
</svg>
<svg viewbox="0 0 300 300" width=100 height=100>
<rect x=50 y=30 width=100 height=100></rect>
<svg id="in-css" viewbox="50 50 100 100">
<rect width=50 height=50 x=80 y=80></rect>
</svg>
</svg>
Problem
Setting the width or height attribute of the inner svg works if I do it inline, but I can't set it if I try targeting that element with css. Does anybody know why? I'm using chrome for reference if that helps :)

Resources