Scale inline SVG symbol referenced with <use> - css
I have an SVG logo defined as a symbol like so:
<svg class="SpriteSheet">
<symbol id="icon-logo" viewBox="-12 -79.61 407.19 108.36">
<path id="logo-upperLeft" d="M0-67.61l83.66 0 0-10 -93.66 0 0 30.92 10 0Z" transform="translate(-2 -2)"></path>
<path id="logo-upperRight" d="M383.19-67.61l-83.66 0 0-10 93.66 0 0 30.92 -10 0Z" transform="translate(2 -2)"></path>
<path id="logo-lowerLeft" d="M0 16.75l83.66 0 0 10 -93.66 0 0-30.92 10 0Z" transform="translate(-2 2)"></path>
<path id="logo-lowerRight" d="M383.19 16.75l-83.66 0 0 10 93.66 0 0-30.92 -10 0Z" transform="translate(2 2)"></path>
</symbol>
</svg>
This definition is included at the top of the body and styled with display:none.
Later in the document, I use the logo in this way:
<header class="Header">
<h1 class="Header-headline">
<a href="/">
<svg class="Header-logo">
<use xlink:href="#icon-logo"></use>
</svg>
</a>
</h1>
</header>
I want to make the logo a certain height, with an automatic width:
.Header-logo {
height: 5rem;
}
This results in this:
Although the height is correct (here, 1rem is 24px), the width remains the default 300px. Adding width:auto causes no changes. In researching this problem, I came across several possible solutions here and here. However, none have worked with my application: reapplying the viewBox at the point of usage cuts off a large part of the image and using an <img> tag is not possible because I need to retain access to the SVG's DOM for styling purposes.
I could add a hard-coded width based on the known aspect ratio of the image, but this seems to be a non-optimal solution: what if the aspect ratio of the logo changes in the future? Another option is to define width:100%, which does work, however, this makes the 'clickable' area of the <a> extend across the entire width of the header, which I would like to avoid.
Is it possible to have an automatically-sized width with a defined height when the viewBox is described in the <symbol> definition? Must I be relegated to using an <img> tag or an absolute width for the SVG element?
Unfortunately it is the dimensions of the <svg> element that appears in your <header> that is important. There is no way to inherit a viewBox from a child symbol reference.
You would need to copy the viewBox (width and height) from the symbol.
.Header-logo {
height: 5rem;
}
.Header-logo2 {
height: 8rem;
}
<svg class="SpriteSheet" width="0" height="0">
<symbol id="icon-logo" viewBox="-12 -79.61 407.19 108.36">
<path id="logo-upperLeft" d="M0-67.61l83.66 0 0-10 -93.66 0 0 30.92 10 0Z" transform="translate(-2 -2)"></path>
<path id="logo-upperRight" d="M383.19-67.61l-83.66 0 0-10 93.66 0 0 30.92 -10 0Z" transform="translate(2 -2)"></path>
<path id="logo-lowerLeft" d="M0 16.75l83.66 0 0 10 -93.66 0 0-30.92 10 0Z" transform="translate(-2 2)"></path>
<path id="logo-lowerRight" d="M383.19 16.75l-83.66 0 0 10 93.66 0 0-30.92 -10 0Z" transform="translate(2 2)"></path>
</symbol>
</svg>
<header class="Header">
<h1 class="Header-headline">
<a href="/">
<svg class="Header-logo" viewBox="0 0 407.19 108.36">
<use xlink:href="#icon-logo"></use>
</svg>
</a>
</h1>
</header>
<header class="Header">
<h1 class="Header-headline">
<a href="/">
<svg class="Header-logo2" viewBox="0 0 407.19 108.36">
<use xlink:href="#icon-logo"></use>
</svg>
</a>
</h1>
</header>
Related
How to use color to fill an SVG icon in tailwind css?
I am trying to figure out how to use a fill color in svg icons using tailwinds css. If i use fill="#hex color value" in the path, I can apply a color. I am trying to follow the tailwinds docs and use it's colors. I have tried as many variations on the below as I can find in various blog posts, but can't find a version that works. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="fill-blue-500"><path fill="none" d="M0 0h24v24H0z" /> <path d="M18 7h3a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h15v4zM4 9v10h16V9H4zm0-4v2h12V5H4zm11 8h3v2h-3v-2z" fill="fill-slate-200" // note: fill="#2d3047" works to change the icon color /> </svg> When I try: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="fill-current"><path fill="none" d="M0 0h24v24H0z" /> <path d="M18 7h3a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h15v4zM4 9v10h16V9H4zm0-4v2h12V5H4zm11 8h3v2h-3v-2z" /> </svg> And then try using it in a div: <div className="mx-auto max-w-2xl md:text-center"> <p className="text-center text-blue-700"> <Image src={company.logo} alt={company.name} unoptimized className="text-center mx-auto text-blue-700" /> </p> The text svg renders black. I am trying to force it to use blue. I have tried adding blue at every container level - but none of them feed through to the svg image container
You're trying to use a Tailwind class as the fill value. fill="fill-slate-200" Tailwind classes do not work outside of the class context. You have a class that is working in the fill-blue-500 on the SVG element itself so you can either carry on in that way or you can change it to fill-current and then it will adopt whatever the parent element's text color is which is helpful for things like changing color on hover. <div class="m-3 flex space-x-2 text-green-600 hover:text-red-600 cursor-default"> <svg viewBox="0 0 24 24" width="24" height="24" class="fill-current"> <path d="M18 7h3a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h15v4zM4 9v10h16V9H4zm0-4v2h12V5H4zm11 8h3v2h-3v-2z" /> </svg> <span>Wallet</span> </div> Here is this example on Tailwind Play https://play.tailwindcss.com/AINTKQdbZg
You are using your color in your path, that is one level deep from your parent div. So color is getting overridden by your path component. <svg class="fill-blue-500"> <path ... fill="none" /> 👈 This fill is overriding <path ... fill="fill-slate-200"/> 👈 your parent fill-blue-500 </svg> So you can't access its fill from parent class How to overcome ? Try using class of fill-blue-500 inside your path component <svg> <path ... class="fill-blue-500" d="M0 0h24v24H0z" /> 👈 use fill-blue-500 here <path ... class="fill-yellow-500" /> 👈 now you can use tailwind classes </svg> End Code: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100" class="m-10"> <path class="fill-blue-500" d="M0 0h24v24H0z" /> <path d="M18 7h3a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h15v4zM4 9v10h16V9H4zm0-4v2h12V5H4zm11 8h3v2h-3v-2z" class="fill-yellow-500" /> </svg> Output: Also refer: How to modify svg icon colors with Tailwind
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.
Any way to use SVG Sprite from CSS?
HTML: <svg> <use xlink:href="/assets/images/icons-sprite.svg#icon-name"></use> </svg> SVG sprite: <svg width="0" height="0" class="hidden"> <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="icon-name"> <path ... fill="currentColor"></path> </symbol> </svg> Is there any way to use SVG sprite from CSS Like this <div class=“icon”></div> .icon { background-image: “/assets/images/icons-sprite.svg#icon-name” height: 30px }
I’m using the technique for including SVGs described here whereby you create a doc that looks something like this… <svg xmlns="http://www.w3.org/2000/svg"> <symbol id="arrow-left" viewBox="0 0 10 16"> <path d="M9.4 1.4L8 0 0 8l8 8 1.4-1.4L2.8 8z"/> </symbol> <symbol id="arrow-right" viewBox="0 0 10 16"> <path d="M0 14.6L1.4 16l8-8-8-8L0 1.4 6.6 8z"/> </symbol> </svg> Include it in the top of your HTML and then insert the SVG icons in your markup like this… <svg class="arrow-right"> <use xlink:href="#arrow-right" /> </svg> It’s easy and works great. However, I’m trying to use the same icons in my CSS pseudo classes :before and :after using an empty content attribute and the SVG in the background. Something like this… .title:after { float: right; width: 16px; height: 10px; content: ""; background: url('#arrow-right'); }
Shrinking SVG to size
I've tried a bunch of different things, but can't figure out how to get this SVG twitter icon to shrink to 24x24 when it's wrapped in a link. I've tried viewbox, tried setting setting width/height, but can't seem to figure it out. In chrome, the below code produces a 24x24 container but the SVG itself is 400x400 so I only see the top left corner. Seems like I'm missing something obvious, but any help would be appreciated. <a class="twitter-share-button" href="https://twitter.com/intent/tweet"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24px" height="24px" viewBox="0 0 24 24"> <style type="text/css"> .st0{fill:#1DA1F2;} .st1{fill:#FFFFFF;} </style> <g id="Dark_Blue"> <path class="st0" d="M350,400H50c-27.6,0-50-22.4-50-50V50C0,22.4,22.4,0,50,0h300c27.6,0,50,22.4,50,50v300 C400,377.6,377.6,400,350,400z"/> </g> <g id="Logo__x2014__FIXED"> <path class="st1" d="M153.6,301.6c94.3,0,145.9-78.2,145.9-145.9c0-2.2,0-4.4-0.1-6.6c10-7.2,18.7-16.3,25.6-26.6 c-9.2,4.1-19.1,6.8-29.5,8.1c10.6-6.3,18.7-16.4,22.6-28.4c-9.9,5.9-20.9,10.1-32.6,12.4c-9.4-10-22.7-16.2-37.4-16.2 c-28.3,0-51.3,23-51.3,51.3c0,4,0.5,7.9,1.3,11.7c-42.6-2.1-80.4-22.6-105.7-53.6c-4.4,7.6-6.9,16.4-6.9,25.8 c0,17.8,9.1,33.5,22.8,42.7c-8.4-0.3-16.3-2.6-23.2-6.4c0,0.2,0,0.4,0,0.7c0,24.8,17.7,45.6,41.1,50.3c-4.3,1.2-8.8,1.8-13.5,1.8 c-3.3,0-6.5-0.3-9.6-0.9c6.5,20.4,25.5,35.2,47.9,35.6c-17.6,13.8-39.7,22-63.7,22c-4.1,0-8.2-0.2-12.2-0.7 C97.7,293.1,124.7,301.6,153.6,301.6"/> </g> </svg> </a>
SVG is all about the viewBox, this SVG should have a 400 x 400 viewbox <style> svg { width: 80px; height: 80px; background: lightcoral </style> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path fill="#1da1f2" d="M350,400H50c-27.6,0-50-22.4-50-50V50C0,22.4,22.4,0,50,0h300c27.6,0,50,22.4,50,50v300C400,377.6,377.6,400,350,400z"/> <path fill="white" d="M153.6,301.6c94.3,0,145.9-78.2,145.9-145.9c0-2.2,0-4.4-0.1-6.6c10-7.2,18.7-16.3,25.6-26.6c-9.2,4.1-19.1,6.8-29.5,8.1c10.6-6.3,18.7-16.4,22.6-28.4c-9.9,5.9-20.9,10.1-32.6,12.4c-9.4-10-22.7-16.2-37.4-16.2c-28.3,0-51.3,23-51.3,51.3c0,4,0.5,7.9,1.3,11.7c-42.6-2.1-80.4-22.6-105.7-53.6c-4.4,7.6-6.9,16.4-6.9,25.8c0,17.8,9.1,33.5,22.8,42.7c-8.4-0.3-16.3-2.6-23.2-6.4c0,0.2,0,0.4,0,0.7c0,24.8,17.7,45.6,41.1,50.3c-4.3,1.2-8.8,1.8-13.5,1.8c-3.3,0-6.5-0.3-9.6-0.9c6.5,20.4,25.5,35.2,47.9,35.6c-17.6,13.8-39.7,22-63.7,22c-4.1,0-8.2-0.2-12.2-0.7 C97.7,293.1,124.7,301.6,153.6,301.6"/> </svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400"> <path fill="#1da1f2" d="M350,400H50c-27.6,0-50-22.4-50-50V50C0,22.4,22.4,0,50,0h300c27.6,0,50,22.4,50,50v300C400,377.6,377.6,400,350,400z"/> <path fill="white" d="M153.6,301.6c94.3,0,145.9-78.2,145.9-145.9c0-2.2,0-4.4-0.1-6.6c10-7.2,18.7-16.3,25.6-26.6c-9.2,4.1-19.1,6.8-29.5,8.1c10.6-6.3,18.7-16.4,22.6-28.4c-9.9,5.9-20.9,10.1-32.6,12.4c-9.4-10-22.7-16.2-37.4-16.2c-28.3,0-51.3,23-51.3,51.3c0,4,0.5,7.9,1.3,11.7c-42.6-2.1-80.4-22.6-105.7-53.6c-4.4,7.6-6.9,16.4-6.9,25.8c0,17.8,9.1,33.5,22.8,42.7c-8.4-0.3-16.3-2.6-23.2-6.4c0,0.2,0,0.4,0,0.7c0,24.8,17.7,45.6,41.1,50.3c-4.3,1.2-8.8,1.8-13.5,1.8c-3.3,0-6.5-0.3-9.6-0.9c6.5,20.4,25.5,35.2,47.9,35.6c-17.6,13.8-39.7,22-63.7,22c-4.1,0-8.2-0.2-12.2-0.7 C97.7,293.1,124.7,301.6,153.6,301.6"/> </svg> Or optimized <style> svg { width:80px; height:80px; } </style> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"> <rect fill="#1da1f2" width='100%' height='100%' rx="15%"/> <path fill="white" d="M39 76c24 0 37-20 37-37c0-1 0-1 0-2c3-2 5-4 7-7 c-2 1-5 2-8 2c3-2 5-4 6-7c-3 2-5 3-8 3c-2-3-6-4-9-4c-7 0-13 6-13 13c0 1 0 2 0 3 c-11-1-20-6-27-14c-1 2-2 4-2 7c0 5 2 9 6 11c-2 0-4-1-6-2 c0 0 0 0 0 0c0 6 5 12 10 13c-1 0-2 1-4 1c-1 0-2 0-3 0c2 5 7 9 12 9 c-5 4-10 6-16 6c-1 0-2 0-3 0C25 73 31 76 39 76"/> </svg>
The viewport should be the size of the original content (400). Since you are using a small viewport (24), the image only shows a portion of the entire svg. Make the viewport 400 and then use height and width to get the size in which the svg will be presented. Note: Also you should remove the any px from the height and width. You this: <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 400 400">
Simple solution .twitter-share-button >svg{ height:24px; width:24px; }
Responsive clip-path with inline SVG
On an element with a background (image or solid color don't really matter): <header id="block-header"></header> I am trying to apply a clip-path using SVG. To achieve this, I am putting SVG inline into the same element like this: <header id="block-header"> … <svg width="100%" height="100%" viewBox="0 0 4000 1696" preserveAspectRatio="none"> <defs> <clipPath id="myClip"> <path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/> </clipPath> </defs> </svg> … </header> You can run the code snippet below or check the JSFiddle. You can see original SVG image (in black) put inline, having curviness along the bottom and being responsive. In contrast, the red rectangle shows the same image applied (or, rather, not applied) as a clip-path. I guess I misunderstand either viewBox or preserveAspectRatio attributes though can not find what is exactly wrong here. Any help would be appreciated. #block-header { background: Red; min-height: 100px; -webkit-clip-path: url(#myClip); clip-path: url(#myClip); } <h1>SVG image</h1> <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none"><path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/></svg> <h1><code>clip-path</code> using the same SVG</h1> <header id="block-header"> <svg width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none"> <defs> <clipPath id="myClip"> <path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/> </clipPath> </defs> </svg> </header>
References to SVG clip paths are to the clip path definitions themselves and the dimensions or other attributes of the <svg> are meaningless in this context. What is happening in your example is that you are applying a 4000 px wide clip path to your header. Which is probably only of the order of 900 px wide. So the curvature isn't visible. If you want a responsive clip path, you should define it using clipPathUnits="objectBoundingBox". #block-header { background: Red; min-height: 100px; -webkit-clip-path: url(#myClip); clip-path: url(#myClip); } <h1>SVG image</h1> <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 1 1" preserveAspectRatio="none"><path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/></svg> <h1><code>clip-path</code> using the same SVG</h1> <header id="block-header"> <svg width="0" height="0"> <defs> <clipPath id="myClip" clipPathUnits="objectBoundingBox"> <path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/> </clipPath> </defs> </svg> </header> Fiddle here