Is it possible with compass to loop through a folder and generate css classes of the files within? [duplicate] - sass

I'm using sass and compass and I am trying to create css classes for images matching a given pattern.
The intended/resulting css mostly looks like this:
.class1 { background-image: url(class1.png); }
.class2 { background-image: url(class2.png); }
While it might be possible to use the compass sprite functionality ( http://compass-style.org/help/tutorials/spriting/ ) it is inconvenient (as it will generate new files) in my case as the images are already spritesheets themselves.
So being able to do something like
#each $clazz in listFiles("images/*") {
.#{$clazz} {
background-image: url('#{$clazz}.png');
}
}
would be great.
Is there a more or less easy way to do so?

You can accomplish this by supplementing the builtin SASS/Compass functions with your own custom Ruby function. (See the section titled "Adding Custom Functions" in the SASS reference here.) Just define a Ruby file (say, "list-files.rb") with your custom code like so:
module Sass::Script::Functions
def listFiles(path)
return Sass::Script::List.new(
Dir.glob(path.value).map! { |x| Sass::Script::String.new(x) },
:comma
)
end
end
Then, you can include this file from your compass configuration file (say, "config.rb"):
require File.join(File.dirname(__FILE__), 'list-files.rb')
And access it in your SASS stylesheet just like you want to:
#each $clazz in listFiles("images/*") {
.#{$clazz} {
background-image: url('#{$clazz}.png');
}
}
You can then compile using compass compile -c config.rb, as normal.

Related

SASS add ampersand to mixin output

I'm trying to use an Angular Material mixin with a custom scope. I want to generate my theme like this:
.material-green-theme.mat-mdc-<selector> {
// content
}
However my compiled CSS turns out to be this:
.material-green-theme .mat-mdc-<selector> {
// content
}
This is my code:
.material-green-theme {
#include mat.slide-toggle-color($green-theme);
}
I've tried adding #at-root among other things to make it connect however I can't get it work; nor can I modify the mixin since it's from the Angular Material package. Is there a way for me to somehow make this work?

Sass, create css class dynamic depending on data

I have this class:
.currency-flag-clp:before {
background-image: url('~currency-flags/dist/square-flags/clp.svg');
}
I want to add that class dynamically to an html element, so I need to add a class like:
.currency-flag-XXXXX:before {
background-image: url('~currency-flags/dist/square-flags/XXXXX.svg');
}
Is there a way with sass to do that? I don't want to define 270 class per value, I just want to create the class depending on my data.
As you want to set an individual class on the element it seems you have access to your currency data when building the page. In that case there may be an alternative more simple approach without SASS.
(1) ALTERNATIVE (NON SASS) SOLUTION - maybe a simpler approach
(a) Write a css variable 'actual-currency-flag-url' for your actual flag-image to a style block in the head of your file based on the actual user setting/currency.
(b) Then use that variable to build the url-path in css.
// add to <head> of page:
// based on your data maybe you can do it by php
// note: don't use slashes when building url(...)
<style>
:root {
--actual-currency-url: url(url-path/flag-[actualCurrency].jpg);
}
</style>
// change class off html element
// from <div class="currency-flag-XXXXX"> to:
<div class="currency-flag">
// now you can do in your separate stylesheet file:
.currency-flag:before {
background-image: var(--actual-currency-url);
}
Writing the style direct to the element is less elegant but works as well of course.
(2) POSSIBLE SASS SOLUTION - building 270 classes in SASS using a mixin
(a) Based on your data: generate a simple suffix-list and use it to build a SASS map with the suffixes of your flags.
(b) Use #each to build all 270 classes at once
// example code in SASS:
$flag-suffixes: (
USD,
AUD,
EUR,
//...
);
#each $suffix in $flag-suffixes {
.currency-flag-#{$suffix}:before {
background-image: url('~currency-flags/dist/square-flags/#{$suffix}.svg');
}
}

Sass extend class from module

With the new module system in sass (with #use instead of #import) how can i define a class in one file and the use it in another file with #extend ?
File colors.scss
.element {
background-color: blue;
}
main file
#use "./colors.scss" as colors;
body {
#extend .element;
}
This gives the following error:
"body" failed to #extend ".element".
The selector ".element" was not found.
Use "#extend .element !optional" if the extend should be able to fail.
Example:
https://stackblitz.com/edit/angular-tufq7f?file=src%2Fstyles.scss
How can I tell sass to get it from colors.scss?
Turns out there are a few different problems here. The first is that the stacblitz example is using an old version of sass witch does not have module support. The other is that there is no way to specify from witch sass module to extend a css class from. The correct solution is what I wrote in the question:
#extend .element;
Does the following work?
#use "./colors.scss" as colors;
body {
#extend colors.element;
}
(Modules are imported as a namespace, so you have to 'use' the 'module' by it's name)
https://sass-lang.com/documentation/at-rules/use#choosing-a-namespace

Sass - Create custom control directive (like #if or #for)

I'm wondering whether Sass provides a way to create custom control directive which is the "#" command like #if or #for.
I want to make media query syntax looks simpler like:
#below 800px {
...
}
#above 480px {
...
}
Currenly I'm using mixin for this which make the code longer:
#mixin below($size) {
#media only screen and (max-width: $size) { #content; }
}
#include below(800px) {
...
}
So does Sass support this custom control? I can't seem to find solution online.
Note: I don't want to modify the source code.
Thanks
No. Sass does not allow you to create custom control directives. You would have to modify the Sass parser if you wish to do so or continue using mixins as you are currently already doing.

Getting a list of files in sass/compass

I'm using sass and compass and I am trying to create css classes for images matching a given pattern.
The intended/resulting css mostly looks like this:
.class1 { background-image: url(class1.png); }
.class2 { background-image: url(class2.png); }
While it might be possible to use the compass sprite functionality ( http://compass-style.org/help/tutorials/spriting/ ) it is inconvenient (as it will generate new files) in my case as the images are already spritesheets themselves.
So being able to do something like
#each $clazz in listFiles("images/*") {
.#{$clazz} {
background-image: url('#{$clazz}.png');
}
}
would be great.
Is there a more or less easy way to do so?
You can accomplish this by supplementing the builtin SASS/Compass functions with your own custom Ruby function. (See the section titled "Adding Custom Functions" in the SASS reference here.) Just define a Ruby file (say, "list-files.rb") with your custom code like so:
module Sass::Script::Functions
def listFiles(path)
return Sass::Script::List.new(
Dir.glob(path.value).map! { |x| Sass::Script::String.new(x) },
:comma
)
end
end
Then, you can include this file from your compass configuration file (say, "config.rb"):
require File.join(File.dirname(__FILE__), 'list-files.rb')
And access it in your SASS stylesheet just like you want to:
#each $clazz in listFiles("images/*") {
.#{$clazz} {
background-image: url('#{$clazz}.png');
}
}
You can then compile using compass compile -c config.rb, as normal.

Resources