CSS cancel property by overriding class - css

I have following html:
<div class="red placeholder"></div>
<div class="blue placeholder"></div>
<div class="green placeholder"></div>
and CSS:
.placeholder {
width: 100px;
height: 100px;
margin: 10px;
border: 1px solid black;
}
.placeholder:hover {
background-color: gray;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
}
I should not change initial placeholder declaration(s) and I don't want DIVs to change colour on hover.
Is there any way I can override placeholder class to "cancel" or turn off that hover property?
jsFiddle: http://jsfiddle.net/8QJEq/4/

That was really a good question, since am not able to work out any easier way than this, you can check out my solution
div[class="red placeholder"]:hover {
background-color: red;
}
div[class="blue placeholder"]:hover {
background-color: blue;
}
div[class="green placeholder"]:hover {
background-color: green;
}
Demo
Explanation: What we are doing here is, we are selecting the elements having a combination of 2 classes, and than we use the same color on hover, which is their default background-color, so inshort, this won't take out the hover, it does hover, but because of the same background color, you won't see any change.

I would recommend to avoid targeting the elements in the first place if at all possible.
If that's not possible, you could just declare the hover state with each color. As long as .color:hover is declared after .placeholder:hover it will override it since they share the same specificity.
jsfiddle 1
CSS
.color, .color:hover { background-color: color; }
Though I wouldn't recommend it, but it sounds like you don't want divs with color classes to not change background-color you could also just declare the rules as !important. But this would only be a last resort option since you wouldn't be able to easily override the background-color again.
jsfiddle 2
CSS
.color { background-color: color !important; }

Related

SCSS target classes and pseudo selectors simultaneously

I'm writing a library and I'd like to style all buttons.
HTML
<div>
<p>Buttons</p>
<button>Button</button>
<button class="r1">Button</button>
</div>
<div>
<p>File inputs</p>
<input type="file" />
<input type="file" class="r1" />
</div>
SCSS
button,
input[type=file]::file-selector-button {
background: #81ecec;
border: 2px solid #00cec9;
&.r1{
background: red;
}
}
This code processes to:
button.r1,
input[type=file]::file-selector-button.r1 {
background: red;
}
[This is invalid and does not work]
Is there a mixin or method I can use so that I can place the classes on only the parent selector, without this getting out of hand? I intend to have multiple classes (primary, secondary, large, small) and I don't want to write:
button.r1,
input[type=file].r1::file-selector-button{
...
}
button.large,
input[type=file].large::file-selector-button{
...
}
button.small,
input[type=file].small::file-selector-button{
...
}
I can't figure out a good way of targeting the parent input[type="file"]
This codepen has the first example in it, and as it isn't valid CSS the background: red doesn't take effect:
https://codepen.io/EightArmsHQ/pen/VwxwPGM/139933ae274200149b84afdb726478c5?editors=1100
Attempt 1
At the moment I am using a mixin like so:
#mixin button{
background: var(--button-primary);
color: #fff;
text-decoration: none;
border: none;
display: inline-block;
padding: 4px 8px;
}
#mixin button-r1{
border-radius: 3px;
}
button,
.button,
input[type="submit"],
input[type="reset"]{
#include button;
&.r1{
#include button-r1;
}
}
input[type=file]{
&::file-selector-button{
#include button;
}
&.r1::file-selector-button{
#include button-r1;
}
}
The benefit is that I don't need to repeat the same styles over and over, however I feel like there must be a better way of creating a mixin that interpolates a class somehow.
Attempt 2
Using the classname as an argument works well, however I lose the ability to nest the rules, which is a shame and one of my favourite parts of SCSS.
#mixin buttonAndFileInputs($classname: "") {
button#{$classname},
.button#{$classname},
input[type="submit"]#{$classname},
input[type="reset"]#{$classname},
input[type="file"]#{$classname}::file-selector-button {
#content;
}
}
#include buttonAndFileInputs {
background: var(--button-primary);
color: #fff;
}
#include buttonAndFileInputs(".r1") {
border-radius: 3px;
}
I'm not 100% clear on what you're trying to do
But I think if you edit your codepen to this scss
button,
input[type=file] {
background: #81ecec;
border: 2px solid #00cec9;
&.r1{
background: red;
}
}
::file-selector-button {
background: inherit;
border: inherit;
}
that will get what you're looking for
Edit to add explanation:
This will make the file-selector-button follow the background and border properties of the input[type=file].
This means that the file-selector-button will match the rest of the input background.

CSS Background Color for :before / :after independent of parent

I have a series of CSS rules to add FontAwesome icons before/after links for PDFs, phone numbers, email addresses, etc.
Additionally, I have a global hover rule for links, which makes the background color of all link elements yellow.
.main a:hover {
background-color: yellow;
}
.main a[href^="tel"]:before {
content: '\f879';
background-color: transparent;
}
.main a[href^"tel"]:hover::before {
background-color: transparent;
}
<div class="main">
<p>Phone: 131313</p>
<p>Normal link - no icon</p>
</div>
My problem is that I don't want the yellow hover color to apply to the icons.
If I set the hover color on the pseudo-elements to a specific color (e.g., not transparent), everything is okay. But these links can appear anywhere (cards, accordions, etc.), which may have different background colors, so I'd rather not have to define every possible instance.
Here's my solution using jQuery to wrap with span all anchors that have attribute href starting with "tel". I don't have FontAwesome imported here so your icon does not display correctly, but you can see that your desired highlighting works even when the anchor is surrounded by paragraph text.
$(function() {
$('a[href^="tel"]').html('<span>' + $('a[href^="tel"]').html() + '</span>');
});
.main a:before {
content: '\f879A';
}
.main a span:hover {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="main">
<p>Hello, 131313!</p>
</div>
You can give position: absolute styling to your pseudo-element. This will seperate it from its parent. Try the following:
.main a[href^="tel"] {
content: '\f879';
background-color: transparent;
margin-left: 10px;
}
.main a[href^="tel"]:before {
content: '\f879';
background-color: transparent;
position: absolute;
left: 0;
}
Adjust the margin according to your liking!
You can use a shifted gradient but you will need to update the value based on your case as it will depend on the size of the icon:
.main a:hover {
background: linear-gradient(yellow 0 0) 10px no-repeat;
}
.main a[href^="tel"]:before {
content: '\f879';
background-color: transparent;
}
.main a[href^"tel"]:hover::before {
background-color: transparent;
}
<div class="main">
<p>131313</p>
</div>

CSS hover modify self and other class

I know there are a ton of answers on :hover effecting other classes. What I'm trying to do is change the font color of itself (.footer_status_tex) and background-color of another class (.footer_status_gear)
Simplified CSS - Something like this:
CSS
.footer_status_tex {
cursor: pointer;
color: #fff;
}
.footer_status_gear {
width: 36px;
height: 36px;
background-color: #000;
}
.footer_status_tex: hover {
color: #81aaf3;
}
.footer_status_tex:hover .footer_status_gear {
background-color: #aba51e;
}
HTML
<div class="footer_status_tex" style="">Hello</div>
<div class="footer_status_gear"></div>
Current setup only changes font color.
Thanks
First, you need to fix the selector .footer_status_tex: hover, remove the gap after :.
Second, the selector .footer_status_tex:hover .footer_status_gear only works if the latter one is a child of the former one.
What you need is .footer_status_tex:hover + .footer_status_gear or ~ if the latter one is a sibling of the former one, also the latter one must be placed next to the former one in the DOM.
.footer_status_tex:hover {
color: #81aaf3;
}
.footer_status_tex:hover + .footer_status_gear {
background-color: #aba51e;
height: 20px;
}
<div class="footer_status_tex">Hello</div>
<div class="footer_status_gear"></div>
You can use ~ adjacent selector to target the adjacent elements
Stack Snippet
.footer_status_tex {
cursor: pointer;
color: #fff;
}
.footer_status_gear {
width: 36px;
height: 36px;
background-color: #000;
}
.footer_status_tex:hover {
color: #81aaf3;
}
.footer_status_tex:hover ~ .footer_status_gear {
background-color: #aba51e;
}
<div class="footer_status_tex" style="">Hello</div>
<div class="footer_status_gear"></div>
When posting CSS problems, please also include the associated HTML code as without it, we're can only assess half the problem.
I'm assuming this is your structure: https://codepen.io/barrymcgee/pen/vdGOra?editors=1100#
The reason why the background of .footer_status_gear doesn't change is because it's the parent element of the link. A :hover pseudo-class can only direct the children of the element to which it is applied.
If the assumption I made about your HTML structure is wrong, please provide it and I'll look again.

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 */

Resources