Why does a descendant selector override a class selector? - css

I have classes like this:
.tableGeneric tr td
{
text-align: center;
vertical-align: middle;
border: 1px solid black;
}
.tdValignTop
{
vertical-align: top;
}
When I apply these classes, I expect that a td with class .tdValignTop would be vertically-aligned to the top, even when .tableGeneric tries to align it to the middle. However, it would seem that I am wrong: the table cell would use .tableGeneric's styles instead of .tdValignTop's styles.
Here's a fiddle to demonstrate.
So... why? Isn't a specific class style/selector supposed to override base/parent styles? Is there some kind of logic or reasoning behind this behavior? I assume the behavior is intentional, but I cannot find any documentation on it.

What you think of as “specific” is not more specific in the CSS sense, and it is CSS specificity that matters when applying CSS. The CSS specificity rules define specificity on terms of the syntactic structure of a selector. In this case, the first selector has one class name and two element names, so it is more specific than the other, which only contains a class name.

This is because the first style rule you defined is more specific than the second, thus it will override.
If you do this it will work as you expect:
.tableGeneric tr td
{
text-align: center;
vertical-align: middle;
border: 1px solid black;
}
.tableGeneric tr td.tdValignTop
{
vertical-align: top;
}
Working example here.

Related

How to apply only custom properties to an element?

In very simple html/css, I have my menu in a <table id="menu">. The menu has no border, however I would like all the other tables in my blog to have borders.
I made it work this way:
#menu, #menu th, #menu td {border: none; color: red}
table, th, td {border: 1px solid black;}
However this is not very robust. If I add something else to tables I might forget to 'reset' it in #menu. Is there a way to force all properties in #menu so that I don't have to override one by one anything I would add to table, th, td {...}?
I tried the :not() selector but it doesn't feel robust either, I would rather specify what I want for menu on the #menu {...} line, not elsewhere. Let me know if that makes sense or I can reformulate
I think that I understand now. I was searching for a way to unset all values for a css class and came across this page: Reset/remove CSS styles for element only
It tells us that we can do something like this to achieve what you want:
#menu, #menu th, #menu td {
all: unset;
color: red;
}
table, th, td {
border: 1px solid black;
}
Notice how I added the all: unset; and removed the border: none;
This should reset all the styles for elements with that id, but make sure to put your other styles AFTER the all: unset, or else it will unset the styles you just wrote. Hope this helps!
Maybe using classes instead of id's.
If you use a class you can apply a css rule to all elements that have It
So for example to your table you can use
.custum-table
The prevoius class Will apply css styles to all elements
And finally if you wanna apply another css rule you can add another class to your element in this way
Another html file
.custom-table__no--effect
Previous class with BEM Will apply css styles to only one element for example table element

How to make inheritence in CSS?

I have the following problem:
I have a font with a given style in a css class:
.font_arial_36 {
font-family:Arial;
font-size:36px;
}
And now I have a css that gives me the size of a div in a given situation:
.a_div_test {
width:300px;
max-width:350px;
}
I want the a_div_test to have the properties of the font_arial_36, like an inheritance.
Somethin like (this is wrong just posting what I wanted):
.font_arial_36 {
font-family:Arial;
font-size:36px;
}
.a_div_test extends font_arial_36 {
width:300px;
max-width:350px;
}
and now the .a_div_test should also have the font_arial_36 properties.
Is it possible with css?
PS: I do not want to add multiple classes to an Html Element like that:
<div class="font_arial_36 a_div_test"></div>
Because I should rewrite my code in many places where .a_div_test appear.
This is not possible in CSS. What you do is you assign the 2 classes to the element you want.
<div class="font_arial_36 a_div_test"></div>
CSS stands for "Cascading Style Sheets". That means that a top-level element will cascade its styles to its child elements. As long as .a_div_test elements are contained within the subtree of elements of .font_arial_36, they will receive (inherit) all the styles from .font_arial_36.
That's why you define a font-family inside the <body> tag if you want it to apply to all elements within the page.
That is, the inheritance is defined by the HTML structure, not the CSS itself.
why you need to extend when you can add multiple classes with space on HTML element.
<div class="font_arial_36 a_div_test">Like this</div>
As suggested by others, there is no way you can inherit once CSS property into another. Only way is to add both the class to a DOM element to mimic the inheritance. Css solution:
<button class="uiButton disabledButton">Click Here</button>
For below CSS:
.uiButton {
background-color: gray;
color: lightgray;
font-size: 20px;
font-family: "Segoe UI", Helvetica, sans-serif;
text-align: center;
text-decoration: none;
padding: 10px 10px;
border:none;
display: inline-block;
margin: 5px 5px;
cursor: pointer;
}
.disabledButton
{
background-color: gray;
color: lightgray;
cursor: not-allowed;
}
In above: The Button is first styled with uiButton class and then disabledButton class. So whichever CSS class you write later in 'class' attribute, will overwrite properties of earlier one (in case if anything is common).
But, there is a better way:
Yes, if you are ready to use CSS pre-processors like https://sass-lang.com/guide
Note that Sass is a pre-processor. Meaning, Sass file (.scss) will be compiled into CSS (but chrome provides nice debugging for .scss i.e. Sass file). You can write plain CSS in the SCSS file and additionally use directives to achieve inheritance and much more. To make the life easier, there are some software which will automatically create css when scss file is modified (I know http://koala-app.com/ which does that).
if you don't want to add multiple classes to html element then
.font_arial_36, .a_div_test {
font-family:Arial;
font-size:36px;
}
.a_div_test {
width:300px;
max-width:350px;
}
other than this no other possible way seems to be there for inheritance in css, we have to use sass

Css selector when one class is present and not both classes

I want to do something like this .horizontal-nav:not(.horizontal-nav.responsive-nav-enabled)
i.e. I want to apply styles of .horizontal-nav only if the div does not have the .responsive-nav-enabled class. If it has both classes then the styles of .horizontal-nav must not apply. Is it possible?
You need to use .horizontal-nav:not(.responsive-nav-enabled) to get the desired result:
.horizontal-nav {
height: 20px;
border: thin solid;
}
.horizontal-nav:not(.responsive-nav-enabled) {
background-color: red;
}
<div class='horizontal-nav'></div>
<div class='horizontal-nav responsive-nav-enabled'></div>
The problem with your original selector is that it is invalid and rejected by the browser. :not accepts a simple selector while .horizontal-nav.responsive-nav-enabled is a sequence of simple selectors.

Polymer custom style sometimes cascades incorreclty

I've noticed that the cascade isn't always correct when using polymer custom style. From the looks of it, this could be a bug in the way the cascade is being applied to custom elements, but I'd just like to confirm that I'm not doing something silly.
Consider the following, scoped style, for my custom element:
#price ::content .price span {
display: block;
padding: 4px;
border-top: 1px solid var(--color-gray1);
}
#price ::content .price span:first-child { border-top: none; }
... but once rendered, the :first-child gets overridden by first definition, as you can see in the image below. The only way to ensure that my border: none is applied correctly, is to use !important, which I'd rather not.
I should note that I've seen this behaviour in many other places, and have opted to just use !important as a quick solution, but this starts to feel clunky.
Just adding the image of the rendered element here to show the "incorrect" top border.
From what I’ve understood, the problem comes from the CSS variables/custom properties polyfill.
It adds another class, .product-0 in this case, to scope the property where you use var(--color-gray). You probably figured this also already, but just pointing it out.
You can override that with an equally specific selector (no need to use !important), e.g. #price ::content .price.price span:first-child (notice the duplicate .price).
I don’t know if this can be fixed in the polyfill.
The first declaration is more specific than the second one. This could be the problem.
The Specification of the DOM structure is Major role to override the css.
#price ::content .price span {
display: block;
padding: 4px;
border-top: 1px solid var(--color-gray1);
}
#price ::content .price span more specific than the #price ::content .price span:first-child.

Force to use style for a selector, no matter where it is in the dom

Say I would like to define a numbered circle, that looks like this:
http://jsfiddle.net/edi9999/6QJyX/
.number
{
border-radius: 50%;
width: 32px;
height: 24px;
text-align: center;
padding-top:8px;
font-size: 14px;
display:inline-block;
line-height: 16px;
margin-left:8px;
color:white;
background-color:black;
border-color:white;
}
I would like to add importance to the selector, so that no matter in what context the element is, an element with class number looks the same.
Here's an example of the code breaking: http://jsfiddle.net/edi9999/6QJyX/2/
A way to do this would be to add !important to all properties of the CSS, but I wonder if they could be other solutions, because it is a bit crappy.
I have added the private tag as that seems a bit like code-encapsulation.
Your best option is to increase the specificity of the selector. Other than that there is not much you can do.
#id .number
The ID selector will increase specificity so that only another ID in a selector will be able to override it.
http://jsfiddle.net/6QJyX/3/
Increasing the specificity of selectors will only lead to specificity wars (which leads to anger, which leads to hate, which leads to suffering). I would suggest decreasing the specificity of the selector that's causing the problem.
Pseudo code below:
.number {...}
.card span {...} // this selector is questionable
<div.number> this is styled correctly </div>
<div.card>
<span.number> this is styled incorrectly </span>
</div>
Why do all .card spans need to be styled a particular way? It seems as if the second selector is more like a grenade and less like a sniper—that is, it targets a blanket set of elements rather than just the ones you need.

Resources