Less Immediate Parent Selector
A Base Example
It partly depends upon how you structure your LESS code. There is currently no way to do this with a normal nested structure. However, take the following example, where the .grandchild
is our final target in all cases (it must be the outermost level--I called this "end target grouping" in a previous answer before LESS added documentation about using &
as a parent selector):
LESS
.grandchild {
grandchild: 1;
.child & {
child: 1;
.parent & {
parent: 1;
.grandparent & {
grandparent: 1;
}
}
}
}
CSS Output
.grandchild {
grandchild: 1;
}
.child .grandchild {
child: 1;
}
.parent .child .grandchild {
parent: 1;
}
.grandparent .parent .child .grandchild {
grandparent: 1;
}
As you can see, any code nested in the first level only has the end target of .grandchild
in its selector string. Each level one goes "down" in the nest, one is actually going "up" in selector specificity. So to target just the "immediate parent" for the selector string, place it in the .child
of this example.
Hovers Still Work
LESS
.grandchild {
grandchild: 1;
&:hover {
grandchildhover: 1;
}
.child & {
child: 1;
.parent & {
parent: 1;
.grandparent & {
grandparent: 1;
&:hover {
grandchildhover: 1;
}
}
}
}
}
This will add to the above css these two outputs:
.grandchild:hover {
grandchildhover: 1;
}
.grandparent .parent .child .grandchild:hover {
grandchildhover: 1;
}
Skip Generations
You can code it to skip some generations, like so:
LESS
.grandchild {
grandchildonly: 1;
.child & {
withchild: 1;
.parent & {
withparentchild: 1;
}
}
.parent & {
skipgenchild: 1;
}
}
CSS Output
.grandchild {
grandchildonly: 1;
}
.child .grandchild {
withchild: 1;
}
.parent .child .grandchild {
withparentchild: 1;
}
.parent .grandchild {
skipgenchild: 1;
}
Abstracted
There are various ways this could be abstracted out, such that the code does not give the appearance of a nested look (which could confuse a user). Something like this is one way (output similar to that given in first and second examples above):
.addParent(@parent) {
@parentescaped: e(@parent);
@{parentescaped} & {.setWithParentProps(@parent);}
}
.grandchild {
grandchild: 1;
&:hover {
grandchildhover: 1;
}
.addParent('.child');
.setWithParentProps('.child'){
child: 1;
.addParent('.parent');
}
.setWithParentProps('.parent'){
parent: 1;
.addParent('.grandparent');
}
.setWithParentProps('.grandparent'){
grandparent: 1;
&:hover {
morespecifichover: 1;
}
}
}
Final Comments
As seven-phases-max linked to in his comment, there is talk of adding generational precision within a normal nested context. The solution given here requires one to think "opposite" of nesting, but rather think only about the element being targeted. So the way to add a .grandchild
into another selector would not be this mixin:
LESS (expecting to add a parent by normal nesting)
.another-generational-parent {
.grandchild;
}
CSS Output
.another-generational-parent {
grandchildonly: 1;
}
.child .another-generational-parent {
withchild: 1;
}
.parent .child .another-generational-parent {
withparentchild: 1;
}
It would be best to add it into the original code according to the proper place, but if that is not possible, then some repetition is needed (unless you set up some way in the original code to "insert" parents through creative mixin calling--I have no time to devout to that here).
.parent .child .grandchild {
.another-generational-parent & {
another-generational-parent: 1;
}
}
Whether such opposite coding can be useful or not all depends upon one's goals and desires in organizing the LESS code.
LESS parent selector for first parent
You have put the &
(parent selector) at the wrong place. It shouldn't be put after the selector, instead it should be before the .
. Setting the &
after the selector means the whole parent selector (from the topmost selector) will be appended at the end of the current selector instead of getting inserted before (which is what you need for .header .menu.no-borderradius
or ul li.active
.
.header {
.menu {
border-radius: 5px;
&.no-borderradius { /* here & is equal to .header .menu */
background-image: url('images/button-background.png');
}
}
}
ul {
li {
&.active, /* here & is equal to ul li */
&:hover {
color: red;
}
}
}
Regarding the update to the question - it is currently not possible to achieve ul li.active a
using the below structure as parent selector means the entire chain of selectors till the current level and not just the immediate parent. There is no way to just pick the immediate parent.
ul {
li {
a {
.active &,
&:hover {
color: red;
}
}
}
}
The only option currently possible is to write it like below:
ul {
li {
&.active a,
a:hover {
color: red;
}
}
}
There is an open feature request for parent selectors to have targets but there is no decision on by when this would be done.
LESS CSS How to capture parent selector in variable
You can possible solve your issue by using the parent reference &
to (change selector order)[http://lesscss.org/features/#parent-selectors-feature-changing-selector-order]
.media {
&__body{
color: green;
}
&.-reverse & {
&__body {
color: red;
}
}
}
compiles into CSS code as follows:
.media__body {
color: green;
}
.media.-reverse .media__body {
color: red;
}
LESS - styling classes differently dependent on the parent element
Well, you could always do
.zero {
span & { color: #fff; }
div & { color: #389c40; }
}
Apply a tag selector to the immediate parent of a rule within a deeply-nested structure
Looks like you're getting tangled up in wanting über-optimized LESS. If I understand correctly, either way your compiled CSS will be
article .foo {
general `article .foo` styles
}
article a.foo {
additional styles specific to `article a.foo`
}
In LESS you could write that as is, or you could do
article {
.foo {
general `article .foo` styles
}
a.foo {
additional styles specific to `article a.foo`
}
}
or depending on your styles you might be able to do
article .foo {
general `article .foo` styles
}
a.foo {
additional styles specific to `a.foo`
}
Specify an attribute value using the parent selector in LESS?
The parent selector (&
) only holds a reference to an entire complex selector, with the option to extend the selector provided that you use the entire thing as a base:
.one > .two {
&::after, &::before {
// Compiles to .one > .two::after, .one > .two::before
}
& + .three {
// Compiles to .one > .two + .three
&-suffix {
// Compiles to .one > .two + .three-suffix
}
}
}
It cannot be used to reference a part of a compound or simple selector, in particular it cannot be used to reference just the attribute name in an attribute selector. You'll have to stick with vanilla CSS.
The reason that abomination doesn't work is because both preprocessors expect all selectors in style rules to be valid; [some-attribute
is not a valid selector. You could write a mixin and/or use selector interpolation, but it still has to result in a valid selector when used with a style rule, since the compiler can't assume that you won't be using the selector in its own set of style declarations (though of course, whether a preprocessor should be controlling the author in this way is up for debate...).
Related Topics
Using Bootstrap and My Own CSS Together
Css: Flex Box Not Printing All Pages on Firefox
How to Limit a Table Cell to One Line of Text Using CSS
Preload CSS File Not Supported on Firefox and Safari MAC
CSS Animate Circle Border Filling with Color
How Bad Is It in Practice to Over-Nest Selectors in SASS/Scss
Datatables Pagination Buttons - Remove Unwanted Space
What Is the Simplest Way to Implement Pure CSS Show/Hide
Find Definition of CSS Class in External Stylesheet
Hexagonal Shaped Cells in HTML
Flexbox - Align-Self: Flex-End Horizontally
Align Lines of Text to Center in Svg
Background Image Transparency with CSS3
Bootstrap 3 Responsive Desktop and Mobile Layout
CSS Label Text Right Below Input Element