Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS - Change specific box-shadow in box-shadows list

How can we override one specific value and preserve all other values in box-shadow list like this:

div{

    box-shadow: 0 0 0 5px #00ff00 ,  0 0 0 10px #ff0000 ,  0 0 0 15px #0000ff ; 

}

Let's say we want to override only the second value without losing others:

div.with-another-shadow{

    box-shadow:       ???         ,  0 0 0 5px #abcdef ,       ???           ;  

}

Seems like it is possible only when we are copy-pasting the first and the third values too. It is not working not with auto and not with inherit.

Is it possible to achieve this only with css or we need to use jQuery or JavaScript' getComputedStyle method or something ?

Here is the playground: http://jsfiddle.net/cherniv/uspTj/5/

P.S. Seems like it is relevant to multiple background images list too..

like image 592
Ivan Chernykh Avatar asked Sep 09 '13 06:09

Ivan Chernykh


2 Answers

This is not a real solution to the general case, but a trick to solve the particular case of your fiddle:

div{
    box-shadow: 0 0 0 5px green,  0 0 0 10px #ff0000 ,  0 0 0 15px blue;    
    position: relative;
}

div:nth-of-type(2):after {
    content: '';
    position: absolute;
    left: 0px;
    right: 0px;
    top: 0px;
    bottom: 0px;
    margin: -5px;
    box-shadow: 0 0 0 5px yellow;    
}

demo

I am creating a pseudo element to hold the second shadow, and set a margin (negative) to get it past the first shadow, so that I won't draw on it.

Here is another demo, changing the value thru JavaScript

demo2

The script is the following

function change () {
    var elem = document.getElementById("test");
    var style = window.getComputedStyle(elem);
    var boxShadow = style.boxShadow;
    var arrayBoxShadows = parseFirstComma (boxShadow);

    var newData = elem.dataset.boxshadow;
    var arrayNewData = parseFirstComma (newData);
    boxShadow = "";
    var nmax = Math.min (arrayBoxShadows.length, arrayNewData.length)
    for (var n = 0, lenR = nmax; n < lenR; n++) {
        if (n > 0) {
            boxShadow = boxShadow + ", ";
        }
        if (arrayNewData[n] == "inherit") {
            boxShadow = boxShadow + arrayBoxShadows[n];
        } else {
            boxShadow = boxShadow + arrayNewData[n];

        }
    }
    if (arrayNewData.length > nmax) {
        for (var n = nmax, lenR = arrayNewData.length; n < lenR; n++) {
            if (n > 0) {
                boxShadow = boxShadow + ", ";
            }
            boxShadow = boxShadow + arrayNewData[n];
        }
    }
    if (arrayBoxShadows.length > nmax) {
        for (var n = nmax, lenR = arrayBoxShadows.length; n < lenR; n++) {
            if (n > 0) {
                boxShadow = boxShadow + ", ";
            }
            boxShadow = boxShadow + arrayBoxShadows[n];
        }
    }


    elem.style.boxShadow = boxShadow;
}


function parseFirstComma (property) {
    var properties = new Array();
    var curr = "";
    var chr;
    var nested = "";

    for (inx = 0, len = property.length; inx < len; inx++) {
        chr = property[inx];
        if (chr == "(") nested += 1;
        if (chr == ")") nested -= 1;
        if (nested == 0 && chr == ",") {
            properties.push (curr);
            curr = "";
        } else {
            curr = curr + chr;
        }
    }
    if (curr.length > 0) {
        properties.push (curr);
    }
    return properties;
};

document.onkeydown = function (e) {
    e = e || window.event;
    switch(e.which || e.keyCode) {
        case 37:
            change ();
            break;
    }
}

I am retrieving the box-shadow applied to the element, and retrieve the desired override from a data value. And then, recalculate the result (using inherit as a posible value). The demo is activated pressing the left arrow.

like image 64
vals Avatar answered Nov 19 '22 01:11

vals


Under the current CSS specification, it is not possible to override one of the values of a multiple-value attribute.

You will need to repeat the definition of the 1st and 3rd shadows in the second rule, i.e.

div{
    box-shadow: 0 0 0 5px #00ff00 ,  0 0 0 10px #ff0000 ,  0 0 0 15px #0000ff ; 
}

div:nth-of-type(2){
    box-shadow: 0 0 0 5px #00ff00 ,  0 0 0 10px #abcdef ,  0 0 0 15px #0000ff ; 
}

This message in the W3 mailing list suggests that it's something that's being considered http://lists.w3.org/Archives/Public/www-style/2013Apr/0711.html

like image 41
jingtao Avatar answered Nov 19 '22 03:11

jingtao