SASS: Expression with Combined &:not selectors - css

I am trying to understand what this SASS code will generate:
&--active, &:not(&--disabled):not(&--inactive):hover, &:not(&--disabled):not(&--inactive):focus {
background-color: white;
color: grey;
}
I am wondering about this part:
&:not(&--disabled):not(&--inactive):hover
The first part of the expression is clear to me &:not(&--disabled).
This will exclude the class &--disabled when applying the styles written below. But what does it mean the scss next to it - :not(&--inactive):hover? And these &:not selectors used combined?
Also, this scss has some strange behaviour - on localhost this doesn't not work - does not apply at all, and when it is deployed on a test server, it got applied and works fine (it gets compiled and minified by gulp plugins).
Any help and advice would be appreciated.

why not compile it and then reason about the output ?
into http://www.sassmeister.com/ put the following
(.parent is just a parent rule which is needed to use the & parent selector)
.parent {
&--active, &:not(&--disabled):not(&--inactive):hover, &:not(&--disabled):not(&--inactive):focus {
background-color: white;
color: grey;
}
}
and behold:
.parent--active,
.parent:not(.parent--disabled):not(.parent--inactive):hover,
.parent:not(.parent--disabled):not(.parent--inactive):focus {
background-color: white;
color: grey;
}
so having the output we return to the matter at hand
&:not(&--disabled):not(&--inactive):hover
is
.parent:not(.parent--disabled):not(.parent--inactive):hover
ergo
any .parent which does not have .parent--disabled and .parent--inactive classes will have a white background and grey color on :hover
(.parent is just an example here - could be div,#foo, ...)

Related

Simple SASS modules classes can’t work together for specificity

I want to be able to not have to use !important and instead simply resolve by just using more specific selectors. Take this element for example:
<div>
<p className={`${headerStyles.headerOuter} ${bodyStyles.something} ${otherStyles.another}`}>Test</p>
</div>
It uses three classes each defined in separate css modular files:
import headerStyles from ‘…’
import bodyStyles from ‘…’
import otherStyles from ‘…’
Let’s say that headerStyles.module.scss contains:
.headerOuter {
color: blue;
}
bodyStyles.module.scss contains:
div .something {
color: red;
}
And otherStyles.module.scss contains:
.another {
color: green;
}
The p will have red text since bodyStyles is more specific.
But I want to be able to do this in headerStyles.module.scss:
.headerOuter {
&.another {
color: blue;
}
}
// or .headerOuter.another
So that headerOuter and another can work together to be higher in specificity than bodyStyles to force the element to apply blue text. But the problem is that headerStyles and otherStyles don’t seem to be able to recognise each other.
How can this be fixed?
I’ve made a similar demo here, where the text should be black but it’s not: https://codesandbox.io/s/css-modules-react-forked-mxtt6 - see another.module.scss and the text should be black
Thank you
From the codepen
The color: black selector is:
._src_another_module__another._src_another_module__something
While the actual element's classes are:
_src_test_module__test
_src_sassy_module__something
_src_another_module__another
The second element's class contains "sassy", it is different from the selector, that's why it doesn't match.
You can check it with the DevTools. The blue and red styles are shown as overwritten, the green has more specificity, but the black one doesn't even apply for the element as shown in the picture below.
Edit
I think there is lack of information about the actual tool behavior or just
a misunderstanding. The way it builds the name is _src + _<file_name> + _<selector_name>.
That being said:
/* The final style from "another.module.scss. */
._src_another_module__something {
color: red;
}
._src_another_module__bling {
background: #eee;
font-family: sans-serif;
text-align: center;
}
._src_another_module__bling button {
background: red;
}
._src_another_module__another {
color: blue;
}
._src_another_module__another._src_another_module__something {
color: black;
}
Notice the #import './sassy.module.scss' has nothign to do with the black stuff, it just duplicates the style with a different naming.
<!-- The final element with it's classes. -->
<p class="_src_test_module__test _src_sassy_module__something _src_another_module__another">
test
</p>
Note: all this code comes from the codepen.
Text isn't black because you are including the selector something from the import of sassy.module.scss with the ${style.something}, therefore the class will be named as _src_sassy_module__something (which is the red one).
If not yet, I encourage you to check the results with the DevTools often.
<p className={`${testStyles.test} ${styles.something} ${anotherStyles.another}`}>test</p>
The reason it is not working is that the latest calssname which is another is being called and it dosent effect what you do with the previous classes that are added to the element which here is something. In the scss file another.modules.scss you are importing the sassy.module.scss, this updates the style on the class something but dosent effect the style on the latest class another.
`#import './sassy.module.scss';
.another {
color: blue;
&.something {
color: black; // should be black
}
}

Compile non-root CSS custom property

Are there any tools to compile CSS custom properties declared at not :root rule? I want following code with custom properties
.dark {
--bg-color: black;
--fg-color: white;
}
.light {
--bg-color: white;
--fg-color: black;
}
.foo {
background: var(--bg-color);
display: block;
}
.bar {
color: var(--fg-color);
display: inline;
}
be compiled to their non-custom-prop equivalents like that
.light .foo, .light.foo {
background: white;
}
.dark .foo, .dark.foo {
background: black;
}
.light .bar, .light.bar {
color: black;
}
.dark .bar, .dark.bar {
color: white;
}
.foo {
display: block;
}
.bar {
display: inline;
}
The goal is to
switch color schemes by switching dark/light class on root DOM element
use valid css syntax (no sass less)
keep rules code compact
It's actually not safe to do that. I can tell you because I tried so hard to make a safe transformation.
But I failed.
https://github.com/postcss/postcss-custom-properties/issues/1
Ideal solution. Your example is valid CSS and can be used in many browsers (not in IE, Edge (but is in development) and Opera Mini as of writing this answer, 2017-03-27, other major browsers are fine).
Suboptimal solution. Some CSS can be transpiled to achieve better browser support. The solution I found does not support variables on non-:root elements, however. There are also other objections against transpiling of 'future' CSS into 'current' CSS. To the best of my knowledge, you will have to implement your own transpiler (or postcss plugin) if you want to transpile custom properties not on the :root element, but be warned that that is hard in general. Now you don't need the general part, so it is possible. Just does, to the best of my knowledge, not exist yet.
Preprocessing solution. Of course, you don't need a general implementation of custom properties. You have different themes that have their own values for the same set of properties and that's it. Thus, a separate stylesheet can be created as a preprocessing step using any CSS preprocessor.
Now you say the following,
use valid css syntax (no sass less)
but I am going to show this anyway, because I believe that it is a valid solution to your problem. It is definitely the only one I know that actually works if you want to/need to support IE, Edge and/or older versions of other major browsers (Firefox < 31, Chrome < 49, Safari < 9.1, Opera < 36)
You could do this using SASS for example, to do the transpiling on the server side.
// define styles, use variables throughout them
// your entire style definition goes into this mixin
#mixin myStyles($fg-color, $bg-color) {
.foo {
display: block;
background: $bg-color;
}
.bar {
display: inline;
color: $fg-color;
}
}
// define themes, that set variables for the above styles
// use named arguments for clarity
.dark {
#include myStyles(
$fg-color: white,
$bg-color: black
);
}
.light {
#include myStyles(
$fg-color: black,
$bg-color: white
);
}
This compiles to the following.
.dark .foo {
display: block;
background: black;
}
.dark .bar {
display: inline;
color: white;
}
.light .foo {
display: block;
background: white;
}
.light .bar {
display: inline;
color: black;
}
This is not exactly what you want to obtain, but very close. Realistically, I think this is the closest you will get to obtaining your desired output. I know you want to
keep rules code compact
but what you are saying there (I think) is that you want to split out custom properties from their rules to save on number of rules, which is not something any preprocessor I know supports.
You can organize your source SASS in separate files to keep an overview easily. You can even set up a build system that generates a separate stylesheet for every theme you have. It is then possible to have your users select an alternative stylesheet. Browsers have some support for this, but switching using JavaScript is also definitely possible in the latter case. Simply set all stylesheets to be disabled except for the selected one. Here is an example.

CSS/LESS if more then one element

Is there any way, of having a if like syntax, where I can check (for an example) there are more than input[type="text"]
Something like:
.my-element >= 1 {
border: 1px solid red; // Each .my-element will have a red border
}
.my-lement == 1 {
border: 1px solid green; // The only .my-element will have a green border
}
In javascript I would do something like:
if ($('input[type="text"]').length >= 1)
I mentioned LESS in the title, because I'm writing my css code in a LESS syntax
You can, in some cases, approximate this (albeit it requires an up-to-date browser, compliant with CSS3):
input {
border-color: #f00;
}
input:only-of-type {
border-color: #0f0;
}
JS Fiddle demo.
The above works on the assumption that you're trying to style an input element which is the only input element (or 'element of that type') as a child of its parent (it has no siblings of the same input element-type).
If, however, you're trying to style an element differently according to whether it has any sibling elements, you can use:
input {
border-color: #f00;
}
input:only-child {
border-color: #0f0;
}
JS Fiddle demo.
References:
:only-of-type (Mozilla Developer Network).
:only-of-type (W3C.org).
NO, in CSS there is no if else . Use JavaScript for changing your css dynamically.
the if statement is not present in LESS as well. But this language supports guard expression which may help in mimicking some if statements.
Check this tutorial

Is it possible to use previous class declaration in new definition in CSS?

I've tried to find the answer, and can't seem to do so, which is leading me to believe that it isn't possible. With my minimal knowledge of how CSS works, I also don't think it would be possible, but I just want to ask before I start working around a problem that may or may not exist.
Basically what I'm trying to do is use a previously defined attribute in a new class in my CSS stylesheet. For instance, say I had a couple of classes that just held background or font colors, like this:
.black { background-color: #000000; color: #000000; }
.white { background-color: #FFFFFF; color: #FFFFFF; }
Now if I was defining a new class (or using any selector for that matter), would it be possible to use the value of an attribute from an already existing class? Here is what my idea would look like:
.newClass {
width: 100%;
height: 100%;
background-color: .black; /* this would just get the background-color attribute from the .black class definition */
}
background-color: .black; is basically just a placeholder for "get the background-color attribute from the .black class definition". Is that possible using purely CSS? I'm aware of a ton of alternatives with PHP/JS, but I'd like to know if CSS can tackle this by itself. Thanks guys.
SASS is a thing to go. Your code will be like
#mixin black-theme {
.black { background-color: #000000; color: #000000; }
}
.newClass {
width: 100%;
height: 100%;
#include black-theme;
}
SASS
PHP compiler for SASS PHPSASS
There are javascript based solutions too like LESS but I generally don't recommend them as if Javascript load slow then presentation becomes jerky.
No, this is not currently possible in CSS. CSS does not have variables or the ability to reference values from previous rules. You would have to look for a CSS preprocessing language that gets processed into plain CSS before going onto the web site.
If you're willing to go the preprocessed way, you can look at SASS or LESS.
Yea possible using SASS or LESS css
#bgcolor : black;
.newClass {
width: 100%;
height: 100%;
background-color:#bgcolor;
}

New to E4 (Styling UI with css). Confused with TabFolder & CTabFolder

I am learning the E4. Trying to add styling css to my simple RCP. I've use the TabFolder & TabItem in my code, but when I tried:
CTabFolder, CTabItem {
background-color: red;
}
It does not affect the UI, then I tried
TabFolder, TabItem {
background-color: red;}
This does not work, either.
I did a quick search in internet and found that all the samples are using CTabFolder, CTabItem. And nobody tells the TabFolder, TabItem
I got confused on it. What's the difference between them? And what kind of css could work properly for components TabFolder, TabItem?
I suggest you to use the CSS Spy and CSS Scratchpad, to see the available properties, and test the possible combinations.
For a list of SWT - CSS mappings for CTabFolder, you can visit this page: https://wiki.eclipse.org/E4/CSS/SWT_Mapping#Widget:_CTabFolder
Below, you can see a CSS with a simple example
CTabFolder Composite {
background-color: pink;
}
CTabFolder CTabItem {
background-color: lime;
color: green;
}
CTabFolder CTabItem:selected {
background-color: blue;
color: white;
}
And then see the result in the image below, applied using the CSS Scratchpad

Resources