Reputation: 619
What is the correct selector for selecting even and odd level children?
I would like to simplify my current CSS while allowing for infinite levels without manually writing in the CSS for them.
.box {
max-width:100%;margin:25px 0px;padding: 15px;
border:#d1ddbd solid 2px;
background-color:#f3fae8;
}
.box > .box {
border:#d1ddbd solid 1px;
background-color:#fff;
}
.box > .box > .box {
border:#d1ddbd solid 1px;
background-color:#f3fae8;
}
.box > .box > .box > .box {
border:#d1ddbd solid 1px;
background-color:#fff;
}
Upvotes: 7
Views: 2576
Reputation: 36
You can do it with container queries now! just took 8 years.
basically, you use a container query to target a specific style, and inside of it you toggle the style itself:
layering {
container-name: layering;
--depth-is-odd: true;
}
@container layering style(--depth-is-odd: true) {
.layering {
// styles for odd levels of nesting
--depth-is-odd: false;
}
}
@container layering style(--depth-is-odd: false) {
.layering {
// styles for even levels of nesting
--depth-is-odd: true;
}
}
Upvotes: 2
Reputation: 1363
I think a bit of JS would be the easiest way to simplify the CSS, unless you wanna use LESS/SASS. - As already written above, there is no real way of doing this with short CSS selectors.
(function addClasses(element, selector, level){
[].forEach.call(element.querySelectorAll(selector),
function (item, index) {
item.className += " " + (level % 2 ? "white-bg" : "green-bg");
item.innerHTML += "";
addClasses(item, ".box", level+1);
}
);
})(document, ".box", 0);
.box {
max-width: 100%;
margin:25px 0px;
padding: 15px;
border: #d1ddbd solid 2px;
}
.box.white-bg {
background-color: #ffffff;
border: #d1ddbd solid 1px;
}
.box.green-bg {
background-color: #f3fae8;
border: #d1ddbd solid 1px;
}
<div class="box">
1
<div class="box">1.1</div>
<div class="box">1.2</div>
</div>
<div class="box">
2
<div class="box">
2.1
<div class="box">
2.1.1
<div class="box">2.1.1.1</div>
</div>
<div class="box">2.1.2</div>
<div class="box">2.1.3</div>
<div class="box">2.1.4</div>
<div class="box">2.1.5</div>
</div>
<div class="box">
2.2
</div>
<div class="box">
2.3
</div>
</div>
<div class="box">
3
<div class="box">3.1</div>
</div>
Upvotes: 0
Reputation: 4243
You can easily set classes by JavaScript.
Depends on planed amount and appropriate performance. (I presume you don't need thousands.)
This example takes: 500 8ms, 5.5K 47ms, 55K 446ms
/** Extending Javascript Array for function Contains */
Array.prototype.contains = function (element) {
return this.indexOf(element) > -1;
};
/** Set class "odd" to itself and run proceedEven() on all children with class "box" */
function proceedOdd(oddItem) {
oddItem.classList.add("odd");
if (oddItem.children.length) {
[].forEach.call(oddItem.children, function (child) {
if (child.classList.contains("box")) {
proceedEven(child);
}
})
}
}
/** Set class "even" to itself and run proceedOdd() on all children with class "box" */
function proceedEven(evenItem) {
evenItem.classList.add("even");
if (evenItem.children.length)
[].forEach.call(evenItem.children, function (child) {
if (child.classList.contains("box")) {
proceedOdd(child);
}
})
}
// set root having first even box as child
var root = document.querySelectorAll("body");
if (root.length) {
// just for case more in root
[].forEach.call(root, function (rootItem) {
if (rootItem.children.length)
[].forEach.call(rootItem.children, function (child) {
// proceed first level of evens - rest done recursively
if (child.classList.contains("box")) proceedEven(child);
});
})
}
Upvotes: 0
Reputation:
There's no way to do this in CSS, other than just sitting down and writing the rules. It's not that big a deal to write ten rules, taking you down to ten nesting levels. Your alternative is to spend more time writing JS to add classes, or having your back-end add classes, or fighting with a SASS macro, any of which will take more time than this is worth.
.box {
max-width: 100%;
margin: 25px 0px;
padding: 15px;
border: #d1ddbd solid 2px;
}
.box > .box {
border-width: 1px;
}
.box,
.box > .box > .box,
.box > .box > .box > .box > .box,
.box > .box > .box > .box > .box > .box > .box,
.box > .box > .box > .box > .box > .box > .box > .box > .box {
background-color:#f3fae8;
}
.box > .box,
.box > .box > .box > .box,
.box > .box > .box > .box > .box > .box,
.box > .box > .box > .box > .box > .box > .box > .box,
.box > .box > .box > .box > .box > .box > .box > .box, .box > .box {
background-color:#fff;
}
Upvotes: 5
Reputation: 310
In the event you make "box" using div's you could do something like this. (See code and preview below)
div:nth-child(even)
{
border:#d1ddbd solid 1px;
background-color:#f3fae8;
width:76px;
height:75px;
}
div:nth-child(odd)
{
border:#d1ddbd solid 1px;
background-color:#fff;
width:76px;
height:75px;
}
#MainDiv{
max-width:100%;margin:25px 0px;padding: 15px;
border:#d1ddbd solid 2px;
background-color:#f3fae8;
display:block;
padding:2px;
height:auto;
}
<div id="MainDiv">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Upvotes: 0