SCSS/SASS dynamic background image based on class name - css

I was looking for a "sassy" way to do something like this:
.btn-save {
background: image-url('save.svg');
}
.btn-load {
background: image-url('load.svg');
}
.btn-back {
background: image-url('back.svg');
}
Is there a way I could grab the last part of the class name and pass it to a function to load the appropriate SVG icon? I was thinking it'd look something like:
#function load-svg($svg-name) {
background: image-url($svg-name + ".svg");
}
.btn-* {
// I'm not sure how to get the $svg-name here
load-svg($svg-name);
}
But I wasn't sure if that's possible to do in SCSS. Any help would be much appreciated, thanks!

If you want a DRY approach you could pass a list to a mixin
#mixin setSVGButton($svgs) {
#each $svg in $svgs {
.btn-#{$svg} {
background-image: url(#{$svg}.svg);
}
}
}
#include setSVGButton(('save', 'load', 'back'));

Do you mean something like this
#mixin btn($btn-type) {
.btn-#{$btn-type} {
background: image-url('#{$btn-type}.svg');
}
}
#include btn('save');
#include btn('load');
#include btn('back');

Related

The Sass ampersand and attribute selectors

I want to create a sass file that the selectors will be attribute selectors.
When I work with class selectors, in most of the cases I will do
.parent {
&-child {
}
}
which gives me the following css: .parent-child {}.
I want to achieve the same thing with attribute selectors:
[data-parent] {
&-child {
}
}
which I want to become: [data-parent-child] {}
someone knows how to achieve this? thanks.
You can use this mixin as a workaround to get the desired result.
#mixin child-attribute($child) {
$string: inspect(&);
$original: str-slice($string, 3, -4);
#at-root #{ selector-replace(&, &, "[#{$original}#{$child}]" ) } {
#content;
}
}
The code simply does the following
$string variable is responsible for turning the parent selector to a string using the inspect function
$original variable is responsible for getting the text content of the $string variable i.e the value 'data-parent' from '([data-parent])'
selector-replace function then replaces the parent selector with the concatenation of the $original variable and child variable
When used in the following ways
[data-parent] {
#include child-attribute('-child') {
color: green;
}
}
The css output
[data-parent-child] {
color: green;
}
Depending on what you want to achieve, it can also be used like this
[grandparent] {
#include child-attribute('-parent') {
color: white;
#include child-attribute('-child') {
color: blue;
}
}
}
Which generates the following css
[grandparent-parent] {
color: white;
}
[grandparent-parent-child] {
color: blue;
}
Hope this helps you
You can create mixin that will set styles for elements with data attribytes.
Scss:
#mixin data($name) {
[data-#{$name}] {
#content;
}
}
* {
#include data('lol') {
color: red;
};
}
Css output:
* [data-lol] {
color: red;
}
DEMO
I would go down a slightly different route of having a class on your elements that contain the data attributes.
<div class="data-obj" data-parent="true"></div>
<div class="data-obj" data-parent-child="true"></div>
then in your SASS do
.data-obj {
...
&[data-parent] { ... }
&[data-parent-child] { ... }
}

SASS/SCSS does not accept &.&

Inside my component I'd like to add a modifier, which should have a higher specification so my output should look like this:
Wanted output:
.component {
// ...
}
.component.component--modifier {
// ...
}
SCSS Suggestion:
.component {
// ...
&.&--modifier {
// ...
}
}
But this does not work, I'm getting compile errors: Kind of "format errors" or "invalid CSS".
You could define a mixin:
#mixin mod($n) {
.#{$n} {
color: blue;
}
.#{$n}.#{$n}--modifier {
color: red;
}
}
#include mod(component);
Output:
.component {
color: blue;
}
.component.component--modifier {
color: red;
}
But there's probably a more raisonnable approach to your real problem, like having a modifier class.
You have a period next to the & (&.&). This would produce component..component--modifier, which is incorrect(two periods). What you really want is && but sass doesn't let you do this. What you want to do is escape the second & like this:
&#{&}--modifier
A simpler solution is to interpolate the second & by putting it into #{&}:
.component {
// ...
&#{&}--modifier {
// ...
}
}
Note: The dot between the two & is not needed, because & contains it already.
An equivalent mixin related to Densys would be:
#mixin modifier($modifier) {
&#{&}--#{$modifier} {
#content;
}
}
Usage:
.component {
#include modifier(breadcrumb) {
// ...
}
}

Vaadin, change grid column color

I want to change the column color of my grid. Unfortunately nothing happens... here is my code:
grid.setCellStyleGenerator(( Grid.CellReference cellReference ) -> {
if ( "name".equals( cellReference.getPropertyId() ) ) {
return "highlight-green";
} else {
return "rightAligned";
}
});
mytheme.scss:
#import "../valo/valo.scss";
#mixin mytheme {
#include valo;
// Insert your own theme rules here
.rightAligned {
text-align: right;
}
.v-table-row.v-table-row-highlight-green,
.v-table-row-odd.v-table-row-highlight-green {
background-color: #00ff00;
}
}
The rightAligned works great, but highlight-green doesn't
Try to add background-color: #00ff00 !important;
It looks like you need to rewrite existing styles of your framework, !important must help with this.

Sass and libraries for theming [duplicate]

I'm refactoring some of my Sass code and I came across a weird issue. My code currently looks like this:
// household
$household_Sector: 'household';
$household_BaseColor: #ffc933;
// sports
$sports_Sector: 'sports';
$sports_BaseColor: #f7633e;
// the mixin to output all sector specific css
#mixin sector-css($sector_Sector,$sector_BaseColor) {
.sector-#{$sector_Sector} {
&%baseColor {
background-color: $sector_BaseColor;
}
}
}
// execute the mixin for all sectors
#include sector-css($household_Sector, $household_BaseColor);
#include sector-css($sports_Sector, $sports_BaseColor);
.product-paging {
h2 {
#extend %baseColor;
}
}
DEMO
The compiled result looks like this:
.product-paging h2.sector-household {
background-color: #ffc933;
}
.product-paging h2.sector-sports {
background-color: #f7633e;
}
But what I need is this:
.sector-household.product-paging h2 {
background-color: #ffc933;
}
.sector-sports.product-paging h2 {
background-color: #f7633e;
}
What I don't understand is why my placeholder (&%baseColor) isn't attached to the parent selector (&%baseColor) as I added the ampersand right in front of it?
Is this maybe a bug when combining & and %? Is there another solution on how to achieve what I want?
EDIT
Alright I figured out why this isn't possible. Anyway is there a workaround for what I'd like to achieve?
Extends, as you've already discovered, can get rather messy. I would go about solving your problem by using an #content aware mixin in combination with global variables (this uses mappings, which are part of 3.3... you can do it with lists of lists, but it's a little less elegant):
$base-color: null; // don't touch
$accent-color: null; // don't touch
$sections:
( household:
( base-color: #ffc933
, accent-color: white
)
, sports:
( base-color: #f7633e
, accent-color: white
)
);
// the mixin to output all sector specific css
#mixin sector-css() {
#each $sector, $colors in $sections {
$base-color: map-get($colors, base-color) !global;
$accent-color: map-get($colors, accent-color) !global;
&.sector-#{$sector} {
#content;
}
}
}
.product-paging {
#include sector-css() {
h2 {
background-color: $base-color;
}
}
}
Output:
.product-paging.sector-household h2 {
background-color: #ffc933;
}
.product-paging.sector-sports h2 {
background-color: #f7633e;
}
Update: Since you want to guarantee that the sector class is always at the top, you just need to switch around a little.
#mixin sector-css() {
#each $sector, $colors in $sections {
$base-color: map-get($colors, base-color) !global;
$accent-color: map-get($colors, accent-color) !global;
.sector-#{$sector} {
#content;
}
}
}
#include sector-css() {
&.product-paging {
h2 {
background-color: $base-color;
}
h3 {
background-color: #CCC;
}
h2, h3 {
color: $accent-color;
}
}
}

How can I create a Sass mixin with a class as a variable

I am trying to write something like this :
#mixin variableChild($child:".theChild") {
//some css
$child {
//css specific to the child
}
}
#parent { #include variableChild(".specificChild"); };
So it would generate this CSS :
#parent {//some css}
#parent .specificChild {
//css specific to the child
}
You were almost right, you just missed the #{} around your child selector I think. There’s more information about it in the Sass documentation.
#mixin variableChild($child:".theChild") {
#{$child} {
color: red;
}
}
#parent {
#include variableChild(".specificChild");
};
http://jsfiddle.net/UrLdB/

Resources