How to I avoid that the CSS rule * {} trump .a .b {}? [duplicate] - css

This question already has answers here:
How are the points in CSS specificity calculated
(7 answers)
Closed 3 years ago.
Using MDC I get the following structure:
<div class="mdc-fab">
<span class="mdc-fab__icon">
<i>x</i>
</span>
</div>
In the CSS file from MDC there is the following rule:
.mdc-fab .mdc-fab__icon {
font-size: 24px;
}
However in my own CSS-file I have this rule that overrides the rule above:
* {
font-size: 1rem;
}
I want that rule to ensure that no font-size is less than 16px. However here it overrides the rule from MDC which is not what I want.
Can I rewrite my rule in some way?
EDIT: Since there seem to be some confusion, please look at this Codepen: https://codepen.io/lborgman/pen/RwNGzmP
And please observe that I can not change the MDC rule.

.mdc-fab .mdc-fab__icon {
font-size: 1rem;
}
Specificity wins so you will need to be specific.

You are mistaken in that your selector of * overrides .mdc-fab .mdc-fab__icon; the latter will override the former. This is a problem of specificity.
In order to overcome this, you'll want to increase the specificity of your selector so that it is either higher than that of MDC or equal to it and referenced later.
It depends on the specific element you need to target, and there are numerous ways to achieve this, but one approach would be to target the <i> with:
.mdc-fab .mdc-fab__icon i {
font-size: 1rem;
}
Or alternatively make use of the child combinator > with:
.mdc-fab > .mdc-fab__icon {
font-size: 1rem;
}
To target the <span> itself.
If you only want to have to declare it once, you can make use of the !important declaration, though this is generally frowned upon, as it carried the highest level of specificity (making it very difficult to override). If, however, you are certain that you want to apply this font-size to all elements on your page, then it will be the easiest option:
* {
font-size: 1rem !important;
}

Related

Increase class specifity automatically with sass

I need to increase class specifity of a given class selector.
Example:
.test {
color: #fff;
}
At the moment i need to type .test.test to increase specifity.
Is there another approach to solve this, like a function increase() or some other way of increasing it without appending the same classname?
If you're using SCSS, then the simplest way (besides forcing it with !important) is to include a parent selector so that it has a higher specificity:
.parent {
.test {
color: #fff;
}
}
Another method is to target the element as well (if it's always the same type of element). This would also give it a higher specificity.
div.test {
color: #fff;
}
If all else fails, you can try moving the code block lower in the SCSS file, since the last selector in the document will win if they have the same specificity. Or, give it the good ol' !important at the end.
.test {
color: #fff !important;
}
there are multiple approaches:
- You can use !important, so that you do not need to repeat class twice. but this is a bad practice.
- Best way - you can place the class code in the last so that even if the specificity is equal, last one will override previous.
- you can use parent selector or tag selector, but that makes code dependent on that parent or tag.
- you can learn more about specificity on https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

Why don't media queries override normal CSS? [duplicate]

This question already has answers here:
When to use the !important property in CSS [duplicate]
(13 answers)
How are the points in CSS specificity calculated
(7 answers)
Closed 5 years ago.
Do I need to add !important to all properties in the media queries I've written for my site like in the example below?
I had the CSS below at the bottom of my stylesheet, but I found that these properties did not reflect my design until I added the !important tags. I understand that using the !important tag is not best practice.
CSS
.loginbar {
padding: 20px;
}
.logo {
display: inline-block;
}
#media screen and (max-width: 1042px) {
.loginbar {
padding: 10px !important;
}
.logo {
diplay: none !important;
}
}
HTML
<div class=".logo"></div>
<div class="loginbar">Log In | Sign Up</div>
In theory, no - you don't need the !important flag. The issue you are probably experiencing arrises from specificity:
Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of different sorts of CSS selectors
Mozzila
The basic math (hugely simplified) behind specificity is a weighted approach.
id is worth 100,
class is worth 10,
tag is worth 1.
Therefore a.class (tag + class = 11) is less specific that a#id (tag + id = 101).
CSS is also applied in a last-match-wins format, that is to say that the style for the last declared selector that matches will be applied (sorted according to the above specificity).
So - in your example, it could be that there are elements on you page with the class .element which is being targeted with a more specific selector (such as .container div > ul li + li .element (which is a lot more specific than just .element) so the styles from that is overriding the styles from your media style.
The caveat to this, is if the !important flag is being used. In which case the only way to override the styles is to supply the !important flag again.

Nesting CSS selectors without increasing specificity

Let's take these three selectors, sorted from the highest specificity to the lowest:
.special-section p { }
.weird-font { }
p { }
Many CSS gurus recommend against nesting like in the first selector .special-section p, because its specificity is high enough that you can't override it with a simple class like .weird-font. I would like to find a way to still achieve nesting like in .special-section p, but without increasing specificity. Something like this:
.weird-font { }
.special-section p /* with hack to decrease specificity */ { }
p { }
Use case:
It's pretty safe to apply defaults for typography and such document-wide using simple selectors like p. However, I would like to change those defaults for a particular section, similar to .special-section p, without having to use hacks to increase the specificity of selectors like .weird-font. I would rather use a hack to decrease the specificity of .special-section p than use a hack to increase the specificity of .weird-font. Is there a way to do this?
You can't decrease the specificity, but you can add an even more specific selector for the exception.
.weird-font, /* Normal weird font */
.special-section p.weird-font /* Override for special section */
{ }
But as you can see, it's a sliding scale. So those gurus are probably right. If you would remove .special-section p, and instead give those P's their own selector .special-section-para or something, then you won't have this problem.
But personally, I don't mind having to add an exception like the one above now and then. I think the whole specifity thing is there for that purpose, and if you need a more specific selector to style something, to me that seems the right thing to do.
A commonly heard solution is to use !important. The problem with !important is that there is only one level of override. If you make a more specific selector, you can override it again with a still even more specific selector. After using !important, you're out of options. More importantly, using !important may interfere with special style sheets that a user may have for increased readability. For that reason I never use !important in a situation like this.
But then again, I don't consider myself a CSS guru. ;)
These days, in 2018, this is getting close to possible.
First of all, CSS4 will have a way that allows you to create more specific selectors without increasing specificity:
:where(.special-section) p {
color: red;
}
This will set the paragraph color inside .special-section to red, but with a specificity of 001 (i.e. the same specificity that a plain p selector would have).
The spec still calls this special pseudo-class :something(), but chances are it's going to be called :where(). (Side note: I really want this to be known as the "honey badger selector").
But that's still in the future.
However, there is actually a way to achieve this today, if you don't have to support IE anymore (or are happy with less-than-perfect fallbacks), and that is by using custom properties a.k.a. CSS variables.
So you want this:
.special-section p { color: red; }
.weird-font { color: magenta; }
p { color: green; }
but with the first part having a specificity that's lower than any selector with a class in it. You can do it like this:
.special-section p { --low-specificity-color: red; }
.weird-font { color: magenta; }
p { color: var(--low-specificity-color, green); }
If you run the below snippet in a modern browser, you should notice that the second paragraph is red, because it's in a special section, but the third paragraph is magenta, because it's .weird-font -- even though .weird-font has 010 specificity and .special-section p has 011.
.special-section p { --low-specificity-color: red; }
.weird-font { color: magenta; }
p { color: var(--low-specificity-color, green); }
<p>This is a paragraph.</p>
<section class="special-section">
<p>This is a paragraph inside a special section.</p>
<p class="weird-font">This is a paragraph with a weird font inside a special section.</p>
</section>
<p class="weird-font">This is a paragraph with a weird font.</p>
<div class="weird-font">This is a div with a weird font.</div>
This works because while the --low-specificity-color is changed with 011 specificity, it is only applied with a 001 specificity.
As a CSS guru, I bemoan the idea of throwing out everything Selectors has to offer just to avoid specificity issues. That's not to say I don't believe the specificity mechanic is flawed, but surely there are less dramatic workarounds for it.
First off: no, you can't decrease the specificity of a selector. Selectors doesn't provide any features with negative specificity levels that would decrease specificity in such a manner. The lowest you can go is *, which has zero specificity (i.e. it does not make a complex selector any more or less specific).
So your only recourse on the selector level is to increase it. Whether you can do this without using hacks depends on your definition of "hack".
The following is what I would consider a hack, because it makes use of a syntactically legal but semantically nonsensical selector like :not(_) that has no obvious purpose but to add a type selector's worth of specificity to a complex selector (which is far from obvious especially to the uninitiated):
.special-section p { }
.weird-font, :not(_).weird-font { }
The following is not what I would consider a hack, because it's something you would do normally anyway. Pretty much the only "issue" with it is that it's an apparent repetition of the lone class selector:
.special-section p { }
.weird-font, .special-section p.weird-font { }
If you consider any sort of extraneous selector for the sake of increasing specificity a hack — which is a perfectly reasonable POV, make no mistake — then the next best thing that isn't a hack is !important.
Personally, I would choose a specificity hack. !important has, ahem, important repercussions that don't come with a specificity hack — remember that !important and specificity have different semantics. For example, you cannot override an !important declaration with an inline style or JavaScript unless they are marked important as well.1
1 In fact, this was my response to Lea Verou when she had a discussion on Twitter some time ago regarding specificity hacks versus !important.
I like to be as specific as is currently necessary. I do like to leave room for future CSS changes, so don't go as specific as possible for the sake of it, such as:
.great-grandfather .grandfather .father .child { }
I will if I have to of course. But taking the example above, if I wanted to override the .child for a particular element that uses this class which has styling which might be like this:
.child {
color: black;
}
I'd go one parent above to override it, if possible:
.father .child {
color: white;
}
Further down the line, if an element on a particular page uses the .child class and in this case I need to override both the .father .child, I'll go one more level of specificity:
.grandfather .father .child {
color: red;
}
Doing it this ensures you don't need to use !important... Which I avoid like the plague as much as possible!

How are unknown/invalid pseudo-classes in CSS selectors handled?

What does this CSS selector should point to? AFAIK :bar pseudo-class does not exist...
.Today_s_foo:bar
{
font-size: 21px;
font-family: "Ubuntu";
}
Normally it should invalidate the whole rule, which may be important when using multiple selectors in one rule, see simple example: http://jsfiddle.net/S56xM/
HTML:
<div>Hello!</div>
CSS:
div, div:foobaresque { font-size: 100px; }
You will see that the div { font-size: 100px; } "sub-rule" is not applied, even if our mind tells us it would be applied.
Per the current specification for parsing errors in selectors: "the entire rule in which the selector is used is dropped." See also this part of the spec for an example of the consequences.
By "rule" it means every property setting inside the {brackets} will be ignored if any part of the selector is parsed as invalid.
Correction applied
The rules in .Today_s_foo will not be set on any working browser.
I thought it was listed as an Unrecommended hack on http://www.javascriptkit.com/dhtmltutors/csshacks3.shtml
IE
.Today_s_foo:IE6 /* IE6 hack */
but its not there.

Is it possible to give one CSS class priority over another?

Say I have a div that uses two css classes that both use text-align, but one is centered and the other is right aligned.
Is it possible to specify something that will give one class priority over the other?
specify a more specific selector, eg prefix an ID before it or prefix the nodename before the class
assign it after the other class
if two classes are in separate files, import the priority file second
!important
!important is the lazy way, but you really should go for #1 to avoid important-ception. Once you've added one !important you can't use it to make some other rule even more important.
If you want to be explicit about it, you can specify how the combination of those two classes work together, by supplying a rule for elements that contain both classes. For instance, you can explicitly give something with both classes foo and bar the same styling as just bar as follows. This works because .foo.bar is more specific than just .foo for elements which have both classes, and thus this rule will take precedence over the .foo rule.
.foo { text-align: center }
.bar, .foo.bar { text-align: right }
If you don't want to be this explicit, you could just place the rule for bar after the rule for foo, as given selectors of the same specificity, later rules take precedence over earlier ones:
.foo { text-align: center }
.bar { text-align: right }
You can learn more about how precedence between rules is determined in the CSS specification chapter about the cascade; that's the "C" of CSS, and is important to understand well in order to take full advantage of CSS.
You should use CSS specificity to override previous declarations
http://htmldog.com/guides/cssadvanced/specificity/
p = 1 point
.column = 10 points
#wrap = 100 points
So:
p.column { text-align: right; }
can be overwritten by:
body p.column { text-align: left; }
as “meder omuraliev” has answered, you may use a more specified selector. and I would like to provider a general way that how to sepcific a higher priority for any type of selector, that is use the attr presdeo.
for example:
html body .foo { font-family: Arial !important;}
html body .bar[attr]{ font-family: Arial !important;}
to override this you may use like this:
html body .foo:not([NONE_EXISTS_ATTR]){ font-family: Consolas !important;}
html body .bar[attr]:not([NONE_EXISTS_ATTR]){ font-family: Consolas !important;}
To add to the other answers, you don't need to add selectors not related to what you originally wanted to increase specificity, the same can be achieved by repeating the same selector multiple times:
.foo.foo takes precedence over .foo, and .foo.foo.foo takes precedence over the previous ones.
This is better than adding non-related selectors, because you only select what you really want to select. Otherwise you might get unexpected behaviour when unrelated stuff you added changes.
.bar { text-align: right !important;}
use !important
Example :
p {
background-color: red !important;
}

Resources