IE and Edge ignore absolute position of svg [duplicate] - css

I decided to switch to svg symbols for one of my projects - but need them to be responsive. The main idea is not to have multiple http requests, so I was thinking of merging all SVGs into one SVG, define symbols and use them as follows:
<svg style="display:none;">
<defs>
<symbol id="mys">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#3F77BC" d="M222.1,77.7h-10.3c0.1-0.8,0.2-1.4,0.2-2.3
c0-8.5-6.9-15.4-15.4-15.4c-8.5,0-15.4,6.9-15.4,15.4c0,0.9,0.1,1.5,0.2,2.3h-9.3v4h-24.9v-5.2H89.4c0-0.3,0-0.6,0-0.9
C89.4,67.1,82.5,60,74,60s-15.4,6.9-15.4,15.4c0,0.3,0,0.6,0,0.9h-6.2V60.7h4.3l5.3-5.3h22.8L74.3,44.9l-13.5-3.6l0.5-1.7
l-16.5-4.4c-0.3,0.1-0.7,0.2-1,0.2l0,21.4h2v7.2c0,0-2,0.6-1.9,1.3c0.1,0.7,4.1,2.6,3.4,5.5c-0.6,2.9-1.6,4.8-4.4,4.5
c-2.7-0.3-3.4-1.4-3.4-2.6c-0.1-1.2,0-3,0-3L38,67.9c0,0,2-0.5,2.6,1.1c0.6,1.5-0.2,2.7,0.6,3.5c0.8,0.8,4.1,1.4,4.1-1.1
c0-2.5-0.5-2.4-2.1-3.6c-1.7-1.2-3.4-2.8-3.4-3.3c0-0.5-0.1-7.7-0.1-7.7h2.1l0-21.7c-1.4-0.7-2.5-2.1-2.5-3.8
c0-2.3,1.9-4.2,4.2-4.2c2,0,3.6,1.4,4.1,3.2l15.3,4.1l0.4-1.6l55.8,15.1h28.1c0,0,0-23.5,0-26.2c0-2.7,2.1-2.6,2.1-2.6
s32.5-0.5,35.1,0.5c2.7,1,3.3,3.7,3.3,3.7h-2l5,11.6c0,0,7.3,4.6,17.6,7.6c10.3,3,13.6,7.6,13.6,7.6l-1,17.6l1.3,2V77.7z
M81.5,46.8l8.6,8.6h9.3l2.9-2.9L81.5,46.8z M175.5,25l-17.4-0.1v12.6h9.6l2.7,2.7h6.6L175.5,25z M183,23.7h-4c0,0,2,6.6,3,9.9
s0.9,4.2,2.7,4.2c1.9,0,4.2,0,4.2,0L183,23.7z M74.2,63.8c6.8,0,12.3,5.5,12.3,12.3S81,88.4,74.2,88.4c-6.8,0-12.3-5.5-12.3-12.3
S67.4,63.8,74.2,63.8z M196.6,63.8c6.8,0,12.3,5.5,12.3,12.3s-5.5,12.3-12.3,12.3s-12.3-5.5-12.3-12.3S189.8,63.8,196.6,63.8z"/>
</symbol>
</defs>
</svg>
<div style="position:relative;width:100%;background:blue;">
<svg class="mys" viewBox="0 0 254 108" preserveAspectRatio="xMaxYMax meet" style="width:100%;">
<use xlink:href="#mys"></use>
<svg>
</div>
Here is a jsfiddle, check the different behaviour in IE (I checked 11 but read that 9 has multiple issues as well):
http://jsfiddle.net/ws472q71/
For the life of me I can't get this to work properly. The above code works correctly in Firefox and Chrome, but fails in IE. I read about IE issues, but I couldn't find anything that works.
What am I doing wrong?
Is there any other similar solution that can merge SVGs into one file and use them as responsive images?
Thanks!

As you have discovered, IE has a bug where it doesn't scale the SVG properly if you don't provide both the width and height.
To get it working in IE, you can use a trick discovered (?) by Nicolas Gallagher.
http://nicolasgallagher.com/canvas-fix-svg-scaling-in-internet-explorer/
The trick uses a <canvas> element. IE does properly scale canvas elements. So if you place one in the <div> with the SVG, the SVG will end up the correct size. You just need to give the canvas the same aspect ratio as your SVG.
<div style="position:relative;width:100%;background:blue;">
<canvas width="254" height="108"></canvas>
<svg class="mys" viewBox="0 0 254 108" preserveAspectRatio="xMaxYMax meet">
<use xlink:href="#mys"></use>
</svg>
</div>
with CSS
canvas {
display: block;
width: 100%;
visibility: hidden;
}
svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
canvas {
display: block;
width: 100%;
visibility: hidden;
}
svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
<svg style="display:none;">
<defs>
<symbol id="mys">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#3F77BC" d="M222.1,77.7h-10.3c0.1-0.8,0.2-1.4,0.2-2.3
c0-8.5-6.9-15.4-15.4-15.4c-8.5,0-15.4,6.9-15.4,15.4c0,0.9,0.1,1.5,0.2,2.3h-9.3v4h-24.9v-5.2H89.4c0-0.3,0-0.6,0-0.9
C89.4,67.1,82.5,60,74,60s-15.4,6.9-15.4,15.4c0,0.3,0,0.6,0,0.9h-6.2V60.7h4.3l5.3-5.3h22.8L74.3,44.9l-13.5-3.6l0.5-1.7
l-16.5-4.4c-0.3,0.1-0.7,0.2-1,0.2l0,21.4h2v7.2c0,0-2,0.6-1.9,1.3c0.1,0.7,4.1,2.6,3.4,5.5c-0.6,2.9-1.6,4.8-4.4,4.5
c-2.7-0.3-3.4-1.4-3.4-2.6c-0.1-1.2,0-3,0-3L38,67.9c0,0,2-0.5,2.6,1.1c0.6,1.5-0.2,2.7,0.6,3.5c0.8,0.8,4.1,1.4,4.1-1.1
c0-2.5-0.5-2.4-2.1-3.6c-1.7-1.2-3.4-2.8-3.4-3.3c0-0.5-0.1-7.7-0.1-7.7h2.1l0-21.7c-1.4-0.7-2.5-2.1-2.5-3.8
c0-2.3,1.9-4.2,4.2-4.2c2,0,3.6,1.4,4.1,3.2l15.3,4.1l0.4-1.6l55.8,15.1h28.1c0,0,0-23.5,0-26.2c0-2.7,2.1-2.6,2.1-2.6
s32.5-0.5,35.1,0.5c2.7,1,3.3,3.7,3.3,3.7h-2l5,11.6c0,0,7.3,4.6,17.6,7.6c10.3,3,13.6,7.6,13.6,7.6l-1,17.6l1.3,2V77.7z
M81.5,46.8l8.6,8.6h9.3l2.9-2.9L81.5,46.8z M175.5,25l-17.4-0.1v12.6h9.6l2.7,2.7h6.6L175.5,25z M183,23.7h-4c0,0,2,6.6,3,9.9
s0.9,4.2,2.7,4.2c1.9,0,4.2,0,4.2,0L183,23.7z M74.2,63.8c6.8,0,12.3,5.5,12.3,12.3S81,88.4,74.2,88.4c-6.8,0-12.3-5.5-12.3-12.3
S67.4,63.8,74.2,63.8z M196.6,63.8c6.8,0,12.3,5.5,12.3,12.3s-5.5,12.3-12.3,12.3s-12.3-5.5-12.3-12.3S189.8,63.8,196.6,63.8z"/>
</symbol>
</defs>
</svg>
<div style="position:relative;width:100%;background:blue;">
<canvas width="254" height="108"></canvas>
<svg class="mys" viewBox="0 0 254 108" preserveAspectRatio="xMaxYMax meet">
<use xlink:href="#mys"></use>
</svg>
</div>
The trick works whether you are trying to get it to match a width or a height.

On a side note to help anyone struggling to implement this fix or finding its not working with external svg files rather than in-page svg markup
You need to ensure that when editing your svg file in a text editor it is not missing viewBox or preserveAspectRatio attributes in the opening <svg> tag. If these are missing regardless of what fixes you apply the svg will still not scale in IE - even though it'll scale in other browsers without issue.
If these options are set you can define the width/height on the image element used to pull in the svg to 100% and use max-width or max-height to limit the scaling and it will perform as expected. Though - you could still get some alignment issues.

Nicolas Gallagher's solution works great, however, I ran into some responsive issues as I decreased the viewport. I thought I would pass along the fix I used:
<div class="parent-div">
<canvas width="3" height="1"></canvas>
<svg class="mys" viewBox="0 0 254 108">
<use xlink:href="#mys"></use>
</svg>
</div>
I updated the "parent-div" with max-width:100%;
.parent-div{
position: relative;
display: inline-block;
height: 550px;
max-width: 100%;
}
This will not solve all your scaling issues. You will still have to use media queries to change the height as you go, but at least the svg doesn't blow out its container. Hope this helps someone.

This can be rewritten like so if you're working with <img>
HTML
<div class="ie-svgHeight">
<img src="path.svg" class="ie-svgHeight-img">
<canvas class="ie-svgHeight-canvas"></canvas>
</div>
SCSS
.ie-svgHeight {
position: relative;
&-canvas {
display: block;
visibility: hidden;
position: absolute;
top: 0;
left: 0;
height: 100%;
}
&-img { height: 100%; }
}

Related

How to make an element of such a complex shape? [duplicate]

So I'm working on a site and I was wondering if it's possible to, purely using HTML5, CSS3 (and JavaScript if needed), make a div with a curved bottom, so it will look practically like this:
Or can this only be done using a background image?
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<ul class="nav">
<li>Home</li>
</ul>
</div>
</div>
</body>
There are different approaches that can be adopted to create this shape. Below is a detailed description of possibilities:
SVG Based Approaches:
SVG is the recommended way to create such shapes. It offers simplicity and scale-ability. Below are a couple of possible ways:
1- Using Path Element:
We can use SVG's path element to create this shape and fill it with some solid color, gradient or a pattern.
Only one attribute d is used to define shapes in path element. This attribute itself contains a number of short commands and few parameters that are necessary for those commands to work.
Below is the necessary code to create this shape:
<path d="M 0,0
L 0,40
Q 250,80 500,40
L 500,0
Z" />
Below is a brief description of path commands used in above code:
M command is used to define the starting point. It appears at the beginning and specify the point from where drawing should start.
L command is used to draw straight lines.
Q command is used to draw curves.
Z command is used to close the current path.
Output Image:
Working Demo:
svg {
width: 100%;
}
<svg width="500" height="80" viewBox="0 0 500 80" preserveAspectRatio="none">
<path d="M0,0 L0,40 Q250,80 500,40 L500,0 Z" fill="black" />
</svg>
2- Clipping:
Clipping means removing or hiding some parts of an element.
In this approach, we define a clipping region by using SVG's clipPath element and apply this to a rectangular element. Any area that is outside the clipping region will be hidden.
Below is the necessary code:
<defs>
<clipPath id="shape">
<path d="M0,0 L0,40 Q250,80 500,40 L500,0 Z" />
</clipPath>
</defs>
<rect x="0" y="0" width="500" height="80" fill="#000" clip-path="url(#shape)" />
Below is brief description of the elements used in above code:
defs element is used to define element / objects for later use in SVG document.
clipPath element is used to define a clipping region.
rect element is used to create rectangles.
clip-path attribute is used to link the clipping path created earlier.
Working Demo:
svg {
width: 100%;
}
<svg width="500" height="80" viewBox="0 0 500 80" preserveAspectRatio="none">
<defs>
<clipPath id="shape">
<path d="M0,0 L0,40 Q250,80 500,40 L500,0 Z" />
</clipPath>
</defs>
<rect x="0" y="0" width="500" height="80" fill="#000" clip-path="url(#shape)" />
</svg>
CSS Based Approaches:
1- Using Pseudo Element:
We can use ::before or ::after pseudo element to create this shape. Steps to create this are given below:
Create a layer with ::before OR ::after pseudo element having width and height more than its parent.
Add border-radius to create the rounded shape.
Add overflow: hidden on parent to hide the unnecessary part.
Required HTML:
All we need is a single div element possibly having some class like shape:
<div class="shape"></div>
Working Demo:
.shape {
position: relative;
overflow: hidden;
height: 80px;
}
.shape::before {
border-radius: 100%;
position: absolute;
background: black;
right: -200px;
left: -200px;
top: -200px;
content: '';
bottom: 0;
}
<div class="shape"></div>
2- Radial Gradient:
In this approach we will use CSS3's radial-gradient() function to draw this shape on the element as a background. However, this approach doesn't produce very sharp image and it might have some jagged corners.
Required HTML:
Only single div element with some class will be required i.e.
<div class="shape"></div>
Necessary CSS:
.shape {
background-image: radial-gradient(120% 120px at 50% -30px, #000 75%, transparent 75%);
}
Working Demo:
.shape {
background: radial-gradient(120% 120px at 50% -30px, #000 75%, transparent 75%) no-repeat;
height: 80px;
}
<div class="shape"></div>
JavaScript Based Approaches:
Although not required in this case but for the sake of completeness, I'm adding this approach as well. This can be useful in some cases as well:
HTML5 Canvas:
We can draw this shape on HTML5 Canvas element using path functions:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, 40);
ctx.quadraticCurveTo(311, 80, 622, 40);
ctx.lineTo(622, 0);
ctx.fill();
<canvas id="canvas" width="622" height="80"></canvas>
Below is a brief description of the methods used in above code:
beginPath() is used to create a new path. Once a new path is created, future drawing commands are directed into the path.
moveTo(x, y) moves the pen to the coordinates specified by x and y.
lineTo(x, y) draws a straight line from the current pen position to the point specified by x and y.
quadraticCurveTo(cp1x, cp1y, x, y) draws a curve from current pen position to the point specified by x and y using control point specified by cp1x and cp1y.
fill() fills the current path using non-zero or even-odd winding rule.
Useful Resources:
Radial Gradient: Specs, MDN
SVG: Specs, MDN
HTML5 Canvas: Specs, MDN
CSS:
div{
background-color:black;
width:500px;
height:50px;
border-bottom-left-radius:50%;
border-bottom-right-radius:50%;
}
see is this ok for you
div {
background-color: black;
width: 500px;
height: 50px;
border-bottom-left-radius: 50%;
border-bottom-right-radius: 50%;
}
<div>
</div>
This is what you want:
div{
background-color: black;
width: 500px;
height: 300px;
border-radius: 0 0 50% 50% / 50px;
}
Unlike the accepted answer, this works even when the height of the div is increased.
Demo: jsFiddle
Yes, you can do this in CSS - basically make your div wider than the page to fix the too-rounded edges, then left-positioned to compensate, with bottom border radius using both x & y values, and negative bottom margin to compensate for the gap:
.round-bottom {
border-bottom-left-radius: 50% 200px; // across half & up 200px at left edge
border-bottom-right-radius: 50% 200px; // across half & up 200px at right edge
width: 160%; overflow: hidden; // make larger, hide side bits
margin-bottom: -50px; // apply negative margin to compensate for bottom gap
position: relative; left:-30%; // re-position whole element so extra is on each side (you may need to add display:block;)
}
.round-bottom {
border-bottom-left-radius: 50% 150px !important;
border-bottom-right-radius: 50% 150px !important;
position: relative;
overflow: hidden;
width: 160%;
margin-bottom:-50px;
left:-30%;
background-color:#444;
background-image: url('https://upload.wikimedia.org/wikipedia/commons/a/a2/Tropical_Forest_with_Monkeys_A10893.jpg'); background-position: center center;
background-size: 42% auto;
height:150px;
}
.container { width: 100%; height: height:100px; padding-bottom:50px; overflow:hidden;}
<div class="container"><div class="round-bottom"></div></div>
Try this
.navbar{
border-radius:50% 50% 0 0;
-webkit-border-radius:50% 50% 0 0;
background:#000;
min-height:100px;
}
jsFiddle File

How to display icon from svg sprite in pseudo element with ruby on rails

I want to create a menu like this Home > where the right arrow is an icon in an svg sprite. I would like to place the > as a psuedo element in the css selector so that i can make any menu have the right arrow just by adding the css selector .menu-arrow. I am trying to do this in ruby on rails 6 with no success.
I have tried adding the svg icon sprite as a background content but it doesn't seem to work correctly.
My svg sprite
path to svg sprite: app/assets/images/sprites.svg
<svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-check-solid" viewBox="0 0 32 32">
<path d="M10.869 27.463l-10.4-10.4c-0.625-0.625-0.625-1.638 0-2.263l2.263-2.263c0.625-0.625 1.638-0.625 2.263 0l7.006 7.006 15.006-15.006c0.625-0.625 1.638-0.625 2.263 0l2.263 2.263c0.625 0.625 0.625 1.638 0 2.263l-18.4 18.4c-0.625 0.625-1.638 0.625-2.263-0z"></path>
</symbol>
<symbol id="icon-chevron-down-solid" viewBox="0 0 28 32">
<path d="M12.939 23.842l-12.146-12.146c-0.586-0.586-0.586-1.536 0-2.121l1.417-1.417c0.585-0.585 1.533-0.586 2.119-0.002l9.672 9.626 9.672-9.626c0.586-0.583 1.534-0.582 2.119 0.002l1.417 1.417c0.586 0.586 0.586 1.536 0 2.121l-12.146 12.146c-0.586 0.586-1.536 0.586-2.121 0z"></path>
</symbol>
</defs>
</svg>`
My css class
.menu-arrow {
&::after {
content: '';
display: inline-block;
height: 2rem;
width: 2rem;
background-image: asset-url("images/sprites.svg#icon-chevron-down-solid");
transform: rotate(90deg) scale(1.5);
fill: var(--color-white);
color: var(--color-white);
font-weight: 700;
border: 1px solid red;
}
}
}
How do i make this work?
This article suggests the #id in the CSS url is referencing a view rather than a symbol
You can certainly use your sprite as an inline SVG (shadow) DOM element via use, and make a helper to streamline the process (see this)
For your chevron specifically, you can achieve an almost identical graphic element using your pseudo element without a background (borders on two sides with rounded corners and rotated 45deg). I made a pen here that demonstrates this approach

CSS "filter" property does not work on Safari when using inline SVG in CSS like 'filter: url(data:image, ...)'

[EDIT] I've reviewed my entire post to add precisions about the problem and for additional ressources.
...
I'm new to SVG usage for webdesign, but I intend to implement a cool CSS feature for a theme. For information, I work with SASS to compile my styles.
What I want to achieve is to obtain a configurable theme that can change of color simply by changing some vars in my SASS files.
To do so :
I use "uncolored" SVGs as background for some elements of my website.
Then I apply a SVG filter for those elements to "colorize" them.
At this point, I'm pretty happy, because it is working... on almost all browsers : Brave, Chrome, Firefox, Opera, Edge
But it doesn't work on Safari and I'm not sure Why :
it seems that I cannot use the CSS filter with value url('data:image/svg+xml, <svg>...</svg>')
However it seems that I can use the filter property with url value if I'm targeting an element already in the DOM.
I've found an interesting article that talk about the same problem :
https://www.stefanjudis.com/today-i-learned/svgs-filters-can-be-inlined-in-css/#til%3A-svg-filters-can-be-inlined-in-css
I tested the included examples in Firefox 84 and and Chrome 87. It worked in Safari 14 but stopped for unknown reason.
The "included example" being inline SVG in the CSS
Do someone know if using inline CSS SVG is possible with Safari ?
Here is an example to illustrate the problem:
/* Basic style for parent */
.parent {
border: 3px dotted violet;
background: pink;
width: 400px;
height: 50px;
margin-bottom: 30px;
position: relative;
}
/* Basic style for children */
.children {
text-align: center;
color: #ffffff;
line-height: 40px;
}
.children::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Using a pseudo element inside childrens that carry the background image */
.v0 .children::after, .v1 .children::after{
background-image: url('https://public.xspawn.fr/svg-bg-btn.svg');
background-repeat: no-repeat;
background-size: 100% 100%;
}
/*Creating a new stack context to be able to display text*/
.parent{position: relative; z-index:0;}
.children::after{ z-index:-1;}
/* Applying a filter to each children 'after' pseudo element to colorize its content (the SVG background or the background color) */
.children.recolor::after{
filter : url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg"><filter id="recolor" color-interpolation-filters="sRGB"><feColorMatrix type="matrix" values="0 0 0 0 .13725 0 0 0 0 .23137 0 0 0 0 .32157 0 0 0 1 0"/></filter></svg>#recolor');
);
}
.children.recolor2::after{
filter : url('#dom-filter');
}
[v0] Element without Without SVG filter
<div class="parent v0">
<div class="children">No filter</div>
</div>
<strong style='color:orangered;'>[v1] KO : Filtered with "filter: url(data:image... )"</strong>
<div class="parent v1">
<div class="children recolor">filter: url(data:image..., < svg > .. .< svg \> )</div>
</div>
<strong style='color:green;'>[v2] OK : Filtered with filter DOM SVG and "filter: url('#elementid')"</strong>
<div class="parent v1">
<div class="children recolor2">filter: url('#dom-filter')</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg"><filter id="dom-filter" color-interpolation-filters="sRGB"><feColorMatrix type="matrix" values="0 0 0 0 .13725 0 0 0 0 .23137 0 0 0 0 .32157 0 0 0 1 0"/></filter></svg>
Question: "Do someone know if using inline CSS SVG is possible with Safari ?"
Answer: "Yes it is possible".
If you use filters on svg elements in css/scss file like this
filter: url(#filter_id);
Transfer the styles from the css/scss file into the svg file separately into styles, and everything will work, like this:
<svg>
...
<g filter="url(#filter)">
..
</g>
<filter id="filter" x="5.54736" y="0" width={width-11.3} height="80.0002" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood floodOpacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="10" result="effect1_foregroundBlur_326_868"/>
</filter>
</svg>

How to apply clipPath to a div with the clipPath position being relative to the div position

Not sure if I've formulated the title properly, but here goes the question.
I have an SVG path of a cloud-like shape which I would like to use in CSS with the clip-path property.
<path d="M46.9819755,61.8637972 C42.0075109,66.8848566 35.0759468,70 27.4091794,70 C12.2715076,70 0,57.8557238 0,42.875 C0,32.9452436 5.3914988,24.2616832 13.4354963,19.534921 C14.8172134,8.52285244 24.3072531,0 35.8087666,0 C43.9305035,0 51.0492374,4.2498423 55.01819,10.6250065 C58.2376107,8.87215568 61.9363599,7.875 65.8704472,7.875 C78.322403,7.875 88.4167076,17.8646465 88.4167076,30.1875 C88.4167076,32.1602271 88.1580127,34.0731592 87.6723639,35.8948845 L87.6723639,35.8948845 C93.3534903,38.685457 97.2583784,44.4851888 97.2583784,51.1875 C97.2583784,60.6108585 89.5392042,68.25 80.0171204,68.25 C75.4841931,68.25 71.3598367,66.5188366 68.2822969,63.6881381 C65.5613034,65.4654463 62.3012892,66.5 58.7971106,66.5 C54.2246352,66.5 50.0678912,64.7384974 46.9819755,61.8637972 Z" fill="lightblue" />
When I add an SVG element in HTML and define <clipPath> with that path, the browser positions the clipping path in the top-left corner. If I apply a margin to the clipped element, the mask is not linked and stays in its initial position.
Other similar threads state that the clipPathUnits="objectBoundingBox" attribute should be added to the <clipPath> object, but that doesn't seem to solve my problem. I even transformed the path from absolute to relative and tried it like that, but got the same result.
Is it possible to somehow link the clipping path with the clipped element so that when positioning is applied to the clipped element, the clipping path moves as well?
Here is the relative path, if it helps:
<path d="M46.9819755,61.8637972c-4.974,5.021,-11.906,8.136,-19.573,8.136c-15.137,0,-27.409,-12.144,-27.409,-27.125c0,-9.93,5.392,-18.613,13.436,-23.34c1.381,-11.012,10.871,-19.535,22.373,-19.535c8.122,0,15.24,4.25,19.209,10.625c3.22,-1.753,6.918,-2.75,10.852,-2.75c12.452,0,22.547,9.99,22.547,22.313c0,1.972,-0.259,3.885,-0.745,5.707l0,0c5.682,2.791,9.586,8.59,9.586,15.293c0,9.423,-7.719,17.062,-17.241,17.062c-4.533,0,-8.657,-1.731,-11.735,-4.562c-2.721,1.778,-5.981,2.812,-9.485,2.812c-4.572,0,-8.729,-1.761,-11.815,-4.636z fill="lightblue" />
As well as some test HTML/CSS. (I've set the left property to 10px so that you see the clipping issue occur)
.clippedElement {
width: 200px;
height: 200px;
position: absolute;
left: 10px;
top: 0;
background-color: lightblue;
-webkit-clip-path: url(#cloudClip);
-moz-clip-path: url(#cloudClip);
clip-path: url(#cloudClip);
}
<svg>
<defs>
<clipPath id="cloudClip">
<path d="M46.9819755,61.8637972 C42.0075109,66.8848566 35.0759468,70 27.4091794,70 C12.2715076,70 0,57.8557238 0,42.875 C0,32.9452436 5.3914988,24.2616832 13.4354963,19.534921 C14.8172134,8.52285244 24.3072531,0 35.8087666,0 C43.9305035,0 51.0492374,4.2498423 55.01819,10.6250065 C58.2376107,8.87215568 61.9363599,7.875 65.8704472,7.875 C78.322403,7.875 88.4167076,17.8646465 88.4167076,30.1875 C88.4167076,32.1602271 88.1580127,34.0731592 87.6723639,35.8948845 L87.6723639,35.8948845 C93.3534903,38.685457 97.2583784,44.4851888 97.2583784,51.1875 C97.2583784,60.6108585 89.5392042,68.25 80.0171204,68.25 C75.4841931,68.25 71.3598367,66.5188366 68.2822969,63.6881381 C65.5613034,65.4654463 62.3012892,66.5 58.7971106,66.5 C54.2246352,66.5 50.0678912,64.7384974 46.9819755,61.8637972 Z"
/>
</clipPath>
</defs>
</svg>
<div class="clippedElement"></div>
Thanks to Robert's comment, I was able to solve the issue I had.
Here is a PHP snippet I used to convert the absolute path to relative, so that the values are between 0 and 1.
$absolute_path = "M46.9819755,61.8637972 C42.0075109,66.8848566 35.0759468,70 27.4091794,70 C12.2715076,70 0,57.8557238 0,42.875 C0,32.9452436 5.3914988,24.2616832 13.4354963,19.534921 C14.8172134,8.52285244 24.3072531,0 35.8087666,0 C43.9305035,0 51.0492374,4.2498423 55.01819,10.6250065 C58.2376107,8.87215568 61.9363599,7.875 65.8704472,7.875 C78.322403,7.875 88.4167076,17.8646465 88.4167076,30.1875 C88.4167076,32.1602271 88.1580127,34.0731592 87.6723639,35.8948845 L87.6723639,35.8948845 C93.3534903,38.685457 97.2583784,44.4851888 97.2583784,51.1875 C97.2583784,60.6108585 89.5392042,68.25 80.0171204,68.25 C75.4841931,68.25 71.3598367,66.5188366 68.2822969,63.6881381 C65.5613034,65.4654463 62.3012892,66.5 58.7971106,66.5 C54.2246352,66.5 50.0678912,64.7384974 46.9819755,61.8637972 Z";
function regex_callback($matches) {
static $count = -1;
$count++;
$width = 98;
$height = 70;
if($count % 2) {
return $matches[0] / $height;
} else {
return $matches[0] / $width;
}
}
$relative_path = preg_replace_callback('(\d+(\.\d+)?)', 'regex_callback', $absolute_path);
Since the clipping path is not rectangular, I couldn't divide the values with one number, but had to use the width and the height of the clipping path itself.
.clippedElement {
width: 98px;
height: 70px;
position: absolute;
left: 10px;
top: 0;
background-color: lightblue;
-webkit-clip-path: url(#cloudClip);
-moz-clip-path: url(#cloudClip);
clip-path: url(#cloudClip);
}
<svg width="98" height="70">
<defs>
<clipPath id="cloudClip" clipPathUnits="objectBoundingBox">
<path d="M0.47940791326531,0.88376853142857 C0.42864807040816,0.95549795142857 0.3579178244898,1 0.27968550408163,1 C0.12521946530612,1 0,0.82651034 0,0.6125 C0,0.47064633714286 0.055015293877551,0.34659547428571 0.13709690102041,0.2790703 C0.15119605510204,0.12175503485714 0.24803319489796,0 0.36539557755102,0 C0.44827044387755,0 0.52091058571429,0.060712032857143 0.56141010204082,0.15178580714286 C0.59426133367347,0.12674508114286 0.63200367244898,0.1125 0.67214742040816,0.1125 C0.79920819387755,0.1125 0.90221130204082,0.25520923571429 0.90221130204082,0.43125 C0.90221130204082,0.45943181571429 0.89957155816327,0.48675941714286 0.89461595816327,0.51278406428571 L0.89461595816327,0.51278406428571 C0.95258663571429,0.55264938571429 0.99243243265306,0.63550269714286 0.99243243265306,0.73125 C0.99243243265306,0.86586940714286 0.91366534897959,0.975 0.81650122857143,0.975 C0.77024686836735,0.975 0.72816159897959,0.95026909428571 0.69675813163265,0.90983054428571 C0.66899289183673,0.93522066142857 0.63572744081633,0.95 0.59997051632653,0.95 C0.55331260408163,0.95 0.51089684897959,0.92483567714286 0.47940791326531,0.88376853142857 Z"></path>
</clipPath>
</defs>
</svg>
<div class="clippedElement"></div>

Problem with IE overflow: auto; and Raphael canvas being loaded into a DIV

I'm trying to place a Raphael canvas in to a div which is smaller than the actual canvas. So basically I have something like this:
var paper = Raphael("test", 2000, 2000);
var a = paper.rect(0, 0, 2000, 2000).attr({fill: "#000"});
//
<div id="test" style="width: 500px; height: 500px; overflow: auto;"></div>
Seems simple enough? Most browsers have no problem with this but IE7 forces the whole 2000x2000 rectangle on screen ignoring the whole div constraints.
I tried placing the div within another div like so:
<div id="ieholder" style="width: 500px; height: 500px; overflow: auto;">
<div id="test" style="width: 2000px; height:2000px;"></div>
</div>
But no luck, same thing happened. Is there a way around this? This
whole thing is already a compromise as I use raphael-zpd to give users
zoom and pan functionality but as it doesn't work on IE I thought I'd
just give IE users the image with basic pan functionality but no! Damn
you IE!
http://jsfiddle.net/WdwGQ/
<div id="ieholder" style="width: 500px; height: 500px; overflow: auto;">
<div id="map" style="width: 2132px; height: 2872px;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="2000" height="2000">
<desc>Created with Raphaël</desc>
<defs>
<rect x="0" y="0" width="2000" height="2000" r="0" rx="0" ry="0" fill="#000000" stroke="#000">
</svg>
</div>
</div>
Prompt your users to use Google's Chrome Frame, which embeds Chrome's rendering engine in IE?
Alternatively, prompt them to use a better browser?
That's not really a solution to the underlying problem, but it would make the underlying problem irrelevant. There may or may not be a way of getting IE7 to do what you want. I have often found there isn't...
This post provides the answer:
IE7 CSS Scrolling Div Bug
Making the outer <div> (the one with the overflow:auto style) position:relative sorts it out.

Resources