Reputation: 15699
On the first time my HTML,CSS looks perfect, but as shown in fiddle, when clicking on button, I want to hide/show some .show
elements. When I hide them, CSS is broken. I dont know what I am missing.
HTML:
<div>
<span class="show">box</span>
<span class="show">box</span>
<span class="show">box</span>
<span class="show">box</span>
<span class="show">box</span>
<span class="show">box</span>
<span class="show">box</span>
<span class="show">box</span>
</div>
<input type="button" id="button" value="click" />
CSS:
div .show:nth-of-type(-n+4) {
margin-top:0;
}
div .show:nth-of-type(4n) {
margin-right:0;
}
JS:
$("#button").click(function () {
$("span:eq(0),span:eq(2)").toggle().toggleClass("show");
});
Any help would be appreciated.
Thanks for your time.
Upvotes: 3
Views: 130
Reputation: 1074455
The :nth-of-type
will not count only the .show
elements, it will count all spans
. So when you hide some of them, even though they're hidden, they still count.
If you're going to show and hide the spans, nth-of-type
probably isn't what you need.
I'm not a CSS wizard. Two options come to me:
Don't hide the elements, detach
them, and then reattach them later. Then they aren't in the parent anymore and :nth-of-type
will keep working. See the example below.
(And I don't like this, but...) Don't use :nth-of-type
, use classes you assign via JavaScript whenever you show/hide spans (basically running through the visible ones and giving them classes to do what you need.)
Here's an example of doing the detach/reattach thing: Fiddle
// Get the spans
var $spans = $("#container span");
// Assign them indexes
$spans.each(function(index) {
this.setAttribute("data-index", index);
});
// Attach/detach on a toggle
var detached;
$("#button").click(function () {
if (detached) {
reattach(detached);
detached = undefined;
}
else {
detached = detach();
}
});
function detach() {
var rnd1, rnd2;
// Pick two at random
rnd1 = Math.floor(Math.random() * $spans.length);
do {
rnd2 = Math.floor(Math.random() * $spans.length);
}
while (rnd2 === rnd1);
// Detach them
return $("#container span:eq(" + rnd1 + "),span:eq(" + rnd2 + ")").detach();
}
function reattach(spans) {
spans.each(function() {
var $span = $(this),
index = +$span.attr("data-index");
if (index === 0) {
$span.prependTo("#container");
}
else {
$span.insertAfter($spans[index - 1]);
}
});
}
Note that it's important that the div
containing the spans not have an empty text node as its first child (your fiddle does, I've removed it in mine). That's because when we put the spans back, since we always do them in order, if we're reattaching the first one we have to use prependTo
rather than insertAfter
, and the text node messes things up.
Upvotes: 6