Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are alternate nested styles possible in CSS?

Tags:

css

I'm doing a little experiment, trying to alternate background colours for nested divs.

This is what I intend to achieve (without the inline styles):

<div style="background: #fff;">
    <div style="background: #000;">
        <div style="background: #fff;">
            <div style="background: #000;">
                and so on...
            </div>
        </div>
    </div>
</div>

I feel like I must be missing something obvious! I tried div:nth-of-type(2n) but this appears to only apply on one level.

This is for an experiment where the divs are generated, so the solution needs to be endless (not something along the lines of div div div div = white). I know it's quite easy with JavaScript, just looking for a pure CSS solution.

like image 400
daviestar Avatar asked Apr 07 '12 14:04

daviestar


People also ask

Can you nested styles in CSS?

A style rule can be directly nested within another style rule if its selector is nest-prefixed. To be nest-prefixed , a nesting selector must be the first simple selector in the first compound selector of the selector.

How do I target a nested class in CSS?

You can simply target paragraph tags inside main differently than you would paragraph tags inside footer by nesting the paragraph tag inside its parent. It's that simple. To nest a selector, you simply separate them with a space.


2 Answers

As stated by others, this is not possible in pure CSS. However using js it is quite possible and fairly easy too.

For ease I implemented this in jQuery but you could do with pure JS.

http://jsfiddle.net/sg3s/Suf3p/

I basically made a small jQuery plugin that colors the selector you apply it on with the primary color, and uses the subselect to get a matching child to color with the secondary color and so on until no children matching the subselect are left.

jQuery(function($) {
    $.fn.alternateNestedBgColor = function(subselect, colors) {
        // While not a great optimization, length of the colors array always stays the same
        var l = colors.length;

        // Itterate over all element in possible array
        // jQuery best practice to handle initializing multiple elements at once
        return this.each(function() {
            var $sub = $(this), i = 0; 

            // Executes code, at least once
            do {

                // Set bg color for current $sub element
                $sub.css('backgroundColor', colors[i++ % l]);
                // Set $sub to direct children matching given selector
                $sub = $sub.children(subselect);

            // Will repeat the do section if the condition returns true
            } while ($sub.length > 0);
        });
    };

    // target first div in the body
    // first argument = child selector
    // second argument = array list of colors
    $('body>div').alternateNestedBgColor('div', ['red', 'green', 'blue', 'purple', 'grey']);
});

Update As requested an update detailing how apply and modulo were used.

It's been almost 2 year since I recently posted this. And while working, the solution I made back then was a bit verbose and confusing, as for instance, I never needed apply. I got a little bit more comfortable with scopes, so I revised the function to be much simpler.

The only situation where apply is useful is when you need to pass a value to the this variable inside the function scope. Unless working with classes there aren't a whole lot of situations you should have a need for apply or call. If you want to read up on it I would like to refer you to this answer which explains it in context of classes. The MDN link is a good resource as well (for this and other javascript constructs/concepts).

As for modulo, this is basic math and this question explains the operation quite well. In short it will give you the full integer remainder after dividing a number by another. So 33 % 8 = 1 which you could write as 33-parseInt(33/8)*8 in js though that would be grossly inefficient. The result of the operation will always be 0 (when the number perfectly divides) to the 2nd argument minus 1 (so 7 in my example).

0 % 3 = 0 // technically doesn't exist (as you can't divide 0 with anything) but 0 for practicality in all programming languages afaik(?)
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0 etc...

It's one of those operations which is inherently simple for your CPU, in fact without it being able to do this we wouldn't have computers.

In the javascript revision I've written the selection of the color from the given array as colors[i++ % l].

In writing this would be give me the remainder of i / l and use that integer as an index for the colors array which returns a color for use.

The ++ will add 1 only after returning the value of i for use in the modulo, this behaviour would be reversed if I had written ++i, but that wouldn't work for our purpose here.

For reference here is the MDN article on do...while.

I hope that cleared some things up! :)

like image 149
sg3s Avatar answered Oct 04 '22 13:10

sg3s


As Mr Lister pointed out, nth-of-type works on one level (that of the parent of the selected div).

As far as i know and after looking through the W3C CSS3 Selectors there doesn't appear to be any css selectors for traversing through nesting (except the > selector, which only looks at the direct child of parent).

I would love te be proven wrong though as that could be very usefull.

So the only (css) solution would be the one you already stated: div > div > div {background: white; } Can't you just generate this along with the generation of the div's?

like image 44
Pirokiko Avatar answered Oct 04 '22 15:10

Pirokiko