CSS style priority confusion [duplicate] - css

This question already has answers here:
How are the points in CSS specificity calculated
(7 answers)
Closed 5 years ago.
CSS
.wrapper > * {
background: deepskyblue;
}
.item {
background: deeppink;
}
HTML
<div class="wrapper">
<div class="item">
Test
</div>
</div>
Above is my CSS class and HTML. So since I have gave style for .item class below the wrapper > * here.
But the item's background is still getting deepskyblue.
Should it be deeppink?
I know I can use !important in .item to get it deeppink but why is this happening in this order is what I want to know.

To understand why you aren't seeing the result you want, you need to first understand CSS Specificity and what weight selectors have (which is too long of a discussion as an answer to this question).
First, your original set of rules:
.wrapper > * { // [0,0,0,1,0]
background: deepskyblue;
}
.item { // [0,0,0,1,0]
background: deeppink;
}
Both of these rules have a specificity of [0,0,0,1,0] because of the single class within each selector. The * selector has a weight of 0, so it does not add any weight to the first rule. Since both rules affect the same property on the same element, the rule that comes last wins: in this case, background: deeppink;
However, your actual rules are different:
.wrapper[_ngcontent-c1] > *[_ngcontent-c1] { // [0,0,0,3,0]
background: deepskyblue;
}
.item[_ngcontent-c1] { // [0,0,0,2,0]
background: deeppink;
}
In this case, the first rule wins because it is more specific. Attribute selectors have a weight of [0,0,0,1,0].
To remedy this, you have to make a selector that equals or surpasses the specificity of the rule to be overridden.
For example:
.wrapper[_ngcontent-c1] > *[_ngcontent-c1] { // [0,0,0,3,0]
background: deepskyblue;
}
.wrapper[_ngcontent-c1] > .item[_ngcontent-c1] { // [0,0,0,4,0]
background: deeppink;
}

Related

Why CSS attribute selector followed by element tag is slower?

According to Vue docs here:
Due to the way browsers render various CSS selectors, p { color: red }
will be many times slower when scoped (i.e. when combined with an
attribute selector). If you use classes or ids instead, such as in
.example { color: red }, then you virtually eliminate that performance
hit
So if you put the following in the Vue's style section:
<style scoped>
.parent .child {
background-color: red;
}
.parent p {
background-color: red;
}
</style>
The VueJs will transform it into this:
<style>
.parent[data-v-12345] .child {
background-color: red;
}
.parent[data-v-12345] p {
background-color: red;
}
</style>
The document says, the second selector is many times slower than the first one.
Can someone explain why the second selector is slower?

Can I target multiple divs with one nth-child() selector?

Say I have a parent div with three child divs inside and I want to give each child a different background colour, can this be done with only one nth-child selector - my parent div has a class of "parent" and the three children have classes of "child1", "child2", "child3".
Thanks.
Yoy can't set 3 background-color in one selector (the 2 override by last defenition) as in image
I recommand you learn about selector in css:https://www.w3schools.com/cssref/css_selectors.asp
and more learn here(thanks to #Mosh Feu):https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors
and: https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors
SO you have to do it as below:
.parent .child1{
background-color:red;
}
.parent .child2{
background-color:orange;
}
.parent .child3{
background-color:blue;
}
<div class="parent">
<div class="child1">one </div>
<div class="child2">tow </div>
<div class="child3">three </div>
</div>
You won't be able to do this with just one rule and just one selector.
In CSS, every rule applies a specific set of styles to all the elements that match its selector(s). This is a fundamental aspect of how CSS works. You can't have different declarations in a single rule apply selectively to specific elements — they will all just get overridden, leaving you with just one winning declaration that gets applied to all the elements that are matched. This is true even if you have multiple selectors in the same rule, and even if you use :nth-child() instead of class selectors.
For example,
.child1, .child2, .child3 {
background-color: red;
background-color: blue;
background-color: yellow;
}
is treated as
.child1, .child2, .child3 {
background-color: yellow;
}
which applies a yellow background to all three children, both despite and because of the fact that all three children are listed. The same holds true with .parent > :nth-child(1), .parent > :nth-child(2), .parent > :nth-child(3) as the selector.
Therefore, if you want to style three elements differently, you will need three rules, one for each element:
.child1 {
background-color: red;
}
.child2 {
background-color: blue;
}
.child3 {
background-color: yellow;
}
Again, this is true regardless of what selector you use to actually reach each child element. The point is that each set of style declarations (property: value pairs) needs to appear in its own set of selector {} rules.
Why do you want to use nth selector if your child elements use different classes? Nth-selector should be used for elements that haven't got class selector or where the content is dynamic. In this particular case you don't need nth selector, just use
.parent .child1 {
background-color: #d3d3d3;
}
.parent .child2 {
background-color: #000;
}
<div class="parent">
<div class="child1">child1</div>
<div class="child2">child2</div>
</div>

How to use :not selector with links [duplicate]

This question already has answers here:
CSS negation pseudo-class :not() for parent/ancestor elements
(2 answers)
Closed 7 years ago.
i have a hover effect for the links on my website. i want these to apply to every link EXCEPT ones in a particular div.
Example HTML
<div id="menu">
<div class="menu_item">
<a href="index.html" title="Home" target="_self">
<img src="_images/_menu/Home.png"
onmouseover="this.src='_images/_menu/homeHover.png'"
onmouseout="this.src='_images/_menu/Home.png'"
onclick="this.src='_images/_menu/homePressed.png'" alt=""/></a>
</div>
</div>
The CSS i have been trying to us
a:hover:not(.menu_item) {
background-color: #D6910E;
color: #FFE1A7;
} *no change*
a:hover:not(#menu) { *no change*
a:hover:not(#menu.menu_item) { *turns off hover on all links*
a:hover:not(#menu .menu_item) { *turns off hover on all links*
want these to apply to every link EXCEPT ones in a particular div
The standard approach to such problems in CSS is to give the general rule first, then the specific rule to override it. Using :not is a slippery slope and should be reserved for special cases. So:
/* State the general rule first */
a:hover {
background-color: #D6910E;
color: #FFE1A7;
}
/* Give the exception */
.menu_item a:hover {
background-color: transparent;
color: inherit;
}
If you do want to use :not, you have to understand that the predicate applies to the current element:
a:hover:not(#menu)
does not mean a tags being hovered which are not children of #menu; it means a tags being hovered which are not themselves #menu (which will always match). To do what you are trying to do with :not, you would want to try something like
:not(#menu) a:hover
However, this will also not work, because it means "a tags being hovered which have any ancestor which is not #menu", which will also almost always match.
Why you don't make it easier ?
Like
a:hover {
background-color:red;
color:red;
}
#menu .menu_item:hover{
/* Default color */
}
In your case , you can repair it by change the position of "hover"
a:not(.menu_item):hover {
background-color: #D6910E;
color: #FFE1A7;
} /*no change*/
a:not(#menu):hover { /*no change*/ }
a:not(#menu.menu_item) :hover { /*turns off hover on all links*/
a:not(#menu .menu_item):hover { /*turns off hover on all links*/
Hope it 'll help you

SCSS: Increase a property by fixed pixels [duplicate]

Is it possible, in Sass, to manipulate a value a given element already inherits?
I am aiming for something like this:
body
color: blue
.warning
color: red
strong
color: darken(inherit,20)
Inheritance
No. Sass doesn't 'know' what selector to inherit the color from. It would have to know that strong is a descendant of body. That seems like a reasonable enough assumption for you and I since strong is not allowed outside of the body, but that sort of assumption cannot be made about most selectors. Sass would also have to know that there are no cascades happening from other ancestor elements.
ul {
color: red;
}
ol {
color: blue;
}
li {
// which color do I inherit from ????
}
Well can I specify which selector I want to copy from?
Sass does not grant access to the values of any previously declared variables in any fashion, either. There is no way to specify "be darker than the body's color". CSS rules are not objects or mappings and are not accessible in any way. Your case may be simple, but consider a more complex case like this:
.foo {
background: mix(white, blue); // fallback for non-rgba browsers
background: rgba(blue, .5);
.baz & {
background: yellow;
}
#media (min-width 30em) {
background: orange;
}
#supports (flex-wrap: wrap) {
background: red;
}
}
.bar {
// access which background color from .foo ????
}
Well what can I do?
You'll either need to use variables or it has to be a feature of vanilla CSS to do what you want.
Old-Fashioned CSS
Some properties can give the illusion of being generated/inherited dynamically using stuff that's been supported by browsers for years:
ul.one {
background: white;
}
ul.two {
background: yellow;
}
ul {
background: rgba(0, 120, 255, .2);
padding: 1em;
}
<ul class="one">
<li><ul>
<li><ul>
<li>Foo</li>
</ul></li>
</ul></li>
</ul>
<ul class="two">
<li><ul>
<li><ul>
<li>Foo</li>
</ul></li>
</ul></li>
</ul>
CSS Variables
Generating CSS variables is about as close as you're going to get to being able to manipulate an inherited property. Browser support isn't quite there yet (check caniuse), but here's what that would look like:
Sass:
ul {
--list-color: orange;
--darker-color: darken(orange, 15%);
color: var(--list-color);
}
ol {
--list-color: green;
--darker-color: darken(green, 10%);
color: var(--list-color);
}
li {
background: var(--darker-color);
}
Output:
ul {
--list-color: orange;
--darker-color: #b37400;
color: var(--list-color);
}
ol {
--list-color: green;
--darker-color: #004d00;
color: var(--list-color);
}
li {
background: var(--darker-color);
}
<ul>
<li>Foo</li>
</ul>
<ol>
<li>Bar</li>
</ol>
If you're using a browser that supports CSS variables, the result should look like this:
I was looking for the same thing, and came across this. Your question was answered, but it didn't solve the problem.
Here's the solution: http://codepen.io/monsto/pen/tiokl
If your HTML was this:
<div class="main">
<header class="header">
<div class="warning">
<p><strong>Danger,</strong> Will Robinson!</p>
</div>
</header>
</div>
Then using SASS you could do this:
$bg: #f88;
#mixin colorize {
$bg: darken($bg,15%) !global; // !global flag required for 3.4 or later, remove if using 3.3 or older
background: $bg;
}
.warning {
background: $bg;
p {
#include colorize;
strong {
#include colorize;
}
}
}
SASS seems to have no idea of the results of it's output. Therefore, inherit means nothing to it. You're basically asking it to know what the output is before it's output.
It does however know it's variables as, by default, they're tightly scoped.
From the docs:
Variables are only available within the level of nested selectors where they’re defined. If they’re defined outside of any nested selectors, they’re available everywhere.
AND THEN variables in mixins:
The block of content passed to a mixin are evaluated in the scope where the block is defined, not in the scope of the mixin.
This allows the above mixin to take a known variable, defined in the parent level, and redefines it for the current level and available to it's children. It's like doing $x = $x + 1 inside a multi-nested loop
TBPH, this rather changes the way I think about SASS. It's clearly a lot more programmatic than I thought.
Given that an element cannot have multiple of the same properties that combine and the fact that inherit can't know what the current rendered state is, your options are to
1) Keep track of the past transforms yourself using SASS variables: Demo
.parent {
$firstTrans: translateX(50%);
transform: $firstTrans;
.child {
/* Old followed by new */
transform: $firstTrans rotate(10deg);
}
}
2) Apply the transform to a parent (perhaps adding another container if needed): Demo
3) Use Javascript to combine the current transform with the one you want to add (this is the only way you can make sure to remove the transform applied to the parent if that's desired): Demo
Note: This answer is from a merged post because of this meta post.
This answers addresses the darken function specifically: A possible alternative is using the CSS brightness() filter instead of SASS's (or LESS's) darken() function. You will basically need to wrap the color inside a span tag so the filter would not affect other elements.
Simple demo:
.red {color: red}
.blue {color: blue}
.green {color: green}
span {
display: inline-block;
padding: 1em;
}
.darken span {
-webkit-filter: brightness(0.4);
filter: brightness(0.4);
}
<span class="red">Red</span>
<span class="blue">Blue</span>
<span class="green">Green</span>
<div class="darken">
<span class="red">Red</span>
<span class="blue">Blue</span>
<span class="green">Green</span>
</div>
jsFiddle: https://jsfiddle.net/azizn/hhorhz9s/
You need to keep in mind browser compatibility, it should work for IE Edge, latest Firefox and Chrome. See caniuse or MDN for more information.
In the case of a background darken, you could use a pseudo selector with opacity or add a semi-transparent black PNG background-image.

Is it possible to append CSS transform properties using Sass? [duplicate]

Is it possible, in Sass, to manipulate a value a given element already inherits?
I am aiming for something like this:
body
color: blue
.warning
color: red
strong
color: darken(inherit,20)
Inheritance
No. Sass doesn't 'know' what selector to inherit the color from. It would have to know that strong is a descendant of body. That seems like a reasonable enough assumption for you and I since strong is not allowed outside of the body, but that sort of assumption cannot be made about most selectors. Sass would also have to know that there are no cascades happening from other ancestor elements.
ul {
color: red;
}
ol {
color: blue;
}
li {
// which color do I inherit from ????
}
Well can I specify which selector I want to copy from?
Sass does not grant access to the values of any previously declared variables in any fashion, either. There is no way to specify "be darker than the body's color". CSS rules are not objects or mappings and are not accessible in any way. Your case may be simple, but consider a more complex case like this:
.foo {
background: mix(white, blue); // fallback for non-rgba browsers
background: rgba(blue, .5);
.baz & {
background: yellow;
}
#media (min-width 30em) {
background: orange;
}
#supports (flex-wrap: wrap) {
background: red;
}
}
.bar {
// access which background color from .foo ????
}
Well what can I do?
You'll either need to use variables or it has to be a feature of vanilla CSS to do what you want.
Old-Fashioned CSS
Some properties can give the illusion of being generated/inherited dynamically using stuff that's been supported by browsers for years:
ul.one {
background: white;
}
ul.two {
background: yellow;
}
ul {
background: rgba(0, 120, 255, .2);
padding: 1em;
}
<ul class="one">
<li><ul>
<li><ul>
<li>Foo</li>
</ul></li>
</ul></li>
</ul>
<ul class="two">
<li><ul>
<li><ul>
<li>Foo</li>
</ul></li>
</ul></li>
</ul>
CSS Variables
Generating CSS variables is about as close as you're going to get to being able to manipulate an inherited property. Browser support isn't quite there yet (check caniuse), but here's what that would look like:
Sass:
ul {
--list-color: orange;
--darker-color: darken(orange, 15%);
color: var(--list-color);
}
ol {
--list-color: green;
--darker-color: darken(green, 10%);
color: var(--list-color);
}
li {
background: var(--darker-color);
}
Output:
ul {
--list-color: orange;
--darker-color: #b37400;
color: var(--list-color);
}
ol {
--list-color: green;
--darker-color: #004d00;
color: var(--list-color);
}
li {
background: var(--darker-color);
}
<ul>
<li>Foo</li>
</ul>
<ol>
<li>Bar</li>
</ol>
If you're using a browser that supports CSS variables, the result should look like this:
I was looking for the same thing, and came across this. Your question was answered, but it didn't solve the problem.
Here's the solution: http://codepen.io/monsto/pen/tiokl
If your HTML was this:
<div class="main">
<header class="header">
<div class="warning">
<p><strong>Danger,</strong> Will Robinson!</p>
</div>
</header>
</div>
Then using SASS you could do this:
$bg: #f88;
#mixin colorize {
$bg: darken($bg,15%) !global; // !global flag required for 3.4 or later, remove if using 3.3 or older
background: $bg;
}
.warning {
background: $bg;
p {
#include colorize;
strong {
#include colorize;
}
}
}
SASS seems to have no idea of the results of it's output. Therefore, inherit means nothing to it. You're basically asking it to know what the output is before it's output.
It does however know it's variables as, by default, they're tightly scoped.
From the docs:
Variables are only available within the level of nested selectors where they’re defined. If they’re defined outside of any nested selectors, they’re available everywhere.
AND THEN variables in mixins:
The block of content passed to a mixin are evaluated in the scope where the block is defined, not in the scope of the mixin.
This allows the above mixin to take a known variable, defined in the parent level, and redefines it for the current level and available to it's children. It's like doing $x = $x + 1 inside a multi-nested loop
TBPH, this rather changes the way I think about SASS. It's clearly a lot more programmatic than I thought.
Given that an element cannot have multiple of the same properties that combine and the fact that inherit can't know what the current rendered state is, your options are to
1) Keep track of the past transforms yourself using SASS variables: Demo
.parent {
$firstTrans: translateX(50%);
transform: $firstTrans;
.child {
/* Old followed by new */
transform: $firstTrans rotate(10deg);
}
}
2) Apply the transform to a parent (perhaps adding another container if needed): Demo
3) Use Javascript to combine the current transform with the one you want to add (this is the only way you can make sure to remove the transform applied to the parent if that's desired): Demo
Note: This answer is from a merged post because of this meta post.
This answers addresses the darken function specifically: A possible alternative is using the CSS brightness() filter instead of SASS's (or LESS's) darken() function. You will basically need to wrap the color inside a span tag so the filter would not affect other elements.
Simple demo:
.red {color: red}
.blue {color: blue}
.green {color: green}
span {
display: inline-block;
padding: 1em;
}
.darken span {
-webkit-filter: brightness(0.4);
filter: brightness(0.4);
}
<span class="red">Red</span>
<span class="blue">Blue</span>
<span class="green">Green</span>
<div class="darken">
<span class="red">Red</span>
<span class="blue">Blue</span>
<span class="green">Green</span>
</div>
jsFiddle: https://jsfiddle.net/azizn/hhorhz9s/
You need to keep in mind browser compatibility, it should work for IE Edge, latest Firefox and Chrome. See caniuse or MDN for more information.
In the case of a background darken, you could use a pseudo selector with opacity or add a semi-transparent black PNG background-image.

Resources