5

I want to be able to access classes further up the dom tree from within a nested class using LESS CSS, see example:

HTML:

<html class="svg">
 <body>
  <div class="content">
    <div class="container">
      <div class="logo"></div>
    </div>
 </body>
</html>

LESS:

.container {
  .logo {
      background:url(/images/ws-logo.gif);
  }
}

I want to target the .svg class on the html tag from within the .logo nested rule, to keep things tidy instead of writing another rule like this:

.svg { 
  .container {
    .logo {
        background:url(/images/logo.svg);
    }
  }
}

So, ideally something like this:

 .container {
    .logo {
        background:url(/images/logo.gif);

        (some-symbol).svg {
           background:url(/images/svg-logo.svg);
        }
    }
 }

I'm using modernizr to detect svg support.

Anyone know if this is possible? Or have any recommendations?

albion60
  • 65
  • 1
  • 8

2 Answers2

7

Yes! (an update)

When I tested this here, it worked!

    .container { 
        .logo { 
            background:url(/images/logo.gif);
            .svg & {
                background:url(/images/svg-logo.svg);
            } 
        } 
    }
ScottS
  • 71,703
  • 13
  • 126
  • 146
  • imo unnecessary fuzz and makes **all** your selectors more inefficient. Besides the fact that you actually have to repeat the rule - what the OP wanted to avoid in the first place. – Christoph Jul 17 '12 at 12:58
  • @Christoph--I tend to agree with you (which is why I upvoted your answer). – ScottS Jul 17 '12 at 13:04
  • @Christoph--Actually, there was a more concise way using the `&` selector (one I did not realize would work until I tested it). I've updated my answer. – ScottS Jul 17 '12 at 13:14
  • Although i would consider this horrible coding (it looks so incredibly hacky and is guaranteed to give the reviewer serious headaches) +1 for this nice solution! ;) – Christoph Jul 17 '12 at 13:17
  • Now let's target `.svg .container:hover .logo:before` without writing a new rule :-D – Christoph Jul 17 '12 at 13:19
  • @Christoph--I guess if the reviewer understands how the `&` works. I've come to realize that what it really does is insert the whole nested selector string in its place. So wherever it is in the nest, it copies _all_ the parents (the entire nested selector string) in its place. So it can thus be used to add grandparent(s), which does keep your selector code incredibly more concise. – ScottS Jul 17 '12 at 13:21
  • @Christoph--that rule would definatly require an addition to the `.container` area. Basically, the outermost nest can become the "pivot" for many parent/child operations. – ScottS Jul 17 '12 at 13:28
  • Sure. The problem is, this messes with the whole concept of nesting. When using this like `.svg &.yep .another-class` this can get messy quite quickly. Interesting is also that this usage is not mentioned in the docs of the website (or at least i couldn't find it). – Christoph Jul 17 '12 at 13:34
  • @Christoph--The information on the site concerning `&` is rather limited. I would not have guessed it worked as essentially a "placeholder" for copying in the nested selector string had I not just went and tried it to see what it would do. I agree, too much coding like that could get messy in tracing what is going on. Adding a further nested `&` like `.svg &.yep .another-class { &:hover}` would really begin to try one's mental picture of what is happening. – ScottS Jul 17 '12 at 13:53
  • Well thanks guys, that solved my problem, i too didnt realise the & could be used in this way, and couldnt find anything about it elsewhere. I guess it keeps my LESS files more tidy, the CSS output however may be too specific. Thanks anyway. – albion60 Jul 17 '12 at 14:34
  • @user567476--you say the output may be too specific. What output were you seeking? Your example seemed to indicate you were looking for that type of specific output. – ScottS Jul 17 '12 at 14:50
  • I mean my CSS files could get too specific if i nest for nestings sake, to keep my LESS files tidy. Not necessarily in this case tho. – albion60 Jul 17 '12 at 15:28
  • @user567476--ah, okay. Don't forget to "accept" (by clicking the check mark beside the answer) either Chrstioph's or my answer if you do accept one of them. – ScottS Jul 17 '12 at 15:33
2

This is not possible because you can't "step back" in the path to add another class to a parent. Instead, just write another rule:

.svg .container .logo,
/* or perhaps even simpler, however be aware of rule specificity*/
.svg .logo{
        background:url(/images/logo.svg);
}

It's not much of a deal, is it?

For the sake of completeness: You can reference to the actual element via the &-symbol. THis makes sense if you want to target pseudo-classes/elements or additional classes of the current element:

.container {
     .logo {
         /* styles for ".container .logo" */
     }
     &:hover .logo{
         /* styles for ".container .logo"
            The hover however is bound to the .container element
            equals the following selector: .container:hover .logo */
     }
}
Christoph
  • 50,121
  • 21
  • 99
  • 128
  • You can step back to add a class to the parent with the `&` cominator in LESS, however, I do not believe you can step back another level with the grandparent. – ScottS Jul 17 '12 at 12:54
  • Okay, you are technically correct. Yet it can become essentially a reference to the parent when you follow it with a nested class rule (like in my answer). Personally, your answer is going to be a bit more "concise" in code, the only potential advantage to nesting is to keep it all together in a nesting (which the OP seemed to want). – ScottS Jul 17 '12 at 13:00
  • I agree that it could make sense if the class wasn't on the html tag in the OPs question. – Christoph Jul 17 '12 at 13:01