Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

CSS Sass Basics (retired) Advanced Sass Concepts Creating Loops with @for and @each

Loop through all elements that have a certain html tag name?

Does Sass have a function or method, similar to the html script tag's getElementsByTagName, that I could utilize to loop through all divs on the page?

Hampton's example: ```@for $i from 1 through 100 { .box:nth-child(#{$i}) { background: darken(white, $i); }

I want to do the same thing in such a way that I wouldn't have to count the divs and say "from 1 through (the number I counted)", then have to change the loop number whenever I added or removed a div.
Instead, either I'd use a for loop to go through the length of the array returned by the method,
or I'd use @each to go through the array itself.

You mean that if you suddenly took out 50 of the div's so that you only had 50 you would still want the gradient to go from white to black over 50 div's without having to change the sass?

Sass doesn't interact with your html, it's only a pre-processor for css. There's no way for sass to know how many div's are in the html.

I don't think there's going to be a simple way to do this. If you're talking in the general case and not necessarily a gradient then it might be possible to do something but it probably needs to be taken on a case by case basis.

This stack overflow answer shows how you can size list items based on how many there are: http://stackoverflow.com/a/14960256

The drawback is that you have to know the maximum number you might ever have. I would call this a brute force method too. It outputs all the possible css you might need even though you only need 1 of those rules at any given time.

I think it would be possible to adapt that technique to a gradient but I think it would output a massive amount of css.

Also, I think it should be said that just because you can create a gradient in sass doesn't mean you should. You're better off using the gradient functions native to css.

2 Answers

Codin - Codesmite
Codin - Codesmite
8,600 Points

Hi Megan, can you explain what you are trying to achieve that is different from Hampton's example.

To target all the div elements on a page you can do this simply with normal CSS for example:

div {
   color: red;
}

If you were to loop all divs on a page based on the same selector for example:

@for $i from 1 through 10 {
    div {
        background: darken(grey, $i);
        color: darken(whitesmoke, $i);
    }
}

/* It would only use the last rule: */

div {
  background: #676767;
  color: gainsboro;
}

/* All previous rules would compile and be present in the css file, but they would all share 
the same selector, and the last rule will override the previous
 due to CSS cascading behaviour like so: */

div {
  background: #7d7d7d;
  color: #f2f2f2;
}

div {
  background: #7b7b7b;
  color: #f0f0f0;
}

div {
  background: #787878;
  color: #ededed;
}

div {
  background: #767676;
  color: #ebebeb;
}

div {
  background: #737373;
  color: #e8e8e8;
}

div {
  background: #717171;
  color: #e6e6e6;
}

div {
  background: #6e6e6e;
  color: #e3e3e3;
}

div {
  background: #6c6c6c;
  color: #e1e1e1;
}

div {
  background: dimgray;
  color: #dedede;
}

div {
  background: #676767;
  color: gainsboro;
}

Example: http://codepen.io/anon/pen/NxzGVZ

Unless for example you had:

  <div class="div-1">Example Text</div>
  <div class="div-2">Example Text</div>
  <div class="div-3">Example Text</div>
  <div class="div-4">Example Text</div>
  <div class="div-5">Example Text</div>
  <div class="div-6">Example Text</div>
  <div class="div-7">Example Text</div>
  <div class="div-8">Example Text</div>
  <div class="div-9">Example Text</div>
  <div class="div-10">Example Text</div>
@for $i from 1 through 10 {
    .div-#{$i} {
        background: darken(grey, $i);
        color: darken(whitesmoke, $i);
    }
}

/* This would compile to: */

.div-1 {
  background: #7d7d7d;
  color: #f2f2f2;
}

.div-2 {
  background: #7b7b7b;
  color: #f0f0f0;
}

.div-3 {
  background: #787878;
  color: #ededed;
}

.div-4 {
  background: #767676;
  color: #ebebeb;
}

.div-5 {
  background: #737373;
  color: #e8e8e8;
}

.div-6 {
  background: #717171;
  color: #e6e6e6;
}

.div-7 {
  background: #6e6e6e;
  color: #e3e3e3;
}

.div-8 {
  background: #6c6c6c;
  color: #e1e1e1;
}

.div-9 {
  background: dimgray;
  color: #dedede;
}

.div-10 {
  background: #676767;
  color: gainsboro;
}

Example: http://codepen.io/anon/pen/XXYmLN

In the case of your last example, I think it's easier to do it the way Hampton did with :nth-child. That way you don't have the additional overhead of setting up all those classes in the html.

Codin - Codesmite
Codin - Codesmite
8,600 Points

You could just loop them with php, python, html slim, javascript etc nth child also expects the divs to be in linear order, where as if you target a specific class you can have divs between you do not want to effect, which I think might be what Megan is trying to achieve.

Steven Parker
Steven Parker
229,732 Points

Why would you need a loop? If you want to target every element with the same tag, just use that tag as your selector.

For like if you wanted to do the :nth-child() thing, passing $i as the parameter and styling based on that, like Hampton did in the video.

Hi Megan,

Maybe give some example html and explain what you'd like to do. Or explain how what you want to do is different from what Hampton did.