Compile non-root CSS custom property - css

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.

Related

Can I nest classes in standard CSS like in LESS

With the LESS preprocessor, you can nest CSS code inside other CSS code, like this:
.Element {
.AnotherElement {
background-color: #FFF;
}
.YetAnotherElement {
background-color: #000;
}
}
This would make the background of .Element .AnotherElement white, and it makes .Element .YetAnotherElement have a background color of black. It does it all without writing it out like:
.Element .AnotherElement {
background-color: #FFF;
}
.Element .YetAnotherElement {
background-color: #000;
}
Does the first example coincide with CSS syntax, or do I have to use the LESS preprocessor?
Nesting is a feature of LESS and SASS, not native to CSS.
This is one of the most common uses for CSS preprocessors, but they offer a lot more too.
No, css doesn't support this syntax, in your css example the "Element" and "AnotherElement" will to receive this properties, AnotherElement will not inherit properties of Element.

SASS and Bootstrap - mixins vs. #extend

I'm using the SASS port of Bootstrap, and I'm wondering if there's any difference between using the pre-defined mixins and using SASS's #extend.
For instance, if I have:
<div class="wrapper">
Some content here....
</div>
Is there any difference between doing
.wrapper {
#include make-row();
}
and
.wrapper {
#extend .row;
}
?
If there's no difference, are there other mixins that aren't equivalent to a single #extend statement? If there aren't such mixins, why do the mixins even exist?
The big difference between #extend and a mixin is the way the css is compiled. It doesn't look like much in simple examples, but the differences and implications are significant and can be a real headache in the wild if used carelessly. #extend is a little bit like fools gold, looks great at first, but ...
Let's look at a simple example:
#extend
.row {
width: 50px;
}
.new-row {
#extend .row;
}
.another-row {
#extend .row;
}
compiles into:
.row,
.new-row,
.another-row {
width: 50px;
}
mixin
#mixin row() {
width: 50px;
}
.new-row {
#include row();
}
.another-row {
#include row();
}
compiles into:
.new-row {
width: 50px;
}
.another-row {
width: 50px;
}
A mixin includes the properties everywhere it is hit - copying them each time - whereas an #extend groups the selectors and defines the properties once. This isn't immediately obvious, because the difference is in the compiled css but it has some important implications:
Load order
With #extend the selectors will be grouped at the first point in the sass where they are encountered which can lead to some weird over-riding. If you define a selector and use #extend to bring in a property to and try to override a property defined earlier in your sass, but after the point at which the extended properties are grouped in the css then the override will not work. This can be quite perplexing.
Consider this logically ordered set of css definitions and the likely HTML: <div class='row highlight-row'></div>:
.red-text {
color: red;
}
.row {
color: green;
}
.highlight-row {
#extend .red-text;
}
compiles into:
.red-text,
.highlight-row {
color: red;
}
.row {
color: green;
}
So even though the sass ordering makes it look like the row colour would be red, the compiled css will make it green
Poor groupings
#extend can result in poorly grouped selectors in the resulting css. You can end up with thirty or forty unrelated things all sharing the same property for example. Using #extend for fonts is a good example of this.
Nesting
If you are using deeply nested sass (which is not good, btw) and you use #extend you will duplicate the fully nested selector for every #extend you use, resulting in bloated css. I've seen this a lot:
.selector-1 .selector-2 .selector-3 .selector-4,
.selector-1 .selector-2 .selector-3 .selector-4 a,
.selector-1 .selector-2 .selector-3 .selector-4 li,
.selector-1 .selector-2 .selector-3 .selector-4 td {
font-family: arial;
}
If you're new to SASS it pays to look at the compiled css.
Media queries
#extend do not work inside media queries, because media queries are not selectors.
Conclusion
My rule of thumb is to use an #extend over a mixin if you have no parameters and if you can reasonably define the #extend and share it amongst a few tightly related selectors that exist nearby in the sass, for example, in the same file that defines a sass module. Buttons are a good example of well used #extend:
%button {
padding: 10px;
}
.call-to-action {
#extend %button;
background-color: $green;
}
.submit {
#extend %button;
background-color: $grey;
}
The best article to help make the choice is here
PS, the % sign is a use of placeholder extends

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;
}

How can we know if any website is using Sass and Compass?

How can we know if any website is using Sass and Compass for CSS?
That's a though one, but I would take a look at the CSS files, IF the developers forgot about changing the output, you'll be able to spot the file names and line numbers of the source files.
If not, look for uncommon patterns in the CSS output, for instance SASS makes nesting very easy to do, so a selector could look like this in the CSS (you would never hand-write this long selectors)
div#wrapper div#container ul#myId li a { color: blue; }
div#wrapper div#container ul#myId li.sass a { color: red; }
But would be look like this in SASS source file (no repetition, easy to getaway with)
div#wrapper {
div#container {
ul#myId {
li {
a { color: blue; }
&.sass {
a { color: red; }
}
}
}
}
}
Also, look for lengthy class combinations, those come from using the #extend directive, that would look like this:
.button, .button1, .button-submit, .button-add-to-cart, .button-signup, .button-register {
display: inline-block;
}
Another good idea is to look in the source of CSS3 generated buttons, usually developers only care for Firefox, Safari, Chrome and IE, but a SASS generated output will be REALLY verbose with a lot of vendor prefixes, including ones for Opera.
Good luck!
if the developer forgot to compile for production or minify the .css, than you should still be able to see the automatically inserted comments that point back to the original source, like:
/* line 22, ../../../../../Ruby193/lib/ruby/gems/1.9.1/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
.selector {
bla: 123;
}
or
/* line 5, sass/large/_common.scss */
.selector {
bla: 123;
}

Does sass harm performance?

I've been educating myself. Reading this:
The engine evaluates each rule from right to left, starting from the rightmost selector (called the "key") and moving through each selector until it finds a match or discards the rule. (The "selector" is the document element to which the rule should apply.)
For example:
ul li a {...}
#footer h3 {...}
* html #atticPromo ul li a {...]
Now, some example code SASS outputs for me:
#content #blog {
/* ... */
}
/* line 85, ../sass/screen.scss */
#content #flickr {
/* ... */
}
#content #flickr div p {
/* ... */
}
This seems a bit awkward.. am I doing something wrong? Is this a communication problem between me and Sass? Are we losing it?
Edit:
Some SCSS code:
#flickr {
#include columns(5,8);
background: url('../img/ipadbg.png') no-repeat;
#ipod-gloss {
z-index: 999;
position: relative;
}
div {
margin-top: -80px;
margin-right: 20px;
h2 {
color: $white;
font-size: 24px;
}
p {
margin-top: 40px;
}
}
}
Side Bonus!: The article says browsers (or at least Firefox) search the selectors from right to left. I couldn't understand why this is a more efficient why. Any clues?
You have to find your compromise between maintainability (nesting makes it easier to find your way around in the stylesheet) and rendering performance.
A rule of thumb says you should try to restrict yourself to a three-level nesting and you should avoid to nest IDs if it's not necessary.
However, I think nesting too much is not the biggest issue. As soon as I became aware of the power of mixins, I used them a lot.
For example, this is my often used button mixin:
#mixin small-button($active-color: $active-color, $hover-color: $button-hover-color, $shadow: true)
display: inline-block
padding: 4px 10px
margin:
right: 10px
bottom: 10px
border: none
background-color: $button-color
color: $font-color-inv
+sans-serif-font(9px, 700)
text-align: center
text-transform: uppercase
cursor: pointer
#if $shadow
+light-shadow
&:hover
text-decoration: none
background-color: $hover-color
&:last-child
margin-right: 0
a
color: $font-color-inv
&, &:hover
text-decoration: none
&.disabled
+opacity(0.75)
&:hover
background-color: $button-color
&.active
background-color: $active-color
&.disabled:hover
background-color: $active-color
You see, quite a bit code. Applying such mixins to many elements on your page will result in a big CSS file which takes longer to be interpreted.
In the old fashioned CSS-way you would give each button element e.g. the class .small-button. But this method pollutes your markup with unsemantic classes.
Sass provides a solution though: selector inheritance via the #extend directive.
If you set defaults for your parameter of the mixin, you can also provide a simple class, which uses the mixins with your default:
// Use this mixin via #extend if you are fine with the parameter defaults
.small-button
+small-button
And then you can just inherit from this class in various contexts:
#admin-interface
input[type=submit]
#extend .small-button
The resulting CSS statement aggregates all usages of .small button into one rule with comma-separated selectors:
.small-button, #admin-interface input[type=submit] {
display: inline-block;
...
}
Concluding, a naive usage of Sass can effect your CSS performance. Used wisely, however, it is maintainable thanks to well-structured and DRY code, it leads to proper separation of markup and styling (semantic classes only) and allows for smart and performant CSS code.
SASS is only a language that compiles down to CSS. If you're concerned with SASS' performance in terms of how it runs in the browser, then SASS doesn't enter the equation -- it'll be compiled and served to the browser as regular CSS.
From what I can see of your usage of SASS, there's a couple of things I could suggest:
You don't have to nest everything.
The ability to nest rules inside each-other in SASS is a language feature, but you don't have to do it if it doesn't make sense to do so.
In terms of your general CSS usage:
If the nesting gets too severe/unwieldly, consider using classes where it makes sense.
When it's necessary to use the hierarchy of DOM elements, consider using the [child combinator]: .foo > .bar.
IDs are meant to be unique, thus should always only reference a single element. Most of the time, they can be CSS rules unto themselves -- #content #flickr would become just #flickr, for instance -- and browsers will optimise the lookup for a single ID. The only time you would need something like #id1 #id2 is if #id2 needs to appear in different contexts on different pages.
If your selector contains things like #id div p, that div is either superfluous or serving a specific purpose.
If it's superfluous, change the rule to #id p, which selects any <p> that occurs as a descendant of #id.
If it serves a specific purpose, consider classing the <div> with a class name that describes its purpose -- perhaps <div class="photos-list">. Then your CSS could become .photos-list p, which is far more maintainable and reusable.

Resources