JSFiddle - React, Tailwind, and code Playground
by Jacob Ford
HTML
<table>
<tr><td colspan="2">In Safari 10.0.1 and iOS 10.1, strange behavior can be observed on SVG shapes with <code>rotate</code> values not divisible by 90 degrees, when <code>transform-origin: center center;</code></td></tr>
<tr>
<td>
<svg xmlns="http://www.w3.org/2000/svg">
<circle class="degrot" r="35" cy="40" cx="40" />
</svg>
</td>
<td>
<code>transform: rotate(-90deg);</code>
<p>The stroke improperly begins <a href="https://www.w3.org/TR/SVG11/shapes.html#CircleElement">at 3:00</a>, as if the <code>transform</code> rule hadn't been applied.</p>
</td>
</tr>
<tr>
<td>
<svg xmlns="http://www.w3.org/2000/svg">
<circle class="degrot-offset" r="35" cy="40" cx="40" />
</svg>
</td>
<td>
<code>transform: rotate(-90.1deg);</code>
<p>The stroke begins at (twelve seconds before) 12:00, as expected.</p>
</td>
</tr>
<tr>
<td>
<svg xmlns="http://www.w3.org/2000/svg">
<circle class="turnrot" r="35" cy="40" cx="40" />
</svg>
</td>
<td>
<code>transform: rotate(-0.25turn);</code>
<p>The same bug applies to any <code>rotate</code> value which computes to a multiple of 90 degrees.</p>
</td>
</tr>
<tr>
<td>
<svg xmlns="http://www.w3.org/2000/svg">
<circle class="turnrot-offset" r="35" cy="40" cx="40" />
</svg>
</td>
<td>
<code>transform: rotate(-0.251turn);</code>
<p>43 seconds before noon.</p>
</td>
</tr>
<tr><td colspan="2">But when the SVG element specifies a <code>viewBox</code> which is being scaled down, things can get weird:</td></tr>
<tr>
<td>
<svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg">
<circle class="degrot" r="70" cy="80" cx="80" />
</svg>
</td>
<td>
<code>transform: rotate(-90deg);</code>
<p>So far, so the same.</p>
</td>
</tr>
<tr>
<td>
<svg viewBox="0 0...
CSS
svg {
height: 80px;
width: 80px;
}
circle {
fill: none;
stroke-dasharray: 150;
stroke-width: 4px;
stroke: #6fdb6f;
transform-origin: center center;
}
.degrot {
transform: rotate(-90deg);
}
.degrot-offset {
transform: rotate(-90.1deg);
}
.degrot-offset-more {
transform: rotate(-92deg);
}
.turnrot {
transform: rotate(-0.25turn);
}
.turnrot-offset {
transform: rotate(-0.251turn);
}
svg[viewBox] circle {
stroke-dasharray: 300;
stroke-width: 8px;
}
svg[viewBox].scaledown circle {
stroke-dasharray: 300;
stroke-width: 8px;
}
svg[viewBox].noscale circle {
stroke-dasharray: 150;
stroke-width: 4px;
}
svg[viewBox].scaleup circle {
stroke-dasharray: 75;
stroke-width: 2px;
}
.wc {
will-change: transform;
}
/* Demo prettification */
p:last-child {
margin-bottom: 0;
}
td {
padding: 10px;
}
tr td:first-of-type {
width: 80px;
min-height: 80px;
}
tr + tr td {
border-top: 1px solid #dcdcdc;
}