LESS CSS naming convention - Child selectors on hover - css

In LESS, you can reference a child selector as follows:
<div class="button">
<div class="button-text"> Text </div>
</div>
.button {
&-text {
color:red;
}
}
This will output:
.button .button-text { color:red; }
This is neat and ideal, however, when using a hover, is there a way to maintain the same / similar syntax for the child element? Currently, this wouldn't naturally work:
.button {
&:hover {
&-text {
color:red;
}
}
}
This won't work and as expected, outputs something along the lines of
.button:hover .hover-text { }
Is there a way to get the expected hover result without defining the full class name, in this instance ".button-text"?
Any help would be greatly appreciated.

Because the parents selector & represents all parent selectors (not just the nearest ancestor), nesting under hover, will always include the :hover text.
This rule:
.button {
&:hover &-text {
color:red;
}
}
Will provide the result (lessismore playgroud):
.button:hover .button-text {
color: red;
}

Related

Sass nesting, mark for the first parent element

I have a root element div.container at my page, there is div.block.scarlet inside with red color for text.
But we also have body is a parent for div.container element. And when body has class .landing I need to make pink color instead of red.
I don't understand how write it correctly. Help with a syntax please!
/* how I do it now */
.container {
.block {
&.scarlet {
color: red;
}
}
}
body.landing .container {
.block {
&.scarlet {
color: pink;
}
}
}
Tooooo much extra copy-paste code! Is it possible to write in one line? Maybe a trick or smth like sass &. What I want:
.container {
.block {
&.scarlet {
color: red;
#if(body.landing || container.landing) { color: pink }
}
}
}
This is short rule that recolor my text if the root nesting element changed.
You need to use parent selector reference to construct complete selector from current context:
.container {
.block {
&.scarlet {
color: red;
body.landing & {
color: pink;
}
}
}
}

Change pseudo-element style based on grandparent class

Consider the following scss:
.link {
....
span {
....
&:after {
....
.link.active & {
background-color: red;
}
.link:hover & {
background-color: red;
}
I want to change the background-color for the span :after pseudo-element when link is either being hovered or has the .active class.
What I've tried ( the code posted above ) doesnt seem to work.
Is there anything I'm missing ?
you should try it like this scheme :
.link {
span {
&:after {
...
}
}
&.active,
&:hover {
span:after {
background-color: red;
}
}
}
Working example : http://jsfiddle.net/92gqap5y/
This question seems to be asked often, as mentioned in this thread.
They increase the size of the link element to be as large as the span. Though I would recommend moving the :hover selector and .active class to the span element directly.

Less cascading & refactoring

I am trying to refactor some css looking like this:
path.myClass {
//some CSS
}
.someOtherClass.myClass {
//some other CSS
}
I am struggling to find the right syntax for the first part. I am trying to have something looking like this:
.myClass {
path.& {
// some CSS
}
.someOtherClass {
// some other CSS
}
}
How can I refactor this correctly?
You can do it like below. Since the top level selector already has . there is no need to add it again before the parent selector (&) in the inner selector. The second one is fairly straightforward as you can append the parent selector either at the start or at the end. The order of classes doesn't matter.
(Note: There should be no space before the parent selector as it would change the meaning.)
.myClass {
path&{
color: red;
}
.someOtherClass& { /* can do &.someOtherClass also, order doesn't matter */
color: blue;
}
}
Below is the compiled CSS output:
path.myClass {
color: red;
}
.someOtherClass.myClass {
color: blue;
}

Apply a style on element A if element B contains a certain class

Is it possible to check the class of an element, see if it exists, and then apply the style for another class?
Example pseudo code:
if (.myClass .myBlock == true) {
.otherClass {
display:none
}
}
It's not possible in this context. But you can achieve a similar result with the cascading nature of CSS.
Apply a class to the body of your website:
.another-class {
display: none; // hides .another-class by default
}
body.special-class {
.another-class {
display: block; // shows if the body contains .special-class
}
}
Since the specificity of the generated output is higher at the second rule, the elements with .another-class will be visible.
Give the following row a class
Utilising the + selector enables us to display the row after the mentioned class. This way we can style dropdowns popups, given we have the following HTML:
.popup {
display: none;
}
.popup:hover {
display: block;
}
.container:hover + .popup {
display: block;
}
<div class="container">Hover me!</div>
<div class="popup">This is a popup!</div>
I'm afraid that's all that is possible with CSS.

CSS nesting: inherit from whom?

here is a fiddle with the problem:
https://jsfiddle.net/c2exs2f7/3/
How does the second "blue" stay like the first instance (it should have color: white) without changing the HTML structure?
HTML
<div class="blue">
<div class="content">
<div class="label">blue</div>
<div class="yellow">
<div class="content">
<div class="label">yellow</div>
<div class="blue">
<div class="content">
<div class="label">blue</div>
</div>
</div>
</div>
</div>
</div>
</div>
SCSS
// Skip until...
div {
border-radius: .25em;
padding: .5em;
font-family: helvetica, sans-serif;
}
// ...here:
.blue {
background-color: hsl(220,100%,50%);
.content {
color: white;
}
}
.yellow {
background-color: hsl(60,100%,50%);
.content {
color: hsl(0,0%,10%);
}
}
EDIT #1
Thank you guys for these fast responses!
I am working on a grid system where I am able to nest different grid systems (with different CSS values).
The selectors .yellow .content and .blue .content have the same specificity (20 in this case), therefore the selector that appears later in the stylesheet will override the first one due to the cascading nature of a stylesheet. In this case, the selector .yellow .content is overriding .blue .content, which is why the nested .blue element is black.
One quick solution would be to select nested .blue element with the selector .blue .blue:
Updated Example
.blue,
.blue .blue {
background-color: hsl(220,100%,50%);
.content {
color: white;
}
}
An arguably better approach would be to only select direct .content children elements using the child selector, >:
Updated Example
.blue {
background-color: hsl(220,100%,50%);
> .content {
color: white;
}
}
.yellow {
background-color: hsl(60,100%,50%);
> .content {
color: hsl(0,0%,10%);
}
}
Based on your comments, the ordering/layering of the elements may vary. An alternative solution would be to set the color property on the .blue/.yellow element and then set the color property of the children elements to inherit:
Updated Example - this seems to work for all variants.
.blue {
background-color: hsl(220,100%,50%);
color: white;
.content {
color: inherit;
}
}
.yellow {
background-color: hsl(60,100%,50%);
color: hsl(0,0%,10%);
.content {
color: inherit;
}
}
See https://jsfiddle.net/c2exs2f7/4/
What I did was to enforce inheritance only for the child content classed DIV, not the entire descendance.
Applying the immediate children operator > in the SCSS makes the .content div to consider only its immediate parent color.
Go on and try nesting more DIVs, you will see that it works.
You can't. Not with inherent anyway. Because the second blue will inherent from the yellow. So if u want all blue always have white letters and yellow always black letters. Why not just put:
.blue { color: #fff; }
.yellow { color: hsl(0,0%,10%); }
And you won't need the ".content" wrapper.
I had this same issue where the HTML nesting varies and so it's not possible to make more specific selectors due to overwhelming complexity and non-DRY code.
Here's the solution I came to:
https://jsfiddle.net/cg0u8v1s/
Basically, a systematic approach to the class names is key so you can use a CSS attribute selector reliably (although I'd recommend a more unique naming convention than "color-" as it's too generic.).
Example:
.color-blue {
&,
[class*="color-"] &,
[class*="color-"] [class*="color-"] & {// Only needed if you want a 3rd level of nesting to work.
background-color: blue;
.content {
color: skyblue;
}
}
}
.color-yellow {
&,
[class*="color-"] &,
[class*="color-"] [class*="color-"] & {// Only needed if you want a 3rd level of nesting to work.
background-color: yellow;
.content {
color: brown;
}
}
}
This will output selectors that become more specific with nesting without the need for non-DRY code or having to use !important.
The CSS output will look like this:
.color-blue,
[class*="color-"] .color-blue,
[class*="color-"] [class*="color-"] .color-blue {
// code...
}

Resources