Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

currentColor seems to get "stuck" in Safari

I'm trying to use CSS currentColor as a border-color to generate CSS triangles using :after content. This works great in all browsers I've tried, except one: Safari seems to be caching the currentColor from the first triangle it generates, and then using that everywhere.

Here's what I'm seeing -- expected behavior from Chrome (and Firefox, and IE9+):

Chrome screenshot

Incorrect behavior from Safari 8.0.4 on Yosemite 10.10.2 (same on iOS 8.2) -- notice all three triangles are red, not the currentColor of their elements:

Safari screenshot

Here's a fiddle with the full code demonstrating the problem. The relevant CSS:

span {
    display: inline-block;
    border-bottom: 2px solid currentColor;
}

span::after {
    /* Generate a triangle (based on Foundation's css-triangle mixin) */
    content:"";
    display: inline-block;
    width: 0;
    height: 0;
    border: inset 0.4em;
    /* Safari seems to cache this currentColor... */
    border-color: currentColor transparent transparent transparent;
    border-top-style: solid;
}

.red { color: #c00; }
.blue { color: #009; }

The HTML is simple:

<div>
    <span class="red">Red</span>
    <span>Default</span>
    <span class="blue">Blue</span>
</div>

Is this a bug in Safari? A matter of interpretation on the CSS spec?

More importantly, any suggestions for working around this? I'd hate to have to explicitly declare the color in separate :after rules for each element. (Using currentColor really simplifies maintenance as our other CSS changes.)

like image 254
medmunds Avatar asked Apr 01 '15 20:04

medmunds


2 Answers

So, this turns out to be an actual Safari bug (which might be fixed soon).

I was able to work around it using this suggestion that border-color defaults to currentColor. Replace this:

    border-color: currentColor transparent transparent transparent;

with expanded properties that avoid mentioning currentColor:

    /* border-top-color: currentColor; is the default behavior */
    border-right-color: transparent;
    border-bottom-color: transparent;
    border-left-color: transparent;

and the problem goes away in Safari (and it still works in the other browsers).

like image 66
medmunds Avatar answered Nov 10 '22 20:11

medmunds


Even I faced a similar issue, so i have to go with a small js trick.

With this trick we can use the currentColor attribute to be set correctly in the desired elements. but it can be achieved only for normal elements. so i moved the pseudo elements into normal elements.

You have to force safari to redraw elements to achieve this. To achieve redrawing elements simply hide and show it.

var nodeStack =[element];
while (node = nodeStack.pop()) {
    if (node.nodeType == 1) {
        node.style.display="none";
        node.style.display="";
        var i = node.childNodes.length;
        while (i--) {
            nodeStack.push(node.childNodes[i]);
        }
    }
}

Check this simple codepen (Your code with little modification)

and also read this for brief info

Pseudo elements cannot be achieved through this trick. You have to move that into a span or some other element.

like image 39
Prasanna Rkv Avatar answered Nov 10 '22 19:11

Prasanna Rkv