1

I have four div container in the following order:

enter image description here

Every container has CSS class "chart multi-mode" with style:

.chart.multi-mode {
    width: 300px;
    height: 200px;
    margin: 0 15px 15px 0;
}

Every second div should have no right margin, so I use:

.chart.multi-mode:nth-child(2n) {
    margin-right: 0px;
}

This is working fine until I use jQuery sortable()

When dragging one div and holding, jQuery adds an placeholder, which I also gave the classes "chart multi-mode" and the original object becomes absolute and I remove the class "multi-mode".

But nth-Child doesn't care about removing the class "multi-mode" and still counts the absolute div and so the margins are set wrong, see here:

enter image description here

Any solution?

mahega
  • 3,231
  • 4
  • 20
  • 32
  • 3
    `nth-child` **mostly** ignores classes...it an element **is** the specified `nth-child` the CSS applies...and that's it. – Paulie_D Feb 20 '15 at 12:35
  • @Paulie_D that is simply not true. – Joe Fitter Feb 20 '15 at 12:37
  • There are cases where a class might impact but `nth-child` is not the same as `nth-of-class` which doesn't exist. – Paulie_D Feb 20 '15 at 12:39
  • 1
    About the editted question's image - It's not the first child... how about that `li` right above it??? – LcSalazar Feb 20 '15 at 12:39
  • Correct! There's one more li above! CSS nth-child starts at 1, not 0. – Jeremy Thille Feb 20 '15 at 12:40
  • But the first li has not the class .chart.multi-mode – mahega Feb 20 '15 at 12:42
  • 1
    @mh-itc - See my first comment...`nth-child` **ignores** classes – Paulie_D Feb 20 '15 at 12:43
  • Ok, so is there any other solution? – mahega Feb 20 '15 at 12:43
  • It doesn't matter... The selector is not cumulative... It is a joined selector, not subjecting the rules to one another. It will target the element that contains the class **and** is also the second child in the container... – LcSalazar Feb 20 '15 at 12:44
  • 1
    possible duplicate of [nth-child doesn't respond to class](http://stackoverflow.com/questions/5428676/nth-child-doesnt-respond-to-class) – Paulie_D Feb 20 '15 at 12:45
  • There's no way of solving this; @Paulie_D explained why. `nth-child` doesn't react to classes when _counting_, no matter if the selector it is applied on is a class selector. It solely relies on element count, not their classes or IDs or whatever. I'd go with different CSS, probably a grid-like system that doesn't rely on the order or number of elements present or if there's one element out of flow. Bootstrap's grid system will do what you want, just tried it out. – maryisdead Feb 20 '15 at 12:54

4 Answers4

0

To select the second element with the class, after the changes, there's not much you could do. The only kind of selector I can think of is to set the hierarchy starting from the element that does not contain the class, and follow using immediate forward sibling selector +, to target the second one:

Untested

li:not(.chart.multi-mode) + .chart.multi-mode + .chart.multi-mode {

}
LcSalazar
  • 16,524
  • 3
  • 37
  • 69
0

I knocked something workable up that uses a different approach laying out the boxes (see my comment Weird behavior of CSS nth-child after editing dom):

Basically is a non-responsive light version of a Bootstrap grid:

* { box-sizing: border-box; }

body {
    padding: 50px;
}

#chartlist {
    list-style: none;
    margin: 0 -8px;
    padding: 0;
    width: 600px;
}

#chartlist::after {
    content:"";
    display:table;
    clear:both;
}

.chart.multi-mode {
    float: left;
    width: 300px;
    height: 200px;
    margin-bottom: 16px;
    padding: 0 8px;
    position: relative;
}

.chart-holder {
    border: 1px solid #333;
    background: #999;
    height: 100%;
}

.chart.placeholder {
    background: rgba(255, 0, 0, 0.5);
    position: absolute;
    right: -20px;
    top: 20px;
}
<ul id="chartlist">
    <li class="chart multi-mode">
        <div class="chart-holder">Chart #1</div>
    </li>
    <li class="chart multi-mode">
        <div class="chart-holder">Chart #2</div>
    </li>
    <li class="chart multi-mode placeholder">Chart Placeholder</li>
    <li class="chart multi-mode">
        <div class="chart-holder">Chart #3</div>
    </li>
    <li class="chart multi-mode">
        <div class="chart-holder">Chart #4</div>
    </li>
</ul>

(Or http://jsfiddle.net/maryisdead/vfm5d3au/)

Community
  • 1
  • 1
maryisdead
  • 1,792
  • 2
  • 19
  • 30
  • But the main problem is, that every element should have "margin: 0 15px 15px 0", expept the elements on the right side (every second) should have margin-right: 0; – mahega Feb 20 '15 at 13:33
  • Sorry, dude, didn't see you commented. I updated my example by using another container for the actual chart. Didn't see any other way of working around this. – maryisdead Feb 24 '15 at 08:31
0

I solved it with Javascript:

            this.$chartList.sortable({
                placeholder : "chart chart-placeholder " + chartTypeClass,
                handle : ".opt-drag",
                start : function(event, ui) {
                    ui.item.addClass('drag-state');
                    $('.multi-mode:not(.drag-state):odd').addClass('odd');
                    $('.multi-mode:not(.drag-state):even').addClass('even');
                },
                change : function(event, ui ) {
                    $('.multi-mode').removeClass('odd');
                    $('.multi-mode').removeClass('even');
                    $('.multi-mode:not(.drag-state):odd').addClass('odd');
                    $('.multi-mode:not(.drag-state):even').addClass('even');
                },
                stop : function(event, ui) {
                    ui.item.removeClass('drag-state');
                    $('.multi-mode').removeClass('odd');
                    $('.multi-mode').removeClass('even');
                },
                update : function() {
                    uiBehavior.startSpinner();
                    var newUuidOrder = [];
                    $('.chart').each(function() {
                        newUuidOrder.push($(this).attr('uuid'));
                    });
                    _this.restSetChartsOrder(newUuidOrder, function() {
                        uiBehavior.stopSpinner();
                    });
                }
            });

On start Draggin or when list change I count elements and add class odd or even.

CSS looks like this:

.chart.multi-mode.odd {
    margin-right: 0px !important;
}

.chart.multi-mode.even {
    margin-right: 15px !important;
}

Thanks to all!

mahega
  • 3,231
  • 4
  • 20
  • 32
-1

negate the placeholder using this

.chart.multi-mode:not(.chart-placeholder):nth-child(2n)
Joe Fitter
  • 1,309
  • 7
  • 11
  • The chart-placeholder should be not ignored. The first element with position absolute should be ignored. I testet to give it a special class (e.g. 'toBeIgnored') and use .chart:not(.toBeIgnored):nth-child(2n) but it is still not working! – mahega Feb 20 '15 at 12:39