I'm trying to learn SASS now, and I'm having trouble trying to visualize exactly how differently I would arrange my code. How would I, for instance, arrange the following code into SASS so that it avoids repetition?
a: link {color: #000; text-decoration: none;}
a: visited {color: #000; text-decoration: none;}
a: acive {color: #000; text-decoration: none;}
Currently the only way I can think of is adding two different variables with the following appropriate attributes, but that still seems repetitive to me. I have also considered mixins, but am unsure how exactly to incorporate them in this example.
��Thanks in advance for the help. Also, as far as I understand it, SASS isn't meant to enhance web performance, just workflow. Is this correct? I say this specifically because, when processed, the code ends up looking the same on CSS.
The repeated part of this is the a and the styles color: #000; text-decoration: none.
So, with SASS you can nest your styles so you only need to write a once. The syntax for :link etc, is &:link.
Therefore, you can write:
a {
&:link,
&:visited,
&:active {
color: #000;
text-decoration: none;
}
}
Or if you do have variables, e.g. $black: #000; you can swap them in. color: $black.
It's not only for workflow though. One of the main advantages of using SASS (or LESS) is that you can organise your SASS files separately e.g. _buttons.scss, _layout.scss etc, and then import (using #import) them all into one 'theme.scss' and then have SASS compile the 'theme.scss'.
How this compilation is done depends on your setup, but Compass (Compass.app for the UI lovers like me) is a very popular option. What you end up with is the browser only request 1 file for styles, rather than many.
#mixin links($color:#000,$tdec:none){
a{
&:link,&:visited,&:active{
color:#{$color};
text-decoration: #{$tdec};
}
}
}
Then use the mixin ;
#include links();
or
#include links(#fee,underline);
may be this is what you're looking for.
Yeah. SASS doesnt meant to enhance web performance. But im sure SASS can mess your CSS if you use it wrong way(unnecessary nesting etc).
When you get used to it, it'll save your coding time alot.
Related
I'm curious what the CSS directive #apply does. I have googled #apply but I couldn't find anything that could explain its meaning properly for me.
What is the usage of such a directive?
The simple way of explaining it would be; introducing variables into CSS (which is a feature of preprocessors, such as Sass), and mixins which are function like behaviors (also in preprocessors).
Imagine that --header-theme is a function (mixin):
:root {
--header-theme: {
color: red;
font-family: cursive;
font-weight: 600;
};
}
h1 {
#apply --header-theme;
}
h2 {
#apply --header-theme;
}
This way, you can use it in many different places without having to rewrite it again (DRY).
Now the variable part could be explained with this example:
:root {
--brand-color: red; /* Default value */
--header-theme: {
color: var(--brand-color);
font-family: cursive;
font-weight: 600;
};
}
h1 {
#apply --header-theme;
}
h2 {
--brand-color: green;
#apply --header-theme;
}
The mixin will have a variable sent to it and change the color.
This is not the limits of the feature, and you can use it for far more. You can read more about mixin and variables in Sass for other ways of using it, and after I suggest you read this blog post.
Now after I got you excited, it is time for the bad news. It is not implemented in browsers yet (Chrome), but it is still worth knowing that it is coming and maybe if you want to prepare yourself start with Sass.
#apply is from a proposal that has since been abandoned, and replaced with CSS Shadow Parts.
the #apply rule, which allows an author to store a set of properties
in a named variable, then reference them in other style rules.
Tailwind uses this as a special directive.
Tailwind's #apply is kind of like a super-class. You can list other classes that should apply to this rule. I think of it as a way to group classes together that are often found together.
#apply is pretty cool. It basically allows you to reuse CSS blocks without having to copy them around and without having to modify their selectors.
It will make it easier to use CSS frameworks and keep semantic class names at the same time.
I found this article to be a nice instruction to this feature.
Unfortunately, at the moment, browser support is basically non-existent. It can be used with a CSS pre-processor such as PostCSS.
It's future is also uncertain, if I understand well. The main advocate behind this feature stopped supporting it.
Is there/what is the best way to set a variable in my CSS stylesheet that is cross browser compatible?
I want to set
color: #123456;
into a variable since I am using it in numerous different spots and if I choose to change that colour I want it all the change.
CSS Variables are a thing but the only browser that has any support for it at this time is Mozilla.
Alternative options:
use Javascript and/or a server-side language to set the variables in your CSS file programatically.
use a CSS preprocessor like SASS. This allows you to create variables. You do have to re-deploy your CSS each time.
consider handling colors a different way in your markup.
Regarding the last one, instead of hardcoding a color into an elements style:
<div class="thisElement"></div>
.thisElement {
font-size: 13px
background: red;
color: #123456;
}
consider using classes for this instea:
<div class="thisElement color1"></div>
.thisElement {
font-size: 13px
background: red;
}
.color1 {
color: #123456;
}
That way you only need to declare the color once in your style sheet. This is essentially 'object oriented CSS'. The idea is that instead of applying monolithic style declarations for each DOM object, you instead declare 'snippets' of style to a bunch of separate classes, then assign those separate classes as you see fit to each DOM object.
In a sense, you've turned the class name, itself, into the variable. You declare it in your CSS once, then use it as many times as needed in your HTML.
If you want to do it in native css you can't. However, you can use technologies / preprocessors like SASS / LESS to achieve exactly what you are describing.
Cross-browser compatibility, variables and calculating.
Once you get used to the syntax (which is really easy to understand and modify) and you are ready to go, SASS creates the "plain" css files for you. Keeps your code clean, simple and easy to maintain.
Have a look at this:
http://sass-lang.com/
Also, here you can find some examples and snippets to have a first impression.
Its not well supported, but this is how it works according to
http://www.w3.org/TR/css-variables/
Custom properties define variables, referenced with the var() notation, which can be used for many purposes. For example, a page that consistently uses a small set of colors in its design can store the colors in custom properties and use them with variables:
:root {
--main-color: #06c;
--accent-color: #006;
}
/* The rest of the CSS file */
#foo h1 {
color: var(--main-color);
}
You can to use a preprocessor like SASS, which has this done much better.
Which CSS authoring technique do rendering engines process more efficiently:
1) repeating the same style property/value pair in multiple selectors, or
2) grouping shared style properties in a single selector
Example 1: Duplicate font-size, but less rules
p {
font-size: 1em;
color: #000;
}
h1 {
font-size: 1em;
color: #fff;
}
or Example 2: More rules but one font-size
p, h1 {
font-size: 1em;
}
p {
color: #000;
}
h1 {
color: #fff;
}
This study by Dave Gregory is the best source I've found on this topic. It shows that duplicating property/value pairs is much worse for performance:
"Long" is what Gregory refers to as the "bloated" format where properties are repeated in multiple selectors.
for performance is better the second option, see this google advice, but take care of using declarations in just one place, you could finish with something like this, this is the problem with extend in css preprocessor like sass and stylus. However your first option could be more modular and makes your css modules more independent and reusable in other sites, you can then make use of a css minifier to group every declaration.
Organizing your css is really up to you and the number of elements you have.
If you are looking for optimization you should instead focus on useless whitespaces and duplicates.
Tools exist to merge the duplicates and minimize your code (here and here for example)
You may also read this article which is a bit old but still valuable I think.
I'm getting an error when attempting to compile my SCSS file into CSS. The error reads: "selector groups may not be extended" in reference to this line #extend .btn, .btn-link;.
Note: I'm importing Bootstrap to use in my main scss file.
Full snippet:
button {
#extend .btn, .btn-link;
background-color: $lf-green;
color: #fff;
font-size: 10px;
padding: 2px 5px;
text-transform: uppercase;
&:hover {
background: rgba(5,97,43,0.9);
color: #fff;
text-decoration: none;
}
}
What am I doing wrong?
Thanks!
UPDATE:
For posterity: The reason I couldn't do this was because I was using lib-sass via node-sass, which doesn't mesh with the current version of sass available through traditional means https://github.com/andrew/node-sass#reporting-sass-compilation-and-syntax-issues.
I believe you cannot extend multiple selectors this way.
Try using this:
#extend .btn;
#extend .btn-link;
Although that seems a little repetitive, but works fine in my codes.
EDIT: while reading through SASS_REFERENCE, I found that:
Multiple extends can also be written using a comma-separated list of selectors. For example, #extend .error, .attention is the same as #extend .error; #extend.attention.
I did found it in the changelog that this format was first introduced in version 3.1.15, so I suppose you are using an older version of Sass than that.
I strongly encourage you to upgrade to the latest version, as it has a lot of great features, just make sure your codes are not broken by an update, although most of the inconsistencies can be worked out rather easily.
You cannot extend more than one selector.
I have a .scss file that, among other things contains this:
nav {
font-size: 0;
ul {
margin: $padding/3;
}
li {
z-index: 10;
position: relative;
display: inline-block;
font-size: $fontSize;
/**
* If we want separated, Uncomment!
margin: $padding/3;
#include border-radius(5px);
*/
&:first-child {
#include border-radius(0 5px 5px 0);
}
&:last-child {
#include border-radius(5px 0 0 5px);
}
padding: $padding/3 0;
#include background(linear-gradient(lighten($textColor, 10%), $textColor));
border: 1px solid lighten($textColor, 20%);
a {
color: $brightColor;
padding: $padding/3 $padding;
font-weight: bold;
text-decoration: none;
#include transition(.2s all);
}
//Nested menues
ul {
opacity: 0;
//display: none;
position: absolute;
margin: 0;
top: 0;
left: 0;
right: 0;
z-index: 5;
pointer-events: none;
#include transition(.2s all);
li {
#include background(linear-gradient(darken($brightColor, 10%), darken($brightColor, 30%)));
display: block;
border: 1px solid lighten($textColor, 20%);
&:first-child {
#include border-radius(0);
}
&:last-child {
#include border-radius(0 0 5px 5px);
}
a {
color: $textColor;
}
}
}
&:hover ul {
pointer-events: all;
top: 100%;
opacity: 1;
//display: block;
}
}
}
How bad/harmful it is in practice? I've heard many talks about "Don't go over 3 nested selectors!" But how harmful is it really? Does it have any visible impact on page loads? The benchmarks I've done say no, but is there anything I'm missing?
It depends on how much dynamic manipulation of the DOM and styles will go on after page load. It's not page loads (mostly) or slow selectors on initial layout that are at issue, it's repaints/reflows.
Now, Steve Souders says that on the average site it's simply not a real concern. However, on a web app or highly interactive site, poorly performing CSS rules can make your repaints slower than they have to be. If you have a lot of repaints...
Experts such as Nicole Sullivan, Paul Irish, and Steve Souders have covered the way CSS interacts with with JavaScript and how to write highly performant CSS selectors. It's more than depth (different selectors have different performance), but a good rule of thumb is to limit both depth and complexity to keep yourself out of trouble--but not so much performance trouble, read on.
However, as jankfree.org notes, it's not so much descendant or specific selectors as it is certain properties in certain contexts (html5rocks.com) that make paints expensive. I see long or complicated selectors more as a maintainability issue (Nicolas Gallagher) than a performance issue--keeping in mind that maintainability interacts with performance. Highly maintainable code can iterate faster and is easier to debug (helping you find and fix performance issues).
Now, as to Sass optimization. Yes, Sass can optimize your CSS. But it cannot optimize your selectors. A 4 level nested block will be output as a 4 level nested selector. Sass cannot change it without possibly making your CSS not work. You, as the author, have to optimize the way you write Sass to optimize your output. I, personally, use nesting only in a limited way (a killer feature in Sass for me is composing styles with #extend and placeholders). However, if you really love nesting you might be able to tweak your output to some degree using the Sass parent selector reference (or the newer #at-root).
So far as I know, neither Sass nor Compass has a built-in tool to analyze selectors and warn about them. It's probably possible to create a tool to do that (set a max depth and have your pre-processor warn you) utilizing an AST. More directly, Google Page Speed does have an existing feature that provides some information. SCSS Lint has a nesting option. There's also CSS Lint. (These can theoretically be added to run in your Compass config's on_stylesheet_saved if you're not already using something like Grunt or Gulp).
Just think about how you would want to write the actual css selector. Don't nest everything just because it is a child of the element.
nav li ul li a {
/* over specific, confusing */
}
.sub-menu a {
/* add a class to nested menus */
}
Once you start chaining that many selectors, it becomes a pain to override and can lead to specificity issues.
Don't nest CSS. We feel comfortable nesting css because that closely mirrors what we do in HTML. Nesting gives us context that .some-child is inside .some-parent. It gives us some control over the cascading. But not much else.
As SMACSS suggests, I would nest in class names instead. i.e, use .child-of-parent instead of .parent .child or .parent > .child
Nesting badly in practice can lead to extremely slow pages. See how github speeded up their diff pages.The least you should do is follow the inception rule which states that you shouldn't be nesting beyond 4 levels.
However, I would go one step further and say that we shouldn't nest CSS at all. I wrote a blog post with my opinions. Hope this is useful.
Just to chime in and enforce what others have said. It's a bad practice not necessarily from a performance point of view (It's probable you'll get better paint time increases from removing blurs/shadows and rounded corners than optimising selectors) but from a maintainability point of view.
The more heavily nested a selector, the more specific the resultant CSS rule (which you know already). Therefore, when you want to 'trump' that rule at some point you'll have to write a rule of equal (or greater) specificity further down the cascade to overrule the first. If you have an ID in there, that's going to make it FAR more specific too (so avoid unless you need them and know you won't need to override down the line).
To follow this to its logical conclusion, don't nest unless you need to. Don't have a rule like this:
.selector .another .yeah-another {}
When this would do the same job:
.yeah-another {}
It just makes life easier for everyone (including you) down the line.
My opinion:
You tell me which is worse on your eyes
from the op
nav li ul li a {color: $textColor;}
or as has been suggested
.nav-menuitem-menu-menuitem-link {color: $textColor;}
So...
The question is "Is it bad practice to hypernest in SCSS?" (or is it SASS?) I say no. But it's an ancillary argument.
The WORSE practice lies in leaving the SASS (or is it SCSS?) output, in it's machine-driven state, for production.
S*SS is a only a tool in your bag of tricks, no different than Notepad++ or Git or Chrome. It's role is to make your life a little easier by bringing some very general programming concepts to the point of building some css. It's role is NOT building your css. You can't expect it to do your job for you and create completely usable, readable, performing output.
Nest as much and as deep as you want, then follow Good Practice...
...which would be going thru your css afterwards and hand tweaking. Test, build, etc with your hypernested output. And when S*SS creates my first example above, give that anchor a class and call it with nav .class.
Although not directly an answer to your question, you can keep highly nested sass for your own purposes but still use #at-root. Check it out here.
.parent {
#at-root {
.child1 { ... }
.child2 { ... }
}
}
// compiles to ...
.child1 { ... }
.child2 { ... }