parent selector in less - css

Normally in less to reference a parent selector is:
.parent {
.grand-pa & {
/* this rules will apply to: .grand-pa .parent {....}
background: grey;
}
}
What I'm trying to do is something similar. example code HTML:
<div class="panel panel-parent">
<div class="panel-child">
{{content}}
</div>
</div>
Less code:
.panel {
.panel-child {
// some rules
&.panel-parent & { //<=== IS IT POSSIBILE SOMETHING LIKE THIS??
// .panel.panel-parent .panel-child{...}
}
}
}
The only solution I have found is to repeat .panel-child:
.panel {
&.panel-parent .panel-child { //<=== Workaround
// .panel.panel-parent .panel-child{...}
}
.panel-child {
// some rules
}
}
}

The order of classes of the same element does not actually matter, i.e. .panel.panel-parent is equal to .panel-parent.panel (both will match <div class="panel panel-parent">), thus you can get what you need with just:
.panel {
.panel-child {
a: a;
.panel-parent& {
b: b;
}
}
}
instead.

Related

Less multiple classes rules using parent selector

I have the following HTML structure:
<div class="block">
<div class="block--is-disabled block--is-focused">Block</div>
</div>
And some LESS code:
// LESS
.block {
&--is-disabled {
// some styles
}
&--is-focused {
// some styles
}
}
Is it possible to apply styles like .block--is-disabled.block--is-focused using LESS parent selectors? The only thing I've reached is:
// LESS
.block {
&--is-focused & {
&--is-disabled {
// some styles
}
}
}
With the following CSS output:
.block--is-focused .block--is-disabled {
// some styles
}
But what I need to get is the next CSS:
.block--is-disabled.block--is-focused {
// some styles
}
You can do it like this:
.block {
&--is-focused&--is-disabled {
...
}
}

CSS :not for selector on the same level

I have this html, sometimes stars--done is not there but I want to alter the CSS.
<div class="stars stars--done">
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
</div>
Currently I have this
.stars {
&:hover {
i {
//do somehting
}
}
}
I only want to make the <i> do something if the parent does not match .stars--done
.stars {
&:not('.stars--done'):hover {
i {
//do somehting
}
}
}
.stars {
&:not('.stars--done'):hover {
i {
…
This will compile to
.stars:not('.stars--done'):hover i { …
which is not what you want. Remove the quotes:
.stars {
&:not(.stars--done):hover {
i {
…
Dont stringify the selector, this is not Jquery. Simply remove the ''.
.stars {
&:not(.stars--done):hover {
i {
//do somehting
}
}
}
Ps you can also write:
.stars {
&:hover:not(.stars--done) {
i {
//do somehting
}
}
}

Sass: Proper way to nest element within modifier with the same block name?

The HTML (which I am unable to alter) looks like:
<div class="cta">
<div class="cta--red">
<div class="cta__inner">
</div>
</div>
</div>
I need to target the content within this - specific to the red, inner cta.
I can do this with:
.cta {
&--red{
.cta {
&__inner {
}
}
}
}
But is there a cleaner way of writing this? (note: my company insists on having each element and modifier on a line break)
I seem to recall something like:
.cta {
&--red & {
&__inner {
}
}
}
but can't quite remember what it's called.
The desired CSS output is: .cta--red .cta-inner {}
You can cache the parent selector:
.cta {
$this: &;
&--red {
// -> .cta--red
& #{$this}__inner {
// -> .cta--red .cta__inner
}
}
}
A more clean option, in my opinion:
.cta {
// -> .cta
.cta--red {
// -> .cta .cta--red
.cta__inner {
// -> .cta .cta--red .cta__inner
}
}
}
Did you try?
.cta {
&--red {
}
&__inner {
}
}

Use unknown values as selectors in Less

Given this markup:
<div class="parent" data-active="typeA">
<div class="child" data-show="typeA">Show only when parent=typeA</div>
<div class="child" data-show="typeB">Show only when parent=typeB</div>
<div class="child" data-show="typeC">Show only when parent=typeC</div>
</div>
I'm trying to write a globally applicable LESS rule that only displays a child when its data-show attribute matches the parent's data-active attribute.
Something like this:
.parent {
.child { display:none; }
&[data-active="?"] .child[data-show="?"] { display:block; }
}
...where ? should not be a fixed value, but a condition that applies no matter the value, as long as they are the same.
Any ideas?
As LESS gets compiled to CSS and there is no generic approach for doing this in CSS, I only come up with a solution that requires you to know every possible type.
.parent {
.child { display: none; }
&[data-active="typeA"] {
.child[data-show="typeA"] { display: block; }
}
&[data-active="typeB"] {
.child[data-show="typeB"] { display: block; }
}
&[data-active="typeC"] {
.child[data-show="typeC"] { display: block; }
}
}
Depending on your preferences and to avoid redundancy you could also define a function for adding the different types.
.parent {
.child { display: none; }
.addType("typeA");
.addType("typeB");
.addType("typeC");
}
.addType(#type) {
&[data-active="#{type}"] {
.child[data-show="#{type}"] { display: block; }
}
}
And if you want to make this even more generic, you could define an array of types and call .addType for each of the types like this:
#types: "typeA", "typeB", "typeC";
.parent {
.child { display: none; }
.-(#i: length(#types)) when (#i > 0) {
#type: extract(#types, #i);
.addType(#type);
.-((#i - 1));
} .-;
}
.addType(#type) { /* see above */ }

CSS select :nth-of-class() alternative

With CSS: how do I target the first class of "approach", the second and the third one. All individually because they need different styles. I can't add an extra class to avoid responsive disorientation.
HTML code:
<div class="approaches">
<div class="col-md-4">
content here...
</div>
<div class="col-md-4">
content here...
</div>
<div class="col-md-4">
content here...
</div>
</div>
CSS code (which doesn't work at the moment):
.approaches .approach:nth-of-type(1){
color: red;
}
.approaches .approach:nth-of-type(2){
color: green;
}
.approaches .approach:nth-of-type(3){
color: blue;
}
There's a <div> between the .approaches and the .approach elements preventing your :nth selector from working properly. The selector looks for elements in their own nesting level, and because the .approach elements are wrapped in <div>s, they have separate nesting levels. Use the selector on the <div>s instead:
.approaches div:nth-of-type(1) .approach {
color: red;
}
.approaches div:nth-of-type(2) .approach {
color: green;
}
.approaches div:nth-of-type(3) .approach {
color: blue;
}
You could use .approaches div:nth-of-type(1) .approach { }, as others have suggested, but this assumes that each and every div inside .approaches has an a with the the .approach class, so it cannot really be considered to be a general way to achieve the equivalent of the non-existent nth-of-class if that's what you want.
To do that, you could use a bit of JS:
[].forEach.call(document.getElementsByClassName('approach'), function(elt, i) {
elt.classList.add('approach-' + i);
});
.approach-1 { color: red; }
Generalizing this for any class:
function add_nth_of_class(cls) {
[].forEach.call(document.getElementsByClassName(cls), function(elt, i) {
elt.classList.add(cls + '-' + i);
});
add_nth_of_class('approach');
However, this will number the classes sequentially throughout the document. To get a true nth-of-class, based on the position within the parent element, we would need to do something like the following, using the little-known TreeWalker API:
function add_nth_of_class(cls) {
var walker = document.createTreeWalker(document, NodeFlter.SHOW_ELEMENT), n;
while (n = walker.nextNode()) { //for each node in turn,
[].filter.call(n.childNodes, function(elt) { //find the children which
return elt.classList.contains(cls); //contain the class we want
}).forEach(function(elt, i) { //and for each of those
elt.classList.add(cls + '-' + (i+1)); //add a numbered class
});
}
}
CSS:
.approach-1 { // targets all elements with class .approach first within their parent
.approaches > div:nth-child(1) .approach {
}
.approaches > div:nth-child(2) .approach {
}
.approaches > div:nth-child(3) .approach {
}

Resources