Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
As a result of using less I have started to use nesting more and more. It's clean and easy to follow, but I use more selectors than normal because of nesting.
For example (simplified):
#footer {
background: #footer-background;
padding: 20px 0;
margin-bottom: 20px;
.seal {
width:22%;
img {
display:block;
margin:0 auto;
}
}
.copyright {
margin: 20px 0 0;
}
}
Or:
#footer {padding: 20px 0; margin-bottom: 20px}
#footer .seal {width:22%}
#footer img {display:block; margin:0 auto}
.copyright {margin: 20px 0 0}
The first will result in additional selectors that are not really needed, but it also prevents duplication and makes it easy to find and remove all unused/unneeded/duplicated css. All of this happens because your less files have a structure.
I think that the reduction in development time is worth the extra selectors. I think that my development time would be better spent elsewhere... but I'm not confident in that answer.
Should I avoid unneeded nesting, or is the gain worth the loss?
You Can Achieve Both Organization and Minimal Specificity
It is generally recommended to use the least specific selector to do the job. If your main desire is to also do some nesting in LESS for structural organization, then you can achieve the best of both worlds. Take your simplified example modified:
LESS
#FOOTER() {
#footer {
background: #footer-background;
padding: 20px 0;
margin-bottom: 20px;
.seal {
width:22%;
}
img {
display:block;
margin:0 auto;
}
}
.copyright {
margin: 20px 0 0;
}
}
#FOOTER();
CSS Output (your original shorter code)
#footer {
background: some color you set for #footer-background;
padding: 20px 0;
margin-bottom: 20px;
}
#footer .seal {
width: 22%;
}
#footer img {
display: block;
margin: 0 auto;
}
.copyright {
margin: 20px 0 0;
}
I've used a mixin with a set of parenthesis to "group" styles related to the footer area, and call that mixin to actually output the styles. This allows me to keep the code together, and insert it "wherever" in my final output css. But the styles can then be a bit more loosely grouped under that. So I have moved the img outside the .seal, and the .copyright outside the #footer. It may be true that the img is found in the html inside the .seal, or the .copyright inside the #footer, but if that is not relevant to selecting it, then simply knowing it is related to the #FOOTER() group may be enough for your organizational needs.
This is still an improvement over merely a /*comment*/ that sets apart a group, because it does still minimize duplication (#footer is not duplicated), and it does allow me to output the css in an organized way--one can envision this:
#RESET();
#HEADER();
#CONTENT();
#FOOTER();
Inside #HEADER(); may be some other sub-groupings:
#NAV();
#BRANDING();
It may be opinion, but in my mind rarely should selectors require more than a single level of nesting to get the specificity needed in a well structured html page. One set of exceptions are sibling relationships, where sometimes a complex set of nesting and sibling relationships are needed to select the elements.
Of course, you have to be aware that, for example, .copyright is defined in #FOOTER() but it is outputting a selector that is not necessarily constrained to that area. If you as the designer know that the copyright appears no where else, okay. If not, then subsuming it under #footer will be important.
Related
I am converting a website using sass, nesting saves me from having to duplicate parent selectors (eg - sociialmedia, socialmedia li, sociallmedia img)
However, when the viewport is at mobile size, I need to change the styling of socialmedia img. Therefore I have create the code below:
my questions are:
1) Is this an efficient way to code (example 1), or is there a better method?
2) example 1 works , but is example 2 more efficient?
Example 1
#socialmedia {
float: right;
li {
float: left;
}
#include bp(mobile) {
img {
width: 1.1em;
}
}
}
Example 2
#socialmedia {
float: right;
li {
float: left;
}
}
#socialmedia img {
#include bp(mobile) {
width: 1.1em;
}
}
Many thanks,
It depends on what you mean by "efficient"—if you are referring to the efficiency of the compiled CSS code, both of your examples are equivalent; they both compile down to the same CSS.
If you are referring to developer efficiency, in my opinion the first example is more readable and maintainable (one of the nice features of Sass is the ability to nest media queries in context, which is what you are doing). Your example 1 is usually the approach I take.
So, in answer to your questions:
This is a perfectly acceptable method.
No.
I'm still getting to grips with SASS. I want to check within a selector whether or not an element is within a certain other ancestor/parent element.
I have this:
p.key-name {
float: left;
padding: 4px 32px 0 2px;
}
li:last-of-type p.key-name {
padding-right: 0;
}
Works great, but is regular CSS so no surprise there. But I'd rather have that second selector grouped within the first, so I tried this:
p.key-name {
float: left;
padding: 4px 32px 0 2px;
li:last-of-type & {
padding-right: 0;
}
}
That doesn't work. I can see why by looking at the processed CSS, but I'm wondering if there's a way of using SASS to make this notion work.
Thanks for any help offered!
Edit: As explored in the comments, it turns out that the code works but there's a parent <li> higher up the hierarchy interfering due to a lack of specificity in the SASS (i.e. no class or anything more qualifying on the li:last-of-type). So the two snippets above are in fact equivalent _as long as there are no <li>s surrounding these ones.
So I was writing up some code when I decided I wanted to make a variable for margin and padding, along with some other positioning too. But when I try I get errors.
This is what my code looks like:
//Positioning
#margin_t: margin-top:0;
#margin_r: margin-right:0;
#margin_l: margin-left:0;
#margin_b: margin-bottom:0;
#padding_t: padding-top:0;
#padding_r: padding-right:0;
#padding_l: padding-left:0;
#padding:_b: padding-bottom:0;
#center: text-align: center;
#left: text-align: left;
#right: text-align: right;
#relative: position: relative;
#justify: position: justify;
Can anyone give me their two-cents? Thank you!
As of LESS 1.7
You can include property values in variables by rulesets, like so (note bracketing and following semicolon; p.s. position: justify is not valid, I've changed it to absolute):
//Positioning
#margin_t: {margin-top:0;};
#margin_r: {margin-right:0;};
#margin_l: {margin-left:0;};
#margin_b: {margin-bottom:0;};
#padding_t: {padding-top:0;};
#padding_r: {padding-right:0;};
#padding_l: {padding-left:0;};
#padding:_b: {padding-bottom:0;};
#center: {text-align: center;};
#left: {text-align: left;};
#right: {text-align: right;};
#relative: {position: relative;};
#absolute: {position: absolute;};
A variable assigned ruleset is use much like a mixin (note the parentheses on the call), so:
.yourClass {
#relative();
}
Produces:
.yourClass {
position: relative;
}
The differences of a variable ruleset to a mixin are that you cannot pass parameters to a ruleset (directly anyway), but a ruleset can itself be passed as a parameter to a mixin. Also, variable rulesets will overwrite a previous definition (no matter properties defined), whereas mixins will merge property values. Rulesets work well for fixed values, like some of your items. They can be parametrized indirectly, something like so:
#margin_t: {margin-top: #tm;};
.yourClass {
#tm: 0;
#margin_t();
}
Varible rulesets actually work best for when one wants to pass to a mixin a group of properties or a single, unknown dynamic property. As an example of the latter, suppose you know you will want to set a single margin for an element, but depending on some context, you don't know which you want to set, so you want a single way to handle it. Then something like this can be done:
#margin_t: {margin-top: #value;};
#margin_r: {margin-right: #value};
#margin_l: {margin-left: #value;};
#margin_b: {margin-bottom: #value;};
.set-a-margin(#prop; #value: 0;) {
#prop();
}
.yourClass {
.set-a-margin(#margin_r; 10px);
}
.anotherClass {
.set-a-margin(#margin_b; 5px);
}
Produces:
.yourClass {
margin-right: 10px;
}
.anotherClass {
margin-bottom: 5px;
}
Basically, variable assigned rulesets just offer another way LESS can be used to code the way you may want to code. They can offer some functionality like mixins, with certain limitations and advantages different from those as related to variables.
Firstly, define your mixins like this:
.margin_t {
margin-top: 0;
}
.margin_b (#value: 0) {
margin-bottom: #value;
}
and then just use it!
body {
.margin_t();
.margin_b(15px);
}
You don't set the whole style. you would do #margin_t: 0;
Then use it
.myClass {
margin-top: #margin_t;
}
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.
Usually in order to get the style the same for every browser you see some sites have something like this:
html, body, div, span, object, ... {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
Is there a reason why they don't simply use:
*, html { ... }
The more broad a set of CSS rules is, the more processing it'll take to load them. The best ruleset is also the most specific.
You can use something along the lines of
* {
margin: 0;
padding: 0;
...
}
to reset everything, the big drawback is, it does exactly that. Then paragraphs don't have any spacing, etc. I'd rather have universal style than having no style and starting from scratch.
This article does a good job explaining the benefits as well, starting at the section titled "A reset to where it all started…"