I'm using SASS for a project and so far I'm pretty satisfied with it.
However I have some code that should only be presented for IE 7 and below, using the class name .ie-lt8 for that. But when i extend that selector in SASS, with a nested selector i create multiple selectors.
Example (extending a display: inline-block code for IE):
SASS
/* My extension code */
.ie-lt8 %ie-inline-block {
display: inline;
zoom: 1;
}
/* I want the li to be inline-block */
#my-ul li {
display: inline-block;
#extend %ie-inline-block;
}
CSS produced
/* My extension code */
.ie-lt8 #my-ul, #my-ul .ie-lt8 li {
display: inline;
zoom: 1;
}
/* I want the li to be inline-block */
#my-ul li {
display: inline-block;
}
Generally this is just fine, but the #my-ul .ie-lt8 li worries me a little. In this example it's ok as the code works fine with both selector (the mentioned selector just doesn't exists). But what if i have another code where the selector DOES matter, then this would cause a problem.
A thought example:
SASS
/* I want the div to get a red border,
but the div inside .container to have a green border */
#myid .container div { border: 5px dotted green; }
#myid div {
#extend %red-border;
}
/* My extension code */
.container %red-border {
border: 1px solid red;
}
CSS it would produce
/* I want the div to get a red border,
but the div inside .container to have a green border */
#myid .container div { border: 5px dotted green; }
/* My extension code */
.container #myid div, #myid .container div {
border: 1px solid red; /* [OVERRIDE OF THE BORDER] */
}
My question is then; is there a way to make SASS only take the initial selector, without creating multiple selectors from a nested selector (a lot of selectors in one sentence)?
I tried gooling for this issue, but i find it hard to find any articles/blogs/etc. regarding this issue.
UPDATE
I'm aware of various workarounds, such as using #mixin's instead. I was just wondering whether there was something i missed regardig SASS, or if someone could tell me why this is? Cause it seems to me like it's kind of a bug.
My answer is in SCSS - not SASS so you'll have to convert...
For browser targeting like this, I would recommend using mixins, and furthermore - #content within a #mixin to achieve your desired results. It also sets up a much more understandable set of rules with context.
For your specific example, it's as simple as moving your inline-block fix into a mixin instead of declaring only as a class.
#mixin ie7-inline-block {
display: inline;
zoom: 1;
}
#my-ul li {
display: inline-block;
.ie-lt8 & {
#include ie7-inline-block;
}
}
Even better than that though, by using #content, you can always ensure that your style is prefixed with .ie-lt8 by making a mixin like so:
#mixin ie7 {
.ie-lt8 & {
#content;
}
}
#my-ul li {
display: inline-block;
#include ie7 {
display: inline;
zoom: 1;
}
}
Which will output the same css, but allows your IE7-Specific styles to be wrapped each time in some context that makes sense to anyone who reads your code.
Related
I have a custom element x-foo which I have defined a custom CSS property on to set the background-color called --xbg.
I use the element with elements of itself as children as so:
<x-foo class="outer">
Outer
<x-foo class="inner">
Inner 1
</x-foo>
</x-foo>
When I set --xbg on the outer, that value overrides the value of the inner element:
x-foo.outer {
--xbg: orange;
}
x-foo.outer x-foo {
--xbg: red;
/* Doesn't work, have to use !important?!?!*/
}
I've used the inspector in Chrome and can see that the child definition indeed is "lower" then the parent.
I have to "force" it to get higher with !important, which then has all sorts of other implications.
x-foo.outer x-foo {
--xbg: red !important;
/* Works */
}
Why is the child not overriding the parent property?
Here's a plunker for this with some more examples:
https://plnkr.co/edit/uZxg7G?p=preview (Only works in Chrome)
Simpler JSBin for other browsers:
http://jsbin.com/wuqobejeci/edit?html,output
the best way to solve this is to say the style only applies to the class contentwrapper from that host down
<style>
:host {
display: block;
}
:host > .contentwrapper {
padding: 1em;
background-color: var(--xbg, yellow);
}
</style>
Like that,
Here is a working Fiddle
The element has lower priority than the class. Try
x-foo.outer {
--xbg: orange;
}
x-foo.outer x-foo.inner {
--xbg: red;
}
Thought this was worth trying just based on Andrew's answer above -- just using the host style alone seems to work:
<style>
:host {
display: block;
padding: 1em;
background-color: var(--xbg, yellow);
}
</style>
https://jsfiddle.net/6tzoacxr/
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Is it possible to do something similar to this in CSS:
.class1:checked + class2{
.sidebar{
color:blue;
}
}
In the case of class1 being checked, look at it's sibling(class2) and change #sidebar's color to blue.
yes, you can target a class inside of CSS statement by using SASS features. First you should Learn SASS.
Nesting feature:
SCSS Syntax:
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
Output:
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
in CSS you could do something like :
.class1:checked + .class2 > .sidebar {
color : blue
}
If the checkbox with class="class1" is checked, class="class2" his child, class="sidebar" will adept the blue color.
Here is a working Codepen
It worked for me this way!! Now it depends, how are you actually using your code, or how you have written your HTML.
/* by default, next text is red */
.class2 {
color: red;
}
/* if checked, next text is green */
.class1:checked + .class2 {
color: green;
}
#sidebar {
color: pink;
}
/* if checked, next text is blue and its child gets below CSS */
.class1:checked + .class2 #sidebar {
color: blue;
border: 1px solid #f00;
display: inline-block;
}
<label for="check">we are trying to make your code work</label>
<input type="checkbox" id="check" class="class1">
<p class="class2">If the checkbox is checked, the next link SIDEBARLINK should have border of red color for demo purpose.
Sidebar Link
</p>
Assuming #sidebar is in a different part of the HTML from .class1 etc., then no, you cannot do this. CSS selectors are a sequence of element specifiers where each specifier is either below (child or descendant) or at the same level (following sibling) as the previous one, and the final one is the one targeted. You cannot randomly reach out and affect a different part of the HTML. The curly bracket notation you invented in an attempt to target the sidebar is not CSS, and although it looks a bit like SASS, which confused some of the people answering, is not SASS and no, SASS cannot magically do what CSS cannot. SASS is mere syntax sugar.
My website here I'm creating for a friend is giving me issues with the input[type="button"]. I only a specific style to be applied to the button in the sidebar ONLY. However no matter what I do it effects all buttons.
#sidebar.widget-wrap input[type="button"], input[type="submit"] {
clear: both;
display: block;
margin-top: 2em;
width: 100%;
}
How do I make it only effect the go button in the sidebar?
You must duplicate #sidebar.widget-wrap:
#sidebar.widget-wrap input[type="button"],
#sidebar.widget-wrap input[type="submit"] {
}
Otherwise your selector would result in every input[type="button"] that is inside #sidebar.widget-wrap and every input[type="submit"].
The comma has no special meaning, it only combines two (or more) selectors. The result will always be the same if you use two separate selectors instead of the combined one:
div a, div span { color: yellow }
/* is the same as */
div a { color: yellow }
div span { color: yellow }
in the following there are some IE6 css hacks I need their standard equivalence.
.header {
zoom: expression(runtimeStyle.zoom=1);
z-index: 1;
}
.hmenu ul li {
float: left !important;
}
ul.hmenu li {
margin-left: expression(this.previousSibling==null?'0':'1px');
}
.nav {
position: expression(runtimeStyle.position='relative');
}
ul.hmenu li {
margin-left:expression(this.previousSibling==null?'0':'1px');
}
This is equivalent to li { margin-left: 1px; } and li:first-child { margin-left: 0; }.
I don't see the point of the other expressions, other than to set the properties in an IE<9-only way.
zoom: expression(runtimeStyle.zoom=1);
is setting zoom:1 so you can achieve hasLayout
float: left !important;
!important is supported in all browser and simply adds another layer of specificity to your declaration. i am quite positive that !important is not important in the above css...no pun intended :)
position: expression(runtimeStyle.position='relative');
runtimeStyle object represents the style of the object, which overrides the format and style specified in global style sheets, inline styles, as well as HTML attributes.
in this case, on pageload, .nav's position is set to relative
My Html is like this:
<a class="another addAnother">Add another</a>
I defined a style for the above using 'another' class like this in a external style sheet.
fieldset.associations a.another {
color: #693;
display: block;
margin: 7.5px 0px 15px;
}
I am trying to override the style of tag using 'addAnother' class, like this(wherever required):
fieldset.associations a.addAnother {
display: none;
}
But I am unable to override. Any help is appreciated.
Is there any rule that while overriding a style the selector should be same(I tried this, but no avail)??
Both properties have the same importance, because both selectors are equally specific. So if the second one appears first in the CSS, it needs to acquire more importance to override one that is lower down. You could override the first one by being more specific, like this:
fieldset.associations a.addAnother.another {
display: none;
}
or
#someID fieldset.associations a.addAnother {
display: none;
}
or
body fieldset.associations a.addAnother {
display: none;
}
Both your original declarations have a specificity of 0,0,2,2. If the second declaration is below the first, it should overrule it. If it doesn't, reorder your declarations or increase the specificity.
You could add the body tag in order to increase specificity:
body fieldset.associations a.addAnother {
display: none;
}
That will increase specificity by 0,0,0,1, the minimum amount of specificity you can add.
You can also make it specific to the .another class by chaining class declarations:
fieldset.associations a.another.addAnother {
display: none;
}
That will increase specificity by 0,0,1,0.
Here is an article explaining CSS specificity. Note that the article fails to mention that !important increase specificity by 1,0,0,0, making it near impossible to overrule.
fieldset.associations a.addAnother {
display: none !important;
}
It would ultimately depend on where those two styles are in your CSS, but you can't give one more importance like this:
fieldset.associations a.addAnother {
display: none !important;
}