How to apply format depending on absence of a CSS class? - css

If I would like to format an element that has a given class, sometimes (very rare) I use:
.beigeButton[class~="enabledButton"] {
}
What if I want to give properties to an element only when it does NOT contain the given string?
This does not work:
.beigeButton[class!="enabledButton"] {
}
How can I do that?

Use :not:
.beigeButton:not(.enabledButton)

In general you would style the basic button and overwrite the style with additional classes, somehow like this:
.beigeButton {
background-color: beige;
cursor: pointer;
}
.beigeButton.disabled {
background-color: grey;
cursor: not-allowed;
}
.beigeButton.enabled {
background-color: green; //or just keep the basic color
}
you could also define a more general 'disabled class' which can be applied to any other Element this way:
.disabled {
background-color: red;
pointer: not-allowed;
}
A button with the class 'disabled' will get a grey background, though the rule .beigeButton.disabled is more specific as the general .disabled rule.
Any other element (or if the more specific rule doesn't exist or apply) will get a red background-color.
edit:
To answer your initial question, you can style the other way round too, like marcinjuraszek already described:
.beigeButton:not(.enabled) {
background-color: grey;
cursor: not-allowed;
}
Note: check browser compatibilty here
Hope this helps :)

Related

How to refer parent property within nested rule with the same name

I am trying to reuse a background-color definition of the parent rule set in background-color definition of a child rule set. However, Less evaluates the lookup as a recursion.
I would like this:
.button {
background-color: whitesmoke;
&:hover {
background-color: darken($background-color, 10%);
}
}
to work the same way as this:
#the-color: whitesmoke;
.button {
background-color: #the-color;
&:hover {
background-color: darken(#the-color, 10%);
}
}
but without the need for an extra variable.
The documentation isn't very specific on this. Am I missing something or is this just not possible?
I am aware of other solutions to changing the tint of a button on hover (e.g. using the filter property).
EDIT 1:
The closest I can get to is this. I just need it to be background-color instead of color.
.button {
background-color: whitesmoke;
&:hover {
color: darken($background-color, 10%);
}
}
The problem is the lookup of $background-color evaluates to the background-color of the same row (which, I think, doesn't ever make sense) and refuses to compile instead of evaluating to a rule in the parent rule set or just simply evaluating to one of the previous rows.

How to reference SCSS sibling?

Assuming that I have the following HTML:
<div class="navigation__item">
<span class="navigation__item__icon"></span>
</div>
I want to apply some rules to an icon, when hovering an item, which can be described with the following CSS:
.navigation__item__icon {
color: black;
}
.navigation__item:hover .navigation__item__icon {
color: white;
}
I can achieve this using the following SCSS:
.navigation__item {
&:hover {
.navigation__item__icon { <-- here
color: white;
}
}
&__icon {
color: black;
}
}
Here, is there any way to avoid writing navigation__item? Something like "parent rule \ element".
I like Sass for logical structure so that if I want to rename the whole navigation block with elements, I can simply change navigation class name in the root, and everything is renamed. This case breaks this advantage.
Update: Actually, I have found a way to do this without using {} braces. & can be repeated more than once:
.navigation__item {
&:hover &__icon {
color: white;
}
&__icon {
color: black;
}
}
It is great, but it doesn't make much sense if I have many rules and rules for &:hover itself. The question is still open - is this possible to access sibling element definition from within the {} block.
In Stylus there is a Partial reference but I don't know anything similar in SASS. One solution could be using a variable for the parent selector:
.navigation__item {
$selector: &;
&:hover {
#{$selector}__icon {
color: white;
}
}
&__icon {
color: black;
}
}
Is usefull is you change navigation__item class for another.
EDIT: I had used a wrong example, it's OK now.

Is there a way to fall back to a non-pseudo-class style in CSS?

If I have a blue div that someone else owns the code for
.stuff {
background-color: blue;
}
And I want it to be red on hover
.stuff:hover {
background-color: red;
}
But then I want to be able to add a class for it to go back to its non-pseudo-class state:
.stuff.otherclass:hover {
background-color: unset; /* Want blue in this case */
}
Is there a CSS option of going back to a pre-pseudo-class state?
Codepen demo:
http://codepen.io/anon/pen/EyEWww
The only way to roll back the cascade is using the revert keyword, but it rolls back to another origin.
There is no way to make the 2nd value in the output of the cascade become the cascaded value, ignoring the winner.
Instead, you can modify your selector and use the :not() pseudo class:
.stuff {
background-color: blue;
}
.stuff:not(.otherclass):hover {
background-color: red;
}
Or, alternatively, take advantage of .stuff.otherclass:hover having more specificity than .stuff:hover
.stuff, .stuff.otherclass:hover {
background-color: blue;
}
.stuff:hover {
background-color: red;
}

Confused about overriding CSS styles

I understand CSS basics, but I keep running into trouble with conflicting styles. Consider the following styles.
First, the default font color in my style sheets is black. I want that color applied to all picture captions - unless they're contained in divs with a class CoolL or CoolR...
.CoolL .Caption, .CoolR .Caption { color: #900; }
Now all the captions in the Cool series have brown text. But there are situations where I want the captions to have a black background with white text, so I created this rule:
.Black { background: #000; color: #fff; }
Now consider the following HTML. Class Caption by itself should have black text. However, this is inside a div with a class CoolR, so it displays brown text instead. But I added the class Black to the last div, which should change the background to black and the text color to white...
<div class="CoolR Plus Max300">
<div class="Shadow2">
<img src="">
<div class="Caption Black">Text</div>
</div>
</div>
In fact, the background is displaying black, but the text color is still brown.
I get these problems all the time, and the only way I can fix them is to write long, detailed styles, like this...
.Black, .Caption .Black, .CoolR .Caption.Black, .EverythingElseThatCouldBeBlack .Black { background: #000; color: #fff; }
What am I missing? Thanks.
I think you are over complicating things. This will become a maintenance issue as you add more styles. I would define separate classes and keep things simple. It's also important to understand CSS specificity.
.caption {
color: #000;
}
.cool-caption {
color: #900;
}
.caption-with-background {
background-color: #000;
color: #fff;
}
You could try :
.Black { background: #000 !important; color: #fff !important; }
There are a few fixes, but as previously recommended you should mark all of the settings you want to override previous ones with !important. With that, your code would look like this:
.Black {
background: #000;
color: #fff;
}
Also, not sure if you asked this, but you can apply CSS to all components by using the *, like so:
* {
//blahblahblah
}
you are defining the first case with a descendant selector which overrides the second class, which is merely a class. every answer given already will work but are entirely unnecessary. just add this to your style sheet:
.CoolR1 .Black, .Black{ background: #000; color: #fff;}
/** you could also chain your classes for specificity power **/
.Black.Caption{color:#fff}
that should do it. you can read more about selectors here:
http://docs.webplatform.org/wiki/css/selectors
I think that generally a more specific rule overrides a more general one, thus the more specific '.CoolR .Caption' is overriding the more general .Black. You'll probably be able to override this with !important, but a better style might be to reduce the complexity of your rules:
.Cool .caption { color: #900; }
.Cool .caption.black { color: background: #000; color: #fff; }
And put .L and .R in separate classes
.Cool.L { . . . } /* For things specific to CoolL, but not CoolR */
.Cool.R { . . . } /* and vice-versa */

How do I have an attribute reference itself in LESS?

I would like to have a property reference its "self", I am not sure how to do this in LESS. Heck I am having a hard time crafting the wording of the question. Basically I would like to accomplish the following:
a:visited {
color: lighten(color, 10%);
}
Where a's color could vary based on its container div.
So I might have the following selectors:
div#blue-text a {
color: #00F;
}
div#black-text a {
color: #000;
}
Once I visit the links, I should have a lighter blue and gray link texts respectively.
Note: this is a very simple scenario, but I have much more complicated needs, and if there is a clean way to do this, then I would be a happy camper.
Basically, since you're going to set the parent's color in LESS as well, you would store the color in a variable and reference it.
Here is an example:
#column1Color: #aaaaaa;
#column2Color: #bbbbbb;
#column3Color: #cccccc;
.columns {
// set the color of the first column
.column:nth-child(1) {
background-color: #column1Color;
a {
color: lighten(#column1Color, 10%);
}
}
// set the color of the second column
.column:nth-child(2) {
background-color: #column2Color;
a {
color: lighten(#column2Color, 10%);
}
}
// set the color of the third column
.column:nth-child(3) {
background-color: #column3Color;
a {
color: lighten(#column3Color, 10%);
}
}
}
LESS would not know what the color of the hyperlink is unless you "told" it. Same goes for the browser, it would not know the color unless it executes all the linked CSS files.
So, what you need (if I understood you correctly) can not be achieved the way you're thinking about it.

Resources